diff mbox series

[1/9] dma-buf: add new dma_fence_chain container v6

Message ID 20190320054724.14636-1-david1.zhou@amd.com (mailing list archive)
State New, archived
Headers show
Series [1/9] dma-buf: add new dma_fence_chain container v6 | expand

Commit Message

Chunming Zhou March 20, 2019, 5:47 a.m. UTC
From: Christian König <ckoenig.leichtzumerken@gmail.com>

Lockless container implementation similar to a dma_fence_array, but with
only two elements per node and automatic garbage collection.

v2: properly document dma_fence_chain_for_each, add dma_fence_chain_find_seqno,
    drop prev reference during garbage collection if it's not a chain fence.
v3: use head and iterator for dma_fence_chain_for_each
v4: fix reference count in dma_fence_chain_enable_signaling
v5: fix iteration when walking each chain node
v6: add __rcu for member 'prev' of struct chain node

Signed-off-by: Christian König <christian.koenig@amd.com>
Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 drivers/dma-buf/Makefile          |   3 +-
 drivers/dma-buf/dma-fence-chain.c | 241 ++++++++++++++++++++++++++++++
 include/linux/dma-fence-chain.h   |  81 ++++++++++
 3 files changed, 324 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma-buf/dma-fence-chain.c
 create mode 100644 include/linux/dma-fence-chain.h

Comments

kernel test robot March 21, 2019, 12:24 a.m. UTC | #1
Hi Chunming,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.1-rc1 next-20190320]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'


sparse warnings: (new ones prefixed by >>)

>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in initializer (different address spaces) @@    expected struct dma_fence [noderef] <asn:4>*__old @@    got  dma_fence [noderef] <asn:4>*__old @@
   drivers/dma-buf/dma-fence-chain.c:73:23:    expected struct dma_fence [noderef] <asn:4>*__old
   drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence *[assigned] prev
>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in initializer (different address spaces) @@    expected struct dma_fence [noderef] <asn:4>*__new @@    got  dma_fence [noderef] <asn:4>*__new @@
   drivers/dma-buf/dma-fence-chain.c:73:23:    expected struct dma_fence [noderef] <asn:4>*__new
   drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence *[assigned] replacement
>> drivers/dma-buf/dma-fence-chain.c:73:21: sparse: incorrect type in assignment (different address spaces) @@    expected struct dma_fence *tmp @@    got struct dma_fence [noderef] <struct dma_fence *tmp @@
   drivers/dma-buf/dma-fence-chain.c:73:21:    expected struct dma_fence *tmp
   drivers/dma-buf/dma-fence-chain.c:73:21:    got struct dma_fence [noderef] <asn:4>*[assigned] __ret
>> drivers/dma-buf/dma-fence-chain.c:190:28: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct dma_fence *fence @@    got struct dma_fence struct dma_fence *fence @@
   drivers/dma-buf/dma-fence-chain.c:190:28:    expected struct dma_fence *fence
   drivers/dma-buf/dma-fence-chain.c:190:28:    got struct dma_fence [noderef] <asn:4>*prev
>> drivers/dma-buf/dma-fence-chain.c:222:21: sparse: incorrect type in assignment (different address spaces) @@    expected struct dma_fence [noderef] <asn:4>*prev @@    got [noderef] <asn:4>*prev @@
   drivers/dma-buf/dma-fence-chain.c:222:21:    expected struct dma_fence [noderef] <asn:4>*prev
   drivers/dma-buf/dma-fence-chain.c:222:21:    got struct dma_fence *prev
   drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression using sizeof(void)
   drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression using sizeof(void)

vim +73 drivers/dma-buf/dma-fence-chain.c

    38	
    39	/**
    40	 * dma_fence_chain_walk - chain walking function
    41	 * @fence: current chain node
    42	 *
    43	 * Walk the chain to the next node. Returns the next fence or NULL if we are at
    44	 * the end of the chain. Garbage collects chain nodes which are already
    45	 * signaled.
    46	 */
    47	struct dma_fence *dma_fence_chain_walk(struct dma_fence *fence)
    48	{
    49		struct dma_fence_chain *chain, *prev_chain;
    50		struct dma_fence *prev, *replacement, *tmp;
    51	
    52		chain = to_dma_fence_chain(fence);
    53		if (!chain) {
    54			dma_fence_put(fence);
    55			return NULL;
    56		}
    57	
    58		while ((prev = dma_fence_chain_get_prev(chain))) {
    59	
    60			prev_chain = to_dma_fence_chain(prev);
    61			if (prev_chain) {
    62				if (!dma_fence_is_signaled(prev_chain->fence))
    63					break;
    64	
    65				replacement = dma_fence_chain_get_prev(prev_chain);
    66			} else {
    67				if (!dma_fence_is_signaled(prev))
    68					break;
    69	
    70				replacement = NULL;
    71			}
    72	
  > 73			tmp = cmpxchg(&chain->prev, prev, replacement);
    74			if (tmp == prev)
    75				dma_fence_put(tmp);
    76			else
    77				dma_fence_put(replacement);
    78			dma_fence_put(prev);
    79		}
    80	
    81		dma_fence_put(fence);
    82		return prev;
    83	}
    84	EXPORT_SYMBOL(dma_fence_chain_walk);
    85	
    86	/**
    87	 * dma_fence_chain_find_seqno - find fence chain node by seqno
    88	 * @pfence: pointer to the chain node where to start
    89	 * @seqno: the sequence number to search for
    90	 *
    91	 * Advance the fence pointer to the chain node which will signal this sequence
    92	 * number. If no sequence number is provided then this is a no-op.
    93	 *
    94	 * Returns EINVAL if the fence is not a chain node or the sequence number has
    95	 * not yet advanced far enough.
    96	 */
    97	int dma_fence_chain_find_seqno(struct dma_fence **pfence, uint64_t seqno)
    98	{
    99		struct dma_fence_chain *chain;
   100	
   101		if (!seqno)
   102			return 0;
   103	
   104		chain = to_dma_fence_chain(*pfence);
   105		if (!chain || chain->base.seqno < seqno)
   106			return -EINVAL;
   107	
   108		dma_fence_chain_for_each(*pfence, &chain->base) {
   109			if ((*pfence)->context != chain->base.context ||
   110			    to_dma_fence_chain(*pfence)->prev_seqno < seqno)
   111				break;
   112		}
   113		dma_fence_put(&chain->base);
   114	
   115		return 0;
   116	}
   117	EXPORT_SYMBOL(dma_fence_chain_find_seqno);
   118	
   119	static const char *dma_fence_chain_get_driver_name(struct dma_fence *fence)
   120	{
   121	        return "dma_fence_chain";
   122	}
   123	
   124	static const char *dma_fence_chain_get_timeline_name(struct dma_fence *fence)
   125	{
   126	        return "unbound";
   127	}
   128	
   129	static void dma_fence_chain_irq_work(struct irq_work *work)
   130	{
   131		struct dma_fence_chain *chain;
   132	
   133		chain = container_of(work, typeof(*chain), work);
   134	
   135		/* Try to rearm the callback */
   136		if (!dma_fence_chain_enable_signaling(&chain->base))
   137			/* Ok, we are done. No more unsignaled fences left */
   138			dma_fence_signal(&chain->base);
   139		dma_fence_put(&chain->base);
   140	}
   141	
   142	static void dma_fence_chain_cb(struct dma_fence *f, struct dma_fence_cb *cb)
   143	{
   144		struct dma_fence_chain *chain;
   145	
   146		chain = container_of(cb, typeof(*chain), cb);
   147		irq_work_queue(&chain->work);
   148		dma_fence_put(f);
   149	}
   150	
   151	static bool dma_fence_chain_enable_signaling(struct dma_fence *fence)
   152	{
   153		struct dma_fence_chain *head = to_dma_fence_chain(fence);
   154	
   155		dma_fence_get(&head->base);
   156		dma_fence_chain_for_each(fence, &head->base) {
   157			struct dma_fence_chain *chain = to_dma_fence_chain(fence);
   158			struct dma_fence *f = chain ? chain->fence : fence;
   159	
   160			dma_fence_get(f);
   161			if (!dma_fence_add_callback(f, &head->cb, dma_fence_chain_cb)) {
   162				dma_fence_put(fence);
   163				return true;
   164			}
   165			dma_fence_put(f);
   166		}
   167		dma_fence_put(&head->base);
   168		return false;
   169	}
   170	
   171	static bool dma_fence_chain_signaled(struct dma_fence *fence)
   172	{
   173		dma_fence_chain_for_each(fence, fence) {
   174			struct dma_fence_chain *chain = to_dma_fence_chain(fence);
   175			struct dma_fence *f = chain ? chain->fence : fence;
   176	
   177			if (!dma_fence_is_signaled(f)) {
   178				dma_fence_put(fence);
   179				return false;
   180			}
   181		}
   182	
   183		return true;
   184	}
   185	
   186	static void dma_fence_chain_release(struct dma_fence *fence)
   187	{
   188		struct dma_fence_chain *chain = to_dma_fence_chain(fence);
   189	
 > 190		dma_fence_put(chain->prev);
   191		dma_fence_put(chain->fence);
   192		dma_fence_free(fence);
   193	}
   194	
   195	const struct dma_fence_ops dma_fence_chain_ops = {
   196		.get_driver_name = dma_fence_chain_get_driver_name,
   197		.get_timeline_name = dma_fence_chain_get_timeline_name,
   198		.enable_signaling = dma_fence_chain_enable_signaling,
   199		.signaled = dma_fence_chain_signaled,
   200		.release = dma_fence_chain_release,
   201	};
   202	EXPORT_SYMBOL(dma_fence_chain_ops);
   203	
   204	/**
   205	 * dma_fence_chain_init - initialize a fence chain
   206	 * @chain: the chain node to initialize
   207	 * @prev: the previous fence
   208	 * @fence: the current fence
   209	 *
   210	 * Initialize a new chain node and either start a new chain or add the node to
   211	 * the existing chain of the previous fence.
   212	 */
   213	void dma_fence_chain_init(struct dma_fence_chain *chain,
   214				  struct dma_fence *prev,
   215				  struct dma_fence *fence,
   216				  uint64_t seqno)
   217	{
   218		struct dma_fence_chain *prev_chain = to_dma_fence_chain(prev);
   219		uint64_t context;
   220	
   221		spin_lock_init(&chain->lock);
 > 222		chain->prev = prev;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Chunming Zhou March 21, 2019, 6:34 a.m. UTC | #2
Hi Lionel and Christian,

Below is robot report for chain->prev, which was added __rcu as you 
suggested.

How to fix this line "tmp = cmpxchg(&chain->prev, prev, replacement); "?
I checked kernel header file, seems it has no cmpxchg for rcu.

Any suggestion to fix this robot report?

Thanks,
-David

On 2019年03月21日 08:24, kbuild test robot wrote:
> Hi Chunming,
>
> I love your patch! Perhaps something to improve:
>
> [auto build test WARNING on linus/master]
> [also build test WARNING on v5.1-rc1 next-20190320]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url:    https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607
> reproduce:
>          # apt-get install sparse
>          make ARCH=x86_64 allmodconfig
>          make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
>
>
> sparse warnings: (new ones prefixed by >>)
>
>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in initializer (different address spaces) @@    expected struct dma_fence [noderef] <asn:4>*__old @@    got  dma_fence [noderef] <asn:4>*__old @@
>     drivers/dma-buf/dma-fence-chain.c:73:23:    expected struct dma_fence [noderef] <asn:4>*__old
>     drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence *[assigned] prev
>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in initializer (different address spaces) @@    expected struct dma_fence [noderef] <asn:4>*__new @@    got  dma_fence [noderef] <asn:4>*__new @@
>     drivers/dma-buf/dma-fence-chain.c:73:23:    expected struct dma_fence [noderef] <asn:4>*__new
>     drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence *[assigned] replacement
>>> drivers/dma-buf/dma-fence-chain.c:73:21: sparse: incorrect type in assignment (different address spaces) @@    expected struct dma_fence *tmp @@    got struct dma_fence [noderef] <struct dma_fence *tmp @@
>     drivers/dma-buf/dma-fence-chain.c:73:21:    expected struct dma_fence *tmp
>     drivers/dma-buf/dma-fence-chain.c:73:21:    got struct dma_fence [noderef] <asn:4>*[assigned] __ret
>>> drivers/dma-buf/dma-fence-chain.c:190:28: sparse: incorrect type in argument 1 (different address spaces) @@    expected struct dma_fence *fence @@    got struct dma_fence struct dma_fence *fence @@
>     drivers/dma-buf/dma-fence-chain.c:190:28:    expected struct dma_fence *fence
>     drivers/dma-buf/dma-fence-chain.c:190:28:    got struct dma_fence [noderef] <asn:4>*prev
>>> drivers/dma-buf/dma-fence-chain.c:222:21: sparse: incorrect type in assignment (different address spaces) @@    expected struct dma_fence [noderef] <asn:4>*prev @@    got [noderef] <asn:4>*prev @@
>     drivers/dma-buf/dma-fence-chain.c:222:21:    expected struct dma_fence [noderef] <asn:4>*prev
>     drivers/dma-buf/dma-fence-chain.c:222:21:    got struct dma_fence *prev
>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression using sizeof(void)
>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression using sizeof(void)
>
> vim +73 drivers/dma-buf/dma-fence-chain.c
>
>      38	
>      39	/**
>      40	 * dma_fence_chain_walk - chain walking function
>      41	 * @fence: current chain node
>      42	 *
>      43	 * Walk the chain to the next node. Returns the next fence or NULL if we are at
>      44	 * the end of the chain. Garbage collects chain nodes which are already
>      45	 * signaled.
>      46	 */
>      47	struct dma_fence *dma_fence_chain_walk(struct dma_fence *fence)
>      48	{
>      49		struct dma_fence_chain *chain, *prev_chain;
>      50		struct dma_fence *prev, *replacement, *tmp;
>      51	
>      52		chain = to_dma_fence_chain(fence);
>      53		if (!chain) {
>      54			dma_fence_put(fence);
>      55			return NULL;
>      56		}
>      57	
>      58		while ((prev = dma_fence_chain_get_prev(chain))) {
>      59	
>      60			prev_chain = to_dma_fence_chain(prev);
>      61			if (prev_chain) {
>      62				if (!dma_fence_is_signaled(prev_chain->fence))
>      63					break;
>      64	
>      65				replacement = dma_fence_chain_get_prev(prev_chain);
>      66			} else {
>      67				if (!dma_fence_is_signaled(prev))
>      68					break;
>      69	
>      70				replacement = NULL;
>      71			}
>      72	
>    > 73			tmp = cmpxchg(&chain->prev, prev, replacement);
>      74			if (tmp == prev)
>      75				dma_fence_put(tmp);
>      76			else
>      77				dma_fence_put(replacement);
>      78			dma_fence_put(prev);
>      79		}
>      80	
>      81		dma_fence_put(fence);
>      82		return prev;
>      83	}
>      84	EXPORT_SYMBOL(dma_fence_chain_walk);
>      85	
>      86	/**
>      87	 * dma_fence_chain_find_seqno - find fence chain node by seqno
>      88	 * @pfence: pointer to the chain node where to start
>      89	 * @seqno: the sequence number to search for
>      90	 *
>      91	 * Advance the fence pointer to the chain node which will signal this sequence
>      92	 * number. If no sequence number is provided then this is a no-op.
>      93	 *
>      94	 * Returns EINVAL if the fence is not a chain node or the sequence number has
>      95	 * not yet advanced far enough.
>      96	 */
>      97	int dma_fence_chain_find_seqno(struct dma_fence **pfence, uint64_t seqno)
>      98	{
>      99		struct dma_fence_chain *chain;
>     100	
>     101		if (!seqno)
>     102			return 0;
>     103	
>     104		chain = to_dma_fence_chain(*pfence);
>     105		if (!chain || chain->base.seqno < seqno)
>     106			return -EINVAL;
>     107	
>     108		dma_fence_chain_for_each(*pfence, &chain->base) {
>     109			if ((*pfence)->context != chain->base.context ||
>     110			    to_dma_fence_chain(*pfence)->prev_seqno < seqno)
>     111				break;
>     112		}
>     113		dma_fence_put(&chain->base);
>     114	
>     115		return 0;
>     116	}
>     117	EXPORT_SYMBOL(dma_fence_chain_find_seqno);
>     118	
>     119	static const char *dma_fence_chain_get_driver_name(struct dma_fence *fence)
>     120	{
>     121	        return "dma_fence_chain";
>     122	}
>     123	
>     124	static const char *dma_fence_chain_get_timeline_name(struct dma_fence *fence)
>     125	{
>     126	        return "unbound";
>     127	}
>     128	
>     129	static void dma_fence_chain_irq_work(struct irq_work *work)
>     130	{
>     131		struct dma_fence_chain *chain;
>     132	
>     133		chain = container_of(work, typeof(*chain), work);
>     134	
>     135		/* Try to rearm the callback */
>     136		if (!dma_fence_chain_enable_signaling(&chain->base))
>     137			/* Ok, we are done. No more unsignaled fences left */
>     138			dma_fence_signal(&chain->base);
>     139		dma_fence_put(&chain->base);
>     140	}
>     141	
>     142	static void dma_fence_chain_cb(struct dma_fence *f, struct dma_fence_cb *cb)
>     143	{
>     144		struct dma_fence_chain *chain;
>     145	
>     146		chain = container_of(cb, typeof(*chain), cb);
>     147		irq_work_queue(&chain->work);
>     148		dma_fence_put(f);
>     149	}
>     150	
>     151	static bool dma_fence_chain_enable_signaling(struct dma_fence *fence)
>     152	{
>     153		struct dma_fence_chain *head = to_dma_fence_chain(fence);
>     154	
>     155		dma_fence_get(&head->base);
>     156		dma_fence_chain_for_each(fence, &head->base) {
>     157			struct dma_fence_chain *chain = to_dma_fence_chain(fence);
>     158			struct dma_fence *f = chain ? chain->fence : fence;
>     159	
>     160			dma_fence_get(f);
>     161			if (!dma_fence_add_callback(f, &head->cb, dma_fence_chain_cb)) {
>     162				dma_fence_put(fence);
>     163				return true;
>     164			}
>     165			dma_fence_put(f);
>     166		}
>     167		dma_fence_put(&head->base);
>     168		return false;
>     169	}
>     170	
>     171	static bool dma_fence_chain_signaled(struct dma_fence *fence)
>     172	{
>     173		dma_fence_chain_for_each(fence, fence) {
>     174			struct dma_fence_chain *chain = to_dma_fence_chain(fence);
>     175			struct dma_fence *f = chain ? chain->fence : fence;
>     176	
>     177			if (!dma_fence_is_signaled(f)) {
>     178				dma_fence_put(fence);
>     179				return false;
>     180			}
>     181		}
>     182	
>     183		return true;
>     184	}
>     185	
>     186	static void dma_fence_chain_release(struct dma_fence *fence)
>     187	{
>     188		struct dma_fence_chain *chain = to_dma_fence_chain(fence);
>     189	
>   > 190		dma_fence_put(chain->prev);
>     191		dma_fence_put(chain->fence);
>     192		dma_fence_free(fence);
>     193	}
>     194	
>     195	const struct dma_fence_ops dma_fence_chain_ops = {
>     196		.get_driver_name = dma_fence_chain_get_driver_name,
>     197		.get_timeline_name = dma_fence_chain_get_timeline_name,
>     198		.enable_signaling = dma_fence_chain_enable_signaling,
>     199		.signaled = dma_fence_chain_signaled,
>     200		.release = dma_fence_chain_release,
>     201	};
>     202	EXPORT_SYMBOL(dma_fence_chain_ops);
>     203	
>     204	/**
>     205	 * dma_fence_chain_init - initialize a fence chain
>     206	 * @chain: the chain node to initialize
>     207	 * @prev: the previous fence
>     208	 * @fence: the current fence
>     209	 *
>     210	 * Initialize a new chain node and either start a new chain or add the node to
>     211	 * the existing chain of the previous fence.
>     212	 */
>     213	void dma_fence_chain_init(struct dma_fence_chain *chain,
>     214				  struct dma_fence *prev,
>     215				  struct dma_fence *fence,
>     216				  uint64_t seqno)
>     217	{
>     218		struct dma_fence_chain *prev_chain = to_dma_fence_chain(prev);
>     219		uint64_t context;
>     220	
>     221		spin_lock_init(&chain->lock);
>   > 222		chain->prev = prev;
>
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Christian König March 21, 2019, 11:30 a.m. UTC | #3
Hi David,

For the cmpxchg() case I of hand don't know either. Looks like so far 
nobody has used cmpxchg() with rcu protected structures.

The other cases should be replaced by RCU_INIT_POINTER() or 
rcu_dereference_protected(.., true);

Regards,
Christian.

Am 21.03.19 um 07:34 schrieb zhoucm1:
> Hi Lionel and Christian,
>
> Below is robot report for chain->prev, which was added __rcu as you 
> suggested.
>
> How to fix this line "tmp = cmpxchg(&chain->prev, prev, replacement); "?
> I checked kernel header file, seems it has no cmpxchg for rcu.
>
> Any suggestion to fix this robot report?
>
> Thanks,
> -David
>
> On 2019年03月21日 08:24, kbuild test robot wrote:
>> Hi Chunming,
>>
>> I love your patch! Perhaps something to improve:
>>
>> [auto build test WARNING on linus/master]
>> [also build test WARNING on v5.1-rc1 next-20190320]
>> [if your patch is applied to the wrong git tree, please drop us a 
>> note to help improve the system]
>>
>> url: 
>> https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607
>> reproduce:
>>          # apt-get install sparse
>>          make ARCH=x86_64 allmodconfig
>>          make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
>>
>>
>> sparse warnings: (new ones prefixed by >>)
>>
>>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in 
>>>> initializer (different address spaces) @@    expected struct 
>>>> dma_fence [noderef] <asn:4>*__old @@    got  dma_fence [noderef] 
>>>> <asn:4>*__old @@
>>     drivers/dma-buf/dma-fence-chain.c:73:23:    expected struct 
>> dma_fence [noderef] <asn:4>*__old
>>     drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence 
>> *[assigned] prev
>>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in 
>>>> initializer (different address spaces) @@    expected struct 
>>>> dma_fence [noderef] <asn:4>*__new @@    got  dma_fence [noderef] 
>>>> <asn:4>*__new @@
>>     drivers/dma-buf/dma-fence-chain.c:73:23:    expected struct 
>> dma_fence [noderef] <asn:4>*__new
>>     drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence 
>> *[assigned] replacement
>>>> drivers/dma-buf/dma-fence-chain.c:73:21: sparse: incorrect type in 
>>>> assignment (different address spaces) @@    expected struct 
>>>> dma_fence *tmp @@    got struct dma_fence [noderef] <struct 
>>>> dma_fence *tmp @@
>>     drivers/dma-buf/dma-fence-chain.c:73:21:    expected struct 
>> dma_fence *tmp
>>     drivers/dma-buf/dma-fence-chain.c:73:21:    got struct dma_fence 
>> [noderef] <asn:4>*[assigned] __ret
>>>> drivers/dma-buf/dma-fence-chain.c:190:28: sparse: incorrect type in 
>>>> argument 1 (different address spaces) @@    expected struct 
>>>> dma_fence *fence @@    got struct dma_fence struct dma_fence *fence @@
>>     drivers/dma-buf/dma-fence-chain.c:190:28:    expected struct 
>> dma_fence *fence
>>     drivers/dma-buf/dma-fence-chain.c:190:28:    got struct dma_fence 
>> [noderef] <asn:4>*prev
>>>> drivers/dma-buf/dma-fence-chain.c:222:21: sparse: incorrect type in 
>>>> assignment (different address spaces) @@    expected struct 
>>>> dma_fence [noderef] <asn:4>*prev @@    got [noderef] <asn:4>*prev @@
>>     drivers/dma-buf/dma-fence-chain.c:222:21:    expected struct 
>> dma_fence [noderef] <asn:4>*prev
>>     drivers/dma-buf/dma-fence-chain.c:222:21:    got struct dma_fence 
>> *prev
>>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression 
>> using sizeof(void)
>>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression 
>> using sizeof(void)
>>
>> vim +73 drivers/dma-buf/dma-fence-chain.c
>>
>>      38
>>      39    /**
>>      40     * dma_fence_chain_walk - chain walking function
>>      41     * @fence: current chain node
>>      42     *
>>      43     * Walk the chain to the next node. Returns the next fence 
>> or NULL if we are at
>>      44     * the end of the chain. Garbage collects chain nodes 
>> which are already
>>      45     * signaled.
>>      46     */
>>      47    struct dma_fence *dma_fence_chain_walk(struct dma_fence 
>> *fence)
>>      48    {
>>      49        struct dma_fence_chain *chain, *prev_chain;
>>      50        struct dma_fence *prev, *replacement, *tmp;
>>      51
>>      52        chain = to_dma_fence_chain(fence);
>>      53        if (!chain) {
>>      54            dma_fence_put(fence);
>>      55            return NULL;
>>      56        }
>>      57
>>      58        while ((prev = dma_fence_chain_get_prev(chain))) {
>>      59
>>      60            prev_chain = to_dma_fence_chain(prev);
>>      61            if (prev_chain) {
>>      62                if (!dma_fence_is_signaled(prev_chain->fence))
>>      63                    break;
>>      64
>>      65                replacement = 
>> dma_fence_chain_get_prev(prev_chain);
>>      66            } else {
>>      67                if (!dma_fence_is_signaled(prev))
>>      68                    break;
>>      69
>>      70                replacement = NULL;
>>      71            }
>>      72
>>    > 73            tmp = cmpxchg(&chain->prev, prev, replacement);
>>      74            if (tmp == prev)
>>      75                dma_fence_put(tmp);
>>      76            else
>>      77                dma_fence_put(replacement);
>>      78            dma_fence_put(prev);
>>      79        }
>>      80
>>      81        dma_fence_put(fence);
>>      82        return prev;
>>      83    }
>>      84    EXPORT_SYMBOL(dma_fence_chain_walk);
>>      85
>>      86    /**
>>      87     * dma_fence_chain_find_seqno - find fence chain node by 
>> seqno
>>      88     * @pfence: pointer to the chain node where to start
>>      89     * @seqno: the sequence number to search for
>>      90     *
>>      91     * Advance the fence pointer to the chain node which will 
>> signal this sequence
>>      92     * number. If no sequence number is provided then this is 
>> a no-op.
>>      93     *
>>      94     * Returns EINVAL if the fence is not a chain node or the 
>> sequence number has
>>      95     * not yet advanced far enough.
>>      96     */
>>      97    int dma_fence_chain_find_seqno(struct dma_fence **pfence, 
>> uint64_t seqno)
>>      98    {
>>      99        struct dma_fence_chain *chain;
>>     100
>>     101        if (!seqno)
>>     102            return 0;
>>     103
>>     104        chain = to_dma_fence_chain(*pfence);
>>     105        if (!chain || chain->base.seqno < seqno)
>>     106            return -EINVAL;
>>     107
>>     108        dma_fence_chain_for_each(*pfence, &chain->base) {
>>     109            if ((*pfence)->context != chain->base.context ||
>>     110 to_dma_fence_chain(*pfence)->prev_seqno < seqno)
>>     111                break;
>>     112        }
>>     113        dma_fence_put(&chain->base);
>>     114
>>     115        return 0;
>>     116    }
>>     117    EXPORT_SYMBOL(dma_fence_chain_find_seqno);
>>     118
>>     119    static const char *dma_fence_chain_get_driver_name(struct 
>> dma_fence *fence)
>>     120    {
>>     121            return "dma_fence_chain";
>>     122    }
>>     123
>>     124    static const char 
>> *dma_fence_chain_get_timeline_name(struct dma_fence *fence)
>>     125    {
>>     126            return "unbound";
>>     127    }
>>     128
>>     129    static void dma_fence_chain_irq_work(struct irq_work *work)
>>     130    {
>>     131        struct dma_fence_chain *chain;
>>     132
>>     133        chain = container_of(work, typeof(*chain), work);
>>     134
>>     135        /* Try to rearm the callback */
>>     136        if (!dma_fence_chain_enable_signaling(&chain->base))
>>     137            /* Ok, we are done. No more unsignaled fences left */
>>     138            dma_fence_signal(&chain->base);
>>     139        dma_fence_put(&chain->base);
>>     140    }
>>     141
>>     142    static void dma_fence_chain_cb(struct dma_fence *f, struct 
>> dma_fence_cb *cb)
>>     143    {
>>     144        struct dma_fence_chain *chain;
>>     145
>>     146        chain = container_of(cb, typeof(*chain), cb);
>>     147        irq_work_queue(&chain->work);
>>     148        dma_fence_put(f);
>>     149    }
>>     150
>>     151    static bool dma_fence_chain_enable_signaling(struct 
>> dma_fence *fence)
>>     152    {
>>     153        struct dma_fence_chain *head = to_dma_fence_chain(fence);
>>     154
>>     155        dma_fence_get(&head->base);
>>     156        dma_fence_chain_for_each(fence, &head->base) {
>>     157            struct dma_fence_chain *chain = 
>> to_dma_fence_chain(fence);
>>     158            struct dma_fence *f = chain ? chain->fence : fence;
>>     159
>>     160            dma_fence_get(f);
>>     161            if (!dma_fence_add_callback(f, &head->cb, 
>> dma_fence_chain_cb)) {
>>     162                dma_fence_put(fence);
>>     163                return true;
>>     164            }
>>     165            dma_fence_put(f);
>>     166        }
>>     167        dma_fence_put(&head->base);
>>     168        return false;
>>     169    }
>>     170
>>     171    static bool dma_fence_chain_signaled(struct dma_fence *fence)
>>     172    {
>>     173        dma_fence_chain_for_each(fence, fence) {
>>     174            struct dma_fence_chain *chain = 
>> to_dma_fence_chain(fence);
>>     175            struct dma_fence *f = chain ? chain->fence : fence;
>>     176
>>     177            if (!dma_fence_is_signaled(f)) {
>>     178                dma_fence_put(fence);
>>     179                return false;
>>     180            }
>>     181        }
>>     182
>>     183        return true;
>>     184    }
>>     185
>>     186    static void dma_fence_chain_release(struct dma_fence *fence)
>>     187    {
>>     188        struct dma_fence_chain *chain = 
>> to_dma_fence_chain(fence);
>>     189
>>   > 190        dma_fence_put(chain->prev);
>>     191        dma_fence_put(chain->fence);
>>     192        dma_fence_free(fence);
>>     193    }
>>     194
>>     195    const struct dma_fence_ops dma_fence_chain_ops = {
>>     196        .get_driver_name = dma_fence_chain_get_driver_name,
>>     197        .get_timeline_name = dma_fence_chain_get_timeline_name,
>>     198        .enable_signaling = dma_fence_chain_enable_signaling,
>>     199        .signaled = dma_fence_chain_signaled,
>>     200        .release = dma_fence_chain_release,
>>     201    };
>>     202    EXPORT_SYMBOL(dma_fence_chain_ops);
>>     203
>>     204    /**
>>     205     * dma_fence_chain_init - initialize a fence chain
>>     206     * @chain: the chain node to initialize
>>     207     * @prev: the previous fence
>>     208     * @fence: the current fence
>>     209     *
>>     210     * Initialize a new chain node and either start a new 
>> chain or add the node to
>>     211     * the existing chain of the previous fence.
>>     212     */
>>     213    void dma_fence_chain_init(struct dma_fence_chain *chain,
>>     214                  struct dma_fence *prev,
>>     215                  struct dma_fence *fence,
>>     216                  uint64_t seqno)
>>     217    {
>>     218        struct dma_fence_chain *prev_chain = 
>> to_dma_fence_chain(prev);
>>     219        uint64_t context;
>>     220
>>     221        spin_lock_init(&chain->lock);
>>   > 222        chain->prev = prev;
>>
>> ---
>> 0-DAY kernel test infrastructure                Open Source 
>> Technology Center
>> https://lists.01.org/pipermail/kbuild-all Intel Corporation
>
Chunming Zhou March 21, 2019, 2:13 p.m. UTC | #4
cmpxchg be replaced by some simple c sentance?
otherwise we have to remove __rcu of chian->prev.

-David

-------- Original Message --------
Subject: Re: [PATCH 1/9] dma-buf: add new dma_fence_chain container v6
From: Christian König
To: "Zhou, David(ChunMing)" ,kbuild test robot ,"Zhou, David(ChunMing)"
CC: kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net,"Koenig, Christian" ,"Hector, Tobias"

Hi David,

For the cmpxchg() case I of hand don't know either. Looks like so far
nobody has used cmpxchg() with rcu protected structures.

The other cases should be replaced by RCU_INIT_POINTER() or
rcu_dereference_protected(.., true);

Regards,
Christian.

Am 21.03.19 um 07:34 schrieb zhoucm1:
> Hi Lionel and Christian,
>
> Below is robot report for chain->prev, which was added __rcu as you
> suggested.
>
> How to fix this line "tmp = cmpxchg(&chain->prev, prev, replacement); "?
> I checked kernel header file, seems it has no cmpxchg for rcu.
>
> Any suggestion to fix this robot report?
>
> Thanks,
> -David
>
> On 2019年03月21日 08:24, kbuild test robot wrote:
>> Hi Chunming,
>>
>> I love your patch! Perhaps something to improve:
>>
>> [auto build test WARNING on linus/master]
>> [also build test WARNING on v5.1-rc1 next-20190320]
>> [if your patch is applied to the wrong git tree, please drop us a
>> note to help improve the system]
>>
>> url:
>> https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607
>> reproduce:
>>          # apt-get install sparse
>>          make ARCH=x86_64 allmodconfig
>>          make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
>>
>>
>> sparse warnings: (new ones prefixed by >>)
>>
>>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in
>>>> initializer (different address spaces) @@    expected struct
>>>> dma_fence [noderef] <asn:4>*__old @@    got  dma_fence [noderef]
>>>> <asn:4>*__old @@
>>     drivers/dma-buf/dma-fence-chain.c:73:23:    expected struct
>> dma_fence [noderef] <asn:4>*__old
>>     drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence
>> *[assigned] prev
>>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in
>>>> initializer (different address spaces) @@    expected struct
>>>> dma_fence [noderef] <asn:4>*__new @@    got  dma_fence [noderef]
>>>> <asn:4>*__new @@
>>     drivers/dma-buf/dma-fence-chain.c:73:23:    expected struct
>> dma_fence [noderef] <asn:4>*__new
>>     drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence
>> *[assigned] replacement
>>>> drivers/dma-buf/dma-fence-chain.c:73:21: sparse: incorrect type in
>>>> assignment (different address spaces) @@    expected struct
>>>> dma_fence *tmp @@    got struct dma_fence [noderef] <struct
>>>> dma_fence *tmp @@
>>     drivers/dma-buf/dma-fence-chain.c:73:21:    expected struct
>> dma_fence *tmp
>>     drivers/dma-buf/dma-fence-chain.c:73:21:    got struct dma_fence
>> [noderef] <asn:4>*[assigned] __ret
>>>> drivers/dma-buf/dma-fence-chain.c:190:28: sparse: incorrect type in
>>>> argument 1 (different address spaces) @@    expected struct
>>>> dma_fence *fence @@    got struct dma_fence struct dma_fence *fence @@
>>     drivers/dma-buf/dma-fence-chain.c:190:28:    expected struct
>> dma_fence *fence
>>     drivers/dma-buf/dma-fence-chain.c:190:28:    got struct dma_fence
>> [noderef] <asn:4>*prev
>>>> drivers/dma-buf/dma-fence-chain.c:222:21: sparse: incorrect type in
>>>> assignment (different address spaces) @@    expected struct
>>>> dma_fence [noderef] <asn:4>*prev @@    got [noderef] <asn:4>*prev @@
>>     drivers/dma-buf/dma-fence-chain.c:222:21:    expected struct
>> dma_fence [noderef] <asn:4>*prev
>>     drivers/dma-buf/dma-fence-chain.c:222:21:    got struct dma_fence
>> *prev
>>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression
>> using sizeof(void)
>>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression
>> using sizeof(void)
>>
>> vim +73 drivers/dma-buf/dma-fence-chain.c
>>
>>      38
>>      39    /**
>>      40     * dma_fence_chain_walk - chain walking function
>>      41     * @fence: current chain node
>>      42     *
>>      43     * Walk the chain to the next node. Returns the next fence
>> or NULL if we are at
>>      44     * the end of the chain. Garbage collects chain nodes
>> which are already
>>      45     * signaled.
>>      46     */
>>      47    struct dma_fence *dma_fence_chain_walk(struct dma_fence
>> *fence)
>>      48    {
>>      49        struct dma_fence_chain *chain, *prev_chain;
>>      50        struct dma_fence *prev, *replacement, *tmp;
>>      51
>>      52        chain = to_dma_fence_chain(fence);
>>      53        if (!chain) {
>>      54            dma_fence_put(fence);
>>      55            return NULL;
>>      56        }
>>      57
>>      58        while ((prev = dma_fence_chain_get_prev(chain))) {
>>      59
>>      60            prev_chain = to_dma_fence_chain(prev);
>>      61            if (prev_chain) {
>>      62                if (!dma_fence_is_signaled(prev_chain->fence))
>>      63                    break;
>>      64
>>      65                replacement =
>> dma_fence_chain_get_prev(prev_chain);
>>      66            } else {
>>      67                if (!dma_fence_is_signaled(prev))
>>      68                    break;
>>      69
>>      70                replacement = NULL;
>>      71            }
>>      72
>>    > 73            tmp = cmpxchg(&chain->prev, prev, replacement);
>>      74            if (tmp == prev)
>>      75                dma_fence_put(tmp);
>>      76            else
>>      77                dma_fence_put(replacement);
>>      78            dma_fence_put(prev);
>>      79        }
>>      80
>>      81        dma_fence_put(fence);
>>      82        return prev;
>>      83    }
>>      84    EXPORT_SYMBOL(dma_fence_chain_walk);
>>      85
>>      86    /**
>>      87     * dma_fence_chain_find_seqno - find fence chain node by
>> seqno
>>      88     * @pfence: pointer to the chain node where to start
>>      89     * @seqno: the sequence number to search for
>>      90     *
>>      91     * Advance the fence pointer to the chain node which will
>> signal this sequence
>>      92     * number. If no sequence number is provided then this is
>> a no-op.
>>      93     *
>>      94     * Returns EINVAL if the fence is not a chain node or the
>> sequence number has
>>      95     * not yet advanced far enough.
>>      96     */
>>      97    int dma_fence_chain_find_seqno(struct dma_fence **pfence,
>> uint64_t seqno)
>>      98    {
>>      99        struct dma_fence_chain *chain;
>>     100
>>     101        if (!seqno)
>>     102            return 0;
>>     103
>>     104        chain = to_dma_fence_chain(*pfence);
>>     105        if (!chain || chain->base.seqno < seqno)
>>     106            return -EINVAL;
>>     107
>>     108        dma_fence_chain_for_each(*pfence, &chain->base) {
>>     109            if ((*pfence)->context != chain->base.context ||
>>     110 to_dma_fence_chain(*pfence)->prev_seqno < seqno)
>>     111                break;
>>     112        }
>>     113        dma_fence_put(&chain->base);
>>     114
>>     115        return 0;
>>     116    }
>>     117    EXPORT_SYMBOL(dma_fence_chain_find_seqno);
>>     118
>>     119    static const char *dma_fence_chain_get_driver_name(struct
>> dma_fence *fence)
>>     120    {
>>     121            return "dma_fence_chain";
>>     122    }
>>     123
>>     124    static const char
>> *dma_fence_chain_get_timeline_name(struct dma_fence *fence)
>>     125    {
>>     126            return "unbound";
>>     127    }
>>     128
>>     129    static void dma_fence_chain_irq_work(struct irq_work *work)
>>     130    {
>>     131        struct dma_fence_chain *chain;
>>     132
>>     133        chain = container_of(work, typeof(*chain), work);
>>     134
>>     135        /* Try to rearm the callback */
>>     136        if (!dma_fence_chain_enable_signaling(&chain->base))
>>     137            /* Ok, we are done. No more unsignaled fences left */
>>     138            dma_fence_signal(&chain->base);
>>     139        dma_fence_put(&chain->base);
>>     140    }
>>     141
>>     142    static void dma_fence_chain_cb(struct dma_fence *f, struct
>> dma_fence_cb *cb)
>>     143    {
>>     144        struct dma_fence_chain *chain;
>>     145
>>     146        chain = container_of(cb, typeof(*chain), cb);
>>     147        irq_work_queue(&chain->work);
>>     148        dma_fence_put(f);
>>     149    }
>>     150
>>     151    static bool dma_fence_chain_enable_signaling(struct
>> dma_fence *fence)
>>     152    {
>>     153        struct dma_fence_chain *head = to_dma_fence_chain(fence);
>>     154
>>     155        dma_fence_get(&head->base);
>>     156        dma_fence_chain_for_each(fence, &head->base) {
>>     157            struct dma_fence_chain *chain =
>> to_dma_fence_chain(fence);
>>     158            struct dma_fence *f = chain ? chain->fence : fence;
>>     159
>>     160            dma_fence_get(f);
>>     161            if (!dma_fence_add_callback(f, &head->cb,
>> dma_fence_chain_cb)) {
>>     162                dma_fence_put(fence);
>>     163                return true;
>>     164            }
>>     165            dma_fence_put(f);
>>     166        }
>>     167        dma_fence_put(&head->base);
>>     168        return false;
>>     169    }
>>     170
>>     171    static bool dma_fence_chain_signaled(struct dma_fence *fence)
>>     172    {
>>     173        dma_fence_chain_for_each(fence, fence) {
>>     174            struct dma_fence_chain *chain =
>> to_dma_fence_chain(fence);
>>     175            struct dma_fence *f = chain ? chain->fence : fence;
>>     176
>>     177            if (!dma_fence_is_signaled(f)) {
>>     178                dma_fence_put(fence);
>>     179                return false;
>>     180            }
>>     181        }
>>     182
>>     183        return true;
>>     184    }
>>     185
>>     186    static void dma_fence_chain_release(struct dma_fence *fence)
>>     187    {
>>     188        struct dma_fence_chain *chain =
>> to_dma_fence_chain(fence);
>>     189
>>   > 190        dma_fence_put(chain->prev);
>>     191        dma_fence_put(chain->fence);
>>     192        dma_fence_free(fence);
>>     193    }
>>     194
>>     195    const struct dma_fence_ops dma_fence_chain_ops = {
>>     196        .get_driver_name = dma_fence_chain_get_driver_name,
>>     197        .get_timeline_name = dma_fence_chain_get_timeline_name,
>>     198        .enable_signaling = dma_fence_chain_enable_signaling,
>>     199        .signaled = dma_fence_chain_signaled,
>>     200        .release = dma_fence_chain_release,
>>     201    };
>>     202    EXPORT_SYMBOL(dma_fence_chain_ops);
>>     203
>>     204    /**
>>     205     * dma_fence_chain_init - initialize a fence chain
>>     206     * @chain: the chain node to initialize
>>     207     * @prev: the previous fence
>>     208     * @fence: the current fence
>>     209     *
>>     210     * Initialize a new chain node and either start a new
>> chain or add the node to
>>     211     * the existing chain of the previous fence.
>>     212     */
>>     213    void dma_fence_chain_init(struct dma_fence_chain *chain,
>>     214                  struct dma_fence *prev,
>>     215                  struct dma_fence *fence,
>>     216                  uint64_t seqno)
>>     217    {
>>     218        struct dma_fence_chain *prev_chain =
>> to_dma_fence_chain(prev);
>>     219        uint64_t context;
>>     220
>>     221        spin_lock_init(&chain->lock);
>>   > 222        chain->prev = prev;
>>
>> ---
>> 0-DAY kernel test infrastructure                Open Source
>> Technology Center
>> https://lists.01.org/pipermail/kbuild-all Intel Corporation
>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<div>cmpxchg be replaced by some simple c sentance?<br>
otherwise we have to remove __rcu of chian-&gt;prev.<br>
<br>
-David<br>
<br>
-------- Original Message --------<br>
Subject: Re: [PATCH 1/9] dma-buf: add new dma_fence_chain container v6<br>
From: Christian König <br>
To: &quot;Zhou, David(ChunMing)&quot; ,kbuild test robot ,&quot;Zhou, David(ChunMing)&quot; <br>
CC: kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net,&quot;Koenig, Christian&quot; ,&quot;Hector, Tobias&quot;
<br>
<br>
</div>
<font size="2"><span style="font-size:11pt;">
<div class="PlainText">Hi David,<br>
<br>
For the cmpxchg() case I of hand don't know either. Looks like so far <br>
nobody has used cmpxchg() with rcu protected structures.<br>
<br>
The other cases should be replaced by RCU_INIT_POINTER() or <br>
rcu_dereference_protected(.., true);<br>
<br>
Regards,<br>
Christian.<br>
<br>
Am 21.03.19 um 07:34 schrieb zhoucm1:<br>
&gt; Hi Lionel and Christian,<br>
&gt;<br>
&gt; Below is robot report for chain-&gt;prev, which was added __rcu as you <br>
&gt; suggested.<br>
&gt;<br>
&gt; How to fix this line &quot;tmp = cmpxchg(&amp;chain-&gt;prev, prev, replacement); &quot;?<br>
&gt; I checked kernel header file, seems it has no cmpxchg for rcu.<br>
&gt;<br>
&gt; Any suggestion to fix this robot report?<br>
&gt;<br>
&gt; Thanks,<br>
&gt; -David<br>
&gt;<br>
&gt; On 2019年03月21日 08:24, kbuild test robot wrote:<br>
&gt;&gt; Hi Chunming,<br>
&gt;&gt;<br>
&gt;&gt; I love your patch! Perhaps something to improve:<br>
&gt;&gt;<br>
&gt;&gt; [auto build test WARNING on linus/master]<br>
&gt;&gt; [also build test WARNING on v5.1-rc1 next-20190320]<br>
&gt;&gt; [if your patch is applied to the wrong git tree, please drop us a <br>
&gt;&gt; note to help improve the system]<br>
&gt;&gt;<br>
&gt;&gt; url: <br>
&gt;&gt; <a href="https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607">
https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607</a><br>
&gt;&gt; reproduce:<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # apt-get install sparse<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make ARCH=x86_64 allmodconfig<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; sparse warnings: (new ones prefixed by &gt;&gt;)<br>
&gt;&gt;<br>
&gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in <br>
&gt;&gt;&gt;&gt; initializer (different address spaces) @@&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__old @@&nbsp;&nbsp;&nbsp; got&nbsp; dma_fence [noderef] <br>
&gt;&gt;&gt;&gt; &lt;asn:4&gt;*__old @@<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:73:23:&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__old<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:73:23:&nbsp;&nbsp;&nbsp; got struct dma_fence <br>
&gt;&gt; *[assigned] prev<br>
&gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in <br>
&gt;&gt;&gt;&gt; initializer (different address spaces) @@&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__new @@&nbsp;&nbsp;&nbsp; got&nbsp; dma_fence [noderef] <br>
&gt;&gt;&gt;&gt; &lt;asn:4&gt;*__new @@<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:73:23:&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__new<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:73:23:&nbsp;&nbsp;&nbsp; got struct dma_fence <br>
&gt;&gt; *[assigned] replacement<br>
&gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:73:21: sparse: incorrect type in <br>
&gt;&gt;&gt;&gt; assignment (different address spaces) @@&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt;&gt;&gt; dma_fence *tmp @@&nbsp;&nbsp;&nbsp; got struct dma_fence [noderef] &lt;struct <br>
&gt;&gt;&gt;&gt; dma_fence *tmp @@<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:73:21:&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt; dma_fence *tmp<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:73:21:&nbsp;&nbsp;&nbsp; got struct dma_fence <br>
&gt;&gt; [noderef] &lt;asn:4&gt;*[assigned] __ret<br>
&gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:190:28: sparse: incorrect type in <br>
&gt;&gt;&gt;&gt; argument 1 (different address spaces) @@&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt;&gt;&gt; dma_fence *fence @@&nbsp;&nbsp;&nbsp; got struct dma_fence struct dma_fence *fence @@<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:190:28:&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt; dma_fence *fence<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:190:28:&nbsp;&nbsp;&nbsp; got struct dma_fence <br>
&gt;&gt; [noderef] &lt;asn:4&gt;*prev<br>
&gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:222:21: sparse: incorrect type in <br>
&gt;&gt;&gt;&gt; assignment (different address spaces) @@&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*prev @@&nbsp;&nbsp;&nbsp; got [noderef] &lt;asn:4&gt;*prev @@<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:222:21:&nbsp;&nbsp;&nbsp; expected struct <br>
&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*prev<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:222:21:&nbsp;&nbsp;&nbsp; got struct dma_fence <br>
&gt;&gt; *prev<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression <br>
&gt;&gt; using sizeof(void)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression <br>
&gt;&gt; using sizeof(void)<br>
&gt;&gt;<br>
&gt;&gt; vim &#43;73 drivers/dma-buf/dma-fence-chain.c<br>
&gt;&gt;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 38<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 39&nbsp;&nbsp;&nbsp; /**<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 40&nbsp;&nbsp;&nbsp;&nbsp; * dma_fence_chain_walk - chain walking function<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 41&nbsp;&nbsp;&nbsp;&nbsp; * @fence: current chain node<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 42&nbsp;&nbsp;&nbsp;&nbsp; *<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 43&nbsp;&nbsp;&nbsp;&nbsp; * Walk the chain to the next node. Returns the next fence <br>
&gt;&gt; or NULL if we are at<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 44&nbsp;&nbsp;&nbsp;&nbsp; * the end of the chain. Garbage collects chain nodes <br>
&gt;&gt; which are already<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 45&nbsp;&nbsp;&nbsp;&nbsp; * signaled.<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 46&nbsp;&nbsp;&nbsp;&nbsp; */<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 47&nbsp;&nbsp;&nbsp; struct dma_fence *dma_fence_chain_walk(struct dma_fence <br>
&gt;&gt; *fence)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 48&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 49&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence_chain *chain, *prev_chain;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence *prev, *replacement, *tmp;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 51<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chain = to_dma_fence_chain(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 53&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!chain) {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 54&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 56&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 57<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ((prev = dma_fence_chain_get_prev(chain))) {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 59<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 60&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prev_chain = to_dma_fence_chain(prev);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 61&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (prev_chain) {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 62&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!dma_fence_is_signaled(prev_chain-&gt;fence))<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 63&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 64<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 65&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; replacement = <br>
&gt;&gt; dma_fence_chain_get_prev(prev_chain);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 66&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 67&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!dma_fence_is_signaled(prev))<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 68&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 69<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 70&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; replacement = NULL;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 71&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 72<br>
&gt;&gt; &nbsp;&nbsp; &gt; 73&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp = cmpxchg(&amp;chain-&gt;prev, prev, replacement);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 74&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (tmp == prev)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 75&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(tmp);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 76&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 77&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(replacement);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 78&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(prev);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 79&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 80<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 81&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 82&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return prev;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 83&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 84&nbsp;&nbsp;&nbsp; EXPORT_SYMBOL(dma_fence_chain_walk);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 85<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 86&nbsp;&nbsp;&nbsp; /**<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 87&nbsp;&nbsp;&nbsp;&nbsp; * dma_fence_chain_find_seqno - find fence chain node by <br>
&gt;&gt; seqno<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 88&nbsp;&nbsp;&nbsp;&nbsp; * @pfence: pointer to the chain node where to start<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 89&nbsp;&nbsp;&nbsp;&nbsp; * @seqno: the sequence number to search for<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 90&nbsp;&nbsp;&nbsp;&nbsp; *<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 91&nbsp;&nbsp;&nbsp;&nbsp; * Advance the fence pointer to the chain node which will <br>
&gt;&gt; signal this sequence<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 92&nbsp;&nbsp;&nbsp;&nbsp; * number. If no sequence number is provided then this is <br>
&gt;&gt; a no-op.<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 93&nbsp;&nbsp;&nbsp;&nbsp; *<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 94&nbsp;&nbsp;&nbsp;&nbsp; * Returns EINVAL if the fence is not a chain node or the <br>
&gt;&gt; sequence number has<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 95&nbsp;&nbsp;&nbsp;&nbsp; * not yet advanced far enough.<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 96&nbsp;&nbsp;&nbsp;&nbsp; */<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 97&nbsp;&nbsp;&nbsp; int dma_fence_chain_find_seqno(struct dma_fence **pfence, <br>
&gt;&gt; uint64_t seqno)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 98&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp; 99&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence_chain *chain;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 100<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!seqno)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 102&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 103<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chain = to_dma_fence_chain(*pfence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!chain || chain-&gt;base.seqno &lt; seqno)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EINVAL;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 107<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 108&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_chain_for_each(*pfence, &amp;chain-&gt;base) {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 109&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((*pfence)-&gt;context != chain-&gt;base.context ||<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 110 to_dma_fence_chain(*pfence)-&gt;prev_seqno &lt; seqno)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 111&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 113&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(&amp;chain-&gt;base);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 114<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 115&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 116&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 117&nbsp;&nbsp;&nbsp; EXPORT_SYMBOL(dma_fence_chain_find_seqno);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 118<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 119&nbsp;&nbsp;&nbsp; static const char *dma_fence_chain_get_driver_name(struct <br>
&gt;&gt; dma_fence *fence)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 120&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 121&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &quot;dma_fence_chain&quot;;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 122&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 123<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 124&nbsp;&nbsp;&nbsp; static const char <br>
&gt;&gt; *dma_fence_chain_get_timeline_name(struct dma_fence *fence)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 125&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 126&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &quot;unbound&quot;;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 127&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 128<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 129&nbsp;&nbsp;&nbsp; static void dma_fence_chain_irq_work(struct irq_work *work)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 130&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 131&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence_chain *chain;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 132<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 133&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chain = container_of(work, typeof(*chain), work);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 134<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 135&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Try to rearm the callback */<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 136&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!dma_fence_chain_enable_signaling(&amp;chain-&gt;base))<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 137&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Ok, we are done. No more unsignaled fences left */<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 138&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_signal(&amp;chain-&gt;base);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 139&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(&amp;chain-&gt;base);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 140&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 141<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 142&nbsp;&nbsp;&nbsp; static void dma_fence_chain_cb(struct dma_fence *f, struct <br>
&gt;&gt; dma_fence_cb *cb)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 143&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 144&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence_chain *chain;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 145<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 146&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chain = container_of(cb, typeof(*chain), cb);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 147&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; irq_work_queue(&amp;chain-&gt;work);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 148&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(f);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 149&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 150<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 151&nbsp;&nbsp;&nbsp; static bool dma_fence_chain_enable_signaling(struct <br>
&gt;&gt; dma_fence *fence)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 152&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 153&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence_chain *head = to_dma_fence_chain(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 154<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 155&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_get(&amp;head-&gt;base);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 156&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_chain_for_each(fence, &amp;head-&gt;base) {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 157&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence_chain *chain = <br>
&gt;&gt; to_dma_fence_chain(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 158&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence *f = chain ? chain-&gt;fence : fence;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 159<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 160&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_get(f);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 161&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!dma_fence_add_callback(f, &amp;head-&gt;cb, <br>
&gt;&gt; dma_fence_chain_cb)) {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 162&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 163&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 164&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 165&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(f);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 166&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 167&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(&amp;head-&gt;base);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 168&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 169&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 170<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 171&nbsp;&nbsp;&nbsp; static bool dma_fence_chain_signaled(struct dma_fence *fence)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 172&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 173&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_chain_for_each(fence, fence) {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 174&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence_chain *chain = <br>
&gt;&gt; to_dma_fence_chain(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 175&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence *f = chain ? chain-&gt;fence : fence;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 176<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 177&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!dma_fence_is_signaled(f)) {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 178&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 179&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 180&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 181&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 182<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 183&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 184&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 185<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 186&nbsp;&nbsp;&nbsp; static void dma_fence_chain_release(struct dma_fence *fence)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 187&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 188&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence_chain *chain = <br>
&gt;&gt; to_dma_fence_chain(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 189<br>
&gt;&gt; &nbsp; &gt; 190&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(chain-&gt;prev);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 191&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_put(chain-&gt;fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 192&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dma_fence_free(fence);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 193&nbsp;&nbsp;&nbsp; }<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 194<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 195&nbsp;&nbsp;&nbsp; const struct dma_fence_ops dma_fence_chain_ops = {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 196&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .get_driver_name = dma_fence_chain_get_driver_name,<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 197&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .get_timeline_name = dma_fence_chain_get_timeline_name,<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 198&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .enable_signaling = dma_fence_chain_enable_signaling,<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 199&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .signaled = dma_fence_chain_signaled,<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .release = dma_fence_chain_release,<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 201&nbsp;&nbsp;&nbsp; };<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 202&nbsp;&nbsp;&nbsp; EXPORT_SYMBOL(dma_fence_chain_ops);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 203<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 204&nbsp;&nbsp;&nbsp; /**<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 205&nbsp;&nbsp;&nbsp;&nbsp; * dma_fence_chain_init - initialize a fence chain<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 206&nbsp;&nbsp;&nbsp;&nbsp; * @chain: the chain node to initialize<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 207&nbsp;&nbsp;&nbsp;&nbsp; * @prev: the previous fence<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 208&nbsp;&nbsp;&nbsp;&nbsp; * @fence: the current fence<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 209&nbsp;&nbsp;&nbsp;&nbsp; *<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 210&nbsp;&nbsp;&nbsp;&nbsp; * Initialize a new chain node and either start a new <br>
&gt;&gt; chain or add the node to<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 211&nbsp;&nbsp;&nbsp;&nbsp; * the existing chain of the previous fence.<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 212&nbsp;&nbsp;&nbsp;&nbsp; */<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 213&nbsp;&nbsp;&nbsp; void dma_fence_chain_init(struct dma_fence_chain *chain,<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 214&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence *prev,<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 215&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence *fence,<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 216&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uint64_t seqno)<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 217&nbsp;&nbsp;&nbsp; {<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 218&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct dma_fence_chain *prev_chain = <br>
&gt;&gt; to_dma_fence_chain(prev);<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 219&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uint64_t context;<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 220<br>
&gt;&gt; &nbsp;&nbsp;&nbsp; 221&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock_init(&amp;chain-&gt;lock);<br>
&gt;&gt; &nbsp; &gt; 222&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chain-&gt;prev = prev;<br>
&gt;&gt;<br>
&gt;&gt; ---<br>
&gt;&gt; 0-DAY kernel test infrastructure&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Open Source <br>
&gt;&gt; Technology Center<br>
&gt;&gt; <a href="https://lists.01.org/pipermail/kbuild-all">https://lists.01.org/pipermail/kbuild-all</a> Intel Corporation<br>
&gt;<br>
<br>
</div>
</span></font>
</body>
</html>
Christian König March 21, 2019, 2:40 p.m. UTC | #5
No, atomic cmpxchg is a hardware operation. If you want to replace that 
you need a lock again.

Maybe just add a comment and use an explicit cast to void* ? Not sure if 
that silences the warning.

Christian.

Am 21.03.19 um 15:13 schrieb Zhou, David(ChunMing):
> cmpxchg be replaced by some simple c sentance?
> otherwise we have to remove __rcu of chian->prev.
>
> -David
>
> -------- Original Message --------
> Subject: Re: [PATCH 1/9] dma-buf: add new dma_fence_chain container v6
> From: Christian König
> To: "Zhou, David(ChunMing)" ,kbuild test robot ,"Zhou, David(ChunMing)"
> CC: 
> kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net,"Koenig, 
> Christian" ,"Hector, Tobias"
>
> Hi David,
>
> For the cmpxchg() case I of hand don't know either. Looks like so far
> nobody has used cmpxchg() with rcu protected structures.
>
> The other cases should be replaced by RCU_INIT_POINTER() or
> rcu_dereference_protected(.., true);
>
> Regards,
> Christian.
>
> Am 21.03.19 um 07:34 schrieb zhoucm1:
> > Hi Lionel and Christian,
> >
> > Below is robot report for chain->prev, which was added __rcu as you
> > suggested.
> >
> > How to fix this line "tmp = cmpxchg(&chain->prev, prev, replacement); "?
> > I checked kernel header file, seems it has no cmpxchg for rcu.
> >
> > Any suggestion to fix this robot report?
> >
> > Thanks,
> > -David
> >
> > On 2019年03月21日 08:24, kbuild test robot wrote:
> >> Hi Chunming,
> >>
> >> I love your patch! Perhaps something to improve:
> >>
> >> [auto build test WARNING on linus/master]
> >> [also build test WARNING on v5.1-rc1 next-20190320]
> >> [if your patch is applied to the wrong git tree, please drop us a
> >> note to help improve the system]
> >>
> >> url:
> >> 
> https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607
> >> reproduce:
> >>          # apt-get install sparse
> >>          make ARCH=x86_64 allmodconfig
> >>          make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
> >>
> >>
> >> sparse warnings: (new ones prefixed by >>)
> >>
> >>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in
> >>>> initializer (different address spaces) @@    expected struct
> >>>> dma_fence [noderef] <asn:4>*__old @@    got  dma_fence [noderef]
> >>>> <asn:4>*__old @@
> >>     drivers/dma-buf/dma-fence-chain.c:73:23: expected struct
> >> dma_fence [noderef] <asn:4>*__old
> >>     drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence
> >> *[assigned] prev
> >>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in
> >>>> initializer (different address spaces) @@    expected struct
> >>>> dma_fence [noderef] <asn:4>*__new @@    got  dma_fence [noderef]
> >>>> <asn:4>*__new @@
> >>     drivers/dma-buf/dma-fence-chain.c:73:23: expected struct
> >> dma_fence [noderef] <asn:4>*__new
> >>     drivers/dma-buf/dma-fence-chain.c:73:23:    got struct dma_fence
> >> *[assigned] replacement
> >>>> drivers/dma-buf/dma-fence-chain.c:73:21: sparse: incorrect type in
> >>>> assignment (different address spaces) @@ expected struct
> >>>> dma_fence *tmp @@    got struct dma_fence [noderef] <struct
> >>>> dma_fence *tmp @@
> >>     drivers/dma-buf/dma-fence-chain.c:73:21: expected struct
> >> dma_fence *tmp
> >>     drivers/dma-buf/dma-fence-chain.c:73:21:    got struct dma_fence
> >> [noderef] <asn:4>*[assigned] __ret
> >>>> drivers/dma-buf/dma-fence-chain.c:190:28: sparse: incorrect type in
> >>>> argument 1 (different address spaces) @@ expected struct
> >>>> dma_fence *fence @@    got struct dma_fence struct dma_fence 
> *fence @@
> >>     drivers/dma-buf/dma-fence-chain.c:190:28: expected struct
> >> dma_fence *fence
> >>     drivers/dma-buf/dma-fence-chain.c:190:28: got struct dma_fence
> >> [noderef] <asn:4>*prev
> >>>> drivers/dma-buf/dma-fence-chain.c:222:21: sparse: incorrect type in
> >>>> assignment (different address spaces) @@ expected struct
> >>>> dma_fence [noderef] <asn:4>*prev @@    got [noderef] <asn:4>*prev @@
> >>     drivers/dma-buf/dma-fence-chain.c:222:21: expected struct
> >> dma_fence [noderef] <asn:4>*prev
> >>     drivers/dma-buf/dma-fence-chain.c:222:21: got struct dma_fence
> >> *prev
> >>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression
> >> using sizeof(void)
> >>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression
> >> using sizeof(void)
> >>
> >> vim +73 drivers/dma-buf/dma-fence-chain.c
> >>
> >>      38
> >>      39    /**
> >>      40     * dma_fence_chain_walk - chain walking function
> >>      41     * @fence: current chain node
> >>      42     *
> >>      43     * Walk the chain to the next node. Returns the next fence
> >> or NULL if we are at
> >>      44     * the end of the chain. Garbage collects chain nodes
> >> which are already
> >>      45     * signaled.
> >>      46     */
> >>      47    struct dma_fence *dma_fence_chain_walk(struct dma_fence
> >> *fence)
> >>      48    {
> >>      49        struct dma_fence_chain *chain, *prev_chain;
> >>      50        struct dma_fence *prev, *replacement, *tmp;
> >>      51
> >>      52        chain = to_dma_fence_chain(fence);
> >>      53        if (!chain) {
> >>      54            dma_fence_put(fence);
> >>      55            return NULL;
> >>      56        }
> >>      57
> >>      58        while ((prev = dma_fence_chain_get_prev(chain))) {
> >>      59
> >>      60            prev_chain = to_dma_fence_chain(prev);
> >>      61            if (prev_chain) {
> >>      62                if (!dma_fence_is_signaled(prev_chain->fence))
> >>      63                    break;
> >>      64
> >>      65                replacement =
> >> dma_fence_chain_get_prev(prev_chain);
> >>      66            } else {
> >>      67                if (!dma_fence_is_signaled(prev))
> >>      68                    break;
> >>      69
> >>      70                replacement = NULL;
> >>      71            }
> >>      72
> >>    > 73            tmp = cmpxchg(&chain->prev, prev, replacement);
> >>      74            if (tmp == prev)
> >>      75                dma_fence_put(tmp);
> >>      76            else
> >>      77                dma_fence_put(replacement);
> >>      78            dma_fence_put(prev);
> >>      79        }
> >>      80
> >>      81        dma_fence_put(fence);
> >>      82        return prev;
> >>      83    }
> >>      84    EXPORT_SYMBOL(dma_fence_chain_walk);
> >>      85
> >>      86    /**
> >>      87     * dma_fence_chain_find_seqno - find fence chain node by
> >> seqno
> >>      88     * @pfence: pointer to the chain node where to start
> >>      89     * @seqno: the sequence number to search for
> >>      90     *
> >>      91     * Advance the fence pointer to the chain node which will
> >> signal this sequence
> >>      92     * number. If no sequence number is provided then this is
> >> a no-op.
> >>      93     *
> >>      94     * Returns EINVAL if the fence is not a chain node or the
> >> sequence number has
> >>      95     * not yet advanced far enough.
> >>      96     */
> >>      97    int dma_fence_chain_find_seqno(struct dma_fence **pfence,
> >> uint64_t seqno)
> >>      98    {
> >>      99        struct dma_fence_chain *chain;
> >>     100
> >>     101        if (!seqno)
> >>     102            return 0;
> >>     103
> >>     104        chain = to_dma_fence_chain(*pfence);
> >>     105        if (!chain || chain->base.seqno < seqno)
> >>     106            return -EINVAL;
> >>     107
> >>     108        dma_fence_chain_for_each(*pfence, &chain->base) {
> >>     109            if ((*pfence)->context != chain->base.context ||
> >>     110 to_dma_fence_chain(*pfence)->prev_seqno < seqno)
> >>     111                break;
> >>     112        }
> >>     113        dma_fence_put(&chain->base);
> >>     114
> >>     115        return 0;
> >>     116    }
> >>     117 EXPORT_SYMBOL(dma_fence_chain_find_seqno);
> >>     118
> >>     119    static const char *dma_fence_chain_get_driver_name(struct
> >> dma_fence *fence)
> >>     120    {
> >>     121            return "dma_fence_chain";
> >>     122    }
> >>     123
> >>     124    static const char
> >> *dma_fence_chain_get_timeline_name(struct dma_fence *fence)
> >>     125    {
> >>     126            return "unbound";
> >>     127    }
> >>     128
> >>     129    static void dma_fence_chain_irq_work(struct irq_work *work)
> >>     130    {
> >>     131        struct dma_fence_chain *chain;
> >>     132
> >>     133        chain = container_of(work, typeof(*chain), work);
> >>     134
> >>     135        /* Try to rearm the callback */
> >>     136        if (!dma_fence_chain_enable_signaling(&chain->base))
> >>     137            /* Ok, we are done. No more unsignaled fences 
> left */
> >>     138 dma_fence_signal(&chain->base);
> >>     139        dma_fence_put(&chain->base);
> >>     140    }
> >>     141
> >>     142    static void dma_fence_chain_cb(struct dma_fence *f, struct
> >> dma_fence_cb *cb)
> >>     143    {
> >>     144        struct dma_fence_chain *chain;
> >>     145
> >>     146        chain = container_of(cb, typeof(*chain), cb);
> >>     147        irq_work_queue(&chain->work);
> >>     148        dma_fence_put(f);
> >>     149    }
> >>     150
> >>     151    static bool dma_fence_chain_enable_signaling(struct
> >> dma_fence *fence)
> >>     152    {
> >>     153        struct dma_fence_chain *head = 
> to_dma_fence_chain(fence);
> >>     154
> >>     155        dma_fence_get(&head->base);
> >>     156        dma_fence_chain_for_each(fence, &head->base) {
> >>     157            struct dma_fence_chain *chain =
> >> to_dma_fence_chain(fence);
> >>     158            struct dma_fence *f = chain ? chain->fence : fence;
> >>     159
> >>     160            dma_fence_get(f);
> >>     161            if (!dma_fence_add_callback(f, &head->cb,
> >> dma_fence_chain_cb)) {
> >>     162                dma_fence_put(fence);
> >>     163                return true;
> >>     164            }
> >>     165            dma_fence_put(f);
> >>     166        }
> >>     167        dma_fence_put(&head->base);
> >>     168        return false;
> >>     169    }
> >>     170
> >>     171    static bool dma_fence_chain_signaled(struct dma_fence 
> *fence)
> >>     172    {
> >>     173        dma_fence_chain_for_each(fence, fence) {
> >>     174            struct dma_fence_chain *chain =
> >> to_dma_fence_chain(fence);
> >>     175            struct dma_fence *f = chain ? chain->fence : fence;
> >>     176
> >>     177            if (!dma_fence_is_signaled(f)) {
> >>     178                dma_fence_put(fence);
> >>     179                return false;
> >>     180            }
> >>     181        }
> >>     182
> >>     183        return true;
> >>     184    }
> >>     185
> >>     186    static void dma_fence_chain_release(struct dma_fence *fence)
> >>     187    {
> >>     188        struct dma_fence_chain *chain =
> >> to_dma_fence_chain(fence);
> >>     189
> >>   > 190        dma_fence_put(chain->prev);
> >>     191        dma_fence_put(chain->fence);
> >>     192        dma_fence_free(fence);
> >>     193    }
> >>     194
> >>     195    const struct dma_fence_ops dma_fence_chain_ops = {
> >>     196        .get_driver_name = dma_fence_chain_get_driver_name,
> >>     197        .get_timeline_name = dma_fence_chain_get_timeline_name,
> >>     198        .enable_signaling = dma_fence_chain_enable_signaling,
> >>     199        .signaled = dma_fence_chain_signaled,
> >>     200        .release = dma_fence_chain_release,
> >>     201    };
> >>     202    EXPORT_SYMBOL(dma_fence_chain_ops);
> >>     203
> >>     204    /**
> >>     205     * dma_fence_chain_init - initialize a fence chain
> >>     206     * @chain: the chain node to initialize
> >>     207     * @prev: the previous fence
> >>     208     * @fence: the current fence
> >>     209     *
> >>     210     * Initialize a new chain node and either start a new
> >> chain or add the node to
> >>     211     * the existing chain of the previous fence.
> >>     212     */
> >>     213    void dma_fence_chain_init(struct dma_fence_chain *chain,
> >>     214                  struct dma_fence *prev,
> >>     215                  struct dma_fence *fence,
> >>     216                  uint64_t seqno)
> >>     217    {
> >>     218        struct dma_fence_chain *prev_chain =
> >> to_dma_fence_chain(prev);
> >>     219        uint64_t context;
> >>     220
> >>     221        spin_lock_init(&chain->lock);
> >>   > 222        chain->prev = prev;
> >>
> >> ---
> >> 0-DAY kernel test infrastructure Open Source
> >> Technology Center
> >> https://lists.01.org/pipermail/kbuild-all Intel Corporation
> >
>
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">No, atomic cmpxchg is a hardware
      operation. If you want to replace that you need a lock again.<br>
      <br>
      Maybe just add a comment and use an explicit cast to void* ? Not
      sure if that silences the warning.<br>
      <br>
      Christian.<br>
      <br>
      Am 21.03.19 um 15:13 schrieb Zhou, David(ChunMing):<br>
    </div>
    <blockquote type="cite"
cite="mid:2q1nzdv6akhy5260mi-2nbzia-ttsfc8-dz76ft-4ifnnm-oz4kfp-uezs6vwoq2oq-wd0h34-v7m6m7-cd3muc-v4wzqd-yktmtp-2338r6riorqe-ez3yxk-8jr766yyjh0ob0v5e8-33h712k31w5b1ntkih.1553177522341@email.android.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta name="Generator" content="Microsoft Exchange Server">
      <!-- converted from text -->
      <style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
      <div>cmpxchg be replaced by some simple c sentance?<br>
        otherwise we have to remove __rcu of chian-&gt;prev.<br>
        <br>
        -David<br>
        <br>
        -------- Original Message --------<br>
        Subject: Re: [PATCH 1/9] dma-buf: add new dma_fence_chain
        container v6<br>
        From: Christian König <br>
        To: "Zhou, David(ChunMing)" ,kbuild test robot ,"Zhou,
        David(ChunMing)" <br>
        CC:
<a class="moz-txt-link-abbreviated" href="mailto:kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net">kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net</a>,"Koenig,
        Christian" ,"Hector, Tobias"
        <br>
        <br>
      </div>
      <font size="2"><span style="font-size:11pt;">
          <div class="PlainText">Hi David,<br>
            <br>
            For the cmpxchg() case I of hand don't know either. Looks
            like so far <br>
            nobody has used cmpxchg() with rcu protected structures.<br>
            <br>
            The other cases should be replaced by RCU_INIT_POINTER() or
            <br>
            rcu_dereference_protected(.., true);<br>
            <br>
            Regards,<br>
            Christian.<br>
            <br>
            Am 21.03.19 um 07:34 schrieb zhoucm1:<br>
            &gt; Hi Lionel and Christian,<br>
            &gt;<br>
            &gt; Below is robot report for chain-&gt;prev, which was
            added __rcu as you <br>
            &gt; suggested.<br>
            &gt;<br>
            &gt; How to fix this line "tmp =
            cmpxchg(&amp;chain-&gt;prev, prev, replacement); "?<br>
            &gt; I checked kernel header file, seems it has no cmpxchg
            for rcu.<br>
            &gt;<br>
            &gt; Any suggestion to fix this robot report?<br>
            &gt;<br>
            &gt; Thanks,<br>
            &gt; -David<br>
            &gt;<br>
            &gt; On 2019年03月21日 08:24, kbuild test robot wrote:<br>
            &gt;&gt; Hi Chunming,<br>
            &gt;&gt;<br>
            &gt;&gt; I love your patch! Perhaps something to improve:<br>
            &gt;&gt;<br>
            &gt;&gt; [auto build test WARNING on linus/master]<br>
            &gt;&gt; [also build test WARNING on v5.1-rc1 next-20190320]<br>
            &gt;&gt; [if your patch is applied to the wrong git tree,
            please drop us a <br>
            &gt;&gt; note to help improve the system]<br>
            &gt;&gt;<br>
            &gt;&gt; url: <br>
            &gt;&gt; <a
href="https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607"
              moz-do-not-send="true">
https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607</a><br>
            &gt;&gt; reproduce:<br>
            &gt;&gt;          # apt-get install sparse<br>
            &gt;&gt;          make ARCH=x86_64 allmodconfig<br>
            &gt;&gt;          make C=1 CF='-fdiagnostic-prefix
            -D__CHECK_ENDIAN__'<br>
            &gt;&gt;<br>
            &gt;&gt;<br>
            &gt;&gt; sparse warnings: (new ones prefixed by &gt;&gt;)<br>
            &gt;&gt;<br>
            &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:73:23:
            sparse: incorrect type in <br>
            &gt;&gt;&gt;&gt; initializer (different address spaces)
            @@    expected struct <br>
            &gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__old
            @@    got  dma_fence [noderef] <br>
            &gt;&gt;&gt;&gt; &lt;asn:4&gt;*__old @@<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
            expected struct <br>
            &gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__old<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:    got
            struct dma_fence <br>
            &gt;&gt; *[assigned] prev<br>
            &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:73:23:
            sparse: incorrect type in <br>
            &gt;&gt;&gt;&gt; initializer (different address spaces)
            @@    expected struct <br>
            &gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__new
            @@    got  dma_fence [noderef] <br>
            &gt;&gt;&gt;&gt; &lt;asn:4&gt;*__new @@<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
            expected struct <br>
            &gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__new<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:    got
            struct dma_fence <br>
            &gt;&gt; *[assigned] replacement<br>
            &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:73:21:
            sparse: incorrect type in <br>
            &gt;&gt;&gt;&gt; assignment (different address spaces) @@   
            expected struct <br>
            &gt;&gt;&gt;&gt; dma_fence *tmp @@    got struct dma_fence
            [noderef] &lt;struct <br>
            &gt;&gt;&gt;&gt; dma_fence *tmp @@<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:21:   
            expected struct <br>
            &gt;&gt; dma_fence *tmp<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:21:    got
            struct dma_fence <br>
            &gt;&gt; [noderef] &lt;asn:4&gt;*[assigned] __ret<br>
            &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:190:28:
            sparse: incorrect type in <br>
            &gt;&gt;&gt;&gt; argument 1 (different address spaces) @@   
            expected struct <br>
            &gt;&gt;&gt;&gt; dma_fence *fence @@    got struct dma_fence
            struct dma_fence *fence @@<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:190:28:   
            expected struct <br>
            &gt;&gt; dma_fence *fence<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:190:28:   
            got struct dma_fence <br>
            &gt;&gt; [noderef] &lt;asn:4&gt;*prev<br>
            &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:222:21:
            sparse: incorrect type in <br>
            &gt;&gt;&gt;&gt; assignment (different address spaces) @@   
            expected struct <br>
            &gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*prev
            @@    got [noderef] &lt;asn:4&gt;*prev @@<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:222:21:   
            expected struct <br>
            &gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*prev<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:222:21:   
            got struct dma_fence <br>
            &gt;&gt; *prev<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:235:33:
            sparse: expression <br>
            &gt;&gt; using sizeof(void)<br>
            &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:235:33:
            sparse: expression <br>
            &gt;&gt; using sizeof(void)<br>
            &gt;&gt;<br>
            &gt;&gt; vim +73 drivers/dma-buf/dma-fence-chain.c<br>
            &gt;&gt;<br>
            &gt;&gt;      38<br>
            &gt;&gt;      39    /**<br>
            &gt;&gt;      40     * dma_fence_chain_walk - chain walking
            function<br>
            &gt;&gt;      41     * @fence: current chain node<br>
            &gt;&gt;      42     *<br>
            &gt;&gt;      43     * Walk the chain to the next node.
            Returns the next fence <br>
            &gt;&gt; or NULL if we are at<br>
            &gt;&gt;      44     * the end of the chain. Garbage
            collects chain nodes <br>
            &gt;&gt; which are already<br>
            &gt;&gt;      45     * signaled.<br>
            &gt;&gt;      46     */<br>
            &gt;&gt;      47    struct dma_fence
            *dma_fence_chain_walk(struct dma_fence <br>
            &gt;&gt; *fence)<br>
            &gt;&gt;      48    {<br>
            &gt;&gt;      49        struct dma_fence_chain *chain,
            *prev_chain;<br>
            &gt;&gt;      50        struct dma_fence *prev,
            *replacement, *tmp;<br>
            &gt;&gt;      51<br>
            &gt;&gt;      52        chain = to_dma_fence_chain(fence);<br>
            &gt;&gt;      53        if (!chain) {<br>
            &gt;&gt;      54            dma_fence_put(fence);<br>
            &gt;&gt;      55            return NULL;<br>
            &gt;&gt;      56        }<br>
            &gt;&gt;      57<br>
            &gt;&gt;      58        while ((prev =
            dma_fence_chain_get_prev(chain))) {<br>
            &gt;&gt;      59<br>
            &gt;&gt;      60            prev_chain =
            to_dma_fence_chain(prev);<br>
            &gt;&gt;      61            if (prev_chain) {<br>
            &gt;&gt;      62                if
            (!dma_fence_is_signaled(prev_chain-&gt;fence))<br>
            &gt;&gt;      63                    break;<br>
            &gt;&gt;      64<br>
            &gt;&gt;      65                replacement = <br>
            &gt;&gt; dma_fence_chain_get_prev(prev_chain);<br>
            &gt;&gt;      66            } else {<br>
            &gt;&gt;      67                if
            (!dma_fence_is_signaled(prev))<br>
            &gt;&gt;      68                    break;<br>
            &gt;&gt;      69<br>
            &gt;&gt;      70                replacement = NULL;<br>
            &gt;&gt;      71            }<br>
            &gt;&gt;      72<br>
            &gt;&gt;    &gt; 73            tmp =
            cmpxchg(&amp;chain-&gt;prev, prev, replacement);<br>
            &gt;&gt;      74            if (tmp == prev)<br>
            &gt;&gt;      75                dma_fence_put(tmp);<br>
            &gt;&gt;      76            else<br>
            &gt;&gt;      77                dma_fence_put(replacement);<br>
            &gt;&gt;      78            dma_fence_put(prev);<br>
            &gt;&gt;      79        }<br>
            &gt;&gt;      80<br>
            &gt;&gt;      81        dma_fence_put(fence);<br>
            &gt;&gt;      82        return prev;<br>
            &gt;&gt;      83    }<br>
            &gt;&gt;      84    EXPORT_SYMBOL(dma_fence_chain_walk);<br>
            &gt;&gt;      85<br>
            &gt;&gt;      86    /**<br>
            &gt;&gt;      87     * dma_fence_chain_find_seqno - find
            fence chain node by <br>
            &gt;&gt; seqno<br>
            &gt;&gt;      88     * @pfence: pointer to the chain node
            where to start<br>
            &gt;&gt;      89     * @seqno: the sequence number to search
            for<br>
            &gt;&gt;      90     *<br>
            &gt;&gt;      91     * Advance the fence pointer to the
            chain node which will <br>
            &gt;&gt; signal this sequence<br>
            &gt;&gt;      92     * number. If no sequence number is
            provided then this is <br>
            &gt;&gt; a no-op.<br>
            &gt;&gt;      93     *<br>
            &gt;&gt;      94     * Returns EINVAL if the fence is not a
            chain node or the <br>
            &gt;&gt; sequence number has<br>
            &gt;&gt;      95     * not yet advanced far enough.<br>
            &gt;&gt;      96     */<br>
            &gt;&gt;      97    int dma_fence_chain_find_seqno(struct
            dma_fence **pfence, <br>
            &gt;&gt; uint64_t seqno)<br>
            &gt;&gt;      98    {<br>
            &gt;&gt;      99        struct dma_fence_chain *chain;<br>
            &gt;&gt;     100<br>
            &gt;&gt;     101        if (!seqno)<br>
            &gt;&gt;     102            return 0;<br>
            &gt;&gt;     103<br>
            &gt;&gt;     104        chain = to_dma_fence_chain(*pfence);<br>
            &gt;&gt;     105        if (!chain || chain-&gt;base.seqno
            &lt; seqno)<br>
            &gt;&gt;     106            return -EINVAL;<br>
            &gt;&gt;     107<br>
            &gt;&gt;     108        dma_fence_chain_for_each(*pfence,
            &amp;chain-&gt;base) {<br>
            &gt;&gt;     109            if ((*pfence)-&gt;context !=
            chain-&gt;base.context ||<br>
            &gt;&gt;     110 to_dma_fence_chain(*pfence)-&gt;prev_seqno
            &lt; seqno)<br>
            &gt;&gt;     111                break;<br>
            &gt;&gt;     112        }<br>
            &gt;&gt;     113        dma_fence_put(&amp;chain-&gt;base);<br>
            &gt;&gt;     114<br>
            &gt;&gt;     115        return 0;<br>
            &gt;&gt;     116    }<br>
            &gt;&gt;     117   
            EXPORT_SYMBOL(dma_fence_chain_find_seqno);<br>
            &gt;&gt;     118<br>
            &gt;&gt;     119    static const char
            *dma_fence_chain_get_driver_name(struct <br>
            &gt;&gt; dma_fence *fence)<br>
            &gt;&gt;     120    {<br>
            &gt;&gt;     121            return "dma_fence_chain";<br>
            &gt;&gt;     122    }<br>
            &gt;&gt;     123<br>
            &gt;&gt;     124    static const char <br>
            &gt;&gt; *dma_fence_chain_get_timeline_name(struct dma_fence
            *fence)<br>
            &gt;&gt;     125    {<br>
            &gt;&gt;     126            return "unbound";<br>
            &gt;&gt;     127    }<br>
            &gt;&gt;     128<br>
            &gt;&gt;     129    static void
            dma_fence_chain_irq_work(struct irq_work *work)<br>
            &gt;&gt;     130    {<br>
            &gt;&gt;     131        struct dma_fence_chain *chain;<br>
            &gt;&gt;     132<br>
            &gt;&gt;     133        chain = container_of(work,
            typeof(*chain), work);<br>
            &gt;&gt;     134<br>
            &gt;&gt;     135        /* Try to rearm the callback */<br>
            &gt;&gt;     136        if
            (!dma_fence_chain_enable_signaling(&amp;chain-&gt;base))<br>
            &gt;&gt;     137            /* Ok, we are done. No more
            unsignaled fences left */<br>
            &gt;&gt;     138           
            dma_fence_signal(&amp;chain-&gt;base);<br>
            &gt;&gt;     139        dma_fence_put(&amp;chain-&gt;base);<br>
            &gt;&gt;     140    }<br>
            &gt;&gt;     141<br>
            &gt;&gt;     142    static void dma_fence_chain_cb(struct
            dma_fence *f, struct <br>
            &gt;&gt; dma_fence_cb *cb)<br>
            &gt;&gt;     143    {<br>
            &gt;&gt;     144        struct dma_fence_chain *chain;<br>
            &gt;&gt;     145<br>
            &gt;&gt;     146        chain = container_of(cb,
            typeof(*chain), cb);<br>
            &gt;&gt;     147        irq_work_queue(&amp;chain-&gt;work);<br>
            &gt;&gt;     148        dma_fence_put(f);<br>
            &gt;&gt;     149    }<br>
            &gt;&gt;     150<br>
            &gt;&gt;     151    static bool
            dma_fence_chain_enable_signaling(struct <br>
            &gt;&gt; dma_fence *fence)<br>
            &gt;&gt;     152    {<br>
            &gt;&gt;     153        struct dma_fence_chain *head =
            to_dma_fence_chain(fence);<br>
            &gt;&gt;     154<br>
            &gt;&gt;     155        dma_fence_get(&amp;head-&gt;base);<br>
            &gt;&gt;     156        dma_fence_chain_for_each(fence,
            &amp;head-&gt;base) {<br>
            &gt;&gt;     157            struct dma_fence_chain *chain =
            <br>
            &gt;&gt; to_dma_fence_chain(fence);<br>
            &gt;&gt;     158            struct dma_fence *f = chain ?
            chain-&gt;fence : fence;<br>
            &gt;&gt;     159<br>
            &gt;&gt;     160            dma_fence_get(f);<br>
            &gt;&gt;     161            if (!dma_fence_add_callback(f,
            &amp;head-&gt;cb, <br>
            &gt;&gt; dma_fence_chain_cb)) {<br>
            &gt;&gt;     162                dma_fence_put(fence);<br>
            &gt;&gt;     163                return true;<br>
            &gt;&gt;     164            }<br>
            &gt;&gt;     165            dma_fence_put(f);<br>
            &gt;&gt;     166        }<br>
            &gt;&gt;     167        dma_fence_put(&amp;head-&gt;base);<br>
            &gt;&gt;     168        return false;<br>
            &gt;&gt;     169    }<br>
            &gt;&gt;     170<br>
            &gt;&gt;     171    static bool
            dma_fence_chain_signaled(struct dma_fence *fence)<br>
            &gt;&gt;     172    {<br>
            &gt;&gt;     173        dma_fence_chain_for_each(fence,
            fence) {<br>
            &gt;&gt;     174            struct dma_fence_chain *chain =
            <br>
            &gt;&gt; to_dma_fence_chain(fence);<br>
            &gt;&gt;     175            struct dma_fence *f = chain ?
            chain-&gt;fence : fence;<br>
            &gt;&gt;     176<br>
            &gt;&gt;     177            if (!dma_fence_is_signaled(f)) {<br>
            &gt;&gt;     178                dma_fence_put(fence);<br>
            &gt;&gt;     179                return false;<br>
            &gt;&gt;     180            }<br>
            &gt;&gt;     181        }<br>
            &gt;&gt;     182<br>
            &gt;&gt;     183        return true;<br>
            &gt;&gt;     184    }<br>
            &gt;&gt;     185<br>
            &gt;&gt;     186    static void
            dma_fence_chain_release(struct dma_fence *fence)<br>
            &gt;&gt;     187    {<br>
            &gt;&gt;     188        struct dma_fence_chain *chain = <br>
            &gt;&gt; to_dma_fence_chain(fence);<br>
            &gt;&gt;     189<br>
            &gt;&gt;   &gt; 190        dma_fence_put(chain-&gt;prev);<br>
            &gt;&gt;     191        dma_fence_put(chain-&gt;fence);<br>
            &gt;&gt;     192        dma_fence_free(fence);<br>
            &gt;&gt;     193    }<br>
            &gt;&gt;     194<br>
            &gt;&gt;     195    const struct dma_fence_ops
            dma_fence_chain_ops = {<br>
            &gt;&gt;     196        .get_driver_name =
            dma_fence_chain_get_driver_name,<br>
            &gt;&gt;     197        .get_timeline_name =
            dma_fence_chain_get_timeline_name,<br>
            &gt;&gt;     198        .enable_signaling =
            dma_fence_chain_enable_signaling,<br>
            &gt;&gt;     199        .signaled =
            dma_fence_chain_signaled,<br>
            &gt;&gt;     200        .release = dma_fence_chain_release,<br>
            &gt;&gt;     201    };<br>
            &gt;&gt;     202    EXPORT_SYMBOL(dma_fence_chain_ops);<br>
            &gt;&gt;     203<br>
            &gt;&gt;     204    /**<br>
            &gt;&gt;     205     * dma_fence_chain_init - initialize a
            fence chain<br>
            &gt;&gt;     206     * @chain: the chain node to initialize<br>
            &gt;&gt;     207     * @prev: the previous fence<br>
            &gt;&gt;     208     * @fence: the current fence<br>
            &gt;&gt;     209     *<br>
            &gt;&gt;     210     * Initialize a new chain node and
            either start a new <br>
            &gt;&gt; chain or add the node to<br>
            &gt;&gt;     211     * the existing chain of the previous
            fence.<br>
            &gt;&gt;     212     */<br>
            &gt;&gt;     213    void dma_fence_chain_init(struct
            dma_fence_chain *chain,<br>
            &gt;&gt;     214                  struct dma_fence *prev,<br>
            &gt;&gt;     215                  struct dma_fence *fence,<br>
            &gt;&gt;     216                  uint64_t seqno)<br>
            &gt;&gt;     217    {<br>
            &gt;&gt;     218        struct dma_fence_chain *prev_chain =
            <br>
            &gt;&gt; to_dma_fence_chain(prev);<br>
            &gt;&gt;     219        uint64_t context;<br>
            &gt;&gt;     220<br>
            &gt;&gt;     221        spin_lock_init(&amp;chain-&gt;lock);<br>
            &gt;&gt;   &gt; 222        chain-&gt;prev = prev;<br>
            &gt;&gt;<br>
            &gt;&gt; ---<br>
            &gt;&gt; 0-DAY kernel test infrastructure               
            Open Source <br>
            &gt;&gt; Technology Center<br>
            &gt;&gt; <a
              href="https://lists.01.org/pipermail/kbuild-all"
              moz-do-not-send="true">https://lists.01.org/pipermail/kbuild-all</a>
            Intel Corporation<br>
            &gt;<br>
            <br>
          </div>
        </span></font>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
amd-gfx mailing list
<a class="moz-txt-link-abbreviated" href="mailto:amd-gfx@lists.freedesktop.org">amd-gfx@lists.freedesktop.org</a>
<a class="moz-txt-link-freetext" href="https://lists.freedesktop.org/mailman/listinfo/amd-gfx">https://lists.freedesktop.org/mailman/listinfo/amd-gfx</a></pre>
    </blockquote>
    <br>
  </body>
</html>
Chunming Zhou March 22, 2019, 7:34 a.m. UTC | #6
how about the attached?

If ok, I will merge to pathc#1.


-David


On 2019年03月21日 22:40, Christian König wrote:
> No, atomic cmpxchg is a hardware operation. If you want to replace 
> that you need a lock again.
>
> Maybe just add a comment and use an explicit cast to void* ? Not sure 
> if that silences the warning.
>
> Christian.
>
> Am 21.03.19 um 15:13 schrieb Zhou, David(ChunMing):
>> cmpxchg be replaced by some simple c sentance?
>> otherwise we have to remove __rcu of chian->prev.
>>
>> -David
>>
>> -------- Original Message --------
>> Subject: Re: [PATCH 1/9] dma-buf: add new dma_fence_chain container v6
>> From: Christian König
>> To: "Zhou, David(ChunMing)" ,kbuild test robot ,"Zhou, David(ChunMing)"
>> CC: 
>> kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net,"Koenig, 
>> Christian" ,"Hector, Tobias"
>>
>> Hi David,
>>
>> For the cmpxchg() case I of hand don't know either. Looks like so far
>> nobody has used cmpxchg() with rcu protected structures.
>>
>> The other cases should be replaced by RCU_INIT_POINTER() or
>> rcu_dereference_protected(.., true);
>>
>> Regards,
>> Christian.
>>
>> Am 21.03.19 um 07:34 schrieb zhoucm1:
>> > Hi Lionel and Christian,
>> >
>> > Below is robot report for chain->prev, which was added __rcu as you
>> > suggested.
>> >
>> > How to fix this line "tmp = cmpxchg(&chain->prev, prev, 
>> replacement); "?
>> > I checked kernel header file, seems it has no cmpxchg for rcu.
>> >
>> > Any suggestion to fix this robot report?
>> >
>> > Thanks,
>> > -David
>> >
>> > On 2019年03月21日 08:24, kbuild test robot wrote:
>> >> Hi Chunming,
>> >>
>> >> I love your patch! Perhaps something to improve:
>> >>
>> >> [auto build test WARNING on linus/master]
>> >> [also build test WARNING on v5.1-rc1 next-20190320]
>> >> [if your patch is applied to the wrong git tree, please drop us a
>> >> note to help improve the system]
>> >>
>> >> url:
>> >> 
>> https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607
>> >> reproduce:
>> >>          # apt-get install sparse
>> >>          make ARCH=x86_64 allmodconfig
>> >>          make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
>> >>
>> >>
>> >> sparse warnings: (new ones prefixed by >>)
>> >>
>> >>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in
>> >>>> initializer (different address spaces) @@    expected struct
>> >>>> dma_fence [noderef] <asn:4>*__old @@    got  dma_fence [noderef]
>> >>>> <asn:4>*__old @@
>> >>     drivers/dma-buf/dma-fence-chain.c:73:23: expected struct
>> >> dma_fence [noderef] <asn:4>*__old
>> >>     drivers/dma-buf/dma-fence-chain.c:73:23: got struct dma_fence
>> >> *[assigned] prev
>> >>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in
>> >>>> initializer (different address spaces) @@    expected struct
>> >>>> dma_fence [noderef] <asn:4>*__new @@    got  dma_fence [noderef]
>> >>>> <asn:4>*__new @@
>> >>     drivers/dma-buf/dma-fence-chain.c:73:23: expected struct
>> >> dma_fence [noderef] <asn:4>*__new
>> >>     drivers/dma-buf/dma-fence-chain.c:73:23: got struct dma_fence
>> >> *[assigned] replacement
>> >>>> drivers/dma-buf/dma-fence-chain.c:73:21: sparse: incorrect type in
>> >>>> assignment (different address spaces) @@    expected struct
>> >>>> dma_fence *tmp @@    got struct dma_fence [noderef] <struct
>> >>>> dma_fence *tmp @@
>> >>     drivers/dma-buf/dma-fence-chain.c:73:21: expected struct
>> >> dma_fence *tmp
>> >>     drivers/dma-buf/dma-fence-chain.c:73:21: got struct dma_fence
>> >> [noderef] <asn:4>*[assigned] __ret
>> >>>> drivers/dma-buf/dma-fence-chain.c:190:28: sparse: incorrect type in
>> >>>> argument 1 (different address spaces) @@    expected struct
>> >>>> dma_fence *fence @@    got struct dma_fence struct dma_fence 
>> *fence @@
>> >>     drivers/dma-buf/dma-fence-chain.c:190:28: expected struct
>> >> dma_fence *fence
>> >>     drivers/dma-buf/dma-fence-chain.c:190:28: got struct dma_fence
>> >> [noderef] <asn:4>*prev
>> >>>> drivers/dma-buf/dma-fence-chain.c:222:21: sparse: incorrect type in
>> >>>> assignment (different address spaces) @@    expected struct
>> >>>> dma_fence [noderef] <asn:4>*prev @@    got [noderef] <asn:4>*prev @@
>> >>     drivers/dma-buf/dma-fence-chain.c:222:21: expected struct
>> >> dma_fence [noderef] <asn:4>*prev
>> >>     drivers/dma-buf/dma-fence-chain.c:222:21: got struct dma_fence
>> >> *prev
>> >>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression
>> >> using sizeof(void)
>> >>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression
>> >> using sizeof(void)
>> >>
>> >> vim +73 drivers/dma-buf/dma-fence-chain.c
>> >>
>> >>      38
>> >>      39    /**
>> >>      40     * dma_fence_chain_walk - chain walking function
>> >>      41     * @fence: current chain node
>> >>      42     *
>> >>      43     * Walk the chain to the next node. Returns the next fence
>> >> or NULL if we are at
>> >>      44     * the end of the chain. Garbage collects chain nodes
>> >> which are already
>> >>      45     * signaled.
>> >>      46     */
>> >>      47    struct dma_fence *dma_fence_chain_walk(struct dma_fence
>> >> *fence)
>> >>      48    {
>> >>      49        struct dma_fence_chain *chain, *prev_chain;
>> >>      50        struct dma_fence *prev, *replacement, *tmp;
>> >>      51
>> >>      52        chain = to_dma_fence_chain(fence);
>> >>      53        if (!chain) {
>> >>      54            dma_fence_put(fence);
>> >>      55            return NULL;
>> >>      56        }
>> >>      57
>> >>      58        while ((prev = dma_fence_chain_get_prev(chain))) {
>> >>      59
>> >>      60            prev_chain = to_dma_fence_chain(prev);
>> >>      61            if (prev_chain) {
>> >>      62                if (!dma_fence_is_signaled(prev_chain->fence))
>> >>      63                    break;
>> >>      64
>> >>      65                replacement =
>> >> dma_fence_chain_get_prev(prev_chain);
>> >>      66            } else {
>> >>      67                if (!dma_fence_is_signaled(prev))
>> >>      68                    break;
>> >>      69
>> >>      70                replacement = NULL;
>> >>      71            }
>> >>      72
>> >>    > 73            tmp = cmpxchg(&chain->prev, prev, replacement);
>> >>      74            if (tmp == prev)
>> >>      75                dma_fence_put(tmp);
>> >>      76            else
>> >>      77 dma_fence_put(replacement);
>> >>      78            dma_fence_put(prev);
>> >>      79        }
>> >>      80
>> >>      81        dma_fence_put(fence);
>> >>      82        return prev;
>> >>      83    }
>> >>      84    EXPORT_SYMBOL(dma_fence_chain_walk);
>> >>      85
>> >>      86    /**
>> >>      87     * dma_fence_chain_find_seqno - find fence chain node by
>> >> seqno
>> >>      88     * @pfence: pointer to the chain node where to start
>> >>      89     * @seqno: the sequence number to search for
>> >>      90     *
>> >>      91     * Advance the fence pointer to the chain node which will
>> >> signal this sequence
>> >>      92     * number. If no sequence number is provided then this is
>> >> a no-op.
>> >>      93     *
>> >>      94     * Returns EINVAL if the fence is not a chain node or the
>> >> sequence number has
>> >>      95     * not yet advanced far enough.
>> >>      96     */
>> >>      97    int dma_fence_chain_find_seqno(struct dma_fence **pfence,
>> >> uint64_t seqno)
>> >>      98    {
>> >>      99        struct dma_fence_chain *chain;
>> >>     100
>> >>     101        if (!seqno)
>> >>     102            return 0;
>> >>     103
>> >>     104        chain = to_dma_fence_chain(*pfence);
>> >>     105        if (!chain || chain->base.seqno < seqno)
>> >>     106            return -EINVAL;
>> >>     107
>> >>     108        dma_fence_chain_for_each(*pfence, &chain->base) {
>> >>     109            if ((*pfence)->context != chain->base.context ||
>> >>     110 to_dma_fence_chain(*pfence)->prev_seqno < seqno)
>> >>     111                break;
>> >>     112        }
>> >>     113 dma_fence_put(&chain->base);
>> >>     114
>> >>     115        return 0;
>> >>     116    }
>> >>     117 EXPORT_SYMBOL(dma_fence_chain_find_seqno);
>> >>     118
>> >>     119    static const char *dma_fence_chain_get_driver_name(struct
>> >> dma_fence *fence)
>> >>     120    {
>> >>     121            return "dma_fence_chain";
>> >>     122    }
>> >>     123
>> >>     124    static const char
>> >> *dma_fence_chain_get_timeline_name(struct dma_fence *fence)
>> >>     125    {
>> >>     126            return "unbound";
>> >>     127    }
>> >>     128
>> >>     129    static void dma_fence_chain_irq_work(struct irq_work *work)
>> >>     130    {
>> >>     131        struct dma_fence_chain *chain;
>> >>     132
>> >>     133        chain = container_of(work, typeof(*chain), work);
>> >>     134
>> >>     135        /* Try to rearm the callback */
>> >>     136        if (!dma_fence_chain_enable_signaling(&chain->base))
>> >>     137            /* Ok, we are done. No more unsignaled fences 
>> left */
>> >>     138 dma_fence_signal(&chain->base);
>> >>     139 dma_fence_put(&chain->base);
>> >>     140    }
>> >>     141
>> >>     142    static void dma_fence_chain_cb(struct dma_fence *f, struct
>> >> dma_fence_cb *cb)
>> >>     143    {
>> >>     144        struct dma_fence_chain *chain;
>> >>     145
>> >>     146        chain = container_of(cb, typeof(*chain), cb);
>> >>     147 irq_work_queue(&chain->work);
>> >>     148        dma_fence_put(f);
>> >>     149    }
>> >>     150
>> >>     151    static bool dma_fence_chain_enable_signaling(struct
>> >> dma_fence *fence)
>> >>     152    {
>> >>     153        struct dma_fence_chain *head = 
>> to_dma_fence_chain(fence);
>> >>     154
>> >>     155        dma_fence_get(&head->base);
>> >>     156        dma_fence_chain_for_each(fence, &head->base) {
>> >>     157            struct dma_fence_chain *chain =
>> >> to_dma_fence_chain(fence);
>> >>     158            struct dma_fence *f = chain ? chain->fence : fence;
>> >>     159
>> >>     160            dma_fence_get(f);
>> >>     161            if (!dma_fence_add_callback(f, &head->cb,
>> >> dma_fence_chain_cb)) {
>> >>     162                dma_fence_put(fence);
>> >>     163                return true;
>> >>     164            }
>> >>     165            dma_fence_put(f);
>> >>     166        }
>> >>     167        dma_fence_put(&head->base);
>> >>     168        return false;
>> >>     169    }
>> >>     170
>> >>     171    static bool dma_fence_chain_signaled(struct dma_fence 
>> *fence)
>> >>     172    {
>> >>     173        dma_fence_chain_for_each(fence, fence) {
>> >>     174            struct dma_fence_chain *chain =
>> >> to_dma_fence_chain(fence);
>> >>     175            struct dma_fence *f = chain ? chain->fence : fence;
>> >>     176
>> >>     177            if (!dma_fence_is_signaled(f)) {
>> >>     178                dma_fence_put(fence);
>> >>     179                return false;
>> >>     180            }
>> >>     181        }
>> >>     182
>> >>     183        return true;
>> >>     184    }
>> >>     185
>> >>     186    static void dma_fence_chain_release(struct dma_fence 
>> *fence)
>> >>     187    {
>> >>     188        struct dma_fence_chain *chain =
>> >> to_dma_fence_chain(fence);
>> >>     189
>> >>   > 190        dma_fence_put(chain->prev);
>> >>     191        dma_fence_put(chain->fence);
>> >>     192        dma_fence_free(fence);
>> >>     193    }
>> >>     194
>> >>     195    const struct dma_fence_ops dma_fence_chain_ops = {
>> >>     196        .get_driver_name = dma_fence_chain_get_driver_name,
>> >>     197        .get_timeline_name = dma_fence_chain_get_timeline_name,
>> >>     198        .enable_signaling = dma_fence_chain_enable_signaling,
>> >>     199        .signaled = dma_fence_chain_signaled,
>> >>     200        .release = dma_fence_chain_release,
>> >>     201    };
>> >>     202    EXPORT_SYMBOL(dma_fence_chain_ops);
>> >>     203
>> >>     204    /**
>> >>     205     * dma_fence_chain_init - initialize a fence chain
>> >>     206     * @chain: the chain node to initialize
>> >>     207     * @prev: the previous fence
>> >>     208     * @fence: the current fence
>> >>     209     *
>> >>     210     * Initialize a new chain node and either start a new
>> >> chain or add the node to
>> >>     211     * the existing chain of the previous fence.
>> >>     212     */
>> >>     213    void dma_fence_chain_init(struct dma_fence_chain *chain,
>> >>     214                  struct dma_fence *prev,
>> >>     215                  struct dma_fence *fence,
>> >>     216                  uint64_t seqno)
>> >>     217    {
>> >>     218        struct dma_fence_chain *prev_chain =
>> >> to_dma_fence_chain(prev);
>> >>     219        uint64_t context;
>> >>     220
>> >>     221 spin_lock_init(&chain->lock);
>> >>   > 222        chain->prev = prev;
>> >>
>> >> ---
>> >> 0-DAY kernel test infrastructure Open Source
>> >> Technology Center
>> >> https://lists.01.org/pipermail/kbuild-all Intel Corporation
>> >
>>
>>
>> _______________________________________________
>> amd-gfx mailing list
>> amd-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>how about the attached?</p>
    <p>If ok, I will merge to pathc#1.</p>
    <p><br>
    </p>
    <p>-David<br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 2019年03月21日 22:40, Christian König
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:6bd1f7e6-965b-3bd5-e4e0-f3b04e0638fd@gmail.com">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <div class="moz-cite-prefix">No, atomic cmpxchg is a hardware
        operation. If you want to replace that you need a lock again.<br>
        <br>
        Maybe just add a comment and use an explicit cast to void* ? Not
        sure if that silences the warning.<br>
        <br>
        Christian.<br>
        <br>
        Am 21.03.19 um 15:13 schrieb Zhou, David(ChunMing):<br>
      </div>
      <blockquote type="cite"
cite="mid:2q1nzdv6akhy5260mi-2nbzia-ttsfc8-dz76ft-4ifnnm-oz4kfp-uezs6vwoq2oq-wd0h34-v7m6m7-cd3muc-v4wzqd-yktmtp-2338r6riorqe-ez3yxk-8jr766yyjh0ob0v5e8-33h712k31w5b1ntkih.1553177522341@email.android.com">
        <meta name="Generator" content="Microsoft Exchange Server">
        <!-- converted from text -->
        <style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
        <div>cmpxchg be replaced by some simple c sentance?<br>
          otherwise we have to remove __rcu of chian-&gt;prev.<br>
          <br>
          -David<br>
          <br>
          -------- Original Message --------<br>
          Subject: Re: [PATCH 1/9] dma-buf: add new dma_fence_chain
          container v6<br>
          From: Christian König <br>
          To: "Zhou, David(ChunMing)" ,kbuild test robot ,"Zhou,
          David(ChunMing)" <br>
          CC:
          <a class="moz-txt-link-abbreviated"
href="mailto:kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net"
            moz-do-not-send="true">kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net</a>,"Koenig,
          Christian" ,"Hector, Tobias" <br>
          <br>
        </div>
        <font size="2"><span style="font-size:11pt;">
            <div class="PlainText">Hi David,<br>
              <br>
              For the cmpxchg() case I of hand don't know either. Looks
              like so far <br>
              nobody has used cmpxchg() with rcu protected structures.<br>
              <br>
              The other cases should be replaced by RCU_INIT_POINTER()
              or <br>
              rcu_dereference_protected(.., true);<br>
              <br>
              Regards,<br>
              Christian.<br>
              <br>
              Am 21.03.19 um 07:34 schrieb zhoucm1:<br>
              &gt; Hi Lionel and Christian,<br>
              &gt;<br>
              &gt; Below is robot report for chain-&gt;prev, which was
              added __rcu as you <br>
              &gt; suggested.<br>
              &gt;<br>
              &gt; How to fix this line "tmp =
              cmpxchg(&amp;chain-&gt;prev, prev, replacement); "?<br>
              &gt; I checked kernel header file, seems it has no cmpxchg
              for rcu.<br>
              &gt;<br>
              &gt; Any suggestion to fix this robot report?<br>
              &gt;<br>
              &gt; Thanks,<br>
              &gt; -David<br>
              &gt;<br>
              &gt; On 2019年03月21日 08:24, kbuild test robot wrote:<br>
              &gt;&gt; Hi Chunming,<br>
              &gt;&gt;<br>
              &gt;&gt; I love your patch! Perhaps something to improve:<br>
              &gt;&gt;<br>
              &gt;&gt; [auto build test WARNING on linus/master]<br>
              &gt;&gt; [also build test WARNING on v5.1-rc1
              next-20190320]<br>
              &gt;&gt; [if your patch is applied to the wrong git tree,
              please drop us a <br>
              &gt;&gt; note to help improve the system]<br>
              &gt;&gt;<br>
              &gt;&gt; url: <br>
              &gt;&gt; <a
href="https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607"
                moz-do-not-send="true">
https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607</a><br>
              &gt;&gt; reproduce:<br>
              &gt;&gt;          # apt-get install sparse<br>
              &gt;&gt;          make ARCH=x86_64 allmodconfig<br>
              &gt;&gt;          make C=1 CF='-fdiagnostic-prefix
              -D__CHECK_ENDIAN__'<br>
              &gt;&gt;<br>
              &gt;&gt;<br>
              &gt;&gt; sparse warnings: (new ones prefixed by &gt;&gt;)<br>
              &gt;&gt;<br>
              &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:73:23:
              sparse: incorrect type in <br>
              &gt;&gt;&gt;&gt; initializer (different address spaces)
              @@    expected struct <br>
              &gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__old
              @@    got  dma_fence [noderef] <br>
              &gt;&gt;&gt;&gt; &lt;asn:4&gt;*__old @@<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
              expected struct <br>
              &gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__old<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
              got struct dma_fence <br>
              &gt;&gt; *[assigned] prev<br>
              &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:73:23:
              sparse: incorrect type in <br>
              &gt;&gt;&gt;&gt; initializer (different address spaces)
              @@    expected struct <br>
              &gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__new
              @@    got  dma_fence [noderef] <br>
              &gt;&gt;&gt;&gt; &lt;asn:4&gt;*__new @@<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
              expected struct <br>
              &gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__new<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
              got struct dma_fence <br>
              &gt;&gt; *[assigned] replacement<br>
              &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:73:21:
              sparse: incorrect type in <br>
              &gt;&gt;&gt;&gt; assignment (different address spaces)
              @@    expected struct <br>
              &gt;&gt;&gt;&gt; dma_fence *tmp @@    got struct dma_fence
              [noderef] &lt;struct <br>
              &gt;&gt;&gt;&gt; dma_fence *tmp @@<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:21:   
              expected struct <br>
              &gt;&gt; dma_fence *tmp<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:21:   
              got struct dma_fence <br>
              &gt;&gt; [noderef] &lt;asn:4&gt;*[assigned] __ret<br>
              &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:190:28:
              sparse: incorrect type in <br>
              &gt;&gt;&gt;&gt; argument 1 (different address spaces)
              @@    expected struct <br>
              &gt;&gt;&gt;&gt; dma_fence *fence @@    got struct
              dma_fence struct dma_fence *fence @@<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:190:28:   
              expected struct <br>
              &gt;&gt; dma_fence *fence<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:190:28:   
              got struct dma_fence <br>
              &gt;&gt; [noderef] &lt;asn:4&gt;*prev<br>
              &gt;&gt;&gt;&gt; drivers/dma-buf/dma-fence-chain.c:222:21:
              sparse: incorrect type in <br>
              &gt;&gt;&gt;&gt; assignment (different address spaces)
              @@    expected struct <br>
              &gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*prev
              @@    got [noderef] &lt;asn:4&gt;*prev @@<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:222:21:   
              expected struct <br>
              &gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*prev<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:222:21:   
              got struct dma_fence <br>
              &gt;&gt; *prev<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:235:33:
              sparse: expression <br>
              &gt;&gt; using sizeof(void)<br>
              &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:235:33:
              sparse: expression <br>
              &gt;&gt; using sizeof(void)<br>
              &gt;&gt;<br>
              &gt;&gt; vim +73 drivers/dma-buf/dma-fence-chain.c<br>
              &gt;&gt;<br>
              &gt;&gt;      38<br>
              &gt;&gt;      39    /**<br>
              &gt;&gt;      40     * dma_fence_chain_walk - chain
              walking function<br>
              &gt;&gt;      41     * @fence: current chain node<br>
              &gt;&gt;      42     *<br>
              &gt;&gt;      43     * Walk the chain to the next node.
              Returns the next fence <br>
              &gt;&gt; or NULL if we are at<br>
              &gt;&gt;      44     * the end of the chain. Garbage
              collects chain nodes <br>
              &gt;&gt; which are already<br>
              &gt;&gt;      45     * signaled.<br>
              &gt;&gt;      46     */<br>
              &gt;&gt;      47    struct dma_fence
              *dma_fence_chain_walk(struct dma_fence <br>
              &gt;&gt; *fence)<br>
              &gt;&gt;      48    {<br>
              &gt;&gt;      49        struct dma_fence_chain *chain,
              *prev_chain;<br>
              &gt;&gt;      50        struct dma_fence *prev,
              *replacement, *tmp;<br>
              &gt;&gt;      51<br>
              &gt;&gt;      52        chain = to_dma_fence_chain(fence);<br>
              &gt;&gt;      53        if (!chain) {<br>
              &gt;&gt;      54            dma_fence_put(fence);<br>
              &gt;&gt;      55            return NULL;<br>
              &gt;&gt;      56        }<br>
              &gt;&gt;      57<br>
              &gt;&gt;      58        while ((prev =
              dma_fence_chain_get_prev(chain))) {<br>
              &gt;&gt;      59<br>
              &gt;&gt;      60            prev_chain =
              to_dma_fence_chain(prev);<br>
              &gt;&gt;      61            if (prev_chain) {<br>
              &gt;&gt;      62                if
              (!dma_fence_is_signaled(prev_chain-&gt;fence))<br>
              &gt;&gt;      63                    break;<br>
              &gt;&gt;      64<br>
              &gt;&gt;      65                replacement = <br>
              &gt;&gt; dma_fence_chain_get_prev(prev_chain);<br>
              &gt;&gt;      66            } else {<br>
              &gt;&gt;      67                if
              (!dma_fence_is_signaled(prev))<br>
              &gt;&gt;      68                    break;<br>
              &gt;&gt;      69<br>
              &gt;&gt;      70                replacement = NULL;<br>
              &gt;&gt;      71            }<br>
              &gt;&gt;      72<br>
              &gt;&gt;    &gt; 73            tmp =
              cmpxchg(&amp;chain-&gt;prev, prev, replacement);<br>
              &gt;&gt;      74            if (tmp == prev)<br>
              &gt;&gt;      75                dma_fence_put(tmp);<br>
              &gt;&gt;      76            else<br>
              &gt;&gt;      77               
              dma_fence_put(replacement);<br>
              &gt;&gt;      78            dma_fence_put(prev);<br>
              &gt;&gt;      79        }<br>
              &gt;&gt;      80<br>
              &gt;&gt;      81        dma_fence_put(fence);<br>
              &gt;&gt;      82        return prev;<br>
              &gt;&gt;      83    }<br>
              &gt;&gt;      84    EXPORT_SYMBOL(dma_fence_chain_walk);<br>
              &gt;&gt;      85<br>
              &gt;&gt;      86    /**<br>
              &gt;&gt;      87     * dma_fence_chain_find_seqno - find
              fence chain node by <br>
              &gt;&gt; seqno<br>
              &gt;&gt;      88     * @pfence: pointer to the chain node
              where to start<br>
              &gt;&gt;      89     * @seqno: the sequence number to
              search for<br>
              &gt;&gt;      90     *<br>
              &gt;&gt;      91     * Advance the fence pointer to the
              chain node which will <br>
              &gt;&gt; signal this sequence<br>
              &gt;&gt;      92     * number. If no sequence number is
              provided then this is <br>
              &gt;&gt; a no-op.<br>
              &gt;&gt;      93     *<br>
              &gt;&gt;      94     * Returns EINVAL if the fence is not
              a chain node or the <br>
              &gt;&gt; sequence number has<br>
              &gt;&gt;      95     * not yet advanced far enough.<br>
              &gt;&gt;      96     */<br>
              &gt;&gt;      97    int dma_fence_chain_find_seqno(struct
              dma_fence **pfence, <br>
              &gt;&gt; uint64_t seqno)<br>
              &gt;&gt;      98    {<br>
              &gt;&gt;      99        struct dma_fence_chain *chain;<br>
              &gt;&gt;     100<br>
              &gt;&gt;     101        if (!seqno)<br>
              &gt;&gt;     102            return 0;<br>
              &gt;&gt;     103<br>
              &gt;&gt;     104        chain =
              to_dma_fence_chain(*pfence);<br>
              &gt;&gt;     105        if (!chain || chain-&gt;base.seqno
              &lt; seqno)<br>
              &gt;&gt;     106            return -EINVAL;<br>
              &gt;&gt;     107<br>
              &gt;&gt;     108        dma_fence_chain_for_each(*pfence,
              &amp;chain-&gt;base) {<br>
              &gt;&gt;     109            if ((*pfence)-&gt;context !=
              chain-&gt;base.context ||<br>
              &gt;&gt;     110
              to_dma_fence_chain(*pfence)-&gt;prev_seqno &lt; seqno)<br>
              &gt;&gt;     111                break;<br>
              &gt;&gt;     112        }<br>
              &gt;&gt;     113       
              dma_fence_put(&amp;chain-&gt;base);<br>
              &gt;&gt;     114<br>
              &gt;&gt;     115        return 0;<br>
              &gt;&gt;     116    }<br>
              &gt;&gt;     117   
              EXPORT_SYMBOL(dma_fence_chain_find_seqno);<br>
              &gt;&gt;     118<br>
              &gt;&gt;     119    static const char
              *dma_fence_chain_get_driver_name(struct <br>
              &gt;&gt; dma_fence *fence)<br>
              &gt;&gt;     120    {<br>
              &gt;&gt;     121            return "dma_fence_chain";<br>
              &gt;&gt;     122    }<br>
              &gt;&gt;     123<br>
              &gt;&gt;     124    static const char <br>
              &gt;&gt; *dma_fence_chain_get_timeline_name(struct
              dma_fence *fence)<br>
              &gt;&gt;     125    {<br>
              &gt;&gt;     126            return "unbound";<br>
              &gt;&gt;     127    }<br>
              &gt;&gt;     128<br>
              &gt;&gt;     129    static void
              dma_fence_chain_irq_work(struct irq_work *work)<br>
              &gt;&gt;     130    {<br>
              &gt;&gt;     131        struct dma_fence_chain *chain;<br>
              &gt;&gt;     132<br>
              &gt;&gt;     133        chain = container_of(work,
              typeof(*chain), work);<br>
              &gt;&gt;     134<br>
              &gt;&gt;     135        /* Try to rearm the callback */<br>
              &gt;&gt;     136        if
              (!dma_fence_chain_enable_signaling(&amp;chain-&gt;base))<br>
              &gt;&gt;     137            /* Ok, we are done. No more
              unsignaled fences left */<br>
              &gt;&gt;     138           
              dma_fence_signal(&amp;chain-&gt;base);<br>
              &gt;&gt;     139       
              dma_fence_put(&amp;chain-&gt;base);<br>
              &gt;&gt;     140    }<br>
              &gt;&gt;     141<br>
              &gt;&gt;     142    static void dma_fence_chain_cb(struct
              dma_fence *f, struct <br>
              &gt;&gt; dma_fence_cb *cb)<br>
              &gt;&gt;     143    {<br>
              &gt;&gt;     144        struct dma_fence_chain *chain;<br>
              &gt;&gt;     145<br>
              &gt;&gt;     146        chain = container_of(cb,
              typeof(*chain), cb);<br>
              &gt;&gt;     147       
              irq_work_queue(&amp;chain-&gt;work);<br>
              &gt;&gt;     148        dma_fence_put(f);<br>
              &gt;&gt;     149    }<br>
              &gt;&gt;     150<br>
              &gt;&gt;     151    static bool
              dma_fence_chain_enable_signaling(struct <br>
              &gt;&gt; dma_fence *fence)<br>
              &gt;&gt;     152    {<br>
              &gt;&gt;     153        struct dma_fence_chain *head =
              to_dma_fence_chain(fence);<br>
              &gt;&gt;     154<br>
              &gt;&gt;     155        dma_fence_get(&amp;head-&gt;base);<br>
              &gt;&gt;     156        dma_fence_chain_for_each(fence,
              &amp;head-&gt;base) {<br>
              &gt;&gt;     157            struct dma_fence_chain *chain
              = <br>
              &gt;&gt; to_dma_fence_chain(fence);<br>
              &gt;&gt;     158            struct dma_fence *f = chain ?
              chain-&gt;fence : fence;<br>
              &gt;&gt;     159<br>
              &gt;&gt;     160            dma_fence_get(f);<br>
              &gt;&gt;     161            if (!dma_fence_add_callback(f,
              &amp;head-&gt;cb, <br>
              &gt;&gt; dma_fence_chain_cb)) {<br>
              &gt;&gt;     162                dma_fence_put(fence);<br>
              &gt;&gt;     163                return true;<br>
              &gt;&gt;     164            }<br>
              &gt;&gt;     165            dma_fence_put(f);<br>
              &gt;&gt;     166        }<br>
              &gt;&gt;     167        dma_fence_put(&amp;head-&gt;base);<br>
              &gt;&gt;     168        return false;<br>
              &gt;&gt;     169    }<br>
              &gt;&gt;     170<br>
              &gt;&gt;     171    static bool
              dma_fence_chain_signaled(struct dma_fence *fence)<br>
              &gt;&gt;     172    {<br>
              &gt;&gt;     173        dma_fence_chain_for_each(fence,
              fence) {<br>
              &gt;&gt;     174            struct dma_fence_chain *chain
              = <br>
              &gt;&gt; to_dma_fence_chain(fence);<br>
              &gt;&gt;     175            struct dma_fence *f = chain ?
              chain-&gt;fence : fence;<br>
              &gt;&gt;     176<br>
              &gt;&gt;     177            if (!dma_fence_is_signaled(f))
              {<br>
              &gt;&gt;     178                dma_fence_put(fence);<br>
              &gt;&gt;     179                return false;<br>
              &gt;&gt;     180            }<br>
              &gt;&gt;     181        }<br>
              &gt;&gt;     182<br>
              &gt;&gt;     183        return true;<br>
              &gt;&gt;     184    }<br>
              &gt;&gt;     185<br>
              &gt;&gt;     186    static void
              dma_fence_chain_release(struct dma_fence *fence)<br>
              &gt;&gt;     187    {<br>
              &gt;&gt;     188        struct dma_fence_chain *chain = <br>
              &gt;&gt; to_dma_fence_chain(fence);<br>
              &gt;&gt;     189<br>
              &gt;&gt;   &gt; 190        dma_fence_put(chain-&gt;prev);<br>
              &gt;&gt;     191        dma_fence_put(chain-&gt;fence);<br>
              &gt;&gt;     192        dma_fence_free(fence);<br>
              &gt;&gt;     193    }<br>
              &gt;&gt;     194<br>
              &gt;&gt;     195    const struct dma_fence_ops
              dma_fence_chain_ops = {<br>
              &gt;&gt;     196        .get_driver_name =
              dma_fence_chain_get_driver_name,<br>
              &gt;&gt;     197        .get_timeline_name =
              dma_fence_chain_get_timeline_name,<br>
              &gt;&gt;     198        .enable_signaling =
              dma_fence_chain_enable_signaling,<br>
              &gt;&gt;     199        .signaled =
              dma_fence_chain_signaled,<br>
              &gt;&gt;     200        .release =
              dma_fence_chain_release,<br>
              &gt;&gt;     201    };<br>
              &gt;&gt;     202    EXPORT_SYMBOL(dma_fence_chain_ops);<br>
              &gt;&gt;     203<br>
              &gt;&gt;     204    /**<br>
              &gt;&gt;     205     * dma_fence_chain_init - initialize a
              fence chain<br>
              &gt;&gt;     206     * @chain: the chain node to
              initialize<br>
              &gt;&gt;     207     * @prev: the previous fence<br>
              &gt;&gt;     208     * @fence: the current fence<br>
              &gt;&gt;     209     *<br>
              &gt;&gt;     210     * Initialize a new chain node and
              either start a new <br>
              &gt;&gt; chain or add the node to<br>
              &gt;&gt;     211     * the existing chain of the previous
              fence.<br>
              &gt;&gt;     212     */<br>
              &gt;&gt;     213    void dma_fence_chain_init(struct
              dma_fence_chain *chain,<br>
              &gt;&gt;     214                  struct dma_fence *prev,<br>
              &gt;&gt;     215                  struct dma_fence *fence,<br>
              &gt;&gt;     216                  uint64_t seqno)<br>
              &gt;&gt;     217    {<br>
              &gt;&gt;     218        struct dma_fence_chain *prev_chain
              = <br>
              &gt;&gt; to_dma_fence_chain(prev);<br>
              &gt;&gt;     219        uint64_t context;<br>
              &gt;&gt;     220<br>
              &gt;&gt;     221       
              spin_lock_init(&amp;chain-&gt;lock);<br>
              &gt;&gt;   &gt; 222        chain-&gt;prev = prev;<br>
              &gt;&gt;<br>
              &gt;&gt; ---<br>
              &gt;&gt; 0-DAY kernel test infrastructure               
              Open Source <br>
              &gt;&gt; Technology Center<br>
              &gt;&gt; <a
                href="https://lists.01.org/pipermail/kbuild-all"
                moz-do-not-send="true">https://lists.01.org/pipermail/kbuild-all</a>
              Intel Corporation<br>
              &gt;<br>
              <br>
            </div>
          </span></font> <br>
        <fieldset class="mimeAttachmentHeader"></fieldset>
        <pre class="moz-quote-pre" wrap="">_______________________________________________
amd-gfx mailing list
<a class="moz-txt-link-abbreviated" href="mailto:amd-gfx@lists.freedesktop.org" moz-do-not-send="true">amd-gfx@lists.freedesktop.org</a>
<a class="moz-txt-link-freetext" href="https://lists.freedesktop.org/mailman/listinfo/amd-gfx" moz-do-not-send="true">https://lists.freedesktop.org/mailman/listinfo/amd-gfx</a></pre>
      </blockquote>
      <br>
    </blockquote>
    <br>
  </body>
</html>
From 0cb7171b2a99b425323a8e02a968c9488de29608 Mon Sep 17 00:00:00 2001
From: Chunming Zhou <david1.zhou@amd.com>
Date: Fri, 22 Mar 2019 15:33:01 +0800
Subject: [PATCH] fix rcu warning from kernel robot

Signed-off-by: Chunming Zhou <david1.zhou@amd.com>
---
 drivers/dma-buf/dma-fence-chain.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/dma-buf/dma-fence-chain.c b/drivers/dma-buf/dma-fence-chain.c
index 0c5e3c902fa0..c729f98a7bd3 100644
--- a/drivers/dma-buf/dma-fence-chain.c
+++ b/drivers/dma-buf/dma-fence-chain.c
@@ -70,7 +70,7 @@ struct dma_fence *dma_fence_chain_walk(struct dma_fence *fence)
 			replacement = NULL;
 		}
 
-		tmp = cmpxchg(&chain->prev, prev, replacement);
+		tmp = cmpxchg((void **)&chain->prev, (void *)prev, (void *)replacement);
 		if (tmp == prev)
 			dma_fence_put(tmp);
 		else
@@ -187,7 +187,7 @@ static void dma_fence_chain_release(struct dma_fence *fence)
 {
 	struct dma_fence_chain *chain = to_dma_fence_chain(fence);
 
-	dma_fence_put(chain->prev);
+	dma_fence_put(rcu_dereference_protected(chain->prev, true));
 	dma_fence_put(chain->fence);
 	dma_fence_free(fence);
 }
@@ -219,7 +219,7 @@ void dma_fence_chain_init(struct dma_fence_chain *chain,
 	uint64_t context;
 
 	spin_lock_init(&chain->lock);
-	chain->prev = prev;
+	rcu_assign_pointer(chain->prev, prev);
 	chain->fence = fence;
 	chain->prev_seqno = 0;
 	init_irq_work(&chain->work, dma_fence_chain_irq_work);
Christian König March 22, 2019, 3:44 p.m. UTC | #7
Yeah, that should work.

Christian.

Am 22.03.19 um 08:34 schrieb zhoucm1:
>
> how about the attached?
>
> If ok, I will merge to pathc#1.
>
>
> -David
>
>
> On 2019年03月21日 22:40, Christian König wrote:
>> No, atomic cmpxchg is a hardware operation. If you want to replace 
>> that you need a lock again.
>>
>> Maybe just add a comment and use an explicit cast to void* ? Not sure 
>> if that silences the warning.
>>
>> Christian.
>>
>> Am 21.03.19 um 15:13 schrieb Zhou, David(ChunMing):
>>> cmpxchg be replaced by some simple c sentance?
>>> otherwise we have to remove __rcu of chian->prev.
>>>
>>> -David
>>>
>>> -------- Original Message --------
>>> Subject: Re: [PATCH 1/9] dma-buf: add new dma_fence_chain container v6
>>> From: Christian König
>>> To: "Zhou, David(ChunMing)" ,kbuild test robot ,"Zhou, David(ChunMing)"
>>> CC: 
>>> kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net,"Koenig, 
>>> Christian" ,"Hector, Tobias"
>>>
>>> Hi David,
>>>
>>> For the cmpxchg() case I of hand don't know either. Looks like so far
>>> nobody has used cmpxchg() with rcu protected structures.
>>>
>>> The other cases should be replaced by RCU_INIT_POINTER() or
>>> rcu_dereference_protected(.., true);
>>>
>>> Regards,
>>> Christian.
>>>
>>> Am 21.03.19 um 07:34 schrieb zhoucm1:
>>> > Hi Lionel and Christian,
>>> >
>>> > Below is robot report for chain->prev, which was added __rcu as you
>>> > suggested.
>>> >
>>> > How to fix this line "tmp = cmpxchg(&chain->prev, prev, 
>>> replacement); "?
>>> > I checked kernel header file, seems it has no cmpxchg for rcu.
>>> >
>>> > Any suggestion to fix this robot report?
>>> >
>>> > Thanks,
>>> > -David
>>> >
>>> > On 2019年03月21日 08:24, kbuild test robot wrote:
>>> >> Hi Chunming,
>>> >>
>>> >> I love your patch! Perhaps something to improve:
>>> >>
>>> >> [auto build test WARNING on linus/master]
>>> >> [also build test WARNING on v5.1-rc1 next-20190320]
>>> >> [if your patch is applied to the wrong git tree, please drop us a
>>> >> note to help improve the system]
>>> >>
>>> >> url:
>>> >> 
>>> https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607
>>> >> reproduce:
>>> >>          # apt-get install sparse
>>> >>          make ARCH=x86_64 allmodconfig
>>> >>          make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
>>> >>
>>> >>
>>> >> sparse warnings: (new ones prefixed by >>)
>>> >>
>>> >>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in
>>> >>>> initializer (different address spaces) @@    expected struct
>>> >>>> dma_fence [noderef] <asn:4>*__old @@    got  dma_fence [noderef]
>>> >>>> <asn:4>*__old @@
>>> >>     drivers/dma-buf/dma-fence-chain.c:73:23: expected struct
>>> >> dma_fence [noderef] <asn:4>*__old
>>> >>     drivers/dma-buf/dma-fence-chain.c:73:23: got struct dma_fence
>>> >> *[assigned] prev
>>> >>>> drivers/dma-buf/dma-fence-chain.c:73:23: sparse: incorrect type in
>>> >>>> initializer (different address spaces) @@    expected struct
>>> >>>> dma_fence [noderef] <asn:4>*__new @@    got  dma_fence [noderef]
>>> >>>> <asn:4>*__new @@
>>> >>     drivers/dma-buf/dma-fence-chain.c:73:23: expected struct
>>> >> dma_fence [noderef] <asn:4>*__new
>>> >>     drivers/dma-buf/dma-fence-chain.c:73:23: got struct dma_fence
>>> >> *[assigned] replacement
>>> >>>> drivers/dma-buf/dma-fence-chain.c:73:21: sparse: incorrect type in
>>> >>>> assignment (different address spaces) @@    expected struct
>>> >>>> dma_fence *tmp @@    got struct dma_fence [noderef] <struct
>>> >>>> dma_fence *tmp @@
>>> >>     drivers/dma-buf/dma-fence-chain.c:73:21: expected struct
>>> >> dma_fence *tmp
>>> >>     drivers/dma-buf/dma-fence-chain.c:73:21: got struct dma_fence
>>> >> [noderef] <asn:4>*[assigned] __ret
>>> >>>> drivers/dma-buf/dma-fence-chain.c:190:28: sparse: incorrect 
>>> type in
>>> >>>> argument 1 (different address spaces) @@    expected struct
>>> >>>> dma_fence *fence @@    got struct dma_fence struct dma_fence 
>>> *fence @@
>>> >> drivers/dma-buf/dma-fence-chain.c:190:28:    expected struct
>>> >> dma_fence *fence
>>> >> drivers/dma-buf/dma-fence-chain.c:190:28:    got struct dma_fence
>>> >> [noderef] <asn:4>*prev
>>> >>>> drivers/dma-buf/dma-fence-chain.c:222:21: sparse: incorrect 
>>> type in
>>> >>>> assignment (different address spaces) @@    expected struct
>>> >>>> dma_fence [noderef] <asn:4>*prev @@    got [noderef] 
>>> <asn:4>*prev @@
>>> >> drivers/dma-buf/dma-fence-chain.c:222:21:    expected struct
>>> >> dma_fence [noderef] <asn:4>*prev
>>> >> drivers/dma-buf/dma-fence-chain.c:222:21:    got struct dma_fence
>>> >> *prev
>>> >>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression
>>> >> using sizeof(void)
>>> >>     drivers/dma-buf/dma-fence-chain.c:235:33: sparse: expression
>>> >> using sizeof(void)
>>> >>
>>> >> vim +73 drivers/dma-buf/dma-fence-chain.c
>>> >>
>>> >>      38
>>> >>      39    /**
>>> >>      40     * dma_fence_chain_walk - chain walking function
>>> >>      41     * @fence: current chain node
>>> >>      42     *
>>> >>      43     * Walk the chain to the next node. Returns the next 
>>> fence
>>> >> or NULL if we are at
>>> >>      44     * the end of the chain. Garbage collects chain nodes
>>> >> which are already
>>> >>      45     * signaled.
>>> >>      46     */
>>> >>      47    struct dma_fence *dma_fence_chain_walk(struct dma_fence
>>> >> *fence)
>>> >>      48    {
>>> >>      49        struct dma_fence_chain *chain, *prev_chain;
>>> >>      50        struct dma_fence *prev, *replacement, *tmp;
>>> >>      51
>>> >>      52        chain = to_dma_fence_chain(fence);
>>> >>      53        if (!chain) {
>>> >>      54            dma_fence_put(fence);
>>> >>      55            return NULL;
>>> >>      56        }
>>> >>      57
>>> >>      58        while ((prev = dma_fence_chain_get_prev(chain))) {
>>> >>      59
>>> >>      60            prev_chain = to_dma_fence_chain(prev);
>>> >>      61            if (prev_chain) {
>>> >>      62                if (!dma_fence_is_signaled(prev_chain->fence))
>>> >>      63                    break;
>>> >>      64
>>> >>      65                replacement =
>>> >> dma_fence_chain_get_prev(prev_chain);
>>> >>      66            } else {
>>> >>      67                if (!dma_fence_is_signaled(prev))
>>> >>      68                    break;
>>> >>      69
>>> >>      70                replacement = NULL;
>>> >>      71            }
>>> >>      72
>>> >>    > 73            tmp = cmpxchg(&chain->prev, prev, replacement);
>>> >>      74            if (tmp == prev)
>>> >>      75                dma_fence_put(tmp);
>>> >>      76            else
>>> >>      77 dma_fence_put(replacement);
>>> >>      78            dma_fence_put(prev);
>>> >>      79        }
>>> >>      80
>>> >>      81        dma_fence_put(fence);
>>> >>      82        return prev;
>>> >>      83    }
>>> >>      84    EXPORT_SYMBOL(dma_fence_chain_walk);
>>> >>      85
>>> >>      86    /**
>>> >>      87     * dma_fence_chain_find_seqno - find fence chain node by
>>> >> seqno
>>> >>      88     * @pfence: pointer to the chain node where to start
>>> >>      89     * @seqno: the sequence number to search for
>>> >>      90     *
>>> >>      91     * Advance the fence pointer to the chain node which will
>>> >> signal this sequence
>>> >>      92     * number. If no sequence number is provided then this is
>>> >> a no-op.
>>> >>      93     *
>>> >>      94     * Returns EINVAL if the fence is not a chain node or the
>>> >> sequence number has
>>> >>      95     * not yet advanced far enough.
>>> >>      96     */
>>> >>      97    int dma_fence_chain_find_seqno(struct dma_fence **pfence,
>>> >> uint64_t seqno)
>>> >>      98    {
>>> >>      99        struct dma_fence_chain *chain;
>>> >>     100
>>> >>     101        if (!seqno)
>>> >>     102            return 0;
>>> >>     103
>>> >>     104        chain = to_dma_fence_chain(*pfence);
>>> >>     105        if (!chain || chain->base.seqno < seqno)
>>> >>     106            return -EINVAL;
>>> >>     107
>>> >>     108 dma_fence_chain_for_each(*pfence, &chain->base) {
>>> >>     109            if ((*pfence)->context != chain->base.context ||
>>> >>     110 to_dma_fence_chain(*pfence)->prev_seqno < seqno)
>>> >>     111                break;
>>> >>     112        }
>>> >>     113 dma_fence_put(&chain->base);
>>> >>     114
>>> >>     115        return 0;
>>> >>     116    }
>>> >>     117 EXPORT_SYMBOL(dma_fence_chain_find_seqno);
>>> >>     118
>>> >>     119    static const char *dma_fence_chain_get_driver_name(struct
>>> >> dma_fence *fence)
>>> >>     120    {
>>> >>     121            return "dma_fence_chain";
>>> >>     122    }
>>> >>     123
>>> >>     124    static const char
>>> >> *dma_fence_chain_get_timeline_name(struct dma_fence *fence)
>>> >>     125    {
>>> >>     126            return "unbound";
>>> >>     127    }
>>> >>     128
>>> >>     129    static void dma_fence_chain_irq_work(struct irq_work 
>>> *work)
>>> >>     130    {
>>> >>     131        struct dma_fence_chain *chain;
>>> >>     132
>>> >>     133        chain = container_of(work, typeof(*chain), work);
>>> >>     134
>>> >>     135        /* Try to rearm the callback */
>>> >>     136        if (!dma_fence_chain_enable_signaling(&chain->base))
>>> >>     137            /* Ok, we are done. No more unsignaled fences 
>>> left */
>>> >>     138 dma_fence_signal(&chain->base);
>>> >>     139 dma_fence_put(&chain->base);
>>> >>     140    }
>>> >>     141
>>> >>     142    static void dma_fence_chain_cb(struct dma_fence *f, 
>>> struct
>>> >> dma_fence_cb *cb)
>>> >>     143    {
>>> >>     144        struct dma_fence_chain *chain;
>>> >>     145
>>> >>     146        chain = container_of(cb, typeof(*chain), cb);
>>> >>     147 irq_work_queue(&chain->work);
>>> >>     148        dma_fence_put(f);
>>> >>     149    }
>>> >>     150
>>> >>     151    static bool dma_fence_chain_enable_signaling(struct
>>> >> dma_fence *fence)
>>> >>     152    {
>>> >>     153        struct dma_fence_chain *head = 
>>> to_dma_fence_chain(fence);
>>> >>     154
>>> >>     155 dma_fence_get(&head->base);
>>> >>     156        dma_fence_chain_for_each(fence, &head->base) {
>>> >>     157            struct dma_fence_chain *chain =
>>> >> to_dma_fence_chain(fence);
>>> >>     158            struct dma_fence *f = chain ? chain->fence : 
>>> fence;
>>> >>     159
>>> >>     160            dma_fence_get(f);
>>> >>     161            if (!dma_fence_add_callback(f, &head->cb,
>>> >> dma_fence_chain_cb)) {
>>> >>     162                dma_fence_put(fence);
>>> >>     163                return true;
>>> >>     164            }
>>> >>     165            dma_fence_put(f);
>>> >>     166        }
>>> >>     167 dma_fence_put(&head->base);
>>> >>     168        return false;
>>> >>     169    }
>>> >>     170
>>> >>     171    static bool dma_fence_chain_signaled(struct dma_fence 
>>> *fence)
>>> >>     172    {
>>> >>     173        dma_fence_chain_for_each(fence, fence) {
>>> >>     174            struct dma_fence_chain *chain =
>>> >> to_dma_fence_chain(fence);
>>> >>     175            struct dma_fence *f = chain ? chain->fence : 
>>> fence;
>>> >>     176
>>> >>     177            if (!dma_fence_is_signaled(f)) {
>>> >>     178                dma_fence_put(fence);
>>> >>     179                return false;
>>> >>     180            }
>>> >>     181        }
>>> >>     182
>>> >>     183        return true;
>>> >>     184    }
>>> >>     185
>>> >>     186    static void dma_fence_chain_release(struct dma_fence 
>>> *fence)
>>> >>     187    {
>>> >>     188        struct dma_fence_chain *chain =
>>> >> to_dma_fence_chain(fence);
>>> >>     189
>>> >>   > 190 dma_fence_put(chain->prev);
>>> >>     191        dma_fence_put(chain->fence);
>>> >>     192        dma_fence_free(fence);
>>> >>     193    }
>>> >>     194
>>> >>     195    const struct dma_fence_ops dma_fence_chain_ops = {
>>> >>     196        .get_driver_name = dma_fence_chain_get_driver_name,
>>> >>     197        .get_timeline_name = 
>>> dma_fence_chain_get_timeline_name,
>>> >>     198        .enable_signaling = dma_fence_chain_enable_signaling,
>>> >>     199        .signaled = dma_fence_chain_signaled,
>>> >>     200        .release = dma_fence_chain_release,
>>> >>     201    };
>>> >>     202    EXPORT_SYMBOL(dma_fence_chain_ops);
>>> >>     203
>>> >>     204    /**
>>> >>     205     * dma_fence_chain_init - initialize a fence chain
>>> >>     206     * @chain: the chain node to initialize
>>> >>     207     * @prev: the previous fence
>>> >>     208     * @fence: the current fence
>>> >>     209     *
>>> >>     210     * Initialize a new chain node and either start a new
>>> >> chain or add the node to
>>> >>     211     * the existing chain of the previous fence.
>>> >>     212     */
>>> >>     213    void dma_fence_chain_init(struct dma_fence_chain *chain,
>>> >>     214                  struct dma_fence *prev,
>>> >>     215                  struct dma_fence *fence,
>>> >>     216                  uint64_t seqno)
>>> >>     217    {
>>> >>     218        struct dma_fence_chain *prev_chain =
>>> >> to_dma_fence_chain(prev);
>>> >>     219        uint64_t context;
>>> >>     220
>>> >>     221 spin_lock_init(&chain->lock);
>>> >>   > 222        chain->prev = prev;
>>> >>
>>> >> ---
>>> >> 0-DAY kernel test infrastructure Open Source
>>> >> Technology Center
>>> >> https://lists.01.org/pipermail/kbuild-all Intel Corporation
>>> >
>>>
>>>
>>> _______________________________________________
>>> amd-gfx mailing list
>>> amd-gfx@lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>>
>
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">Yeah, that should work.<br>
      <br>
      Christian.<br>
      <br>
      Am 22.03.19 um 08:34 schrieb zhoucm1:<br>
    </div>
    <blockquote type="cite"
      cite="mid:5cb29811-a383-f473-5443-25e9d968c516@amd.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <p>how about the attached?</p>
      <p>If ok, I will merge to pathc#1.</p>
      <p><br>
      </p>
      <p>-David<br>
      </p>
      <br>
      <div class="moz-cite-prefix">On 2019年03月21日 22:40, Christian König
        wrote:<br>
      </div>
      <blockquote type="cite"
        cite="mid:6bd1f7e6-965b-3bd5-e4e0-f3b04e0638fd@gmail.com">
        <meta http-equiv="Content-Type" content="text/html;
          charset=UTF-8">
        <div class="moz-cite-prefix">No, atomic cmpxchg is a hardware
          operation. If you want to replace that you need a lock again.<br>
          <br>
          Maybe just add a comment and use an explicit cast to void* ?
          Not sure if that silences the warning.<br>
          <br>
          Christian.<br>
          <br>
          Am 21.03.19 um 15:13 schrieb Zhou, David(ChunMing):<br>
        </div>
        <blockquote type="cite"
cite="mid:2q1nzdv6akhy5260mi-2nbzia-ttsfc8-dz76ft-4ifnnm-oz4kfp-uezs6vwoq2oq-wd0h34-v7m6m7-cd3muc-v4wzqd-yktmtp-2338r6riorqe-ez3yxk-8jr766yyjh0ob0v5e8-33h712k31w5b1ntkih.1553177522341@email.android.com">
          <meta name="Generator" content="Microsoft Exchange Server">
          <!-- converted from text -->
          <style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
          <div>cmpxchg be replaced by some simple c sentance?<br>
            otherwise we have to remove __rcu of chian-&gt;prev.<br>
            <br>
            -David<br>
            <br>
            -------- Original Message --------<br>
            Subject: Re: [PATCH 1/9] dma-buf: add new dma_fence_chain
            container v6<br>
            From: Christian König <br>
            To: "Zhou, David(ChunMing)" ,kbuild test robot ,"Zhou,
            David(ChunMing)" <br>
            CC: <a class="moz-txt-link-abbreviated"
href="mailto:kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net"
              moz-do-not-send="true">kbuild-all@01.org,dri-devel@lists.freedesktop.org,amd-gfx@lists.freedesktop.org,lionel.g.landwerlin@intel.com,jason@jlekstrand.net</a>,"Koenig,
            Christian" ,"Hector, Tobias" <br>
            <br>
          </div>
          <font size="2"><span style="font-size:11pt;">
              <div class="PlainText">Hi David,<br>
                <br>
                For the cmpxchg() case I of hand don't know either.
                Looks like so far <br>
                nobody has used cmpxchg() with rcu protected structures.<br>
                <br>
                The other cases should be replaced by RCU_INIT_POINTER()
                or <br>
                rcu_dereference_protected(.., true);<br>
                <br>
                Regards,<br>
                Christian.<br>
                <br>
                Am 21.03.19 um 07:34 schrieb zhoucm1:<br>
                &gt; Hi Lionel and Christian,<br>
                &gt;<br>
                &gt; Below is robot report for chain-&gt;prev, which was
                added __rcu as you <br>
                &gt; suggested.<br>
                &gt;<br>
                &gt; How to fix this line "tmp =
                cmpxchg(&amp;chain-&gt;prev, prev, replacement); "?<br>
                &gt; I checked kernel header file, seems it has no
                cmpxchg for rcu.<br>
                &gt;<br>
                &gt; Any suggestion to fix this robot report?<br>
                &gt;<br>
                &gt; Thanks,<br>
                &gt; -David<br>
                &gt;<br>
                &gt; On 2019年03月21日 08:24, kbuild test robot wrote:<br>
                &gt;&gt; Hi Chunming,<br>
                &gt;&gt;<br>
                &gt;&gt; I love your patch! Perhaps something to
                improve:<br>
                &gt;&gt;<br>
                &gt;&gt; [auto build test WARNING on linus/master]<br>
                &gt;&gt; [also build test WARNING on v5.1-rc1
                next-20190320]<br>
                &gt;&gt; [if your patch is applied to the wrong git
                tree, please drop us a <br>
                &gt;&gt; note to help improve the system]<br>
                &gt;&gt;<br>
                &gt;&gt; url: <br>
                &gt;&gt; <a
href="https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607"
                  moz-do-not-send="true">
https://github.com/0day-ci/linux/commits/Chunming-Zhou/dma-buf-add-new-dma_fence_chain-container-v6/20190320-223607</a><br>
                &gt;&gt; reproduce:<br>
                &gt;&gt;          # apt-get install sparse<br>
                &gt;&gt;          make ARCH=x86_64 allmodconfig<br>
                &gt;&gt;          make C=1 CF='-fdiagnostic-prefix
                -D__CHECK_ENDIAN__'<br>
                &gt;&gt;<br>
                &gt;&gt;<br>
                &gt;&gt; sparse warnings: (new ones prefixed by
                &gt;&gt;)<br>
                &gt;&gt;<br>
                &gt;&gt;&gt;&gt;
                drivers/dma-buf/dma-fence-chain.c:73:23: sparse:
                incorrect type in <br>
                &gt;&gt;&gt;&gt; initializer (different address spaces)
                @@    expected struct <br>
                &gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__old
                @@    got  dma_fence [noderef] <br>
                &gt;&gt;&gt;&gt; &lt;asn:4&gt;*__old @@<br>
                &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
                expected struct <br>
                &gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__old<br>
                &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
                got struct dma_fence <br>
                &gt;&gt; *[assigned] prev<br>
                &gt;&gt;&gt;&gt;
                drivers/dma-buf/dma-fence-chain.c:73:23: sparse:
                incorrect type in <br>
                &gt;&gt;&gt;&gt; initializer (different address spaces)
                @@    expected struct <br>
                &gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__new
                @@    got  dma_fence [noderef] <br>
                &gt;&gt;&gt;&gt; &lt;asn:4&gt;*__new @@<br>
                &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
                expected struct <br>
                &gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*__new<br>
                &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:23:   
                got struct dma_fence <br>
                &gt;&gt; *[assigned] replacement<br>
                &gt;&gt;&gt;&gt;
                drivers/dma-buf/dma-fence-chain.c:73:21: sparse:
                incorrect type in <br>
                &gt;&gt;&gt;&gt; assignment (different address spaces)
                @@    expected struct <br>
                &gt;&gt;&gt;&gt; dma_fence *tmp @@    got struct
                dma_fence [noderef] &lt;struct <br>
                &gt;&gt;&gt;&gt; dma_fence *tmp @@<br>
                &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:21:   
                expected struct <br>
                &gt;&gt; dma_fence *tmp<br>
                &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:73:21:   
                got struct dma_fence <br>
                &gt;&gt; [noderef] &lt;asn:4&gt;*[assigned] __ret<br>
                &gt;&gt;&gt;&gt;
                drivers/dma-buf/dma-fence-chain.c:190:28: sparse:
                incorrect type in <br>
                &gt;&gt;&gt;&gt; argument 1 (different address spaces)
                @@    expected struct <br>
                &gt;&gt;&gt;&gt; dma_fence *fence @@    got struct
                dma_fence struct dma_fence *fence @@<br>
                &gt;&gt;    
                drivers/dma-buf/dma-fence-chain.c:190:28:    expected
                struct <br>
                &gt;&gt; dma_fence *fence<br>
                &gt;&gt;    
                drivers/dma-buf/dma-fence-chain.c:190:28:    got struct
                dma_fence <br>
                &gt;&gt; [noderef] &lt;asn:4&gt;*prev<br>
                &gt;&gt;&gt;&gt;
                drivers/dma-buf/dma-fence-chain.c:222:21: sparse:
                incorrect type in <br>
                &gt;&gt;&gt;&gt; assignment (different address spaces)
                @@    expected struct <br>
                &gt;&gt;&gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*prev
                @@    got [noderef] &lt;asn:4&gt;*prev @@<br>
                &gt;&gt;    
                drivers/dma-buf/dma-fence-chain.c:222:21:    expected
                struct <br>
                &gt;&gt; dma_fence [noderef] &lt;asn:4&gt;*prev<br>
                &gt;&gt;    
                drivers/dma-buf/dma-fence-chain.c:222:21:    got struct
                dma_fence <br>
                &gt;&gt; *prev<br>
                &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:235:33:
                sparse: expression <br>
                &gt;&gt; using sizeof(void)<br>
                &gt;&gt;     drivers/dma-buf/dma-fence-chain.c:235:33:
                sparse: expression <br>
                &gt;&gt; using sizeof(void)<br>
                &gt;&gt;<br>
                &gt;&gt; vim +73 drivers/dma-buf/dma-fence-chain.c<br>
                &gt;&gt;<br>
                &gt;&gt;      38<br>
                &gt;&gt;      39    /**<br>
                &gt;&gt;      40     * dma_fence_chain_walk - chain
                walking function<br>
                &gt;&gt;      41     * @fence: current chain node<br>
                &gt;&gt;      42     *<br>
                &gt;&gt;      43     * Walk the chain to the next node.
                Returns the next fence <br>
                &gt;&gt; or NULL if we are at<br>
                &gt;&gt;      44     * the end of the chain. Garbage
                collects chain nodes <br>
                &gt;&gt; which are already<br>
                &gt;&gt;      45     * signaled.<br>
                &gt;&gt;      46     */<br>
                &gt;&gt;      47    struct dma_fence
                *dma_fence_chain_walk(struct dma_fence <br>
                &gt;&gt; *fence)<br>
                &gt;&gt;      48    {<br>
                &gt;&gt;      49        struct dma_fence_chain *chain,
                *prev_chain;<br>
                &gt;&gt;      50        struct dma_fence *prev,
                *replacement, *tmp;<br>
                &gt;&gt;      51<br>
                &gt;&gt;      52        chain =
                to_dma_fence_chain(fence);<br>
                &gt;&gt;      53        if (!chain) {<br>
                &gt;&gt;      54            dma_fence_put(fence);<br>
                &gt;&gt;      55            return NULL;<br>
                &gt;&gt;      56        }<br>
                &gt;&gt;      57<br>
                &gt;&gt;      58        while ((prev =
                dma_fence_chain_get_prev(chain))) {<br>
                &gt;&gt;      59<br>
                &gt;&gt;      60            prev_chain =
                to_dma_fence_chain(prev);<br>
                &gt;&gt;      61            if (prev_chain) {<br>
                &gt;&gt;      62                if
                (!dma_fence_is_signaled(prev_chain-&gt;fence))<br>
                &gt;&gt;      63                    break;<br>
                &gt;&gt;      64<br>
                &gt;&gt;      65                replacement = <br>
                &gt;&gt; dma_fence_chain_get_prev(prev_chain);<br>
                &gt;&gt;      66            } else {<br>
                &gt;&gt;      67                if
                (!dma_fence_is_signaled(prev))<br>
                &gt;&gt;      68                    break;<br>
                &gt;&gt;      69<br>
                &gt;&gt;      70                replacement = NULL;<br>
                &gt;&gt;      71            }<br>
                &gt;&gt;      72<br>
                &gt;&gt;    &gt; 73            tmp =
                cmpxchg(&amp;chain-&gt;prev, prev, replacement);<br>
                &gt;&gt;      74            if (tmp == prev)<br>
                &gt;&gt;      75                dma_fence_put(tmp);<br>
                &gt;&gt;      76            else<br>
                &gt;&gt;      77               
                dma_fence_put(replacement);<br>
                &gt;&gt;      78            dma_fence_put(prev);<br>
                &gt;&gt;      79        }<br>
                &gt;&gt;      80<br>
                &gt;&gt;      81        dma_fence_put(fence);<br>
                &gt;&gt;      82        return prev;<br>
                &gt;&gt;      83    }<br>
                &gt;&gt;      84    EXPORT_SYMBOL(dma_fence_chain_walk);<br>
                &gt;&gt;      85<br>
                &gt;&gt;      86    /**<br>
                &gt;&gt;      87     * dma_fence_chain_find_seqno - find
                fence chain node by <br>
                &gt;&gt; seqno<br>
                &gt;&gt;      88     * @pfence: pointer to the chain
                node where to start<br>
                &gt;&gt;      89     * @seqno: the sequence number to
                search for<br>
                &gt;&gt;      90     *<br>
                &gt;&gt;      91     * Advance the fence pointer to the
                chain node which will <br>
                &gt;&gt; signal this sequence<br>
                &gt;&gt;      92     * number. If no sequence number is
                provided then this is <br>
                &gt;&gt; a no-op.<br>
                &gt;&gt;      93     *<br>
                &gt;&gt;      94     * Returns EINVAL if the fence is
                not a chain node or the <br>
                &gt;&gt; sequence number has<br>
                &gt;&gt;      95     * not yet advanced far enough.<br>
                &gt;&gt;      96     */<br>
                &gt;&gt;      97    int
                dma_fence_chain_find_seqno(struct dma_fence **pfence, <br>
                &gt;&gt; uint64_t seqno)<br>
                &gt;&gt;      98    {<br>
                &gt;&gt;      99        struct dma_fence_chain *chain;<br>
                &gt;&gt;     100<br>
                &gt;&gt;     101        if (!seqno)<br>
                &gt;&gt;     102            return 0;<br>
                &gt;&gt;     103<br>
                &gt;&gt;     104        chain =
                to_dma_fence_chain(*pfence);<br>
                &gt;&gt;     105        if (!chain ||
                chain-&gt;base.seqno &lt; seqno)<br>
                &gt;&gt;     106            return -EINVAL;<br>
                &gt;&gt;     107<br>
                &gt;&gt;     108       
                dma_fence_chain_for_each(*pfence, &amp;chain-&gt;base) {<br>
                &gt;&gt;     109            if ((*pfence)-&gt;context !=
                chain-&gt;base.context ||<br>
                &gt;&gt;     110
                to_dma_fence_chain(*pfence)-&gt;prev_seqno &lt; seqno)<br>
                &gt;&gt;     111                break;<br>
                &gt;&gt;     112        }<br>
                &gt;&gt;     113       
                dma_fence_put(&amp;chain-&gt;base);<br>
                &gt;&gt;     114<br>
                &gt;&gt;     115        return 0;<br>
                &gt;&gt;     116    }<br>
                &gt;&gt;     117   
                EXPORT_SYMBOL(dma_fence_chain_find_seqno);<br>
                &gt;&gt;     118<br>
                &gt;&gt;     119    static const char
                *dma_fence_chain_get_driver_name(struct <br>
                &gt;&gt; dma_fence *fence)<br>
                &gt;&gt;     120    {<br>
                &gt;&gt;     121            return "dma_fence_chain";<br>
                &gt;&gt;     122    }<br>
                &gt;&gt;     123<br>
                &gt;&gt;     124    static const char <br>
                &gt;&gt; *dma_fence_chain_get_timeline_name(struct
                dma_fence *fence)<br>
                &gt;&gt;     125    {<br>
                &gt;&gt;     126            return "unbound";<br>
                &gt;&gt;     127    }<br>
                &gt;&gt;     128<br>
                &gt;&gt;     129    static void
                dma_fence_chain_irq_work(struct irq_work *work)<br>
                &gt;&gt;     130    {<br>
                &gt;&gt;     131        struct dma_fence_chain *chain;<br>
                &gt;&gt;     132<br>
                &gt;&gt;     133        chain = container_of(work,
                typeof(*chain), work);<br>
                &gt;&gt;     134<br>
                &gt;&gt;     135        /* Try to rearm the callback */<br>
                &gt;&gt;     136        if
                (!dma_fence_chain_enable_signaling(&amp;chain-&gt;base))<br>
                &gt;&gt;     137            /* Ok, we are done. No more
                unsignaled fences left */<br>
                &gt;&gt;     138           
                dma_fence_signal(&amp;chain-&gt;base);<br>
                &gt;&gt;     139       
                dma_fence_put(&amp;chain-&gt;base);<br>
                &gt;&gt;     140    }<br>
                &gt;&gt;     141<br>
                &gt;&gt;     142    static void
                dma_fence_chain_cb(struct dma_fence *f, struct <br>
                &gt;&gt; dma_fence_cb *cb)<br>
                &gt;&gt;     143    {<br>
                &gt;&gt;     144        struct dma_fence_chain *chain;<br>
                &gt;&gt;     145<br>
                &gt;&gt;     146        chain = container_of(cb,
                typeof(*chain), cb);<br>
                &gt;&gt;     147       
                irq_work_queue(&amp;chain-&gt;work);<br>
                &gt;&gt;     148        dma_fence_put(f);<br>
                &gt;&gt;     149    }<br>
                &gt;&gt;     150<br>
                &gt;&gt;     151    static bool
                dma_fence_chain_enable_signaling(struct <br>
                &gt;&gt; dma_fence *fence)<br>
                &gt;&gt;     152    {<br>
                &gt;&gt;     153        struct dma_fence_chain *head =
                to_dma_fence_chain(fence);<br>
                &gt;&gt;     154<br>
                &gt;&gt;     155       
                dma_fence_get(&amp;head-&gt;base);<br>
                &gt;&gt;     156        dma_fence_chain_for_each(fence,
                &amp;head-&gt;base) {<br>
                &gt;&gt;     157            struct dma_fence_chain
                *chain = <br>
                &gt;&gt; to_dma_fence_chain(fence);<br>
                &gt;&gt;     158            struct dma_fence *f = chain
                ? chain-&gt;fence : fence;<br>
                &gt;&gt;     159<br>
                &gt;&gt;     160            dma_fence_get(f);<br>
                &gt;&gt;     161            if
                (!dma_fence_add_callback(f, &amp;head-&gt;cb, <br>
                &gt;&gt; dma_fence_chain_cb)) {<br>
                &gt;&gt;     162                dma_fence_put(fence);<br>
                &gt;&gt;     163                return true;<br>
                &gt;&gt;     164            }<br>
                &gt;&gt;     165            dma_fence_put(f);<br>
                &gt;&gt;     166        }<br>
                &gt;&gt;     167       
                dma_fence_put(&amp;head-&gt;base);<br>
                &gt;&gt;     168        return false;<br>
                &gt;&gt;     169    }<br>
                &gt;&gt;     170<br>
                &gt;&gt;     171    static bool
                dma_fence_chain_signaled(struct dma_fence *fence)<br>
                &gt;&gt;     172    {<br>
                &gt;&gt;     173        dma_fence_chain_for_each(fence,
                fence) {<br>
                &gt;&gt;     174            struct dma_fence_chain
                *chain = <br>
                &gt;&gt; to_dma_fence_chain(fence);<br>
                &gt;&gt;     175            struct dma_fence *f = chain
                ? chain-&gt;fence : fence;<br>
                &gt;&gt;     176<br>
                &gt;&gt;     177            if
                (!dma_fence_is_signaled(f)) {<br>
                &gt;&gt;     178                dma_fence_put(fence);<br>
                &gt;&gt;     179                return false;<br>
                &gt;&gt;     180            }<br>
                &gt;&gt;     181        }<br>
                &gt;&gt;     182<br>
                &gt;&gt;     183        return true;<br>
                &gt;&gt;     184    }<br>
                &gt;&gt;     185<br>
                &gt;&gt;     186    static void
                dma_fence_chain_release(struct dma_fence *fence)<br>
                &gt;&gt;     187    {<br>
                &gt;&gt;     188        struct dma_fence_chain *chain =
                <br>
                &gt;&gt; to_dma_fence_chain(fence);<br>
                &gt;&gt;     189<br>
                &gt;&gt;   &gt; 190       
                dma_fence_put(chain-&gt;prev);<br>
                &gt;&gt;     191        dma_fence_put(chain-&gt;fence);<br>
                &gt;&gt;     192        dma_fence_free(fence);<br>
                &gt;&gt;     193    }<br>
                &gt;&gt;     194<br>
                &gt;&gt;     195    const struct dma_fence_ops
                dma_fence_chain_ops = {<br>
                &gt;&gt;     196        .get_driver_name =
                dma_fence_chain_get_driver_name,<br>
                &gt;&gt;     197        .get_timeline_name =
                dma_fence_chain_get_timeline_name,<br>
                &gt;&gt;     198        .enable_signaling =
                dma_fence_chain_enable_signaling,<br>
                &gt;&gt;     199        .signaled =
                dma_fence_chain_signaled,<br>
                &gt;&gt;     200        .release =
                dma_fence_chain_release,<br>
                &gt;&gt;     201    };<br>
                &gt;&gt;     202    EXPORT_SYMBOL(dma_fence_chain_ops);<br>
                &gt;&gt;     203<br>
                &gt;&gt;     204    /**<br>
                &gt;&gt;     205     * dma_fence_chain_init - initialize
                a fence chain<br>
                &gt;&gt;     206     * @chain: the chain node to
                initialize<br>
                &gt;&gt;     207     * @prev: the previous fence<br>
                &gt;&gt;     208     * @fence: the current fence<br>
                &gt;&gt;     209     *<br>
                &gt;&gt;     210     * Initialize a new chain node and
                either start a new <br>
                &gt;&gt; chain or add the node to<br>
                &gt;&gt;     211     * the existing chain of the
                previous fence.<br>
                &gt;&gt;     212     */<br>
                &gt;&gt;     213    void dma_fence_chain_init(struct
                dma_fence_chain *chain,<br>
                &gt;&gt;     214                  struct dma_fence
                *prev,<br>
                &gt;&gt;     215                  struct dma_fence
                *fence,<br>
                &gt;&gt;     216                  uint64_t seqno)<br>
                &gt;&gt;     217    {<br>
                &gt;&gt;     218        struct dma_fence_chain
                *prev_chain = <br>
                &gt;&gt; to_dma_fence_chain(prev);<br>
                &gt;&gt;     219        uint64_t context;<br>
                &gt;&gt;     220<br>
                &gt;&gt;     221       
                spin_lock_init(&amp;chain-&gt;lock);<br>
                &gt;&gt;   &gt; 222        chain-&gt;prev = prev;<br>
                &gt;&gt;<br>
                &gt;&gt; ---<br>
                &gt;&gt; 0-DAY kernel test infrastructure               
                Open Source <br>
                &gt;&gt; Technology Center<br>
                &gt;&gt; <a
                  href="https://lists.01.org/pipermail/kbuild-all"
                  moz-do-not-send="true">https://lists.01.org/pipermail/kbuild-all</a>
                Intel Corporation<br>
                &gt;<br>
                <br>
              </div>
            </span></font> <br>
          <fieldset class="mimeAttachmentHeader"></fieldset>
          <pre class="moz-quote-pre" wrap="">_______________________________________________
amd-gfx mailing list
<a class="moz-txt-link-abbreviated" href="mailto:amd-gfx@lists.freedesktop.org" moz-do-not-send="true">amd-gfx@lists.freedesktop.org</a>
<a class="moz-txt-link-freetext" href="https://lists.freedesktop.org/mailman/listinfo/amd-gfx" moz-do-not-send="true">https://lists.freedesktop.org/mailman/listinfo/amd-gfx</a></pre>
        </blockquote>
        <br>
      </blockquote>
      <br>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
amd-gfx mailing list
<a class="moz-txt-link-abbreviated" href="mailto:amd-gfx@lists.freedesktop.org">amd-gfx@lists.freedesktop.org</a>
<a class="moz-txt-link-freetext" href="https://lists.freedesktop.org/mailman/listinfo/amd-gfx">https://lists.freedesktop.org/mailman/listinfo/amd-gfx</a></pre>
    </blockquote>
    <br>
  </body>
</html>
diff mbox series

Patch

diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 0913a6ccab5a..1f006e083eb9 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1,4 +1,5 @@ 
-obj-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o
+obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
+	 reservation.o seqno-fence.o
 obj-$(CONFIG_SYNC_FILE)		+= sync_file.o
 obj-$(CONFIG_SW_SYNC)		+= sw_sync.o sync_debug.o
 obj-$(CONFIG_UDMABUF)		+= udmabuf.o
diff --git a/drivers/dma-buf/dma-fence-chain.c b/drivers/dma-buf/dma-fence-chain.c
new file mode 100644
index 000000000000..0c5e3c902fa0
--- /dev/null
+++ b/drivers/dma-buf/dma-fence-chain.c
@@ -0,0 +1,241 @@ 
+/*
+ * fence-chain: chain fences together in a timeline
+ *
+ * Copyright (C) 2018 Advanced Micro Devices, Inc.
+ * Authors:
+ *	Christian König <christian.koenig@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/dma-fence-chain.h>
+
+static bool dma_fence_chain_enable_signaling(struct dma_fence *fence);
+
+/**
+ * dma_fence_chain_get_prev - use RCU to get a reference to the previous fence
+ * @chain: chain node to get the previous node from
+ *
+ * Use dma_fence_get_rcu_safe to get a reference to the previous fence of the
+ * chain node.
+ */
+static struct dma_fence *dma_fence_chain_get_prev(struct dma_fence_chain *chain)
+{
+	struct dma_fence *prev;
+
+	rcu_read_lock();
+	prev = dma_fence_get_rcu_safe(&chain->prev);
+	rcu_read_unlock();
+	return prev;
+}
+
+/**
+ * dma_fence_chain_walk - chain walking function
+ * @fence: current chain node
+ *
+ * Walk the chain to the next node. Returns the next fence or NULL if we are at
+ * the end of the chain. Garbage collects chain nodes which are already
+ * signaled.
+ */
+struct dma_fence *dma_fence_chain_walk(struct dma_fence *fence)
+{
+	struct dma_fence_chain *chain, *prev_chain;
+	struct dma_fence *prev, *replacement, *tmp;
+
+	chain = to_dma_fence_chain(fence);
+	if (!chain) {
+		dma_fence_put(fence);
+		return NULL;
+	}
+
+	while ((prev = dma_fence_chain_get_prev(chain))) {
+
+		prev_chain = to_dma_fence_chain(prev);
+		if (prev_chain) {
+			if (!dma_fence_is_signaled(prev_chain->fence))
+				break;
+
+			replacement = dma_fence_chain_get_prev(prev_chain);
+		} else {
+			if (!dma_fence_is_signaled(prev))
+				break;
+
+			replacement = NULL;
+		}
+
+		tmp = cmpxchg(&chain->prev, prev, replacement);
+		if (tmp == prev)
+			dma_fence_put(tmp);
+		else
+			dma_fence_put(replacement);
+		dma_fence_put(prev);
+	}
+
+	dma_fence_put(fence);
+	return prev;
+}
+EXPORT_SYMBOL(dma_fence_chain_walk);
+
+/**
+ * dma_fence_chain_find_seqno - find fence chain node by seqno
+ * @pfence: pointer to the chain node where to start
+ * @seqno: the sequence number to search for
+ *
+ * Advance the fence pointer to the chain node which will signal this sequence
+ * number. If no sequence number is provided then this is a no-op.
+ *
+ * Returns EINVAL if the fence is not a chain node or the sequence number has
+ * not yet advanced far enough.
+ */
+int dma_fence_chain_find_seqno(struct dma_fence **pfence, uint64_t seqno)
+{
+	struct dma_fence_chain *chain;
+
+	if (!seqno)
+		return 0;
+
+	chain = to_dma_fence_chain(*pfence);
+	if (!chain || chain->base.seqno < seqno)
+		return -EINVAL;
+
+	dma_fence_chain_for_each(*pfence, &chain->base) {
+		if ((*pfence)->context != chain->base.context ||
+		    to_dma_fence_chain(*pfence)->prev_seqno < seqno)
+			break;
+	}
+	dma_fence_put(&chain->base);
+
+	return 0;
+}
+EXPORT_SYMBOL(dma_fence_chain_find_seqno);
+
+static const char *dma_fence_chain_get_driver_name(struct dma_fence *fence)
+{
+        return "dma_fence_chain";
+}
+
+static const char *dma_fence_chain_get_timeline_name(struct dma_fence *fence)
+{
+        return "unbound";
+}
+
+static void dma_fence_chain_irq_work(struct irq_work *work)
+{
+	struct dma_fence_chain *chain;
+
+	chain = container_of(work, typeof(*chain), work);
+
+	/* Try to rearm the callback */
+	if (!dma_fence_chain_enable_signaling(&chain->base))
+		/* Ok, we are done. No more unsignaled fences left */
+		dma_fence_signal(&chain->base);
+	dma_fence_put(&chain->base);
+}
+
+static void dma_fence_chain_cb(struct dma_fence *f, struct dma_fence_cb *cb)
+{
+	struct dma_fence_chain *chain;
+
+	chain = container_of(cb, typeof(*chain), cb);
+	irq_work_queue(&chain->work);
+	dma_fence_put(f);
+}
+
+static bool dma_fence_chain_enable_signaling(struct dma_fence *fence)
+{
+	struct dma_fence_chain *head = to_dma_fence_chain(fence);
+
+	dma_fence_get(&head->base);
+	dma_fence_chain_for_each(fence, &head->base) {
+		struct dma_fence_chain *chain = to_dma_fence_chain(fence);
+		struct dma_fence *f = chain ? chain->fence : fence;
+
+		dma_fence_get(f);
+		if (!dma_fence_add_callback(f, &head->cb, dma_fence_chain_cb)) {
+			dma_fence_put(fence);
+			return true;
+		}
+		dma_fence_put(f);
+	}
+	dma_fence_put(&head->base);
+	return false;
+}
+
+static bool dma_fence_chain_signaled(struct dma_fence *fence)
+{
+	dma_fence_chain_for_each(fence, fence) {
+		struct dma_fence_chain *chain = to_dma_fence_chain(fence);
+		struct dma_fence *f = chain ? chain->fence : fence;
+
+		if (!dma_fence_is_signaled(f)) {
+			dma_fence_put(fence);
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static void dma_fence_chain_release(struct dma_fence *fence)
+{
+	struct dma_fence_chain *chain = to_dma_fence_chain(fence);
+
+	dma_fence_put(chain->prev);
+	dma_fence_put(chain->fence);
+	dma_fence_free(fence);
+}
+
+const struct dma_fence_ops dma_fence_chain_ops = {
+	.get_driver_name = dma_fence_chain_get_driver_name,
+	.get_timeline_name = dma_fence_chain_get_timeline_name,
+	.enable_signaling = dma_fence_chain_enable_signaling,
+	.signaled = dma_fence_chain_signaled,
+	.release = dma_fence_chain_release,
+};
+EXPORT_SYMBOL(dma_fence_chain_ops);
+
+/**
+ * dma_fence_chain_init - initialize a fence chain
+ * @chain: the chain node to initialize
+ * @prev: the previous fence
+ * @fence: the current fence
+ *
+ * Initialize a new chain node and either start a new chain or add the node to
+ * the existing chain of the previous fence.
+ */
+void dma_fence_chain_init(struct dma_fence_chain *chain,
+			  struct dma_fence *prev,
+			  struct dma_fence *fence,
+			  uint64_t seqno)
+{
+	struct dma_fence_chain *prev_chain = to_dma_fence_chain(prev);
+	uint64_t context;
+
+	spin_lock_init(&chain->lock);
+	chain->prev = prev;
+	chain->fence = fence;
+	chain->prev_seqno = 0;
+	init_irq_work(&chain->work, dma_fence_chain_irq_work);
+
+	/* Try to reuse the context of the previous chain node. */
+	if (prev_chain && __dma_fence_is_later(seqno, prev->seqno)) {
+		context = prev->context;
+		chain->prev_seqno = prev->seqno;
+	} else {
+		context = dma_fence_context_alloc(1);
+		/* Make sure that we always have a valid sequence number. */
+		if (prev_chain)
+			seqno = max(prev->seqno, seqno);
+	}
+
+	dma_fence_init(&chain->base, &dma_fence_chain_ops,
+		       &chain->lock, context, seqno);
+}
+EXPORT_SYMBOL(dma_fence_chain_init);
diff --git a/include/linux/dma-fence-chain.h b/include/linux/dma-fence-chain.h
new file mode 100644
index 000000000000..934a442db8ac
--- /dev/null
+++ b/include/linux/dma-fence-chain.h
@@ -0,0 +1,81 @@ 
+/*
+ * fence-chain: chain fences together in a timeline
+ *
+ * Copyright (C) 2018 Advanced Micro Devices, Inc.
+ * Authors:
+ *	Christian König <christian.koenig@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef __LINUX_DMA_FENCE_CHAIN_H
+#define __LINUX_DMA_FENCE_CHAIN_H
+
+#include <linux/dma-fence.h>
+#include <linux/irq_work.h>
+
+/**
+ * struct dma_fence_chain - fence to represent an node of a fence chain
+ * @base: fence base class
+ * @lock: spinlock for fence handling
+ * @prev: previous fence of the chain
+ * @prev_seqno: original previous seqno before garbage collection
+ * @fence: encapsulated fence
+ * @cb: callback structure for signaling
+ * @work: irq work item for signaling
+ */
+struct dma_fence_chain {
+	struct dma_fence base;
+	spinlock_t lock;
+	struct dma_fence __rcu *prev;
+	u64 prev_seqno;
+	struct dma_fence *fence;
+	struct dma_fence_cb cb;
+	struct irq_work work;
+};
+
+extern const struct dma_fence_ops dma_fence_chain_ops;
+
+/**
+ * to_dma_fence_chain - cast a fence to a dma_fence_chain
+ * @fence: fence to cast to a dma_fence_array
+ *
+ * Returns NULL if the fence is not a dma_fence_chain,
+ * or the dma_fence_chain otherwise.
+ */
+static inline struct dma_fence_chain *
+to_dma_fence_chain(struct dma_fence *fence)
+{
+	if (!fence || fence->ops != &dma_fence_chain_ops)
+		return NULL;
+
+	return container_of(fence, struct dma_fence_chain, base);
+}
+
+/**
+ * dma_fence_chain_for_each - iterate over all fences in chain
+ * @iter: current fence
+ * @head: starting point
+ *
+ * Iterate over all fences in the chain. We keep a reference to the current
+ * fence while inside the loop which must be dropped when breaking out.
+ */
+#define dma_fence_chain_for_each(iter, head)	\
+	for (iter = dma_fence_get(head); iter; \
+	     iter = dma_fence_chain_walk(iter))
+
+struct dma_fence *dma_fence_chain_walk(struct dma_fence *fence);
+int dma_fence_chain_find_seqno(struct dma_fence **pfence, uint64_t seqno);
+void dma_fence_chain_init(struct dma_fence_chain *chain,
+			  struct dma_fence *prev,
+			  struct dma_fence *fence,
+			  uint64_t seqno);
+
+#endif /* __LINUX_DMA_FENCE_CHAIN_H */