linux驱动添加延迟队列monitor(Add delay worker for gmsl)

通过delay work实现在linux驱动中添加周期处理函数(monitor)

 

#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>

#ifdef CONFIG_DIAG_CLASS
#include <linux/diagnostic.h>
#include <linux/diagnostic/diagnostic_gmsl.h>
#endif /* CONFIG_DIAG_CLASS */

struct gmsl_device;
struct gmsl_serdes_data;

struct gmsl_serdes_platform_data {
	const char				*name;
	const u8				id;
	const struct mfd_cell			*mfd;
	const int				mfd_size;
	const u8				nb_remote;
	const u8				nb_irq;
	const struct gmsl_serdes_irq		*irq;
	const int				cross_size;
	const int				cross_addr;
};

struct gmsl_monitor {
	const char *name;
	struct workqueue_struct *workq;
	struct delayed_work reader; /* Used to poll link */
	unsigned long interval;
	int (*gmsl_monitor)(struct gmsl_device *);
	struct gmsl_device	 *gd;
};

struct gmsl_device {
	struct i2c_client *client;
	struct regmap *regmap;

	struct gmsl_monitor *monitor;
	struct gmsl_monitor *irq_monitor;
};

struct gmsl_serdes_data {
	/* local device fields */
	struct i2c_client			*client;
	struct device				*dev;
	struct regmap				*regmap;

	const struct gmsl_serdes_platform_data	*pdata;

	struct gmsl_device gd;

};

static struct gmsl_monitor gmsl_monitor_default = {
	.name = "gms_diag_monitor",
	.interval = 2 * HZ,
	.gmsl_monitor = gmsl_line_fault_monitor_polling,
};

static int gmsl_line_fault_monitor_polling(struct gmsl_device *gd)
{
	struct gmsl_serdes_data *gmsl = i2c_get_clientdata(gd->client);
	return 0;
}

static int gmsl_err_irq_monitor(struct gmsl_device *gd)
{
	struct gmsl_serdes_data *gmsl = i2c_get_clientdata(gd->client);
	return 0;
}

void gmsl_trigger_monitor(struct gmsl_monitor *monitor)
{
	queue_delayed_work(monitor->workq, &monitor->reader,
				monitor->interval);
}

static void gmsl_diag_monitor(struct work_struct *work)
{
	struct gmsl_monitor *monitor = container_of(work,struct gmsl_monitor,reader.work);

	/* if link still not established, then continue polling */
	if (monitor->gmsl_monitor(monitor->gd))
		gmsl_trigger_monitor(monitor);
}

static int gmsl_configure_monitor(struct gmsl_monitor *monitor)
{
	if (!monitor || !monitor->gmsl_monitor)
		return -EINVAL;

	monitor->workq = alloc_ordered_workqueue(monitor->name, 0);
	if (monitor->workq == NULL) {
		printk("Failed to create gmsl monitor workqueue\n");
		return -EINVAL;
	}

	/* setup polling interval */
	if (monitor->interval == 0)
		monitor->interval = 1 * HZ;

	INIT_DELAYED_WORK(&monitor->reader, gmsl_diag_monitor);
	return 0;
}

int gmsl_serdes_diag_init(struct gmsl_serdes_data *gmsl)
{
	int status = 0, irq_count, i, j;
	struct resource *res;
	struct i2c_client *client = gmsl->client;
	int err;

	devm_gmsl_alloc_monitor(&gmsl->gd, &gmsl->gd.monitor);

	memcpy(gmsl->gd.monitor, &gmsl_monitor_default,
		sizeof(gmsl_monitor_default));

	gmsl->gd.monitor->gd = &gmsl->gd;
	gmsl->gd.monitor->interval = msecs_to_jiffies(200);

	/* create irq monitor timeout */
	err = devm_gmsl_alloc_monitor(&gmsl->gd, &gmsl->gd.irq_monitor);
	if (err){
		dev_err(gmsl->dev, "can't create irq monitor timeout\n");
	}

	/*  irq monitor timeout data init */
	gmsl->gd.irq_monitor->name = "gmsl_irq_monitor";
	gmsl->gd.irq_monitor->interval = msecs_to_jiffies(500);
	gmsl->gd.irq_monitor->gd = &gmsl->gd;
	gmsl->gd.irq_monitor->gmsl_monitor = gmsl_err_irq_monitor;
	err = gmsl_configure_monitor(gmsl->gd.irq_monitor);
	if (err){
		dev_err(gmsl->dev, "irq monitor timeout data init failed\n");
	}



	if( gmsl->lflt_monitor ){
		gmsl_configure_monitor(gmsl->gd.monitor);
		gmsl_trigger_monitor(gmsl->gd.monitor);
	}
}


static int gmsl_serdes_probe(struct i2c_client *client,
			     const struct i2c_device_id *id)
{
	const struct of_device_id *of_dev_id;
	struct gmsl_serdes_data *gmsl;
	struct device *dev = &client->dev;
	int status;

	gmsl = devm_kzalloc(dev, sizeof(*gmsl), GFP_KERNEL);
	if (!gmsl)
		return -ENOMEM;

	gmsl->dev = dev;
	gmsl->client = client;
	i2c_set_clientdata(client, gmsl);

	of_dev_id = of_match_device(gmsl_serdes_dt_ids, dev);
	if (!of_dev_id) {
		dev_err(dev, "unable to match device\n");
		status = -EINVAL;
		goto fail;
	}
	gmsl->pdata = of_dev_id->data;
	dev_info(dev, "probing %s as local device\n", gmsl->pdata->name);

	gmsl->gd.client = gmsl->client;
	gmsl->gd.regmap = gmsl->regmap;


	status = gmsl_serdes_diag_init(gmsl);
	if (status) {
		dev_err(dev, "unable to initialize serdes diag correctly\n");
		goto fail_client;
	}
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值