diff mbox

[net-next,V2,5/5] net/mlx4_en: Add a service task

Message ID 1366631767-16493-6-git-send-email-amirv@mellanox.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Amir Vadai April 22, 2013, 11:56 a.m. UTC
Add a service task to run tasks that needed to be executed periodically.
Currently the only task is a watchdog to catch NIC clock overflow, to make
timestamping accurate.
Will move the statistics task into this framework in a later patch.

Signed-off-by: Amir Vadai <amirv@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx4/en_clock.c  |   20 ++++++++++++++++++++
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c |   24 ++++++++++++++++++++++++
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h   |    4 ++++
 3 files changed, 48 insertions(+), 0 deletions(-)

Comments

Eric Dumazet April 22, 2013, 7:01 p.m. UTC | #1
On Mon, 2013-04-22 at 14:56 +0300, Amir Vadai wrote:
> Add a service task to run tasks that needed to be executed periodically.
> Currently the only task is a watchdog to catch NIC clock overflow, to make
> timestamping accurate.
> Will move the statistics task into this framework in a later patch.
> 
> Signed-off-by: Amir Vadai <amirv@mellanox.com>
> ---
>  drivers/net/ethernet/mellanox/mlx4/en_clock.c  |   20 ++++++++++++++++++++
>  drivers/net/ethernet/mellanox/mlx4/en_netdev.c |   24 ++++++++++++++++++++++++
>  drivers/net/ethernet/mellanox/mlx4/mlx4_en.h   |    4 ++++
>  3 files changed, 48 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
> index 6d8227d..c1982a4 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
> @@ -126,4 +126,24 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
>  
>  	timecounter_init(&mdev->clock, &mdev->cycles,
>  			 ktime_to_ns(ktime_get_real()));
> +
> +	/* Calculate period in seconds to call the overflow watchdog. Doing
> +	 * that, by dividing the maximal cycles value in nano-seconds, convert
> +	 * it to seconds, and divide by 2 - to make sure counter is checked at
> +	 * least once every wrap around.
> +	 */
> +	mdev->overflow_period =
> +		cyclecounter_cyc2ns(&mdev->cycles,
> +				    mdev->cycles.mask) / 1000000 / 2;
> +}
> +

So this 1000000 looks like NSEC_PER_SEC/HZ ?

What if HZ=100 ?



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Amir Vadai April 23, 2013, 1:56 p.m. UTC | #2
On 22/04/2013 22:01, Eric Dumazet wrote:
> On Mon, 2013-04-22 at 14:56 +0300, Amir Vadai wrote:
>> Add a service task to run tasks that needed to be executed periodically.
>> Currently the only task is a watchdog to catch NIC clock overflow, to make
>> timestamping accurate.
>> Will move the statistics task into this framework in a later patch.
>>
>> Signed-off-by: Amir Vadai <amirv@mellanox.com>
>> ---
>>  drivers/net/ethernet/mellanox/mlx4/en_clock.c  |   20 ++++++++++++++++++++
>>  drivers/net/ethernet/mellanox/mlx4/en_netdev.c |   24 ++++++++++++++++++++++++
>>  drivers/net/ethernet/mellanox/mlx4/mlx4_en.h   |    4 ++++
>>  3 files changed, 48 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
>> index 6d8227d..c1982a4 100644
>> --- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
>> +++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
>> @@ -126,4 +126,24 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
>>  
>>  	timecounter_init(&mdev->clock, &mdev->cycles,
>>  			 ktime_to_ns(ktime_get_real()));
>> +
>> +	/* Calculate period in seconds to call the overflow watchdog. Doing
>> +	 * that, by dividing the maximal cycles value in nano-seconds, convert
>> +	 * it to seconds, and divide by 2 - to make sure counter is checked at
>> +	 * least once every wrap around.
>> +	 */
>> +	mdev->overflow_period =
>> +		cyclecounter_cyc2ns(&mdev->cycles,
>> +				    mdev->cycles.mask) / 1000000 / 2;
>> +}
>> +
> 
> So this 1000000 looks like NSEC_PER_SEC/HZ ?
No. It is just a typo - used 10^6 instead of 10^9 for nano's.
But it is a good idea to have the HZ multiplied in the initialization of
overflow_period - will fix the calculation and change overflow_period
units to be jiffies, and not seconds.
> 
> What if HZ=100 ?
> 
> 
> 

Thanks,
Amir
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
index 6d8227d..c1982a4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
@@ -126,4 +126,24 @@  void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
 
 	timecounter_init(&mdev->clock, &mdev->cycles,
 			 ktime_to_ns(ktime_get_real()));
+
+	/* Calculate period in seconds to call the overflow watchdog. Doing
+	 * that, by dividing the maximal cycles value in nano-seconds, convert
+	 * it to seconds, and divide by 2 - to make sure counter is checked at
+	 * least once every wrap around.
+	 */
+	mdev->overflow_period =
+		cyclecounter_cyc2ns(&mdev->cycles,
+				    mdev->cycles.mask) / 1000000 / 2;
+}
+
+void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev)
+{
+	bool timeout = time_is_before_jiffies(mdev->last_overflow_check +
+					      HZ * mdev->overflow_period);
+
+	if (timeout) {
+		timecounter_read(&mdev->clock);
+		mdev->last_overflow_check = jiffies;
+	}
 }
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 4cb9f32..f4f88b8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -1361,6 +1361,26 @@  static void mlx4_en_do_get_stats(struct work_struct *work)
 	mutex_unlock(&mdev->state_lock);
 }
 
+/* mlx4_en_service_task - Run service task for tasks that needed to be done
+ * periodically
+ */
+static void mlx4_en_service_task(struct work_struct *work)
+{
+	struct delayed_work *delay = to_delayed_work(work);
+	struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
+						 service_task);
+	struct mlx4_en_dev *mdev = priv->mdev;
+
+	mutex_lock(&mdev->state_lock);
+	if (mdev->device_up) {
+		mlx4_en_ptp_overflow_check(mdev);
+
+		queue_delayed_work(mdev->workqueue, &priv->service_task,
+				   SERVICE_TASK_DELAY);
+	}
+	mutex_unlock(&mdev->state_lock);
+}
+
 static void mlx4_en_linkstate(struct work_struct *work)
 {
 	struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
@@ -1865,6 +1885,7 @@  void mlx4_en_destroy_netdev(struct net_device *dev)
 		mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE);
 
 	cancel_delayed_work(&priv->stats_task);
+	cancel_delayed_work(&priv->service_task);
 	/* flush any pending task for this netdev */
 	flush_workqueue(mdev->workqueue);
 
@@ -2084,6 +2105,7 @@  int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
 	INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
 	INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
+	INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
 #ifdef CONFIG_MLX4_EN_DCB
 	if (!mlx4_is_slave(priv->mdev->dev)) {
 		if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_SET_ETH_SCHED) {
@@ -2206,6 +2228,8 @@  int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	}
 	mlx4_en_set_default_moderation(priv);
 	queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
+	queue_delayed_work(mdev->workqueue, &priv->service_task,
+			   SERVICE_TASK_DELAY);
 	return 0;
 
 out:
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 85b0754..f4b61c5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -78,6 +78,7 @@ 
 #define STAMP_SHIFT		31
 #define STAMP_VAL		0x7fffffff
 #define STATS_DELAY		(HZ / 4)
+#define SERVICE_TASK_DELAY	(HZ / 4)
 #define MAX_NUM_OF_FS_RULES	256
 
 #define MLX4_EN_FILTER_HASH_SHIFT 4
@@ -355,6 +356,7 @@  struct mlx4_en_dev {
 	struct cyclecounter	cycles;
 	struct timecounter	clock;
 	unsigned long		last_overflow_check;
+	u32			overflow_period;
 };
 
 
@@ -519,6 +521,7 @@  struct mlx4_en_priv {
 	struct work_struct watchdog_task;
 	struct work_struct linkstate_task;
 	struct delayed_work stats_task;
+	struct delayed_work service_task;
 	struct mlx4_en_perf_stats pstats;
 	struct mlx4_en_pkt_stats pkstats;
 	struct mlx4_en_port_stats port_stats;
@@ -645,6 +648,7 @@  void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
 #define MLX4_EN_NUM_SELF_TEST	5
 void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
 u64 mlx4_en_mac_to_u64(u8 *addr);
+void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev);
 
 /*
  * Functions for time stamping