xref: /linux/drivers/thunderbolt/property.c (revision 928abe19fbf0127003abcb1ea69cabc1c897d0ab)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Thunderbolt XDomain property support
4  *
5  * Copyright (C) 2017, Intel Corporation
6  * Authors: Michael Jamet <michael.jamet@intel.com>
7  *          Mika Westerberg <mika.westerberg@linux.intel.com>
8  */
9 
10 #include <linux/err.h>
11 #include <linux/overflow.h>
12 #include <linux/slab.h>
13 #include <linux/string.h>
14 #include <linux/uuid.h>
15 #include <linux/thunderbolt.h>
16 
17 struct tb_property_entry {
18 	u32 key_hi;
19 	u32 key_lo;
20 	u16 length;
21 	u8 reserved;
22 	u8 type;
23 	u32 value;
24 };
25 
26 struct tb_property_rootdir_entry {
27 	u32 magic;
28 	u32 length;
29 	struct tb_property_entry entries[];
30 };
31 
32 struct tb_property_dir_entry {
33 	u32 uuid[4];
34 	struct tb_property_entry entries[];
35 };
36 
37 #define TB_PROPERTY_ROOTDIR_MAGIC	0x55584401
38 #define TB_PROPERTY_MAX_DEPTH		8
39 
40 static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
41 	size_t block_len, unsigned int dir_offset, size_t dir_len,
42 	bool is_root, unsigned int depth);
43 
44 static inline void parse_dwdata(void *dst, const void *src, size_t dwords)
45 {
46 	be32_to_cpu_array(dst, src, dwords);
47 }
48 
49 static inline void format_dwdata(void *dst, const void *src, size_t dwords)
50 {
51 	cpu_to_be32_array(dst, src, dwords);
52 }
53 
54 static bool tb_property_entry_valid(const struct tb_property_entry *entry,
55 				  size_t block_len)
56 {
57 	u32 end;
58 
59 	switch (entry->type) {
60 	case TB_PROPERTY_TYPE_DIRECTORY:
61 	case TB_PROPERTY_TYPE_DATA:
62 	case TB_PROPERTY_TYPE_TEXT:
63 		if (entry->length > block_len)
64 			return false;
65 		if (check_add_overflow(entry->value, entry->length, &end) ||
66 		    end > block_len)
67 			return false;
68 		break;
69 
70 	case TB_PROPERTY_TYPE_VALUE:
71 		if (entry->length != 1)
72 			return false;
73 		break;
74 	}
75 
76 	return true;
77 }
78 
79 static bool tb_property_key_valid(const char *key)
80 {
81 	return key && strlen(key) <= TB_PROPERTY_KEY_SIZE;
82 }
83 
84 static struct tb_property *
85 tb_property_alloc(const char *key, enum tb_property_type type)
86 {
87 	struct tb_property *property;
88 
89 	property = kzalloc_obj(*property);
90 	if (!property)
91 		return NULL;
92 
93 	strcpy(property->key, key);
94 	property->type = type;
95 	INIT_LIST_HEAD(&property->list);
96 
97 	return property;
98 }
99 
100 static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
101 					const struct tb_property_entry *entry,
102 					unsigned int depth)
103 {
104 	char key[TB_PROPERTY_KEY_SIZE + 1];
105 	struct tb_property *property;
106 	struct tb_property_dir *dir;
107 
108 	if (!tb_property_entry_valid(entry, block_len))
109 		return NULL;
110 
111 	parse_dwdata(key, entry, 2);
112 	key[TB_PROPERTY_KEY_SIZE] = '\0';
113 
114 	property = tb_property_alloc(key, entry->type);
115 	if (!property)
116 		return NULL;
117 
118 	property->length = entry->length;
119 
120 	switch (property->type) {
121 	case TB_PROPERTY_TYPE_DIRECTORY:
122 		dir = __tb_property_parse_dir(block, block_len, entry->value,
123 					      entry->length, false, depth + 1);
124 		if (!dir) {
125 			kfree(property);
126 			return NULL;
127 		}
128 		property->value.dir = dir;
129 		break;
130 
131 	case TB_PROPERTY_TYPE_DATA:
132 		property->value.data = kcalloc(property->length, sizeof(u32),
133 					       GFP_KERNEL);
134 		if (!property->value.data) {
135 			kfree(property);
136 			return NULL;
137 		}
138 		parse_dwdata(property->value.data, block + entry->value,
139 			     entry->length);
140 		break;
141 
142 	case TB_PROPERTY_TYPE_TEXT:
143 		property->value.text = kcalloc(property->length, sizeof(u32),
144 					       GFP_KERNEL);
145 		if (!property->value.text) {
146 			kfree(property);
147 			return NULL;
148 		}
149 		parse_dwdata(property->value.text, block + entry->value,
150 			     entry->length);
151 		/* Force null termination */
152 		property->value.text[property->length * 4 - 1] = '\0';
153 		break;
154 
155 	case TB_PROPERTY_TYPE_VALUE:
156 		property->value.immediate = entry->value;
157 		break;
158 
159 	default:
160 		property->type = TB_PROPERTY_TYPE_UNKNOWN;
161 		break;
162 	}
163 
164 	return property;
165 }
166 
167 static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
168 	size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root,
169 	unsigned int depth)
170 {
171 	const struct tb_property_entry *entries;
172 	size_t i, content_len, nentries;
173 	unsigned int content_offset;
174 	struct tb_property_dir *dir;
175 
176 	if (depth > TB_PROPERTY_MAX_DEPTH)
177 		return NULL;
178 
179 	dir = kzalloc_obj(*dir);
180 	if (!dir)
181 		return NULL;
182 
183 	INIT_LIST_HEAD(&dir->properties);
184 
185 	if (is_root) {
186 		content_offset = dir_offset + 2;
187 		content_len = dir_len;
188 	} else {
189 		if (dir_len < 4) {
190 			tb_property_free_dir(dir);
191 			return NULL;
192 		}
193 		dir->uuid = kmemdup(&block[dir_offset], sizeof(*dir->uuid),
194 				    GFP_KERNEL);
195 		if (!dir->uuid) {
196 			tb_property_free_dir(dir);
197 			return NULL;
198 		}
199 		content_offset = dir_offset + 4;
200 		content_len = dir_len - 4; /* Length includes UUID */
201 	}
202 
203 	entries = (const struct tb_property_entry *)&block[content_offset];
204 	nentries = content_len / (sizeof(*entries) / 4);
205 
206 	for (i = 0; i < nentries; i++) {
207 		struct tb_property *property;
208 
209 		property = tb_property_parse(block, block_len, &entries[i], depth);
210 		if (!property) {
211 			tb_property_free_dir(dir);
212 			return NULL;
213 		}
214 
215 		list_add_tail(&property->list, &dir->properties);
216 	}
217 
218 	return dir;
219 }
220 
221 /**
222  * tb_property_parse_dir() - Parses properties from given property block
223  * @block: Property block to parse
224  * @block_len: Number of dword elements in the property block
225  *
226  * This function parses the XDomain properties data block into format that
227  * can be traversed using the helper functions provided by this module.
228  *
229  * The resulting &struct tb_property_dir needs to be released by
230  * calling tb_property_free_dir() when not needed anymore.
231  *
232  * The @block is expected to be root directory.
233  *
234  * Return: Pointer to &struct tb_property_dir, %NULL in case of failure.
235  */
236 struct tb_property_dir *tb_property_parse_dir(const u32 *block,
237 					      size_t block_len)
238 {
239 	const struct tb_property_rootdir_entry *rootdir =
240 		(const struct tb_property_rootdir_entry *)block;
241 
242 	if (rootdir->magic != TB_PROPERTY_ROOTDIR_MAGIC)
243 		return NULL;
244 	if (rootdir->length > block_len)
245 		return NULL;
246 
247 	return __tb_property_parse_dir(block, block_len, 0, rootdir->length,
248 				       true, 0);
249 }
250 
251 /**
252  * tb_property_create_dir() - Creates new property directory
253  * @uuid: UUID used to identify the particular directory
254  *
255  * Creates new, empty property directory. If @uuid is %NULL then the
256  * directory is assumed to be root directory.
257  *
258  * Return: Pointer to &struct tb_property_dir, %NULL in case of failure.
259  */
260 struct tb_property_dir *tb_property_create_dir(const uuid_t *uuid)
261 {
262 	struct tb_property_dir *dir;
263 
264 	dir = kzalloc_obj(*dir);
265 	if (!dir)
266 		return NULL;
267 
268 	INIT_LIST_HEAD(&dir->properties);
269 	if (uuid) {
270 		dir->uuid = kmemdup(uuid, sizeof(*dir->uuid), GFP_KERNEL);
271 		if (!dir->uuid) {
272 			kfree(dir);
273 			return NULL;
274 		}
275 	}
276 
277 	return dir;
278 }
279 EXPORT_SYMBOL_GPL(tb_property_create_dir);
280 
281 static void tb_property_free(struct tb_property *property)
282 {
283 	switch (property->type) {
284 	case TB_PROPERTY_TYPE_DIRECTORY:
285 		tb_property_free_dir(property->value.dir);
286 		break;
287 
288 	case TB_PROPERTY_TYPE_DATA:
289 		kfree(property->value.data);
290 		break;
291 
292 	case TB_PROPERTY_TYPE_TEXT:
293 		kfree(property->value.text);
294 		break;
295 
296 	default:
297 		break;
298 	}
299 
300 	kfree(property);
301 }
302 
303 /**
304  * tb_property_free_dir() - Release memory allocated for property directory
305  * @dir: Directory to release
306  *
307  * This will release all the memory the directory occupies including all
308  * descendants. It is OK to pass %NULL @dir, then the function does
309  * nothing.
310  */
311 void tb_property_free_dir(struct tb_property_dir *dir)
312 {
313 	struct tb_property *property, *tmp;
314 
315 	if (!dir)
316 		return;
317 
318 	list_for_each_entry_safe(property, tmp, &dir->properties, list) {
319 		list_del(&property->list);
320 		tb_property_free(property);
321 	}
322 	kfree(dir->uuid);
323 	kfree(dir);
324 }
325 EXPORT_SYMBOL_GPL(tb_property_free_dir);
326 
327 static size_t tb_property_dir_length(const struct tb_property_dir *dir,
328 				     bool recurse, size_t *data_len)
329 {
330 	const struct tb_property *property;
331 	size_t len = 0;
332 
333 	if (dir->uuid)
334 		len += sizeof(*dir->uuid) / 4;
335 	else
336 		len += sizeof(struct tb_property_rootdir_entry) / 4;
337 
338 	list_for_each_entry(property, &dir->properties, list) {
339 		len += sizeof(struct tb_property_entry) / 4;
340 
341 		switch (property->type) {
342 		case TB_PROPERTY_TYPE_DIRECTORY:
343 			if (recurse) {
344 				len += tb_property_dir_length(
345 					property->value.dir, recurse, data_len);
346 			}
347 			/* Reserve dword padding after each directory */
348 			if (data_len)
349 				*data_len += 1;
350 			break;
351 
352 		case TB_PROPERTY_TYPE_DATA:
353 		case TB_PROPERTY_TYPE_TEXT:
354 			if (data_len)
355 				*data_len += property->length;
356 			break;
357 
358 		default:
359 			break;
360 		}
361 	}
362 
363 	return len;
364 }
365 
366 static ssize_t __tb_property_format_dir(const struct tb_property_dir *dir,
367 	u32 *block, unsigned int start_offset, size_t block_len)
368 {
369 	unsigned int data_offset, dir_end;
370 	const struct tb_property *property;
371 	struct tb_property_entry *entry;
372 	size_t dir_len, data_len = 0;
373 	int ret;
374 
375 	/*
376 	 * The structure of property block looks like following. Leaf
377 	 * data/text is included right after the directory and each
378 	 * directory follows each other (even nested ones).
379 	 *
380 	 * +----------+ <-- start_offset
381 	 * |  header  | <-- root directory header
382 	 * +----------+ ---
383 	 * |  entry 0 | -^--------------------.
384 	 * +----------+  |                    |
385 	 * |  entry 1 | -|--------------------|--.
386 	 * +----------+  |                    |  |
387 	 * |  entry 2 | -|-----------------.  |  |
388 	 * +----------+  |                 |  |  |
389 	 * :          :  |  dir_len        |  |  |
390 	 * .          .  |                 |  |  |
391 	 * :          :  |                 |  |  |
392 	 * +----------+  |                 |  |  |
393 	 * |  entry n |  v                 |  |  |
394 	 * +----------+ <-- data_offset    |  |  |
395 	 * |  data 0  | <------------------|--'  |
396 	 * +----------+                    |     |
397 	 * |  data 1  | <------------------|-----'
398 	 * +----------+                    |
399 	 * | 00000000 | padding            |
400 	 * +----------+ <-- dir_end <------'
401 	 * |   UUID   | <-- directory UUID (child directory)
402 	 * +----------+
403 	 * |  entry 0 |
404 	 * +----------+
405 	 * |  entry 1 |
406 	 * +----------+
407 	 * :          :
408 	 * .          .
409 	 * :          :
410 	 * +----------+
411 	 * |  entry n |
412 	 * +----------+
413 	 * |  data 0  |
414 	 * +----------+
415 	 *
416 	 * We use dir_end to hold pointer to the end of the directory. It
417 	 * will increase as we add directories and each directory should be
418 	 * added starting from previous dir_end.
419 	 */
420 	dir_len = tb_property_dir_length(dir, false, &data_len);
421 	data_offset = start_offset + dir_len;
422 	dir_end = start_offset + data_len + dir_len;
423 
424 	if (data_offset > dir_end)
425 		return -EINVAL;
426 	if (dir_end > block_len)
427 		return -EINVAL;
428 
429 	/* Write headers first */
430 	if (dir->uuid) {
431 		struct tb_property_dir_entry *pe;
432 
433 		pe = (struct tb_property_dir_entry *)&block[start_offset];
434 		memcpy(pe->uuid, dir->uuid, sizeof(pe->uuid));
435 		entry = pe->entries;
436 	} else {
437 		struct tb_property_rootdir_entry *re;
438 
439 		re = (struct tb_property_rootdir_entry *)&block[start_offset];
440 		re->magic = TB_PROPERTY_ROOTDIR_MAGIC;
441 		re->length = dir_len - sizeof(*re) / 4;
442 		entry = re->entries;
443 	}
444 
445 	list_for_each_entry(property, &dir->properties, list) {
446 		const struct tb_property_dir *child;
447 
448 		format_dwdata(entry, property->key, 2);
449 		entry->type = property->type;
450 
451 		switch (property->type) {
452 		case TB_PROPERTY_TYPE_DIRECTORY:
453 			child = property->value.dir;
454 			ret = __tb_property_format_dir(child, block, dir_end,
455 						       block_len);
456 			if (ret < 0)
457 				return ret;
458 			entry->length = tb_property_dir_length(child, false,
459 							       NULL);
460 			entry->value = dir_end;
461 			dir_end = ret;
462 			break;
463 
464 		case TB_PROPERTY_TYPE_DATA:
465 			format_dwdata(&block[data_offset], property->value.data,
466 				      property->length);
467 			entry->length = property->length;
468 			entry->value = data_offset;
469 			data_offset += entry->length;
470 			break;
471 
472 		case TB_PROPERTY_TYPE_TEXT:
473 			format_dwdata(&block[data_offset], property->value.text,
474 				      property->length);
475 			entry->length = property->length;
476 			entry->value = data_offset;
477 			data_offset += entry->length;
478 			break;
479 
480 		case TB_PROPERTY_TYPE_VALUE:
481 			entry->length = property->length;
482 			entry->value = property->value.immediate;
483 			break;
484 
485 		default:
486 			break;
487 		}
488 
489 		entry++;
490 	}
491 
492 	return dir_end;
493 }
494 
495 /**
496  * tb_property_format_dir() - Formats directory to the packed XDomain format
497  * @dir: Directory to format
498  * @block: Property block where the packed data is placed
499  * @block_len: Length of the property block
500  *
501  * This function formats the directory to the packed format that can be
502  * then sent over the thunderbolt fabric to receiving host.
503  *
504  * Passing %NULL in @block returns number of entries the block takes.
505  *
506  * Return: %0 on success, negative errno otherwise.
507  */
508 ssize_t tb_property_format_dir(const struct tb_property_dir *dir, u32 *block,
509 			       size_t block_len)
510 {
511 	ssize_t ret;
512 
513 	if (!block) {
514 		size_t dir_len, data_len = 0;
515 
516 		dir_len = tb_property_dir_length(dir, true, &data_len);
517 		return dir_len + data_len;
518 	}
519 
520 	ret = __tb_property_format_dir(dir, block, 0, block_len);
521 	return ret < 0 ? ret : 0;
522 }
523 
524 /**
525  * tb_property_copy_dir() - Take a deep copy of directory
526  * @dir: Directory to copy
527  *
528  * The resulting directory needs to be released by calling tb_property_free_dir().
529  *
530  * Return: Pointer to &struct tb_property_dir, %NULL in case of failure.
531  */
532 struct tb_property_dir *tb_property_copy_dir(const struct tb_property_dir *dir)
533 {
534 	struct tb_property *property, *p = NULL;
535 	struct tb_property_dir *d;
536 
537 	if (!dir)
538 		return NULL;
539 
540 	d = tb_property_create_dir(dir->uuid);
541 	if (!d)
542 		return NULL;
543 
544 	list_for_each_entry(property, &dir->properties, list) {
545 		struct tb_property *p;
546 
547 		p = tb_property_alloc(property->key, property->type);
548 		if (!p)
549 			goto err_free;
550 
551 		p->length = property->length;
552 
553 		switch (property->type) {
554 		case TB_PROPERTY_TYPE_DIRECTORY:
555 			p->value.dir = tb_property_copy_dir(property->value.dir);
556 			if (!p->value.dir)
557 				goto err_free;
558 			break;
559 
560 		case TB_PROPERTY_TYPE_DATA:
561 			p->value.data = kmemdup(property->value.data,
562 						property->length * 4,
563 						GFP_KERNEL);
564 			if (!p->value.data)
565 				goto err_free;
566 			break;
567 
568 		case TB_PROPERTY_TYPE_TEXT:
569 			p->value.text = kzalloc(p->length * 4, GFP_KERNEL);
570 			if (!p->value.text)
571 				goto err_free;
572 			strcpy(p->value.text, property->value.text);
573 			break;
574 
575 		case TB_PROPERTY_TYPE_VALUE:
576 			p->value.immediate = property->value.immediate;
577 			break;
578 
579 		default:
580 			break;
581 		}
582 
583 		list_add_tail(&p->list, &d->properties);
584 	}
585 
586 	return d;
587 
588 err_free:
589 	kfree(p);
590 	tb_property_free_dir(d);
591 
592 	return NULL;
593 }
594 
595 /**
596  * tb_property_add_immediate() - Add immediate property to directory
597  * @parent: Directory to add the property
598  * @key: Key for the property
599  * @value: Immediate value to store with the property
600  *
601  * Return: %0 on success, negative errno otherwise.
602  */
603 int tb_property_add_immediate(struct tb_property_dir *parent, const char *key,
604 			      u32 value)
605 {
606 	struct tb_property *property;
607 
608 	if (!tb_property_key_valid(key))
609 		return -EINVAL;
610 
611 	property = tb_property_alloc(key, TB_PROPERTY_TYPE_VALUE);
612 	if (!property)
613 		return -ENOMEM;
614 
615 	property->length = 1;
616 	property->value.immediate = value;
617 
618 	list_add_tail(&property->list, &parent->properties);
619 	return 0;
620 }
621 EXPORT_SYMBOL_GPL(tb_property_add_immediate);
622 
623 /**
624  * tb_property_add_data() - Adds arbitrary data property to directory
625  * @parent: Directory to add the property
626  * @key: Key for the property
627  * @buf: Data buffer to add
628  * @buflen: Number of bytes in the data buffer
629  *
630  * Function takes a copy of @buf and adds it to the directory.
631  *
632  * Return: %0 on success, negative errno otherwise.
633  */
634 int tb_property_add_data(struct tb_property_dir *parent, const char *key,
635 			 const void *buf, size_t buflen)
636 {
637 	/* Need to pad to dword boundary */
638 	size_t size = round_up(buflen, 4);
639 	struct tb_property *property;
640 
641 	if (!tb_property_key_valid(key))
642 		return -EINVAL;
643 
644 	property = tb_property_alloc(key, TB_PROPERTY_TYPE_DATA);
645 	if (!property)
646 		return -ENOMEM;
647 
648 	property->length = size / 4;
649 	property->value.data = kzalloc(size, GFP_KERNEL);
650 	if (!property->value.data) {
651 		kfree(property);
652 		return -ENOMEM;
653 	}
654 
655 	memcpy(property->value.data, buf, buflen);
656 
657 	list_add_tail(&property->list, &parent->properties);
658 	return 0;
659 }
660 EXPORT_SYMBOL_GPL(tb_property_add_data);
661 
662 /**
663  * tb_property_add_text() - Adds string property to directory
664  * @parent: Directory to add the property
665  * @key: Key for the property
666  * @text: String to add
667  *
668  * Function takes a copy of @text and adds it to the directory.
669  *
670  * Return: %0 on success, negative errno otherwise.
671  */
672 int tb_property_add_text(struct tb_property_dir *parent, const char *key,
673 			 const char *text)
674 {
675 	/* Need to pad to dword boundary */
676 	size_t size = round_up(strlen(text) + 1, 4);
677 	struct tb_property *property;
678 
679 	if (!tb_property_key_valid(key))
680 		return -EINVAL;
681 
682 	property = tb_property_alloc(key, TB_PROPERTY_TYPE_TEXT);
683 	if (!property)
684 		return -ENOMEM;
685 
686 	property->length = size / 4;
687 	property->value.text = kzalloc(size, GFP_KERNEL);
688 	if (!property->value.text) {
689 		kfree(property);
690 		return -ENOMEM;
691 	}
692 
693 	strcpy(property->value.text, text);
694 
695 	list_add_tail(&property->list, &parent->properties);
696 	return 0;
697 }
698 EXPORT_SYMBOL_GPL(tb_property_add_text);
699 
700 /**
701  * tb_property_add_dir() - Adds a directory to the parent directory
702  * @parent: Directory to add the property
703  * @key: Key for the property
704  * @dir: Directory to add
705  *
706  * Return: %0 on success, negative errno otherwise.
707  */
708 int tb_property_add_dir(struct tb_property_dir *parent, const char *key,
709 			struct tb_property_dir *dir)
710 {
711 	struct tb_property *property;
712 
713 	if (!tb_property_key_valid(key))
714 		return -EINVAL;
715 
716 	property = tb_property_alloc(key, TB_PROPERTY_TYPE_DIRECTORY);
717 	if (!property)
718 		return -ENOMEM;
719 
720 	property->value.dir = dir;
721 
722 	list_add_tail(&property->list, &parent->properties);
723 	return 0;
724 }
725 EXPORT_SYMBOL_GPL(tb_property_add_dir);
726 
727 /**
728  * tb_property_remove() - Removes property from a parent directory
729  * @property: Property to remove
730  *
731  * Note memory for @property is released as well so it is not allowed to
732  * touch the object after call to this function.
733  */
734 void tb_property_remove(struct tb_property *property)
735 {
736 	list_del(&property->list);
737 	kfree(property);
738 }
739 EXPORT_SYMBOL_GPL(tb_property_remove);
740 
741 /**
742  * tb_property_find() - Find a property from a directory
743  * @dir: Directory where the property is searched
744  * @key: Key to look for
745  * @type: Type of the property
746  *
747  * Finds and returns property from the given directory. Does not
748  * recurse into sub-directories.
749  *
750  * Return: Pointer to &struct tb_property, %NULL if the property was not found.
751  */
752 struct tb_property *tb_property_find(struct tb_property_dir *dir,
753 	const char *key, enum tb_property_type type)
754 {
755 	struct tb_property *property;
756 
757 	list_for_each_entry(property, &dir->properties, list) {
758 		if (property->type == type && !strcmp(property->key, key))
759 			return property;
760 	}
761 
762 	return NULL;
763 }
764 EXPORT_SYMBOL_GPL(tb_property_find);
765 
766 /**
767  * tb_property_get_next() - Get next property from directory
768  * @dir: Directory holding properties
769  * @prev: Previous property in the directory (%NULL returns the first)
770  *
771  * Return: Pointer to &struct tb_property, %NULL if property was not found.
772  */
773 struct tb_property *tb_property_get_next(struct tb_property_dir *dir,
774 					 struct tb_property *prev)
775 {
776 	if (prev) {
777 		if (list_is_last(&prev->list, &dir->properties))
778 			return NULL;
779 		return list_next_entry(prev, list);
780 	}
781 	return list_first_entry_or_null(&dir->properties, struct tb_property,
782 					list);
783 }
784 EXPORT_SYMBOL_GPL(tb_property_get_next);
785