forked from mirrors/linux
		
	gpiolib: cdev: consolidate edge detector configuration flags
Combine the polarity_change flag, struct line eflags, and hte enable flag into a single flag variable. The combination of these flags describes the configuration state of the edge detector, so formalize and clarify that by combining them into a single variable, edflags, in struct line. The edflags is a subset of the GPIO_V2_LINE_FLAGsb relevant to the edge detector, and is also a superset of the eflags it replaces. The eflags name is still used to describe the subset of edflags corresponding to the rising/falling edge flags where edflags is masked down to that subset. This consolidation reduces the number of variables being passed, simplifies state comparisons, and provides a more extensible foundation should additional edge sources be integrated in the future. Signed-off-by: Kent Gibson <warthog618@gmail.com> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
This commit is contained in:
		
							parent
							
								
									242202329f
								
							
						
					
					
						commit
						b1a92e9456
					
				
					 1 changed files with 60 additions and 66 deletions
				
			
		|  | @ -430,12 +430,15 @@ struct line { | ||||||
| 	struct linereq *req; | 	struct linereq *req; | ||||||
| 	unsigned int irq; | 	unsigned int irq; | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * eflags is set by edge_detector_setup(), edge_detector_stop() and | 	 * The flags for the active edge detector configuration. | ||||||
| 	 * edge_detector_update(), which are themselves mutually exclusive, | 	 * | ||||||
| 	 * and is accessed by edge_irq_thread() and debounce_work_func(), | 	 * edflags is set by linereq_create(), linereq_free(), and | ||||||
| 	 * which can both live with a slightly stale value. | 	 * linereq_set_config_unlocked(), which are themselves mutually | ||||||
|  | 	 * exclusive, and is accessed by edge_irq_thread(), | ||||||
|  | 	 * process_hw_ts_thread() and debounce_work_func(), | ||||||
|  | 	 * which can all live with a slightly stale value. | ||||||
| 	 */ | 	 */ | ||||||
| 	u64 eflags; | 	u64 edflags; | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * timestamp_ns and req_seqno are accessed only by | 	 * timestamp_ns and req_seqno are accessed only by | ||||||
| 	 * edge_irq_handler() and edge_irq_thread(), which are themselves | 	 * edge_irq_handler() and edge_irq_thread(), which are themselves | ||||||
|  | @ -541,6 +544,12 @@ struct linereq { | ||||||
| 	 GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE | \ | 	 GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE | \ | ||||||
| 	 GPIO_V2_LINE_BIAS_FLAGS) | 	 GPIO_V2_LINE_BIAS_FLAGS) | ||||||
| 
 | 
 | ||||||
|  | /* subset of flags relevant for edge detector configuration */ | ||||||
|  | #define GPIO_V2_LINE_EDGE_DETECTOR_FLAGS \ | ||||||
|  | 	(GPIO_V2_LINE_FLAG_ACTIVE_LOW | \ | ||||||
|  | 	 GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE | \ | ||||||
|  | 	 GPIO_V2_LINE_EDGE_FLAGS) | ||||||
|  | 
 | ||||||
| static void linereq_put_event(struct linereq *lr, | static void linereq_put_event(struct linereq *lr, | ||||||
| 			      struct gpio_v2_line_event *le) | 			      struct gpio_v2_line_event *le) | ||||||
| { | { | ||||||
|  | @ -580,8 +589,8 @@ static enum hte_return process_hw_ts_thread(void *p) | ||||||
| 	struct line *line; | 	struct line *line; | ||||||
| 	struct linereq *lr; | 	struct linereq *lr; | ||||||
| 	struct gpio_v2_line_event le; | 	struct gpio_v2_line_event le; | ||||||
|  | 	u64 edflags; | ||||||
| 	int level; | 	int level; | ||||||
| 	u64 eflags; |  | ||||||
| 
 | 
 | ||||||
| 	if (!p) | 	if (!p) | ||||||
| 		return HTE_CB_HANDLED; | 		return HTE_CB_HANDLED; | ||||||
|  | @ -592,15 +601,15 @@ static enum hte_return process_hw_ts_thread(void *p) | ||||||
| 	memset(&le, 0, sizeof(le)); | 	memset(&le, 0, sizeof(le)); | ||||||
| 
 | 
 | ||||||
| 	le.timestamp_ns = line->timestamp_ns; | 	le.timestamp_ns = line->timestamp_ns; | ||||||
| 	eflags = READ_ONCE(line->eflags); | 	edflags = READ_ONCE(line->edflags); | ||||||
| 
 | 
 | ||||||
| 	switch (eflags) { | 	switch (edflags & GPIO_V2_LINE_EDGE_FLAGS) { | ||||||
| 	case GPIO_V2_LINE_FLAG_EDGE_BOTH: | 	case GPIO_V2_LINE_FLAG_EDGE_BOTH: | ||||||
| 		level = (line->raw_level >= 0) ? | 		level = (line->raw_level >= 0) ? | ||||||
| 				line->raw_level : | 				line->raw_level : | ||||||
| 				gpiod_get_raw_value_cansleep(line->desc); | 				gpiod_get_raw_value_cansleep(line->desc); | ||||||
| 
 | 
 | ||||||
| 		if (test_bit(FLAG_ACTIVE_LOW, &line->desc->flags)) | 		if (edflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW) | ||||||
| 			level = !level; | 			level = !level; | ||||||
| 
 | 
 | ||||||
| 		le.id = line_event_id(level); | 		le.id = line_event_id(level); | ||||||
|  | @ -681,7 +690,7 @@ static irqreturn_t edge_irq_thread(int irq, void *p) | ||||||
| 	} | 	} | ||||||
| 	line->timestamp_ns = 0; | 	line->timestamp_ns = 0; | ||||||
| 
 | 
 | ||||||
| 	switch (READ_ONCE(line->eflags)) { | 	switch (READ_ONCE(line->edflags) & GPIO_V2_LINE_EDGE_FLAGS) { | ||||||
| 	case GPIO_V2_LINE_FLAG_EDGE_BOTH: | 	case GPIO_V2_LINE_FLAG_EDGE_BOTH: | ||||||
| 		le.id = line_event_id(gpiod_get_value_cansleep(line->desc)); | 		le.id = line_event_id(gpiod_get_value_cansleep(line->desc)); | ||||||
| 		break; | 		break; | ||||||
|  | @ -756,16 +765,13 @@ static void debounce_work_func(struct work_struct *work) | ||||||
| 	struct gpio_v2_line_event le; | 	struct gpio_v2_line_event le; | ||||||
| 	struct line *line = container_of(work, struct line, work.work); | 	struct line *line = container_of(work, struct line, work.work); | ||||||
| 	struct linereq *lr; | 	struct linereq *lr; | ||||||
| 	int level, diff_seqno; | 	u64 eflags, edflags = READ_ONCE(line->edflags); | ||||||
| 	u64 eflags; | 	int level = -1, diff_seqno; | ||||||
| 
 | 
 | ||||||
| 	if (test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) { | 	if (edflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) | ||||||
| 		level = line->raw_level; | 		level = line->raw_level; | ||||||
| 		if (level < 0) | 	if (level < 0) | ||||||
| 			level = gpiod_get_raw_value_cansleep(line->desc); |  | ||||||
| 	} else { |  | ||||||
| 		level = gpiod_get_raw_value_cansleep(line->desc); | 		level = gpiod_get_raw_value_cansleep(line->desc); | ||||||
| 	} |  | ||||||
| 	if (level < 0) { | 	if (level < 0) { | ||||||
| 		pr_debug_ratelimited("debouncer failed to read line value\n"); | 		pr_debug_ratelimited("debouncer failed to read line value\n"); | ||||||
| 		return; | 		return; | ||||||
|  | @ -777,12 +783,12 @@ static void debounce_work_func(struct work_struct *work) | ||||||
| 	WRITE_ONCE(line->level, level); | 	WRITE_ONCE(line->level, level); | ||||||
| 
 | 
 | ||||||
| 	/* -- edge detection -- */ | 	/* -- edge detection -- */ | ||||||
| 	eflags = READ_ONCE(line->eflags); | 	eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS; | ||||||
| 	if (!eflags) | 	if (!eflags) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	/* switch from physical level to logical - if they differ */ | 	/* switch from physical level to logical - if they differ */ | ||||||
| 	if (test_bit(FLAG_ACTIVE_LOW, &line->desc->flags)) | 	if (edflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW) | ||||||
| 		level = !level; | 		level = !level; | ||||||
| 
 | 
 | ||||||
| 	/* ignore edges that are not being monitored */ | 	/* ignore edges that are not being monitored */ | ||||||
|  | @ -796,7 +802,7 @@ static void debounce_work_func(struct work_struct *work) | ||||||
| 	lr = line->req; | 	lr = line->req; | ||||||
| 	le.timestamp_ns = line_event_timestamp(line); | 	le.timestamp_ns = line_event_timestamp(line); | ||||||
| 	le.offset = gpio_chip_hwgpio(line->desc); | 	le.offset = gpio_chip_hwgpio(line->desc); | ||||||
| 	if (test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) { | 	if (edflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) { | ||||||
| 		/* discard events except the last one */ | 		/* discard events except the last one */ | ||||||
| 		line->total_discard_seq -= 1; | 		line->total_discard_seq -= 1; | ||||||
| 		diff_seqno = line->last_seqno - line->total_discard_seq - | 		diff_seqno = line->last_seqno - line->total_discard_seq - | ||||||
|  | @ -843,8 +849,7 @@ static int hte_edge_setup(struct line *line, u64 eflags) | ||||||
| 				 process_hw_ts_thread, line); | 				 process_hw_ts_thread, line); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int debounce_setup(struct line *line, | static int debounce_setup(struct line *line, unsigned int debounce_period_us) | ||||||
| 			  unsigned int debounce_period_us, bool hte_req) |  | ||||||
| { | { | ||||||
| 	unsigned long irqflags; | 	unsigned long irqflags; | ||||||
| 	int ret, level, irq; | 	int ret, level, irq; | ||||||
|  | @ -864,7 +869,7 @@ static int debounce_setup(struct line *line, | ||||||
| 		if (level < 0) | 		if (level < 0) | ||||||
| 			return level; | 			return level; | ||||||
| 
 | 
 | ||||||
| 		if (!hte_req) { | 		if (!test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) { | ||||||
| 			irq = gpiod_to_irq(line->desc); | 			irq = gpiod_to_irq(line->desc); | ||||||
| 			if (irq < 0) | 			if (irq < 0) | ||||||
| 				return -ENXIO; | 				return -ENXIO; | ||||||
|  | @ -915,19 +920,19 @@ static u32 gpio_v2_line_config_debounce_period(struct gpio_v2_line_config *lc, | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void edge_detector_stop(struct line *line, bool hte_en) | static void edge_detector_stop(struct line *line) | ||||||
| { | { | ||||||
| 	if (line->irq && !hte_en) { | 	if (line->irq) { | ||||||
| 		free_irq(line->irq, line); | 		free_irq(line->irq, line); | ||||||
| 		line->irq = 0; | 		line->irq = 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (hte_en) | 	if (READ_ONCE(line->edflags) & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) | ||||||
| 		hte_ts_put(&line->hdesc); | 		hte_ts_put(&line->hdesc); | ||||||
| 
 | 
 | ||||||
| 	cancel_delayed_work_sync(&line->work); | 	cancel_delayed_work_sync(&line->work); | ||||||
| 	WRITE_ONCE(line->sw_debounced, 0); | 	WRITE_ONCE(line->sw_debounced, 0); | ||||||
| 	WRITE_ONCE(line->eflags, 0); | 	WRITE_ONCE(line->edflags, 0); | ||||||
| 	if (line->desc) | 	if (line->desc) | ||||||
| 		WRITE_ONCE(line->desc->debounce_period_us, 0); | 		WRITE_ONCE(line->desc->debounce_period_us, 0); | ||||||
| 	/* do not change line->level - see comment in debounced_value() */ | 	/* do not change line->level - see comment in debounced_value() */ | ||||||
|  | @ -935,23 +940,23 @@ static void edge_detector_stop(struct line *line, bool hte_en) | ||||||
| 
 | 
 | ||||||
| static int edge_detector_setup(struct line *line, | static int edge_detector_setup(struct line *line, | ||||||
| 			       struct gpio_v2_line_config *lc, | 			       struct gpio_v2_line_config *lc, | ||||||
| 			       unsigned int line_idx, | 			       unsigned int line_idx, u64 edflags) | ||||||
| 			       u64 eflags, bool hte_req) |  | ||||||
| { | { | ||||||
| 	u32 debounce_period_us; | 	u32 debounce_period_us; | ||||||
| 	unsigned long irqflags = 0; | 	unsigned long irqflags = 0; | ||||||
|  | 	u64 eflags; | ||||||
| 	int irq, ret; | 	int irq, ret; | ||||||
| 
 | 
 | ||||||
|  | 	eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS; | ||||||
| 	if (eflags && !kfifo_initialized(&line->req->events)) { | 	if (eflags && !kfifo_initialized(&line->req->events)) { | ||||||
| 		ret = kfifo_alloc(&line->req->events, | 		ret = kfifo_alloc(&line->req->events, | ||||||
| 				  line->req->event_buffer_size, GFP_KERNEL); | 				  line->req->event_buffer_size, GFP_KERNEL); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			return ret; | 			return ret; | ||||||
| 	} | 	} | ||||||
| 	WRITE_ONCE(line->eflags, eflags); |  | ||||||
| 	if (gpio_v2_line_config_debounced(lc, line_idx)) { | 	if (gpio_v2_line_config_debounced(lc, line_idx)) { | ||||||
| 		debounce_period_us = gpio_v2_line_config_debounce_period(lc, line_idx); | 		debounce_period_us = gpio_v2_line_config_debounce_period(lc, line_idx); | ||||||
| 		ret = debounce_setup(line, debounce_period_us, hte_req); | 		ret = debounce_setup(line, debounce_period_us); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			return ret; | 			return ret; | ||||||
| 		WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); | 		WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); | ||||||
|  | @ -961,8 +966,8 @@ static int edge_detector_setup(struct line *line, | ||||||
| 	if (!eflags || READ_ONCE(line->sw_debounced)) | 	if (!eflags || READ_ONCE(line->sw_debounced)) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	if (hte_req) | 	if (edflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) | ||||||
| 		return hte_edge_setup(line, eflags); | 		return hte_edge_setup(line, edflags); | ||||||
| 
 | 
 | ||||||
| 	irq = gpiod_to_irq(line->desc); | 	irq = gpiod_to_irq(line->desc); | ||||||
| 	if (irq < 0) | 	if (irq < 0) | ||||||
|  | @ -988,35 +993,29 @@ static int edge_detector_setup(struct line *line, | ||||||
| 
 | 
 | ||||||
| static int edge_detector_update(struct line *line, | static int edge_detector_update(struct line *line, | ||||||
| 				struct gpio_v2_line_config *lc, | 				struct gpio_v2_line_config *lc, | ||||||
| 				unsigned int line_idx, | 				unsigned int line_idx, u64 edflags) | ||||||
| 				u64 flags, bool polarity_change, |  | ||||||
| 				bool prev_hte_flag) |  | ||||||
| { | { | ||||||
| 	u64 eflags = flags & GPIO_V2_LINE_EDGE_FLAGS; | 	u64 active_edflags = READ_ONCE(line->edflags); | ||||||
| 	unsigned int debounce_period_us = | 	unsigned int debounce_period_us = | ||||||
| 			gpio_v2_line_config_debounce_period(lc, line_idx); | 			gpio_v2_line_config_debounce_period(lc, line_idx); | ||||||
| 	bool hte_change = (prev_hte_flag != |  | ||||||
| 		      ((flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) != 0)); |  | ||||||
| 
 | 
 | ||||||
| 	if ((READ_ONCE(line->eflags) == eflags) && !polarity_change && | 	if ((active_edflags == edflags) && | ||||||
| 	    (READ_ONCE(line->desc->debounce_period_us) == debounce_period_us) | 	    (READ_ONCE(line->desc->debounce_period_us) == debounce_period_us)) | ||||||
| 	    && !hte_change) |  | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	/* sw debounced and still will be...*/ | 	/* sw debounced and still will be...*/ | ||||||
| 	if (debounce_period_us && READ_ONCE(line->sw_debounced)) { | 	if (debounce_period_us && READ_ONCE(line->sw_debounced)) { | ||||||
| 		WRITE_ONCE(line->eflags, eflags); |  | ||||||
| 		WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); | 		WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* reconfiguring edge detection or sw debounce being disabled */ | 	/* reconfiguring edge detection or sw debounce being disabled */ | ||||||
| 	if ((line->irq && !READ_ONCE(line->sw_debounced)) || prev_hte_flag || | 	if ((line->irq && !READ_ONCE(line->sw_debounced)) || | ||||||
|  | 	    (active_edflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) || | ||||||
| 	    (!debounce_period_us && READ_ONCE(line->sw_debounced))) | 	    (!debounce_period_us && READ_ONCE(line->sw_debounced))) | ||||||
| 		edge_detector_stop(line, prev_hte_flag); | 		edge_detector_stop(line); | ||||||
| 
 | 
 | ||||||
| 	return edge_detector_setup(line, lc, line_idx, eflags, | 	return edge_detector_setup(line, lc, line_idx, edflags); | ||||||
| 				   flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static u64 gpio_v2_line_config_flags(struct gpio_v2_line_config *lc, | static u64 gpio_v2_line_config_flags(struct gpio_v2_line_config *lc, | ||||||
|  | @ -1285,22 +1284,17 @@ static long linereq_set_config_unlocked(struct linereq *lr, | ||||||
| 					struct gpio_v2_line_config *lc) | 					struct gpio_v2_line_config *lc) | ||||||
| { | { | ||||||
| 	struct gpio_desc *desc; | 	struct gpio_desc *desc; | ||||||
|  | 	struct line *line; | ||||||
| 	unsigned int i; | 	unsigned int i; | ||||||
| 	u64 flags; | 	u64 flags, edflags; | ||||||
| 	bool polarity_change; |  | ||||||
| 	bool prev_hte_flag; |  | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < lr->num_lines; i++) { | 	for (i = 0; i < lr->num_lines; i++) { | ||||||
|  | 		line = &lr->lines[i]; | ||||||
| 		desc = lr->lines[i].desc; | 		desc = lr->lines[i].desc; | ||||||
| 		flags = gpio_v2_line_config_flags(lc, i); | 		flags = gpio_v2_line_config_flags(lc, i); | ||||||
| 		polarity_change = |  | ||||||
| 			(!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) != |  | ||||||
| 			 ((flags & GPIO_V2_LINE_FLAG_ACTIVE_LOW) != 0)); |  | ||||||
| 
 |  | ||||||
| 		prev_hte_flag = !!test_bit(FLAG_EVENT_CLOCK_HTE, &desc->flags); |  | ||||||
| 
 |  | ||||||
| 		gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags); | 		gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags); | ||||||
|  | 		edflags = flags & GPIO_V2_LINE_EDGE_DETECTOR_FLAGS; | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * Lines have to be requested explicitly for input | 		 * Lines have to be requested explicitly for input | ||||||
| 		 * or output, else the line will be treated "as is". | 		 * or output, else the line will be treated "as is". | ||||||
|  | @ -1308,7 +1302,7 @@ static long linereq_set_config_unlocked(struct linereq *lr, | ||||||
| 		if (flags & GPIO_V2_LINE_FLAG_OUTPUT) { | 		if (flags & GPIO_V2_LINE_FLAG_OUTPUT) { | ||||||
| 			int val = gpio_v2_line_config_output_value(lc, i); | 			int val = gpio_v2_line_config_output_value(lc, i); | ||||||
| 
 | 
 | ||||||
| 			edge_detector_stop(&lr->lines[i], prev_hte_flag); | 			edge_detector_stop(line); | ||||||
| 			ret = gpiod_direction_output(desc, val); | 			ret = gpiod_direction_output(desc, val); | ||||||
| 			if (ret) | 			if (ret) | ||||||
| 				return ret; | 				return ret; | ||||||
|  | @ -1317,12 +1311,13 @@ static long linereq_set_config_unlocked(struct linereq *lr, | ||||||
| 			if (ret) | 			if (ret) | ||||||
| 				return ret; | 				return ret; | ||||||
| 
 | 
 | ||||||
| 			ret = edge_detector_update(&lr->lines[i], lc, i, | 			ret = edge_detector_update(line, lc, i, edflags); | ||||||
| 					flags, polarity_change, prev_hte_flag); |  | ||||||
| 			if (ret) | 			if (ret) | ||||||
| 				return ret; | 				return ret; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		WRITE_ONCE(line->edflags, edflags); | ||||||
|  | 
 | ||||||
| 		blocking_notifier_call_chain(&desc->gdev->notifier, | 		blocking_notifier_call_chain(&desc->gdev->notifier, | ||||||
| 					     GPIO_V2_LINE_CHANGED_CONFIG, | 					     GPIO_V2_LINE_CHANGED_CONFIG, | ||||||
| 					     desc); | 					     desc); | ||||||
|  | @ -1449,13 +1444,10 @@ static ssize_t linereq_read(struct file *file, | ||||||
| static void linereq_free(struct linereq *lr) | static void linereq_free(struct linereq *lr) | ||||||
| { | { | ||||||
| 	unsigned int i; | 	unsigned int i; | ||||||
| 	bool hte; |  | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < lr->num_lines; i++) { | 	for (i = 0; i < lr->num_lines; i++) { | ||||||
| 		if (lr->lines[i].desc) { | 		if (lr->lines[i].desc) { | ||||||
| 			hte = !!test_bit(FLAG_EVENT_CLOCK_HTE, | 			edge_detector_stop(&lr->lines[i]); | ||||||
| 					 &lr->lines[i].desc->flags); |  | ||||||
| 			edge_detector_stop(&lr->lines[i], hte); |  | ||||||
| 			gpiod_free(lr->lines[i].desc); | 			gpiod_free(lr->lines[i].desc); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -1491,7 +1483,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) | ||||||
| 	struct gpio_v2_line_config *lc; | 	struct gpio_v2_line_config *lc; | ||||||
| 	struct linereq *lr; | 	struct linereq *lr; | ||||||
| 	struct file *file; | 	struct file *file; | ||||||
| 	u64 flags; | 	u64 flags, edflags; | ||||||
| 	unsigned int i; | 	unsigned int i; | ||||||
| 	int fd, ret; | 	int fd, ret; | ||||||
| 
 | 
 | ||||||
|  | @ -1565,6 +1557,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) | ||||||
| 		if (ret < 0) | 		if (ret < 0) | ||||||
| 			goto out_free_linereq; | 			goto out_free_linereq; | ||||||
| 
 | 
 | ||||||
|  | 		edflags = flags & GPIO_V2_LINE_EDGE_DETECTOR_FLAGS; | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * Lines have to be requested explicitly for input | 		 * Lines have to be requested explicitly for input | ||||||
| 		 * or output, else the line will be treated "as is". | 		 * or output, else the line will be treated "as is". | ||||||
|  | @ -1581,12 +1574,13 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) | ||||||
| 				goto out_free_linereq; | 				goto out_free_linereq; | ||||||
| 
 | 
 | ||||||
| 			ret = edge_detector_setup(&lr->lines[i], lc, i, | 			ret = edge_detector_setup(&lr->lines[i], lc, i, | ||||||
| 				flags & GPIO_V2_LINE_EDGE_FLAGS, | 						  edflags); | ||||||
| 				flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE); |  | ||||||
| 			if (ret) | 			if (ret) | ||||||
| 				goto out_free_linereq; | 				goto out_free_linereq; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		lr->lines[i].edflags = edflags; | ||||||
|  | 
 | ||||||
| 		blocking_notifier_call_chain(&desc->gdev->notifier, | 		blocking_notifier_call_chain(&desc->gdev->notifier, | ||||||
| 					     GPIO_V2_LINE_CHANGED_REQUESTED, desc); | 					     GPIO_V2_LINE_CHANGED_REQUESTED, desc); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Kent Gibson
						Kent Gibson