[lng-odp] 32b support in ODP-Cloud

2017-03-22 Thread Honnappa Nagarahalli
Hi Bill / Matt and others,
What I was trying to say in our discussion is that, the
ODP-Cloud code should not be pointer heavy.

Please take a look at this video from BUD17:
http://connect.linaro.org/resource/bud17/bud17-101/ (unfortunately
there are no slides, I am trying to get them). This talks about the
performance of the 32b application on AArch64. One of the
applications, has huge performance improvement while running in 32b
mode (ILP32 in this particular case) on AArch64 (when compared to the
same application compiled for 64b mode running on AArch64 i.e. in 64b
compilation it performed very poorly). My understanding is that this
particular application is a pointer chasing application. Other
applications which are not pointer heavy, do not have this behavior.

So, we need to make sure ODP-Cloud is not pointer heavy and does not
force the application to be pointer heavy, to get good performance out
of 64b systems.

Thank you,
Honnappa


[lng-odp] [Linaro/odp] 88dbb0: linux-generic: pool: add odp_pool_capability() rc ...

2017-03-22 Thread GitHub
  Branch: refs/heads/api-next
  Home:   https://github.com/Linaro/odp
  Commit: 88dbb00623102878f2e0e1dd720a942fdd980ca3
  
https://github.com/Linaro/odp/commit/88dbb00623102878f2e0e1dd720a942fdd980ca3
  Author: Bill Fischofer 
  Date:   2017-03-02 (Thu, 02 Mar 2017)

  Changed paths:
M platform/linux-generic/odp_pool.c

  Log Message:
  ---
  linux-generic: pool: add odp_pool_capability() rc check

Resolve Bug https://bugs.linaro.org/show_bug.cgi?id=2826 by adding
an explicit check of the rc from odp_pool_capability() for consistency
with other code that calls this routine.

Signed-off-by: Bill Fischofer 
Signed-off-by: Maxim Uvarov 


  Commit: a347c91412f0db5c25141b709a93eaf040a77730
  
https://github.com/Linaro/odp/commit/a347c91412f0db5c25141b709a93eaf040a77730
  Author: Matias Elo 
  Date:   2017-03-02 (Thu, 02 Mar 2017)

  Changed paths:
M platform/linux-generic/m4/odp_dpdk.m4
M platform/linux-generic/pktio/dpdk.c

  Log Message:
  ---
  linux-gen: dpdk: improve pmd driver linking

Previously each dpdk pmd driver had to be individually referred in the odp
code to ensure proper gcc constructor linking. Using the -—whole-archive
option when linking the drivers removes this need. After this patch new
dpdk pmd drivers are automatically linked.

Signed-off-by: Matias Elo 
Signed-off-by: Maxim Uvarov 


  Commit: e6a635ac73e99a9a7a6b499685a72139e87044ea
  
https://github.com/Linaro/odp/commit/e6a635ac73e99a9a7a6b499685a72139e87044ea
  Author: Matias Elo 
  Date:   2017-03-02 (Thu, 02 Mar 2017)

  Changed paths:
M test/linux-generic/validation/api/pktio/pktio_run_dpdk.sh

  Log Message:
  ---
  linux-gen: dpdk: disable pci devices when running make check

Disable pci devices during DPDK pktio validation test. If the system has
pci devices mapped to DPDK pmd drivers they may overlap with the
test vdev device indices, which will cause the validation test to fail.

Signed-off-by: Matias Elo 
Signed-off-by: Maxim Uvarov 


  Commit: 37db76d04174f90f86c8103e6a1ca9d1e9518098
  
https://github.com/Linaro/odp/commit/37db76d04174f90f86c8103e6a1ca9d1e9518098
  Author: Matias Elo 
  Date:   2017-03-02 (Thu, 02 Mar 2017)

  Changed paths:
M .travis.yml
M DEPENDENCIES
M scripts/build-pktio-dpdk

  Log Message:
  ---
  linux-gen: dpdk: bump target dpdk version to 17.02

Signed-off-by: Matias Elo 
Signed-off-by: Maxim Uvarov 


  Commit: ec8a54c9236925ea97ee154eb70093d6effb1311
  
https://github.com/Linaro/odp/commit/ec8a54c9236925ea97ee154eb70093d6effb1311
  Author: Janne Peltonen 
  Date:   2017-03-10 (Fri, 10 Mar 2017)

  Changed paths:
M platform/linux-generic/Makefile.am

  Log Message:
  ---
  linux-gen: abi: fix include/odp/api/abi symlink creation

Fix the ABI symlink creation that went broken in 3d6cbd2.

Signed-off-by: Janne Peltonen 
Signed-off-by: Maxim Uvarov 


  Commit: 746455fcdf279fcef7ec6a3eb6c5f1b465588554
  
https://github.com/Linaro/odp/commit/746455fcdf279fcef7ec6a3eb6c5f1b465588554
  Author: Petri Savolainen 
  Date:   2017-03-16 (Thu, 16 Mar 2017)

  Changed paths:
M platform/linux-generic/odp_packet.c

  Log Message:
  ---
  linux-gen: packet: make inline table visible

Add visibility markers to make inline offset table visible
applications linking against an installed copy of the library.

Signed-off-by: Petri Savolainen 
Reviewed-by: Bill Fischofer 
Signed-off-by: Maxim Uvarov 


  Commit: b056efea2b416831e4d0ecf6494ee10c8da4b117
  
https://github.com/Linaro/odp/commit/b056efea2b416831e4d0ecf6494ee10c8da4b117
  Author: Matias Elo 
  Date:   2017-03-16 (Thu, 16 Mar 2017)

  Changed paths:
M test/common_plat/performance/odp_bench_packet.c

  Log Message:
  ---
  test: bench_packet: add tests for reference functions

Add microbenchmarks for the new packet reference functions.

Signed-off-by: Matias Elo 
Reviewed-and-tested-by: Bill Fischofer 
Signed-off-by: Maxim Uvarov 


  Commit: 97b7d50af6b7239db03d941e4816f4da98ab9449
  
https://github.com/Linaro/odp/commit/97b7d50af6b7239db03d941e4816f4da98ab9449
  Author: Dmitry Eremin-Solenikov 
  Date:   2017-03-16 (Thu, 16 Mar 2017)

  Changed paths:
M platform/linux-generic/odp_pool.c

  Log Message:
  ---
  linux-generic: pool: don't allocate buffers from invalid pool

Add ODP_ASSERT checking that passed pool is not ODP_POOL_INVALID before
tring to allocate buffers from that pool.

Signed-off-by: Dmitry Eremin-Solenikov 
Reviewed-by: Bill Fischofer 
Signed-off-by: Maxim Uvarov 


  Commit: 7ba232f77c60f707d279478a798f6ea14fe9c143
  
https://github.com/Linaro/odp/commit/7ba232f77c60f707d279478a798f6ea14fe9c143
  Author: Brian Brooks 
  Date:   2017-03-22 (Wed, 22 Mar 2017)

  Changed paths:
M platform/linux-generic/include/odp_ring_internal.h

  Log Message:
  ---
  linux-gen: ring: fix memory ordering in ring dequeue

Acquire ordering is needed to maintain proper release consistency with
the ring en

Re: [lng-odp] [PATCH] Fix memory ordering in ring dequeue

2017-03-22 Thread Brian Brooks
On Wed, Mar 22, 2017 at 10:37 AM, Maxim Uvarov  wrote:
> On 03/22/17 07:54, Brian Brooks wrote:
>> Acquire ordering is needed to maintain proper release consistency with
>> the ring enqueue operation. This issue presented itself as deadlock when
>> running on an ARM-based chip.
>>
>> Signed-off-by: Brian Brooks 
>> ---
>>  platform/linux-generic/include/odp_ring_internal.h | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/platform/linux-generic/include/odp_ring_internal.h 
>> b/platform/linux-generic/include/odp_ring_internal.h
>> index 55fedeb3..44b83c60 100644
>> --- a/platform/linux-generic/include/odp_ring_internal.h
>> +++ b/platform/linux-generic/include/odp_ring_internal.h
>> @@ -57,7 +57,7 @@ static inline uint32_t ring_deq(ring_t *ring, uint32_t 
>> mask)
>>
>>   /* Move reader head. This thread owns data at the new head. */
>>   do {
>> - tail = odp_atomic_load_u32(&ring->w_tail);
>> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>>
>>   if (head == tail)
>>   return RING_EMPTY;
>> @@ -90,7 +90,7 @@ static inline uint32_t ring_deq_multi(ring_t *ring, 
>> uint32_t mask,
>>
>>   /* Move reader head. This thread owns data at the new head. */
>>   do {
>> - tail = odp_atomic_load_u32(&ring->w_tail);
>> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>>
>>   /* Ring is empty */
>>   if (head == tail)
>>
>
>
> Brian, can you please write few words why acq (i.e. barriers) is not
> used in first load and in final store?

Memory ordering on these compiler built-ins can lower to either a
sequence of instructions with an explicit memory barrier instruction
(e.g. a dmb variant on ARMv8) or a single instruction with implied
memory ordering (e.g. ldar (a load instruction with acquire memory
ordering) on ARMv8).

Acquire ordering could be used on the initial load of r_head instead.
An explicit acquire fence could be placed before the do-while loop
too.
It is just a bit more symmetrical to have acquire ordering on the
load of w_tail.

What is needed is an ordering to prevent the load of w_tail (in the
do-while loop) to be reordered before the store of w_tail in the enq
operation... on the same core.

Think of the situation where the thread running on one core does
an enq() followed by a deq().  The final store release in enq() prevents
memory accesses from being reordered to after the store.  But, memory
accesses can still be reordered to before that store.  We need acquire
ordering in deq() to prevent subsequent memory accesses from being
reordered into the enq() operation.

> static inline uint32_t ring_deq_multi(ring_t *ring, uint32_t mask,
>   uint32_t data[], uint32_t num)
> {
> uint32_t head, tail, new_head, i;
>
> head = odp_atomic_load_u32(&ring->r_head);
>
> /* Move reader head. This thread owns data at the new head. */
> do {
> tail = odp_atomic_load_acq_u32(&ring->w_tail);
>
> /* Ring is empty */
> if (head == tail)
> return 0;
>
> /* Try to take all available */
> if ((tail - head) < num)
> num = tail - head;
>
> new_head = head + num;
>
> } while (odp_unlikely(odp_atomic_cas_acq_u32(&ring->r_head, &head,
>   new_head) == 0));
>
> /* Read queue index */
> for (i = 0; i < num; i++)
> data[i] = ring->data[(head + 1 + i) & mask];
>
> /* Wait until other readers have updated the tail */
> while (odp_unlikely(odp_atomic_load_acq_u32(&ring->r_tail) != head))
> odp_cpu_pause();
>
> /* Now update the reader tail */
> odp_atomic_store_rel_u32(&ring->r_tail, new_head);
>
> return num;
> }


Re: [lng-odp] [PATCH] Fix memory ordering in ring dequeue

2017-03-22 Thread Maxim Uvarov
On 03/22/17 18:47, Bill Fischofer wrote:
> On Wed, Mar 22, 2017 at 10:37 AM, Maxim Uvarov  
> wrote:
>> On 03/22/17 07:54, Brian Brooks wrote:
>>> Acquire ordering is needed to maintain proper release consistency with
>>> the ring enqueue operation. This issue presented itself as deadlock when
>>> running on an ARM-based chip.
>>>
>>> Signed-off-by: Brian Brooks 
>>> ---
>>>  platform/linux-generic/include/odp_ring_internal.h | 4 ++--
>>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/platform/linux-generic/include/odp_ring_internal.h 
>>> b/platform/linux-generic/include/odp_ring_internal.h
>>> index 55fedeb3..44b83c60 100644
>>> --- a/platform/linux-generic/include/odp_ring_internal.h
>>> +++ b/platform/linux-generic/include/odp_ring_internal.h
>>> @@ -57,7 +57,7 @@ static inline uint32_t ring_deq(ring_t *ring, uint32_t 
>>> mask)
>>>
>>>   /* Move reader head. This thread owns data at the new head. */
>>>   do {
>>> - tail = odp_atomic_load_u32(&ring->w_tail);
>>> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>>>
>>>   if (head == tail)
>>>   return RING_EMPTY;
>>> @@ -90,7 +90,7 @@ static inline uint32_t ring_deq_multi(ring_t *ring, 
>>> uint32_t mask,
>>>
>>>   /* Move reader head. This thread owns data at the new head. */
>>>   do {
>>> - tail = odp_atomic_load_u32(&ring->w_tail);
>>> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>>>
>>>   /* Ring is empty */
>>>   if (head == tail)
>>>
>>
>>
>> Brian, can you please write few words why acq (i.e. barriers) is not
>> used in first load and in final store?
> 
> acq is not needed for the initial fetch of head here because head is
> updated by cas_acq below, which handles the sync in a self-contained
> manner. The update of tail uses store_rel  as a counterpart to the
> previous load_acq. load_acq and store_rel operate as pairs.
> 

Thank you, Bill.

Merged with short message:
"linux-gen: ring: fix memory ordering in ring dequeue"

Maxim.

>>
>> static inline uint32_t ring_deq_multi(ring_t *ring, uint32_t mask,
>>   uint32_t data[], uint32_t num)
>> {
>> uint32_t head, tail, new_head, i;
>>
>> head = odp_atomic_load_u32(&ring->r_head);
>>
>> /* Move reader head. This thread owns data at the new head. */
>> do {
>> tail = odp_atomic_load_acq_u32(&ring->w_tail);
>>
>> /* Ring is empty */
>> if (head == tail)
>> return 0;
>>
>> /* Try to take all available */
>> if ((tail - head) < num)
>> num = tail - head;
>>
>> new_head = head + num;
>>
>> } while (odp_unlikely(odp_atomic_cas_acq_u32(&ring->r_head, &head,
>>   new_head) == 0));
>>
>> /* Read queue index */
>> for (i = 0; i < num; i++)
>> data[i] = ring->data[(head + 1 + i) & mask];
>>
>> /* Wait until other readers have updated the tail */
>> while (odp_unlikely(odp_atomic_load_acq_u32(&ring->r_tail) != head))
>> odp_cpu_pause();
>>
>> /* Now update the reader tail */
>> odp_atomic_store_rel_u32(&ring->r_tail, new_head);
>>
>> return num;
>> }



[lng-odp] [Linaro/odp] 7ba232: linux-gen: ring: fix memory ordering in ring deque...

2017-03-22 Thread GitHub
  Branch: refs/heads/master
  Home:   https://github.com/Linaro/odp
  Commit: 7ba232f77c60f707d279478a798f6ea14fe9c143
  
https://github.com/Linaro/odp/commit/7ba232f77c60f707d279478a798f6ea14fe9c143
  Author: Brian Brooks 
  Date:   2017-03-22 (Wed, 22 Mar 2017)

  Changed paths:
M platform/linux-generic/include/odp_ring_internal.h

  Log Message:
  ---
  linux-gen: ring: fix memory ordering in ring dequeue

Acquire ordering is needed to maintain proper release consistency with
the ring enqueue operation. This issue presented itself as deadlock when
running on an ARM-based chip.

Signed-off-by: Brian Brooks 
Reviewed-by: Bill Fischofer 
Signed-off-by: Maxim Uvarov 




Re: [lng-odp] [PATCH] Fix memory ordering in ring dequeue

2017-03-22 Thread Bill Fischofer
On Wed, Mar 22, 2017 at 10:37 AM, Maxim Uvarov  wrote:
> On 03/22/17 07:54, Brian Brooks wrote:
>> Acquire ordering is needed to maintain proper release consistency with
>> the ring enqueue operation. This issue presented itself as deadlock when
>> running on an ARM-based chip.
>>
>> Signed-off-by: Brian Brooks 
>> ---
>>  platform/linux-generic/include/odp_ring_internal.h | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/platform/linux-generic/include/odp_ring_internal.h 
>> b/platform/linux-generic/include/odp_ring_internal.h
>> index 55fedeb3..44b83c60 100644
>> --- a/platform/linux-generic/include/odp_ring_internal.h
>> +++ b/platform/linux-generic/include/odp_ring_internal.h
>> @@ -57,7 +57,7 @@ static inline uint32_t ring_deq(ring_t *ring, uint32_t 
>> mask)
>>
>>   /* Move reader head. This thread owns data at the new head. */
>>   do {
>> - tail = odp_atomic_load_u32(&ring->w_tail);
>> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>>
>>   if (head == tail)
>>   return RING_EMPTY;
>> @@ -90,7 +90,7 @@ static inline uint32_t ring_deq_multi(ring_t *ring, 
>> uint32_t mask,
>>
>>   /* Move reader head. This thread owns data at the new head. */
>>   do {
>> - tail = odp_atomic_load_u32(&ring->w_tail);
>> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>>
>>   /* Ring is empty */
>>   if (head == tail)
>>
>
>
> Brian, can you please write few words why acq (i.e. barriers) is not
> used in first load and in final store?

acq is not needed for the initial fetch of head here because head is
updated by cas_acq below, which handles the sync in a self-contained
manner. The update of tail uses store_rel  as a counterpart to the
previous load_acq. load_acq and store_rel operate as pairs.

>
> static inline uint32_t ring_deq_multi(ring_t *ring, uint32_t mask,
>   uint32_t data[], uint32_t num)
> {
> uint32_t head, tail, new_head, i;
>
> head = odp_atomic_load_u32(&ring->r_head);
>
> /* Move reader head. This thread owns data at the new head. */
> do {
> tail = odp_atomic_load_acq_u32(&ring->w_tail);
>
> /* Ring is empty */
> if (head == tail)
> return 0;
>
> /* Try to take all available */
> if ((tail - head) < num)
> num = tail - head;
>
> new_head = head + num;
>
> } while (odp_unlikely(odp_atomic_cas_acq_u32(&ring->r_head, &head,
>   new_head) == 0));
>
> /* Read queue index */
> for (i = 0; i < num; i++)
> data[i] = ring->data[(head + 1 + i) & mask];
>
> /* Wait until other readers have updated the tail */
> while (odp_unlikely(odp_atomic_load_acq_u32(&ring->r_tail) != head))
> odp_cpu_pause();
>
> /* Now update the reader tail */
> odp_atomic_store_rel_u32(&ring->r_tail, new_head);
>
> return num;
> }


Re: [lng-odp] [PATCH] Fix memory ordering in ring dequeue

2017-03-22 Thread Maxim Uvarov
On 03/22/17 07:54, Brian Brooks wrote:
> Acquire ordering is needed to maintain proper release consistency with
> the ring enqueue operation. This issue presented itself as deadlock when
> running on an ARM-based chip.
> 
> Signed-off-by: Brian Brooks 
> ---
>  platform/linux-generic/include/odp_ring_internal.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/platform/linux-generic/include/odp_ring_internal.h 
> b/platform/linux-generic/include/odp_ring_internal.h
> index 55fedeb3..44b83c60 100644
> --- a/platform/linux-generic/include/odp_ring_internal.h
> +++ b/platform/linux-generic/include/odp_ring_internal.h
> @@ -57,7 +57,7 @@ static inline uint32_t ring_deq(ring_t *ring, uint32_t mask)
>  
>   /* Move reader head. This thread owns data at the new head. */
>   do {
> - tail = odp_atomic_load_u32(&ring->w_tail);
> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>  
>   if (head == tail)
>   return RING_EMPTY;
> @@ -90,7 +90,7 @@ static inline uint32_t ring_deq_multi(ring_t *ring, 
> uint32_t mask,
>  
>   /* Move reader head. This thread owns data at the new head. */
>   do {
> - tail = odp_atomic_load_u32(&ring->w_tail);
> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>  
>   /* Ring is empty */
>   if (head == tail)
> 


Brian, can you please write few words why acq (i.e. barriers) is not
used in first load and in final store?

static inline uint32_t ring_deq_multi(ring_t *ring, uint32_t mask,
  uint32_t data[], uint32_t num)
{
uint32_t head, tail, new_head, i;

head = odp_atomic_load_u32(&ring->r_head);

/* Move reader head. This thread owns data at the new head. */
do {
tail = odp_atomic_load_acq_u32(&ring->w_tail);

/* Ring is empty */
if (head == tail)
return 0;

/* Try to take all available */
if ((tail - head) < num)
num = tail - head;

new_head = head + num;

} while (odp_unlikely(odp_atomic_cas_acq_u32(&ring->r_head, &head,
  new_head) == 0));

/* Read queue index */
for (i = 0; i < num; i++)
data[i] = ring->data[(head + 1 + i) & mask];

/* Wait until other readers have updated the tail */
while (odp_unlikely(odp_atomic_load_acq_u32(&ring->r_tail) != head))
odp_cpu_pause();

/* Now update the reader tail */
odp_atomic_store_rel_u32(&ring->r_tail, new_head);

return num;
}


Re: [lng-odp] [PATCH] Fix memory ordering in ring dequeue

2017-03-22 Thread Maxim Uvarov
On 03/22/17 07:54, Brian Brooks wrote:
> Acquire ordering is needed to maintain proper release consistency with
> the ring enqueue operation. This issue presented itself as deadlock when
> running on an ARM-based chip.
> 
> Signed-off-by: Brian Brooks 
> ---
>  platform/linux-generic/include/odp_ring_internal.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/platform/linux-generic/include/odp_ring_internal.h 
> b/platform/linux-generic/include/odp_ring_internal.h
> index 55fedeb3..44b83c60 100644
> --- a/platform/linux-generic/include/odp_ring_internal.h
> +++ b/platform/linux-generic/include/odp_ring_internal.h
> @@ -57,7 +57,7 @@ static inline uint32_t ring_deq(ring_t *ring, uint32_t mask)
>  
>   /* Move reader head. This thread owns data at the new head. */
>   do {
> - tail = odp_atomic_load_u32(&ring->w_tail);
> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>  
>   if (head == tail)
>   return RING_EMPTY;
> @@ -90,7 +90,7 @@ static inline uint32_t ring_deq_multi(ring_t *ring, 
> uint32_t mask,
>  
>   /* Move reader head. This thread owns data at the new head. */
>   do {
> - tail = odp_atomic_load_u32(&ring->w_tail);
> + tail = odp_atomic_load_acq_u32(&ring->w_tail);
>  
>   /* Ring is empty */
>   if (head == tail)
> 


Brian, can you please write few words why acq (i.e. barriers) is not
used in first load and in final store?

static inline uint32_t ring_deq_multi(ring_t *ring, uint32_t mask,
  uint32_t data[], uint32_t num)
{
uint32_t head, tail, new_head, i;

head = odp_atomic_load_u32(&ring->r_head);

/* Move reader head. This thread owns data at the new head. */
do {
tail = odp_atomic_load_acq_u32(&ring->w_tail);

/* Ring is empty */
if (head == tail)
return 0;

/* Try to take all available */
if ((tail - head) < num)
num = tail - head;

new_head = head + num;

} while (odp_unlikely(odp_atomic_cas_acq_u32(&ring->r_head, &head,
  new_head) == 0));

/* Read queue index */
for (i = 0; i < num; i++)
data[i] = ring->data[(head + 1 + i) & mask];

/* Wait until other readers have updated the tail */
while (odp_unlikely(odp_atomic_load_acq_u32(&ring->r_tail) != head))
odp_cpu_pause();

/* Now update the reader tail */
odp_atomic_store_rel_u32(&ring->r_tail, new_head);

return num;
}


[lng-odp] [API-NEXT PATCH 2/4] linux-gen: packet: remove lazy parsing

2017-03-22 Thread Matias Elo
Replace old lazy parsing code with a new packet parsing implementation
which follows the latest API (parsing level is selected using
odp_pktio_config()).

Signed-off-by: Matias Elo 
---
 .../include/odp/api/plat/packet_types.h|   1 -
 .../linux-generic/include/odp_packet_internal.h|  39 +--
 platform/linux-generic/odp_classification.c|   7 +-
 platform/linux-generic/odp_packet.c| 382 -
 platform/linux-generic/odp_packet_flags.c  | 111 +++---
 platform/linux-generic/odp_packet_io.c |   2 +
 platform/linux-generic/pktio/dpdk.c|   3 +-
 platform/linux-generic/pktio/loop.c|   3 +-
 platform/linux-generic/pktio/netmap.c  |   3 +-
 platform/linux-generic/pktio/pcap.c|   3 +-
 platform/linux-generic/pktio/socket.c  |   3 +-
 platform/linux-generic/pktio/socket_mmap.c |   3 +-
 platform/linux-generic/pktio/tap.c |   3 +-
 13 files changed, 217 insertions(+), 346 deletions(-)

diff --git a/platform/linux-generic/include/odp/api/plat/packet_types.h 
b/platform/linux-generic/include/odp/api/plat/packet_types.h
index b8f665d..f4e8501 100644
--- a/platform/linux-generic/include/odp/api/plat/packet_types.h
+++ b/platform/linux-generic/include/odp/api/plat/packet_types.h
@@ -96,7 +96,6 @@ typedef union {
uint64_t all;
 
struct {
-   uint64_t parsed_l2:1; /**< L2 parsed */
uint64_t dst_queue:1; /**< Dst queue present */
 
uint64_t flow_hash:1; /**< Flow hash present */
diff --git a/platform/linux-generic/include/odp_packet_internal.h 
b/platform/linux-generic/include/odp_packet_internal.h
index 0a9f177..d0db700 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -80,18 +80,6 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t),
  "OUTPUT_FLAGS_SIZE_ERROR");
 
 /**
- * Protocol stack layers
- */
-typedef enum {
-   LAYER_NONE = 0,
-   LAYER_L1,
-   LAYER_L2,
-   LAYER_L3,
-   LAYER_L4,
-   LAYER_ALL
-} layer_t;
-
-/**
  * Packet parser metadata
  */
 typedef struct {
@@ -102,14 +90,6 @@ typedef struct {
uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */
uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */
uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also ICMP) */
-
-   uint32_t l3_len;/**< Layer 3 length */
-   uint32_t l4_len;/**< Layer 4 length */
-
-   uint16_t ethtype;   /**< EtherType */
-   uint8_t  ip_proto;  /**< IP protocol */
-   uint8_t  parsed_layers; /**< Highest parsed protocol stack layer */
-
 } packet_parser_t;
 
 /**
@@ -203,16 +183,6 @@ static inline void packet_set_len(odp_packet_hdr_t 
*pkt_hdr, uint32_t len)
pkt_hdr->frame_len = len;
 }
 
-static inline int packet_parse_l2_not_done(packet_parser_t *prs)
-{
-   return !prs->input_flags.parsed_l2;
-}
-
-static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr)
-{
-   return pkt_hdr->p.parsed_layers != LAYER_ALL;
-}
-
 /* Forward declarations */
 int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt);
 
@@ -220,11 +190,9 @@ int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, 
odp_packet_t dstpkt);
 int packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len,
   odp_packet_t pkt[], int max_num);
 
-/* Fill in parser metadata for L2 */
-void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len);
-
 /* Perform packet parse up to a given protocol layer */
-int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer);
+int packet_parse_layer(odp_packet_hdr_t *pkt_hdr,
+  odp_pktio_parser_layer_t layer);
 
 /* Reset parser metadata for a new parse */
 void packet_parse_reset(odp_packet_hdr_t *pkt_hdr);
@@ -264,7 +232,8 @@ static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, 
odp_time_t *ts)
 }
 
 int packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr,
-   uint32_t pkt_len, uint32_t seg_len, layer_t layer);
+   uint32_t pkt_len, uint32_t seg_len,
+   odp_pktio_parser_layer_t layer);
 
 int _odp_cls_parse(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr);
 
diff --git a/platform/linux-generic/odp_classification.c 
b/platform/linux-generic/odp_classification.c
index 5d96b00..7ebc47d 100644
--- a/platform/linux-generic/odp_classification.c
+++ b/platform/linux-generic/odp_classification.c
@@ -790,10 +790,6 @@ static inline cos_t *cls_select_cos(pktio_entry_t *entry,
cls = &entry->s.cls;
default_cos = cls->default_cos;
 
-   /* Check for lazy parse needed */
-   if (packet_parse_not_complete(pkt_hdr))
-   packet_parse_layer(pkt_hdr, LAYER_ALL);
-
/* Return error cos for error packet */
if (pkt_h

[lng-odp] [API-NEXT PATCH 4/4] validation: pktio: add tests for packet parsing

2017-03-22 Thread Matias Elo
Test packet parsing using predefined test packets (byte arrays). Test
packets are looped through tested pktio interfaces to force packet parsing.

Signed-off-by: Matias Elo 
---
 test/common_plat/validation/api/pktio/Makefile.am |   4 +-
 test/common_plat/validation/api/pktio/parser.c| 545 ++
 test/common_plat/validation/api/pktio/parser.h| 180 +++
 test/common_plat/validation/api/pktio/pktio.c |   5 +-
 test/common_plat/validation/api/pktio/pktio.h |   3 +
 5 files changed, 733 insertions(+), 4 deletions(-)
 create mode 100644 test/common_plat/validation/api/pktio/parser.c
 create mode 100644 test/common_plat/validation/api/pktio/parser.h

diff --git a/test/common_plat/validation/api/pktio/Makefile.am 
b/test/common_plat/validation/api/pktio/Makefile.am
index 466d690..c6368fb 100644
--- a/test/common_plat/validation/api/pktio/Makefile.am
+++ b/test/common_plat/validation/api/pktio/Makefile.am
@@ -4,7 +4,7 @@ noinst_LTLIBRARIES = libtestpktio.la
 libtestpktio_la_SOURCES = pktio.c
 
 test_PROGRAMS = pktio_main$(EXEEXT)
-dist_pktio_main_SOURCES = pktio_main.c
+dist_pktio_main_SOURCES = pktio_main.c parser.c
 pktio_main_LDADD = libtestpktio.la $(LIBCUNIT_COMMON) $(LIBODP)
 
-EXTRA_DIST = pktio.h
+EXTRA_DIST = pktio.h parser.h
diff --git a/test/common_plat/validation/api/pktio/parser.c 
b/test/common_plat/validation/api/pktio/parser.c
new file mode 100644
index 000..ad7101d
--- /dev/null
+++ b/test/common_plat/validation/api/pktio/parser.c
@@ -0,0 +1,545 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include 
+#include 
+
+#include 
+
+#include 
+#include "parser.h"
+#include "pktio.h"
+
+#define MAX_NUM_IFACES 2
+#define PKT_POOL_NUM   256
+#define PKT_POOL_BUF_LEN   (2 * 1024)
+
+/**
+ * local container for pktio attributes
+ */
+typedef struct {
+   const char *name;
+   odp_pktio_t hdl;
+   odp_pktout_queue_t pktout;
+   odp_pktin_queue_t pktin;
+} pktio_info_t;
+
+/** Interface names used for testing */
+static const char *iface_name[MAX_NUM_IFACES];
+
+/** Test interfaces */
+pktio_info_t pktios[MAX_NUM_IFACES];
+pktio_info_t *pktio_a;
+pktio_info_t *pktio_b;
+
+/** Number of interfaces being used (1=loopback, 2=pair) */
+static int num_ifaces;
+
+/** While testing real-world interfaces additional time may be needed for
+ *  external network to enable link to pktio interface that just become up.
+ */
+static bool wait_for_network;
+
+/** Parser packet pool */
+odp_pool_t parser_pool = ODP_POOL_INVALID;
+
+static inline void wait_linkup(odp_pktio_t pktio)
+{
+   /* wait 1 second for link up */
+   uint64_t wait_ns = (10 * ODP_TIME_MSEC_IN_NS);
+   int wait_num = 100;
+   int i;
+   int ret = -1;
+
+   for (i = 0; i < wait_num; i++) {
+   ret = odp_pktio_link_status(pktio);
+   if (ret < 0 || ret == 1)
+   break;
+   /* link is down, call status again after delay */
+   odp_time_wait_ns(wait_ns);
+   }
+}
+
+static int pkt_pool_create(void)
+{
+   odp_pool_capability_t capa;
+   odp_pool_param_t params;
+
+   if (odp_pool_capability(&capa) != 0) {
+   printf("Error: unable to query pool capability.\n");
+   return -1;
+   }
+
+   if (capa.pkt.max_num && capa.pkt.max_num < PKT_POOL_NUM) {
+   printf("Error: packet pool size not supported.\n");
+   printf("MAX: %" PRIu32 "\n", capa.pkt.max_num);
+   return -1;
+   } else if (capa.pkt.max_len && capa.pkt.max_len < PKT_POOL_BUF_LEN) {
+   printf("Error: packet length not supported.\n");
+   return -1;
+   } else if (capa.pkt.max_seg_len &&
+  capa.pkt.max_seg_len < PKT_POOL_BUF_LEN) {
+   printf("Error: segment length not supported.\n");
+   return -1;
+   }
+
+   odp_pool_param_init(¶ms);
+   params.pkt.seg_len = PKT_POOL_BUF_LEN;
+   params.pkt.len = PKT_POOL_BUF_LEN;
+   params.pkt.num = PKT_POOL_NUM;
+   params.type= ODP_POOL_PACKET;
+
+   parser_pool = odp_pool_create("pkt_pool_default", ¶ms);
+   if (parser_pool == ODP_POOL_INVALID) {
+   printf("Error: packet pool create failed.\n");
+   return -1;
+   }
+
+   return 0;
+}
+
+static odp_pktio_t create_pktio(int iface_idx, odp_pool_t pool)
+{
+   odp_pktio_t pktio;
+   odp_pktio_config_t config;
+   odp_pktio_param_t pktio_param;
+   const char *iface = iface_name[iface_idx];
+
+   odp_pktio_param_init(&pktio_param);
+   pktio_param.in_mode = ODP_PKTIN_MODE_DIRECT;
+   pktio_param.out_mode = ODP_PKTOUT_MODE_DIRECT;
+
+   pktio = odp_pktio_open(iface, pool, &pktio_param);
+   if (pktio == ODP_PKTIO_INVALID) {
+   printf("Error: failed to open %s\n", iface);
+   return ODP_PK

[lng-odp] [API-NEXT PATCH 1/4] linux-gen: packet: recognize ICMPv6 packets

2017-03-22 Thread Matias Elo
Signed-off-by: Matias Elo 
---
 example/generator/odp_generator.c | 4 ++--
 example/ipsec/odp_ipsec_stream.c  | 6 +++---
 helper/include/odp/helper/ip.h| 3 ++-
 platform/linux-generic/include/protocols/ip.h | 3 ++-
 platform/linux-generic/odp_packet.c   | 5 -
 5 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/example/generator/odp_generator.c 
b/example/generator/odp_generator.c
index 8062d87..1fd4899 100644
--- a/example/generator/odp_generator.c
+++ b/example/generator/odp_generator.c
@@ -267,7 +267,7 @@ static odp_packet_t pack_icmp_pkt(odp_pool_t pool)
ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN;
ip->tot_len = odp_cpu_to_be_16(args->appl.payload + ODPH_ICMPHDR_LEN +
   ODPH_IPV4HDR_LEN);
-   ip->proto = ODPH_IPPROTO_ICMP;
+   ip->proto = ODPH_IPPROTO_ICMPv4;
seq = odp_atomic_fetch_add_u64(&counters.seq, 1) % 0x;
ip->id = odp_cpu_to_be_16(seq);
ip->chksum = 0;
@@ -483,7 +483,7 @@ static void print_pkts(int thr, odp_packet_t pkt_tbl[], 
unsigned len)
}
 
/* icmp */
-   if (ip->proto == ODPH_IPPROTO_ICMP) {
+   if (ip->proto == ODPH_IPPROTO_ICMPv4) {
icmp = (odph_icmphdr_t *)(buf + offset);
/* echo reply */
if (icmp->type == ICMP_ECHOREPLY) {
diff --git a/example/ipsec/odp_ipsec_stream.c b/example/ipsec/odp_ipsec_stream.c
index 428ec04..b9576ae 100644
--- a/example/ipsec/odp_ipsec_stream.c
+++ b/example/ipsec/odp_ipsec_stream.c
@@ -219,7 +219,7 @@ odp_packet_t create_ipv4_packet(stream_db_entry_t *stream,
ip->src_addr = odp_cpu_to_be_32(entry->tun_src_ip);
ip->dst_addr = odp_cpu_to_be_32(entry->tun_dst_ip);
} else {
-   ip->proto = ODPH_IPPROTO_ICMP;
+   ip->proto = ODPH_IPPROTO_ICMPv4;
ip->src_addr = odp_cpu_to_be_32(stream->src_ip);
ip->dst_addr = odp_cpu_to_be_32(stream->dst_ip);
}
@@ -262,7 +262,7 @@ odp_packet_t create_ipv4_packet(stream_db_entry_t *stream,
inner_ip = (odph_ipv4hdr_t *)data;
memset((char *)inner_ip, 0, sizeof(*inner_ip));
inner_ip->ver_ihl = 0x45;
-   inner_ip->proto = ODPH_IPPROTO_ICMP;
+   inner_ip->proto = ODPH_IPPROTO_ICMPv4;
inner_ip->id = odp_cpu_to_be_16(stream->id);
inner_ip->ttl = 64;
inner_ip->tos = 0;
@@ -519,7 +519,7 @@ clear_packet:
icmp = (odph_icmphdr_t *)(inner_ip + 1);
data = (uint8_t *)icmp;
} else {
-   if (ODPH_IPPROTO_ICMP != ip->proto)
+   if (ODPH_IPPROTO_ICMPv4 != ip->proto)
return FALSE;
icmp = (odph_icmphdr_t *)data;
}
diff --git a/helper/include/odp/helper/ip.h b/helper/include/odp/helper/ip.h
index ba6e675..91776fa 100644
--- a/helper/include/odp/helper/ip.h
+++ b/helper/include/odp/helper/ip.h
@@ -205,13 +205,14 @@ typedef struct ODP_PACKED {
  * IP protocol values (IPv4:'proto' or IPv6:'next_hdr')
  * @{*/
 #define ODPH_IPPROTO_HOPOPTS 0x00 /**< IPv6 hop-by-hop options */
-#define ODPH_IPPROTO_ICMP0x01 /**< Internet Control Message Protocol (1) */
+#define ODPH_IPPROTO_ICMPv4  0x01 /**< Internet Control Message Protocol (1) */
 #define ODPH_IPPROTO_TCP 0x06 /**< Transmission Control Protocol (6) */
 #define ODPH_IPPROTO_UDP 0x11 /**< User Datagram Protocol (17) */
 #define ODPH_IPPROTO_ROUTE   0x2B /**< IPv6 Routing header (43) */
 #define ODPH_IPPROTO_FRAG0x2C /**< IPv6 Fragment (44) */
 #define ODPH_IPPROTO_AH  0x33 /**< Authentication Header (51) */
 #define ODPH_IPPROTO_ESP 0x32 /**< Encapsulating Security Payload (50) */
+#define ODPH_IPPROTO_ICMPv6  0x3A /**< Internet Control Message Protocol (58) 
*/
 #define ODPH_IPPROTO_INVALID 0xFF /**< Reserved invalid by IANA */
 
 /**@}*/
diff --git a/platform/linux-generic/include/protocols/ip.h 
b/platform/linux-generic/include/protocols/ip.h
index 20041f1..2b34a75 100644
--- a/platform/linux-generic/include/protocols/ip.h
+++ b/platform/linux-generic/include/protocols/ip.h
@@ -157,13 +157,14 @@ typedef struct ODP_PACKED {
  * IP protocol values (IPv4:'proto' or IPv6:'next_hdr')
  * @{*/
 #define _ODP_IPPROTO_HOPOPTS 0x00 /**< IPv6 hop-by-hop options */
-#define _ODP_IPPROTO_ICMP0x01 /**< Internet Control Message Protocol (1) */
+#define _ODP_IPPROTO_ICMPv4  0x01 /**< Internet Control Message Protocol (1) */
 #define _ODP_IPPROTO_TCP 0x06 /**< Transmission Control Protocol (6) */
 #define _ODP_IPPROTO_UDP 0x11 /**< User Datagram Protocol (17) */
 #define _ODP_IPPROTO_ROUTE   0x2B /**< IPv6 Routing header (43) */
 #define _ODP_IPPROTO_FRAG0x2C /**< IPv6 Fragment (44) */
 #define _ODP_IPPROTO_AH  0x33 /**< Authentication Header (51) */
 #define _ODP_I

[lng-odp] [API-NEXT PATCH 3/4] examples: use odp_pktio_config() to select required packet parsing level

2017-03-22 Thread Matias Elo
Select required packet parsing level when full packet parsing is not
required.

Signed-off-by: Matias Elo 
---
 example/l2fwd_simple/odp_l2fwd_simple.c  | 5 +
 example/l3fwd/odp_l3fwd.c| 7 +++
 example/switch/odp_switch.c  | 5 +
 test/common_plat/performance/odp_l2fwd.c | 7 +++
 test/common_plat/performance/odp_pktio_ordered.c | 5 +
 5 files changed, 29 insertions(+)

diff --git a/example/l2fwd_simple/odp_l2fwd_simple.c 
b/example/l2fwd_simple/odp_l2fwd_simple.c
index b97808f..e638145 100644
--- a/example/l2fwd_simple/odp_l2fwd_simple.c
+++ b/example/l2fwd_simple/odp_l2fwd_simple.c
@@ -41,6 +41,7 @@ static odp_pktio_t create_pktio(const char *name, odp_pool_t 
pool,
odp_pktin_queue_param_t in_queue_param;
odp_pktout_queue_param_t out_queue_param;
odp_pktio_t pktio;
+   odp_pktio_config_t config;
 
odp_pktio_param_init(&pktio_param);
 
@@ -50,6 +51,10 @@ static odp_pktio_t create_pktio(const char *name, odp_pool_t 
pool,
exit(1);
}
 
+   odp_pktio_config_init(&config);
+   config.parser.layer = ODP_PKTIO_PARSER_LAYER_L2;
+   odp_pktio_config(pktio, &config);
+
odp_pktin_queue_param_init(&in_queue_param);
odp_pktout_queue_param_init(&out_queue_param);
 
diff --git a/example/l3fwd/odp_l3fwd.c b/example/l3fwd/odp_l3fwd.c
index ba06972..f579d36 100644
--- a/example/l3fwd/odp_l3fwd.c
+++ b/example/l3fwd/odp_l3fwd.c
@@ -101,6 +101,7 @@ static int create_pktio(const char *name, odp_pool_t pool,
odp_pktio_param_t pktio_param;
odp_pktio_t pktio;
odp_pktio_capability_t capa;
+   odp_pktio_config_t config;
int rc;
 
odp_pktio_param_init(&pktio_param);
@@ -120,6 +121,12 @@ static int create_pktio(const char *name, odp_pool_t pool,
return -1;
}
 
+   odp_pktio_config_init(&config);
+   config.parser.layer = global.cmd_args.error_check ?
+   ODP_PKTIO_PARSER_LAYER_ALL :
+   ODP_PKTIO_PARSER_LAYER_L4;
+   odp_pktio_config(pktio, &config);
+
fwd_pktio->nb_rxq = (int)capa.max_input_queues;
fwd_pktio->nb_txq = (int)capa.max_output_queues;
 
diff --git a/example/switch/odp_switch.c b/example/switch/odp_switch.c
index 561c293..5bec6a0 100644
--- a/example/switch/odp_switch.c
+++ b/example/switch/odp_switch.c
@@ -217,6 +217,7 @@ static int create_pktio(const char *dev, int idx, int 
num_rx, int num_tx,
odp_pktio_t pktio;
odp_pktio_param_t pktio_param;
odp_pktio_capability_t capa;
+   odp_pktio_config_t config;
odp_pktin_queue_param_t pktin_param;
odp_pktout_queue_param_t pktout_param;
odp_pktio_op_mode_t mode_rx;
@@ -238,6 +239,10 @@ static int create_pktio(const char *dev, int idx, int 
num_rx, int num_tx,
return -1;
}
 
+   odp_pktio_config_init(&config);
+   config.parser.layer = ODP_PKTIO_PARSER_LAYER_L2;
+   odp_pktio_config(pktio, &config);
+
odp_pktin_queue_param_init(&pktin_param);
odp_pktout_queue_param_init(&pktout_param);
 
diff --git a/test/common_plat/performance/odp_l2fwd.c 
b/test/common_plat/performance/odp_l2fwd.c
index 8f5c5e1..5962fe2 100644
--- a/test/common_plat/performance/odp_l2fwd.c
+++ b/test/common_plat/performance/odp_l2fwd.c
@@ -596,6 +596,7 @@ static int create_pktio(const char *dev, int idx, int 
num_rx, int num_tx,
odp_pktio_param_t pktio_param;
odp_schedule_sync_t  sync_mode;
odp_pktio_capability_t capa;
+   odp_pktio_config_t config;
odp_pktin_queue_param_t pktin_param;
odp_pktout_queue_param_t pktout_param;
odp_pktio_op_mode_t mode_rx;
@@ -632,6 +633,12 @@ static int create_pktio(const char *dev, int idx, int 
num_rx, int num_tx,
return -1;
}
 
+   odp_pktio_config_init(&config);
+   config.parser.layer = gbl_args->appl.error_check ?
+   ODP_PKTIO_PARSER_LAYER_ALL :
+   ODP_PKTIO_PARSER_LAYER_NONE;
+   odp_pktio_config(pktio, &config);
+
odp_pktin_queue_param_init(&pktin_param);
odp_pktout_queue_param_init(&pktout_param);
 
diff --git a/test/common_plat/performance/odp_pktio_ordered.c 
b/test/common_plat/performance/odp_pktio_ordered.c
index bff4586..4bb0bef 100644
--- a/test/common_plat/performance/odp_pktio_ordered.c
+++ b/test/common_plat/performance/odp_pktio_ordered.c
@@ -586,6 +586,7 @@ static int create_pktio(const char *dev, int idx, int 
num_rx, int num_tx,
odp_pktio_t pktio;
odp_pktio_param_t pktio_param;
odp_pktio_capability_t capa;
+   odp_pktio_config_t config;
odp_pktin_queue_param_t pktin_param;
odp_pktout_queue_param_t pktout_param;
odp_pktio_op_mode_t mode_rx;
@@ -611,6 +612,10 @@ static int create_pktio(const char *dev, int idx, int 
num_rx, int num_tx,
return -1;

Re: [lng-odp] [API-NEXT PATCHv2 01/23] drv: adding compiler hints in the driver interface

2017-03-22 Thread Bill Fischofer
On Wed, Mar 22, 2017 at 9:48 AM, Christophe Milard
 wrote:
> Largely inspired from its north api counterpart, the drv/spec/hint.h
> file is added. Also includes the __constructor__ attributes that many
> driver interface items will need.
>
> Signed-off-by: Christophe Milard 
> ---
>  include/odp/drv/spec/hints.h | 119 
> +++
>  platform/Makefile.inc|   1 +
>  2 files changed, 120 insertions(+)
>  create mode 100644 include/odp/drv/spec/hints.h
>
> diff --git a/include/odp/drv/spec/hints.h b/include/odp/drv/spec/hints.h
> new file mode 100644
> index 000..ddae22e
> --- /dev/null
> +++ b/include/odp/drv/spec/hints.h
> @@ -0,0 +1,119 @@
> +/* Copyright (c) 2017, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier: BSD-3-Clause
> + */
> +
> +/**
> + * @file
> + *
> + * ODPDRV compiler hints
> + */
> +
> +#ifndef ODPDRV_API_HINTS_H_
> +#define ODPDRV_API_HINTS_H_
> +#include 
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/** @addtogroup odpdrv_compiler_optim
> + *  Macros that will give hints to the compiler.
> + *  @{
> + */
> +
> +#ifdef __GNUC__
> +
> +/** Define a function that should be run at early init (constructor)
> + */
> +#define ODPDRV_CONSTRUCTOR __attribute__((__constructor__))
> +
> +/** Define a function that does not return
> + */
> +#define ODPDRV_NORETURN __attribute__((__noreturn__))
> +
> +/** Define a weak symbol
> + * This is primarily useful in defining library functions that can be
> + * overridden in user code.
> + */
> +#define ODPDRV_WEAK_SYMBOL __attribute__((__weak__))
> +
> +/**
> + * Hot code section
> + */
> +#define ODPDRV_HOT_CODE__attribute__((__hot__))
> +
> +/**
> + * Cold code section
> + */
> +#define ODPDRV_COLD_CODE   __attribute__((__cold__))
> +
> +/**
> + * Printf format attribute
> + */
> +#define ODPDRV_PRINTF_FORMAT(x, y) __attribute__((format(printf, (x), (y
> +
> +/**
> + * Indicate deprecated variables, functions or types
> + */
> +#define ODPDRV_DEPRECATED __attribute__((__deprecated__))
> +
> +/**
> + * Intentionally unused variables of functions
> + */
> +#define ODPDRV_UNUSED __attribute__((__unused__))
> +
> +/**
> + * Branch likely taken
> + */
> +#define odpdrv_likely(x)   __builtin_expect((x), 1)
> +
> +/**
> + * Branch unlikely taken
> + */
> +#define odpdrv_unlikely(x) __builtin_expect((x), 0)
> +
> +/*
> + * __builtin_prefetch (const void *addr, rw, locality)
> + *
> + * rw 0..1   (0: read, 1: write)
> + * locality 0..3 (0: don't leave to cache, 3: leave on all cache levels)
> + */
> +
> +/**
> + * Cache prefetch address
> + */
> +#define odpdrv_prefetch(x) __builtin_prefetch((x), 0, 3)
> +
> +/**
> + * Cache prefetch address for storing
> + */
> +#define odpdrv_prefetch_store(x)   __builtin_prefetch((x), 1, 3)
> +
> +#else
> +
> +#define ODPDRV_CONSTRUCTOR
> +#define ODPDRV_NORETURN
> +#define ODPDRV_WEAK_SYMBOL
> +#define ODPDRV_HOT_CODE
> +#define ODPDRV_COLD_CODE
> +#define ODPDRV_DEPRECATED
> +#define ODPDRV_UNUSED
> +#define odpdrv_likely(x)
> +#define odpdrv_unlikely(x)

These have to be defined as:
#define odpdrv_likely(x) (x)
#define odpdrv_unlikely(x) (x)

> +#define odpdrv_prefetch(x)
> +#define odpdrv_prefetch_store(x)
> +
> +#endif
> +
> +/**
> + * @}
> + */
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#include 
> +#endif
> diff --git a/platform/Makefile.inc b/platform/Makefile.inc
> index 874cf88..e439e3c 100644
> --- a/platform/Makefile.inc
> +++ b/platform/Makefile.inc
> @@ -69,6 +69,7 @@ odpdrvspecinclude_HEADERS = \
>   $(top_srcdir)/include/odp/drv/spec/byteorder.h \
>   $(top_srcdir)/include/odp/drv/spec/compiler.h \
>   $(top_srcdir)/include/odp/drv/spec/driver.h \
> + $(top_srcdir)/include/odp/drv/spec/hints.h \
>   $(top_srcdir)/include/odp/drv/spec/shm.h \
>   $(top_srcdir)/include/odp/drv/spec/spinlock.h \
>   $(top_srcdir)/include/odp/drv/spec/std_types.h \
> --
> 2.7.4
>


[lng-odp] [API-NEXT PATCHv2 23/23] test: drv: test for setting and retrieving driver's data

2017-03-22 Thread Christophe Milard
trivial tests for function odpdrv_device_set_data() and
odpdrv_device_get_data().

Signed-off-by: Christophe Milard 
---
 test/common_plat/validation/drv/drvdriver/drvdriver_driver.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/test/common_plat/validation/drv/drvdriver/drvdriver_driver.c 
b/test/common_plat/validation/drv/drvdriver/drvdriver_driver.c
index d90aa56..edcb0f4 100644
--- a/test/common_plat/validation/drv/drvdriver/drvdriver_driver.c
+++ b/test/common_plat/validation/drv/drvdriver/drvdriver_driver.c
@@ -380,6 +380,8 @@ static int driver1_probe(odpdrv_device_t dev, 
odpdrv_devio_t devio, int idx)
if (dev == E1_devs[i]) {
driver1_probed_index |= (1 << i);
dev_found = 1;
+   /* just set dev index as driver data */
+   odpdrv_device_set_data(dev, (void *)(uintptr_t)i);
}
}
CU_ASSERT(dev_found);
@@ -430,6 +432,7 @@ static int driver1_unbind(odpdrv_device_t dev,
  void (*callback)(odpdrv_device_t dev),
  uint32_t flags)
 {
+   CU_ASSERT(E1_devs[(uintptr_t)odpdrv_device_get_data(dev)] == dev);
CU_ASSERT(dev != ODPDRV_DEVICE_INVALID);
CU_ASSERT(flags == ODPDRV_DRV_UNBIND_IMMEDIATE);
callback(dev);
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 21/23] drv: driver: adding functions to attach driver's data to the device

2017-03-22 Thread Christophe Milard
Driver will need to attach their data to devices when bound.
The patch introduce a data setter and a data getter function to do so.

Signed-off-by: Christophe Milard 
---
 include/odp/drv/spec/driver.h | 21 +
 1 file changed, 21 insertions(+)

diff --git a/include/odp/drv/spec/driver.h b/include/odp/drv/spec/driver.h
index ad2b8db..224baf4 100644
--- a/include/odp/drv/spec/driver.h
+++ b/include/odp/drv/spec/driver.h
@@ -450,6 +450,27 @@ odpdrv_devio_t odpdrv_devio_register(odpdrv_devio_param_t 
*param);
 odpdrv_driver_t odpdrv_driver_register(odpdrv_driver_param_t *param);
 
 /**
+* Sets the device driver data, i.e. the driver data which should be attached to
+* the device.
+* After a driver is bound to a device, this driver will need to keep
+* data attached to this device. This data is, of course, driver dependent.
+*
+* @param dev: the device to which data should be attached.
+* @param data Pointer to whatever thre driver want to keep attached to the
+* device
+*/
+void odpdrv_device_set_data(odpdrv_device_t dev, void *data);
+
+/**
+* Gets the device driver data, i.e. the driver data which should be attached to
+* the device.
+* Retrieve the pointer which was set with odpdrv_device_set_data()
+* @param dev: the device from which the driver data should be retrieved.
+* @return the driver data pointer (as set by odpdrv_device_set_data()) or NULL.
+*/
+void *odpdrv_device_get_data(odpdrv_device_t dev);
+
+/**
 * Print (ODP_DBG) the driver interface status (debug).
 *
 * @return 0 on success, less than zero on error (inconsistency detected)
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 22/23] linux-gen: adding functions to attach driver's data to the device

2017-03-22 Thread Christophe Milard
Implementation of the functions to set/retrieve driver's data to/from
a bound device.

Signed-off-by: Christophe Milard 
---
 platform/linux-generic/drv_driver.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index ea92457..70bf318 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -70,6 +70,7 @@ struct _odpdrv_device_s {
odpdrv_device_param_t param;
_odpdrv_driver_t *driver; /* driver for the device (if bound), or NULL*/
_odpdrv_devio_t *devio;   /* devio used for device (if bound), or NULL*/
+   void *driver_data;/* anything that the driver need to attach. */
void (*enumr_destroy_callback)(void *enum_dev);/*dev destroy callback */
struct _odpdrv_device_s *next;
 } _odpdrv_device_s;
@@ -395,6 +396,7 @@ odpdrv_device_t odpdrv_device_create(odpdrv_device_param_t 
*param)
dev->enumr_destroy_callback = NULL;
dev->driver = NULL;
dev->devio = NULL;
+   dev->driver_data = NULL;
dev_list_write_lock();
dev->next = device_lst.head;
device_lst.head = dev;
@@ -852,6 +854,22 @@ void _odpdrv_driver_probe_drv_items(void)
probe_all();
 }
 
+void odpdrv_device_set_data(odpdrv_device_t dev, void *data)
+{
+   _odpdrv_device_t *_dev;
+
+   _dev = get_device(dev);
+   _dev->driver_data = data;
+}
+
+void *odpdrv_device_get_data(odpdrv_device_t dev)
+{
+   _odpdrv_device_t *_dev;
+
+   _dev = get_device(dev);
+   return _dev->driver_data;
+}
+
 int odpdrv_print_all(void)
 {
_odpdrv_enumr_class_t *enumr_c;
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 14/23] drv: driver: adding a probe and remove callback for devio

2017-03-22 Thread Christophe Milard
Needed to delete the resources needed for the devio. That is possibly
the memory allocated for its "ops" part if it was allocated. May be NULL
if nothing needs to be done at devio deletion time.

Signed-off-by: Christophe Milard 
---
 include/odp/drv/spec/driver.h | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/include/odp/drv/spec/driver.h b/include/odp/drv/spec/driver.h
index e861396..f89c282 100644
--- a/include/odp/drv/spec/driver.h
+++ b/include/odp/drv/spec/driver.h
@@ -269,6 +269,24 @@ struct odpdrv_devio_param_t {
char enumr_api_name[ODPDRV_NAME_SIZE];
uint32_t enumr_api_version; /**<< required enumerator API version */
 
+   /** Probe function:
+* Tell whether this devio can handle the given device.
+* The devio is hence given a chance to reject a given device for
+* any reason. No binding occurs here. binding occurs when the
+* driver is probed.
+* returns 0 if this devio can handle the given device, or a negative
+* value if not.
+* If left to NULL, a 0 returned value is assumed
+*/
+   int (*probe)(odpdrv_device_t dev);
+
+   /** Remove function:
+* Should destroy the memory allocated for ops and anything else
+* under it, or any resource for this devio.
+* Returns 0 on success or a negative value on error.
+*/
+   int (*remove)(void);
+
/** Ops
 * Pointer to a devio ops structure (specific to each devio)
 */
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 13/23] test: drv: device creation and destruction

2017-03-22 Thread Christophe Milard
Testing that devices can be created and removed from ODP.

Signed-off-by: Christophe Milard 
---
 .../validation/drv/drvdriver/.gitignore|   1 +
 .../validation/drv/drvdriver/Makefile.am   |  11 ++
 .../validation/drv/drvdriver/drvdriver_device.c| 218 +
 .../validation/drv/drvdriver/drvdriver_device.h|  24 +++
 .../drv/drvdriver/drvdriver_device_main.c  |  12 ++
 test/linux-generic/Makefile.am |   1 +
 6 files changed, 267 insertions(+)
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_device.c
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_device.h
 create mode 100644 
test/common_plat/validation/drv/drvdriver/drvdriver_device_main.c

diff --git a/test/common_plat/validation/drv/drvdriver/.gitignore 
b/test/common_plat/validation/drv/drvdriver/.gitignore
index a842448..97b4312 100644
--- a/test/common_plat/validation/drv/drvdriver/.gitignore
+++ b/test/common_plat/validation/drv/drvdriver/.gitignore
@@ -1,2 +1,3 @@
 drvdriver_enumr_class_main
 drvdriver_enumr_main
+drvdriver_device_main
diff --git a/test/common_plat/validation/drv/drvdriver/Makefile.am 
b/test/common_plat/validation/drv/drvdriver/Makefile.am
index 3476c50..544586c 100644
--- a/test/common_plat/validation/drv/drvdriver/Makefile.am
+++ b/test/common_plat/validation/drv/drvdriver/Makefile.am
@@ -25,3 +25,14 @@ drvdriver_enumr_main_LDADD = libtestdrvdriverenumr.la \
   $(LIBCUNIT_COMMON) $(LIBODP)
 
 EXTRA_DIST += drvdriver_enumr.h
+
+#tests for device creation:
+noinst_LTLIBRARIES += libtestdrvdriverdevice.la
+libtestdrvdriverdevice_la_SOURCES = drvdriver_device.c
+
+test_PROGRAMS += drvdriver_device_main$(EXEEXT)
+dist_drvdriver_device_main_SOURCES = drvdriver_device_main.c
+drvdriver_device_main_LDADD = libtestdrvdriverdevice.la \
+  $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST += drvdriver_device.h
diff --git a/test/common_plat/validation/drv/drvdriver/drvdriver_device.c 
b/test/common_plat/validation/drv/drvdriver/drvdriver_device.c
new file mode 100644
index 000..d010026
--- /dev/null
+++ b/test/common_plat/validation/drv/drvdriver/drvdriver_device.c
@@ -0,0 +1,218 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include 
+#include 
+#include 
+#include "drvdriver_device.h"
+#include 
+
+static odp_instance_t odp_instance;
+static odpdrv_enumr_class_t enumr_class1;
+static odpdrv_enumr_t enumr1;
+
+typedef struct dev_enumr_data_t { /* enumerator data for registered devices */
+   odpdrv_shm_tshm_handle;
+   int device_number;
+} dev_enumr_data_t;
+
+#define NB_DEVICES 5
+
+/* forward declaration */
+static int enumr1_probe(void);
+static int enumr1_remove(void);
+static int enumr_class1_probe(void);
+static int enumr_class1_remove(void);
+
+/* because many things to be checked are performed during ODP initialisation,
+ * the initialisation functions have to be a part of the test
+ */
+static int tests_global_init(void)
+{
+   if (0 != odp_init_global(&odp_instance, NULL, NULL)) {
+   fprintf(stderr, "error: odp_init_global() failed.\n");
+   return -1;
+   }
+   if (0 != odp_init_local(odp_instance, ODP_THREAD_CONTROL)) {
+   fprintf(stderr, "error: odp_init_local() failed.\n");
+   return -1;
+   }
+
+   return 0;
+}
+
+static int tests_global_term(void)
+{
+   if (0 != odp_term_local()) {
+   fprintf(stderr, "error: odp_term_local() failed.\n");
+   return -1;
+   }
+
+   if (0 != odp_term_global(odp_instance)) {
+   fprintf(stderr, "error: odp_term_global() failed.\n");
+   return -1;
+   }
+
+   return 0;
+}
+
+/*enumerator register functions */
+static odpdrv_enumr_t enumr1_register(void)
+{
+   odpdrv_enumr_param_t param = {
+   .enumr_class = enumr_class1,
+   .api_name = "Enumerator_interface_1",
+   .api_version = 1,
+   .probe = enumr1_probe,
+   .remove = enumr1_remove,
+   .register_notifier = NULL
+   };
+
+   enumr1 = odpdrv_enumr_register(¶m);
+   return enumr1;
+}
+
+/*enumerator probe functions, just making sure they have been run: */
+static int enumr1_probe(void)
+{
+   int dev;
+   odpdrv_shm_t shm;
+   dev_enumr_data_t *dev_data;
+
+   odpdrv_device_param_t param = {
+   .enumerator = enumr1,
+   .address = "00:00:0X",
+   .enum_dev = NULL
+   };
+
+   /* create 5 devices: */
+   for (dev = 0; dev < NB_DEVICES; dev++) {
+   shm = odpdrv_shm_reserve(NULL, sizeof(dev_enumr_data_t),
+0, ODPDRV_SHM_SINGLE_VA);
+   CU_ASSERT(ODPDRV_SHM_INVALID != shm);
+   dev_data = odpdrv_shm_a

[lng-odp] [API-NEXT PATCHv2 20/23] test: drv: driver registration and probing

2017-03-22 Thread Christophe Milard
Register driver, devios, enumerators, create devices, and check
that probing occurs correctely.

Signed-off-by: Christophe Milard 
---
 .../validation/drv/drvdriver/.gitignore|   1 +
 .../validation/drv/drvdriver/Makefile.am   |  11 +
 .../validation/drv/drvdriver/drvdriver_driver.c| 515 +
 .../validation/drv/drvdriver/drvdriver_driver.h|  24 +
 .../drv/drvdriver/drvdriver_driver_main.c  |  12 +
 test/linux-generic/Makefile.am |   1 +
 6 files changed, 564 insertions(+)
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_driver.c
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_driver.h
 create mode 100644 
test/common_plat/validation/drv/drvdriver/drvdriver_driver_main.c

diff --git a/test/common_plat/validation/drv/drvdriver/.gitignore 
b/test/common_plat/validation/drv/drvdriver/.gitignore
index 829c8b4..76bb6ba 100644
--- a/test/common_plat/validation/drv/drvdriver/.gitignore
+++ b/test/common_plat/validation/drv/drvdriver/.gitignore
@@ -2,3 +2,4 @@ drvdriver_enumr_class_main
 drvdriver_enumr_main
 drvdriver_device_main
 drvdriver_devio_main
+drvdriver_driver_main
diff --git a/test/common_plat/validation/drv/drvdriver/Makefile.am 
b/test/common_plat/validation/drv/drvdriver/Makefile.am
index 8e695ba..88bd828 100644
--- a/test/common_plat/validation/drv/drvdriver/Makefile.am
+++ b/test/common_plat/validation/drv/drvdriver/Makefile.am
@@ -47,3 +47,14 @@ drvdriver_devio_main_LDADD = libtestdrvdriverdevio.la \
   $(LIBCUNIT_COMMON) $(LIBODP)
 
 EXTRA_DIST += drvdriver_devio.h
+
+#tests for driver registration and probing:
+noinst_LTLIBRARIES += libtestdrvdriverdriver.la
+libtestdrvdriverdriver_la_SOURCES = drvdriver_driver.c
+
+test_PROGRAMS += drvdriver_driver_main$(EXEEXT)
+dist_drvdriver_driver_main_SOURCES = drvdriver_driver_main.c
+drvdriver_driver_main_LDADD = libtestdrvdriverdriver.la \
+  $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST += drvdriver_driver.h
diff --git a/test/common_plat/validation/drv/drvdriver/drvdriver_driver.c 
b/test/common_plat/validation/drv/drvdriver/drvdriver_driver.c
new file mode 100644
index 000..d90aa56
--- /dev/null
+++ b/test/common_plat/validation/drv/drvdriver/drvdriver_driver.c
@@ -0,0 +1,515 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* This file is a bit long as it tries to simulate the presence of 2
+ * enumerator classes, 2 enumerators, and 3 drivers in one go to
+ * see how things are handled by the driver framework.
+ * The following is done:
+ * - create 2 enumerator classes,
+ * - each with its own enumerator providing interfaces: E1 and E2.
+ * - E1 and E2 create 4 devices each.
+ * - the following devio are created:
+ *   devio1 enabling device handling from DRVIF-1 to E1
+ *   devio2 enabling device handling from DRVIF-2 to E2
+ *   devio3 enabling device handling from DRVIF-3 to E2
+ *   devio4 enabling device handling from DRVIF-3 to E3 (does not exist)
+ *   devio5 enabling device handling from DRVIF-4 to E3 (does not exist)
+ *
+ * -then the following driver are created:
+ *  driver1, requiring devio DRVIF-1
+ *  driver2, requiring devio DRVIF-2 (preferred) and DRVIF-3
+ *  driver3, requiring devio DRVIF-4
+ *
+ * The test amkes sure that:
+ * driver 1 is probed (and accepts) the 4 devices of E1 with devio1
+ * driver 2 is probed (and rejects) the 4 devices of E2 with devio2 and devio4
+ * driver3 is never probed.
+ */
+
+#include 
+#include 
+#include 
+#include "drvdriver_driver.h"
+#include 
+
+static odp_instance_t odp_instance;
+static odpdrv_enumr_class_t enumr_class1;
+static odpdrv_enumr_class_t enumr_class2;
+static odpdrv_enumr_t enumr1;
+static odpdrv_enumr_t enumr2;
+#define NB_DEVICES 4
+static odpdrv_device_t E1_devs[NB_DEVICES];
+static odpdrv_device_t E2_devs[NB_DEVICES];
+static odpdrv_devio_t devio1;
+static odpdrv_devio_t devio2;
+static odpdrv_devio_t devio3;
+static odpdrv_devio_t devio4;
+static odpdrv_devio_t devio5;
+static odpdrv_driver_t driver1;
+static odpdrv_driver_t driver2;
+static odpdrv_driver_t driver3;
+
+static int driver1_probed_index;
+static int driver2_probed_index;
+
+/* forward declaration */
+static int enumr1_probe(void);
+static int enumr2_probe(void);
+static int enumr1_remove(void);
+static int enumr2_remove(void);
+static int enumr_class1_probe(void);
+static int enumr_class2_probe(void);
+static int driver1_probe(odpdrv_device_t dev, odpdrv_devio_t devio, int idx);
+static int driver2_probe(odpdrv_device_t dev, odpdrv_devio_t devio, int idx);
+static int driver3_probe(odpdrv_device_t dev, odpdrv_devio_t devio, int idx);
+static int driver1_unbind(odpdrv_device_t dev,
+ void (*callback)(odpdrv_device_t dev),
+ uint32_t flags);
+static int driver2_unbind(odpdrv_device_t dev,
+  

[lng-odp] [API-NEXT PATCHv2 19/23] linux-gen: driver registration and probing

2017-03-22 Thread Christophe Milard
Driver registration and probing is implemented for linux-gen ODP.

Signed-off-by: Christophe Milard 
---
 platform/linux-generic/drv_driver.c | 349 ++--
 1 file changed, 336 insertions(+), 13 deletions(-)

diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index 873ec3c..ea92457 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -29,6 +30,11 @@ typedef struct _odpdrv_enumr_class_s _odpdrv_enumr_class_t;
 typedef struct _odpdrv_enumr_s _odpdrv_enumr_t;
 typedef struct _odpdrv_device_s _odpdrv_device_t;
 typedef struct _odpdrv_devio_s _odpdrv_devio_t;
+typedef struct _odpdrv_driver_s _odpdrv_driver_t;
+
+static int unbind_device_driver(_odpdrv_device_t *dev,
+   void (*callback)(odpdrv_device_t odpdrv_dev),
+   int immediate);
 
 /* an enumerator class (list element) */
 struct _odpdrv_enumr_class_s {
@@ -62,6 +68,8 @@ static struct _odpdrv_enumr_lst_t enumr_lst;
 /* a device (list element) */
 struct _odpdrv_device_s {
odpdrv_device_param_t param;
+   _odpdrv_driver_t *driver; /* driver for the device (if bound), or NULL*/
+   _odpdrv_devio_t *devio;   /* devio used for device (if bound), or NULL*/
void (*enumr_destroy_callback)(void *enum_dev);/*dev destroy callback */
struct _odpdrv_device_s *next;
 } _odpdrv_device_s;
@@ -87,6 +95,21 @@ typedef struct _odpdrv_devio_lst_t {
 } _odpdrv_devio_lst_t;
 static struct _odpdrv_devio_lst_t devio_lst;
 
+/* a driver (list element) */
+struct _odpdrv_driver_s {
+   odpdrv_driver_param_t param;
+   _odp_ishm_pool_t *pool;
+   odp_ticketlock_t probelock; /* to avoid concurrent probe on same drv*/
+   struct _odpdrv_driver_s *next;
+};
+
+/* the driver list: */
+typedef struct _odpdrv_driver_lst_t {
+   odp_rwlock_recursive_t lock;
+   _odpdrv_driver_t *head;
+} _odpdrv_driver_lst_t;
+static struct _odpdrv_driver_lst_t driver_lst;
+
 /* some driver elements (such as enumeraor classes, drivers, devio) may
  * register before init_global and init_local complete. Mutex will fail
  * in this cases but should be used later on.
@@ -188,6 +211,30 @@ static void devio_list_write_unlock(void)
odp_rwlock_recursive_write_unlock(&devio_lst.lock);
 }
 
+static void driver_list_read_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_lock(&driver_lst.lock);
+}
+
+static void driver_list_read_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_unlock(&driver_lst.lock);
+}
+
+static void driver_list_write_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_lock(&driver_lst.lock);
+}
+
+static void driver_list_write_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_unlock(&driver_lst.lock);
+}
+
 /* some functions to get internal pointers from handles... */
 static inline _odpdrv_enumr_class_t *get_enumr_class(odpdrv_enumr_class_t 
class)
 {
@@ -346,6 +393,8 @@ odpdrv_device_t odpdrv_device_create(odpdrv_device_param_t 
*param)
/* save and set dev init parameters and insert new device in list */
dev->param = *param;
dev->enumr_destroy_callback = NULL;
+   dev->driver = NULL;
+   dev->devio = NULL;
dev_list_write_lock();
dev->next = device_lst.head;
device_lst.head = dev;
@@ -399,19 +448,17 @@ int odpdrv_device_destroy(odpdrv_device_t dev,
 */
target->enumr_destroy_callback = callback;
 
-   /* TODO: if a driver is bound to the device, unbind it!
-* passing the flag andf device_destroy_terminate() as a callback */
-
-   /* no driver is handling this device, or no callback was
-* provided: continue removing the device: */
-   device_destroy_terminate(dev);
+   /* unbind the driver from the device (if bound).
+* The callback is always called. */
+   unbind_device_driver(target,
+device_destroy_terminate,
+(flags & ODPDRV_DEV_DESTROY_IMMEDIATE));
 
return 0;
 }
 
 /* This function is called as a callback from the driver, when unbindind
- * a device, or directely from odpdrv_device_destroy() if no driver
- * was bound to the device.
+ * a device drom odpdrv_device_destroy()
  * just call the enumerator callback to cleanup the enumerator part
  * and free device memory */
 static void device_destroy_terminate(odpdrv_device_t drv_device)
@@ -532,10 +579,239 @@ odpdrv_devio_t 
odpdrv_devio_register(odpdrv_devio_param_t *param)
 
 odpdrv_driver_t odpdrv_driver_register(odpdrv_driver_param_t *param)
 {
-   ODP_ERR("NOT Supported yet! Driver %s Registration!\n.",
-   param->name);
+   _odpd

[lng-odp] [API-NEXT PATCHv2 18/23] drv: complement parameters to the driver probe() function

2017-03-22 Thread Christophe Milard
Of course, when probing a driver, the latter should be given the devio
handle to be used. This is what this patch adds. It also adds the index
of the devio, hence telling the driver which of the possible
ODPDRV_MAX_DEVIOS devios was selected, as this is going to be the first
thing the driver needs to know.

Signed-off-by: Christophe Milard 
---
 include/odp/drv/spec/driver.h | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/odp/drv/spec/driver.h b/include/odp/drv/spec/driver.h
index 394aa92..ad2b8db 100644
--- a/include/odp/drv/spec/driver.h
+++ b/include/odp/drv/spec/driver.h
@@ -314,9 +314,12 @@ struct odpdrv_driver_param_t {
 
/** Probe function:
 * Called by ODP to see if the driver can drive a given device
-*
+* -dev the device to be probed
+* -devio is the devio to be used.
+* -devio_idx actually tells which devio was selected: it is the
+* index in the devios array above.
 */
-   int (*probe)(odpdrv_device_t *dev);
+   int (*probe)(odpdrv_device_t dev, odpdrv_devio_t devio, int devio_idx);
 
/** unbind function:
 * Only called with devices whose probe() returned true
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 17/23] drv: adding driver remove function

2017-03-22 Thread Christophe Milard
The remove function, as for other driver items (such as enumerators...) is
called before the driver is to be removed, i.e. after all devices have been
been unbound from the driver. remove() should release any resource held
by the driver.

Signed-off-by: Christophe Milard 
---
 include/odp/drv/spec/driver.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/include/odp/drv/spec/driver.h b/include/odp/drv/spec/driver.h
index f89c282..394aa92 100644
--- a/include/odp/drv/spec/driver.h
+++ b/include/odp/drv/spec/driver.h
@@ -336,6 +336,14 @@ struct odpdrv_driver_param_t {
int (*unbind)(odpdrv_device_t dev,
  void (*callback)(odpdrv_device_t dev),
  uint32_t flags);
+
+   /** remove function:
+* remove any resource taken by the driver. Called when the driver
+* itself is to be removed, i.e. after all devices are unbound
+* Can be set to NULL if the driver has nothing to release.
+*
+*/
+   int (*remove)(void);
 };
 
 /** The callback function must be called mmediately by the current ODP thread 
*/
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 16/23] test: drv: devio creation and destruction

2017-03-22 Thread Christophe Milard
Testing that devios can be registered and removed in/from ODP.

Signed-off-by: Christophe Milard 
---
 .../validation/drv/drvdriver/.gitignore|   1 +
 .../validation/drv/drvdriver/Makefile.am   |  11 ++
 .../validation/drv/drvdriver/drvdriver_devio.c | 209 +
 .../validation/drv/drvdriver/drvdriver_devio.h |  24 +++
 .../drv/drvdriver/drvdriver_devio_main.c   |  12 ++
 test/linux-generic/Makefile.am |   1 +
 6 files changed, 258 insertions(+)
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_devio.c
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_devio.h
 create mode 100644 
test/common_plat/validation/drv/drvdriver/drvdriver_devio_main.c

diff --git a/test/common_plat/validation/drv/drvdriver/.gitignore 
b/test/common_plat/validation/drv/drvdriver/.gitignore
index 97b4312..829c8b4 100644
--- a/test/common_plat/validation/drv/drvdriver/.gitignore
+++ b/test/common_plat/validation/drv/drvdriver/.gitignore
@@ -1,3 +1,4 @@
 drvdriver_enumr_class_main
 drvdriver_enumr_main
 drvdriver_device_main
+drvdriver_devio_main
diff --git a/test/common_plat/validation/drv/drvdriver/Makefile.am 
b/test/common_plat/validation/drv/drvdriver/Makefile.am
index 544586c..8e695ba 100644
--- a/test/common_plat/validation/drv/drvdriver/Makefile.am
+++ b/test/common_plat/validation/drv/drvdriver/Makefile.am
@@ -36,3 +36,14 @@ drvdriver_device_main_LDADD = libtestdrvdriverdevice.la \
   $(LIBCUNIT_COMMON) $(LIBODP)
 
 EXTRA_DIST += drvdriver_device.h
+
+#tests for devio creation:
+noinst_LTLIBRARIES += libtestdrvdriverdevio.la
+libtestdrvdriverdevio_la_SOURCES = drvdriver_devio.c
+
+test_PROGRAMS += drvdriver_devio_main$(EXEEXT)
+dist_drvdriver_devio_main_SOURCES = drvdriver_devio_main.c
+drvdriver_devio_main_LDADD = libtestdrvdriverdevio.la \
+  $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST += drvdriver_devio.h
diff --git a/test/common_plat/validation/drv/drvdriver/drvdriver_devio.c 
b/test/common_plat/validation/drv/drvdriver/drvdriver_devio.c
new file mode 100644
index 000..cf7c7c9
--- /dev/null
+++ b/test/common_plat/validation/drv/drvdriver/drvdriver_devio.c
@@ -0,0 +1,209 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include 
+#include 
+#include 
+#include "drvdriver_devio.h"
+#include 
+
+static odp_instance_t odp_instance;
+
+static int devio1_removed;
+static int devio2_removed;
+static int devio3_removed;
+static int devio4_removed;
+
+static int devio1_remove(void);
+static int devio2_remove(void);
+static int devio3_remove(void);
+
+/* because many things to be checked are performed during ODP initialisation,
+ * the initialisation functions have to be a part of the test
+ */
+static int tests_global_init(void)
+{
+   if (0 != odp_init_global(&odp_instance, NULL, NULL)) {
+   fprintf(stderr, "error: odp_init_global() failed.\n");
+   return -1;
+   }
+   if (0 != odp_init_local(odp_instance, ODP_THREAD_CONTROL)) {
+   fprintf(stderr, "error: odp_init_local() failed.\n");
+   return -1;
+   }
+
+   return 0;
+}
+
+static int tests_global_term(void)
+{
+   if (0 != odp_term_local()) {
+   fprintf(stderr, "error: odp_term_local() failed.\n");
+   return -1;
+   }
+
+   if (0 != odp_term_global(odp_instance)) {
+   fprintf(stderr, "error: odp_term_global() failed.\n");
+   return -1;
+   }
+
+   return 0;
+}
+
+/*devio register functions, all "statically linked"
+ *(i.e. directely run at start), due to the fact that platorm independent
+ * shared lib loading in autotools is a mess */
+static void ODPDRV_CONSTRUCTOR devio1_register(void)
+{
+   odpdrv_devio_param_t param = {
+   .api_name = "devio_api_1",
+   .api_version = 1,
+   .enumr_api_name = "Enumerator_interface_1",
+   .enumr_api_version = 1,
+   .remove = devio1_remove,
+   .ops = NULL,
+   };
+
+   odpdrv_devio_register(¶m);
+}
+
+static void ODPDRV_CONSTRUCTOR devio2_register(void)
+{
+   odpdrv_devio_param_t param = {
+   .api_name = "devio_api_2",
+   .api_version = 1,
+   .enumr_api_name = "Enumerator_interface_1",
+   .enumr_api_version = 1,
+   .probe = NULL,
+   .remove = devio2_remove,
+   .ops = NULL,
+   };
+
+   odpdrv_devio_register(¶m);
+}
+
+static odpdrv_devio_t devio2_register_retry(void)
+{
+   odpdrv_devio_param_t param = {
+   .api_name = "devio_api_2",
+   .api_version = 1,
+   .enumr_api_name = "Enumerator_interface_1",
+   .enumr_api_version = 1,
+   .probe = NULL,
+   .remove = NULL,
+   

[lng-odp] [API-NEXT PATCHv2 15/23] linux-gen: drv: devio registration

2017-03-22 Thread Christophe Milard
devios (dev IO) provide a interface for drivers to access a device:
Devices enumerated by enumerators may be accessed in by different
mechanisms (depending on iommu presence or other factors). This extra
abstraction is provided by devios, which provide a sets of methods to
access the devices of a given type (i.e. registred enumerator(s)
enumerating devices of the same kind (e.g. PCI)).
This patch just implements the devio registration method provided by the
driver API.

Signed-off-by: Christophe Milard 
---
 platform/linux-generic/drv_driver.c | 134 +++-
 1 file changed, 131 insertions(+), 3 deletions(-)

diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index 3e4780b..873ec3c 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -28,6 +28,7 @@ static _odp_ishm_pool_t *list_elt_pool;
 typedef struct _odpdrv_enumr_class_s _odpdrv_enumr_class_t;
 typedef struct _odpdrv_enumr_s _odpdrv_enumr_t;
 typedef struct _odpdrv_device_s _odpdrv_device_t;
+typedef struct _odpdrv_devio_s _odpdrv_devio_t;
 
 /* an enumerator class (list element) */
 struct _odpdrv_enumr_class_s {
@@ -72,6 +73,20 @@ typedef struct _odpdrv_device_lst_t {
 } _odpdrv_device_lst_t;
 static struct _odpdrv_device_lst_t device_lst;
 
+/* a devio (list element) */
+struct _odpdrv_devio_s {
+   odpdrv_devio_param_t param;
+   _odp_ishm_pool_t *pool;
+   struct _odpdrv_devio_s *next;
+} _odpdrv_devio_s;
+
+/* the devio list: */
+typedef struct _odpdrv_devio_lst_t {
+   odp_rwlock_recursive_t lock;
+   _odpdrv_devio_t *head;
+} _odpdrv_devio_lst_t;
+static struct _odpdrv_devio_lst_t devio_lst;
+
 /* some driver elements (such as enumeraor classes, drivers, devio) may
  * register before init_global and init_local complete. Mutex will fail
  * in this cases but should be used later on.
@@ -149,6 +164,30 @@ static void dev_list_write_unlock(void)
odp_rwlock_recursive_write_unlock(&device_lst.lock);
 }
 
+static void devio_list_read_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_lock(&devio_lst.lock);
+}
+
+static void devio_list_read_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_unlock(&devio_lst.lock);
+}
+
+static void devio_list_write_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_lock(&devio_lst.lock);
+}
+
+static void devio_list_write_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_unlock(&devio_lst.lock);
+}
+
 /* some functions to get internal pointers from handles... */
 static inline _odpdrv_enumr_class_t *get_enumr_class(odpdrv_enumr_class_t 
class)
 {
@@ -430,10 +469,65 @@ odpdrv_device_t *odpdrv_device_query(odpdrv_enumr_t 
enumr, const char *address)
 
 odpdrv_devio_t odpdrv_devio_register(odpdrv_devio_param_t *param)
 {
-   ODP_ERR("NOT Supported yet! Driver %s Registration!\n.",
-   param->api_name);
+   _odpdrv_devio_t *devio;
+
+   /* parse the list of already registered devios to make
+* sure no devio providing the same interface using th esame enumerator
+* already exists:
+*/
+   devio_list_read_lock();
+   devio = devio_lst.head;
+   while (devio) {
+   if ((strncmp(param->api_name, devio->param.api_name,
+ODPDRV_NAME_SIZE) == 0) &&
+   (strncmp(param->enumr_api_name, devio->param.enumr_api_name,
+ODPDRV_NAME_SIZE) == 0)) {
+   ODP_ERR("a devio providing interface '%s' for devices "
+   "of type '%s' is already registered\n!",
+   param->api_name, param->enumr_api_name);
+   devio_list_read_unlock();
+   return ODPDRV_DEVIO_INVALID;
+   }
+   devio = devio->next;
+   }
+   devio_list_read_unlock();
 
-   return ODPDRV_DEVIO_INVALID;
+   /* allocate memory for the new devio:
+* If init_global has not been done yet, then, we cannot allocate
+* from any _ishm pool (ishm has not even been initialised at this
+* stage...this happens when statically linked devios
+* register: their __constructor__ function is run before main()
+* is called). But any malloc performed here(before init_global)
+* will be inherited by any odpthreads (process or pthreads) as we
+* are still running in the ODP instantiation processes and all
+* other processes are guaranteed to be descendent of this one...
+* If init_global has been done, then we allocate from the _ishm pool
+* to guarantee visibility from any ODP thread.
+*/
+
+   if (init_global_status == UNDONE) {
+   devio = malloc(sizeof(_odpdrv_devio_t));
+ 

[lng-odp] [API-NEXT PATCHv2 12/23] linux-gen: drv: driver: adding device querry function

2017-03-22 Thread Christophe Milard
Implementation of the device query function for the linux-gen ODP.

Signed-off-by: Christophe Milard 
---
 platform/linux-generic/drv_driver.c | 37 +
 1 file changed, 37 insertions(+)

diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index 60edde1..3e4780b 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -391,6 +391,43 @@ static void device_destroy_terminate(odpdrv_device_t 
drv_device)
_odp_ishm_pool_free(list_elt_pool, device);
 }
 
+odpdrv_device_t *odpdrv_device_query(odpdrv_enumr_t enumr, const char *address)
+{
+   _odpdrv_device_t *dev;
+   odpdrv_device_t *res;
+   int index = 0;
+
+   int size = sizeof(odpdrv_device_t); /* for the ODPDRV_DEVICE_INVALID */
+
+   /* parse the list of device a first time to determine the size of
+* the memory to be allocated:
+*/
+   dev_list_read_lock();
+   dev = device_lst.head;
+   while (dev) {
+   if ((dev->param.enumerator == enumr) &&
+   ((address == NULL) ||
+(strcmp(dev->param.address, address) == 0)))
+   size += sizeof(odpdrv_device_t);
+   dev = dev->next;
+   }
+
+   /* then fill the list: */
+   res = (odpdrv_device_t *)malloc(size);
+   dev = device_lst.head;
+   while (dev) {
+   if ((dev->param.enumerator == enumr) &&
+   ((address == NULL) ||
+(strcmp(dev->param.address, address) == 0)))
+   res[index++] = (odpdrv_device_t)dev;
+   dev = dev->next;
+   }
+   dev_list_read_unlock();
+   res[index++] = ODPDRV_DEVICE_INVALID;
+
+   return res; /* must be freed by caller! */
+}
+
 odpdrv_devio_t odpdrv_devio_register(odpdrv_devio_param_t *param)
 {
ODP_ERR("NOT Supported yet! Driver %s Registration!\n.",
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 10/23] linux-gen: drv: device creation and deletion

2017-03-22 Thread Christophe Milard
Functions to create and remove devices are populated to do
more proper things.

Signed-off-by: Christophe Milard 
---
 platform/linux-generic/drv_driver.c | 181 ++--
 1 file changed, 173 insertions(+), 8 deletions(-)

diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index 4ade3c3..60edde1 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -19,12 +19,15 @@
 
 static enum {UNDONE, IN_PROGRESS, DONE} init_global_status;
 
+static void device_destroy_terminate(odpdrv_device_t device);
+
 /* pool from which different list elements are alocated: */
 #define ELT_POOL_SIZE (1 << 20)  /* 1Mb */
 static _odp_ishm_pool_t *list_elt_pool;
 
 typedef struct _odpdrv_enumr_class_s _odpdrv_enumr_class_t;
 typedef struct _odpdrv_enumr_s _odpdrv_enumr_t;
+typedef struct _odpdrv_device_s _odpdrv_device_t;
 
 /* an enumerator class (list element) */
 struct _odpdrv_enumr_class_s {
@@ -55,6 +58,20 @@ typedef struct _odpdrv_enumr_lst_t {
 } _odpdrv_enumr_lst_t;
 static struct _odpdrv_enumr_lst_t enumr_lst;
 
+/* a device (list element) */
+struct _odpdrv_device_s {
+   odpdrv_device_param_t param;
+   void (*enumr_destroy_callback)(void *enum_dev);/*dev destroy callback */
+   struct _odpdrv_device_s *next;
+} _odpdrv_device_s;
+
+/* the device list (all devices, from all enumerators): */
+typedef struct _odpdrv_device_lst_t {
+   odp_rwlock_recursive_t lock;
+   _odpdrv_device_t *head;
+} _odpdrv_device_lst_t;
+static struct _odpdrv_device_lst_t device_lst;
+
 /* some driver elements (such as enumeraor classes, drivers, devio) may
  * register before init_global and init_local complete. Mutex will fail
  * in this cases but should be used later on.
@@ -108,12 +125,46 @@ static void enumr_list_write_unlock(void)
odp_rwlock_recursive_write_unlock(&enumr_lst.lock);
 }
 
+static void dev_list_read_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_lock(&device_lst.lock);
+}
+
+static void dev_list_read_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_unlock(&device_lst.lock);
+}
+
+static void dev_list_write_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_lock(&device_lst.lock);
+}
+
+static void dev_list_write_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_unlock(&device_lst.lock);
+}
+
 /* some functions to get internal pointers from handles... */
 static inline _odpdrv_enumr_class_t *get_enumr_class(odpdrv_enumr_class_t 
class)
 {
return (_odpdrv_enumr_class_t *)(void *)class;
 }
 
+static inline _odpdrv_enumr_t *get_enumr(odpdrv_enumr_t enumr)
+{
+   return (_odpdrv_enumr_t *)(void *)enumr;
+}
+
+static inline _odpdrv_device_t *get_device(odpdrv_device_t dev)
+{
+   return (_odpdrv_device_t *)(void *)dev;
+}
+
 odpdrv_enumr_class_t odpdrv_enumr_class_register(odpdrv_enumr_class_param_t
 *param)
 {
@@ -227,24 +278,119 @@ odpdrv_enumr_t 
odpdrv_enumr_register(odpdrv_enumr_param_t *param)
 
 odpdrv_device_t odpdrv_device_create(odpdrv_device_param_t *param)
 {
-   ODP_ERR("odpdrv_device_create not Supported yet! devaddress: %s\n.",
-   param->address);
-   return ODPDRV_DEVICE_INVALID;
+   _odpdrv_device_t *dev;
+
+   /* If init_global has not been done yet, we have a big issue. */
+   if (init_global_status == UNDONE)
+   return ODPDRV_DEVICE_INVALID;
+
+   /* make sure that the provided device address does not already exist: */
+   dev_list_read_lock();
+   dev = device_lst.head;
+   while (dev) {
+   if (strcmp(param->address, dev->param.address) == 0) {
+   ODP_ERR("device already exists!\n");
+   dev_list_read_unlock();
+   return ODPDRV_DEVICE_INVALID;
+   }
+   dev = dev->next;
+   }
+   dev_list_read_unlock();
+
+   dev = _odp_ishm_pool_alloc(list_elt_pool,
+  sizeof(_odpdrv_device_t));
+   if (!dev) {
+   ODP_ERR("_odp_ishm_pool_alloc failed!\n");
+   return ODPDRV_DEVICE_INVALID;
+   }
+
+   /* save and set dev init parameters and insert new device in list */
+   dev->param = *param;
+   dev->enumr_destroy_callback = NULL;
+   dev_list_write_lock();
+   dev->next = device_lst.head;
+   device_lst.head = dev;
+   dev_list_write_unlock();
+
+   /* todo: probe for drivers */
+
+   return (odpdrv_device_t)dev;
 }
 
 int odpdrv_device_destroy(odpdrv_device_t dev,
  void (*callback)(void *enum_dev), uint32_t flags)
 {
-   if (dev == ODPDRV_DEVICE_INVALID)
+   _odpdrv_device_t *device = get_device(dev);
+   _odpdrv_device_t *_de

[lng-odp] [API-NEXT PATCHv2 11/23] drv: driver: adding device query function

2017-03-22 Thread Christophe Milard
Adding a function for querying a list of devices: this function may be
used by enumerators to query for the list of their registered devices
or for a subset of them.
Note that this function returns a malloc'd list of devices which is to
be freed by the caller.

Signed-off-by: Christophe Milard 
---
 include/odp/drv/spec/driver.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/include/odp/drv/spec/driver.h b/include/odp/drv/spec/driver.h
index 9643268..e861396 100644
--- a/include/odp/drv/spec/driver.h
+++ b/include/odp/drv/spec/driver.h
@@ -387,6 +387,18 @@ int odpdrv_device_destroy(odpdrv_device_t dev,
 /** The callback function must be called by the current ODP thread */
 #define ODPDRV_DEV_DESTROY_IMMEDIATE   0x0001
 
+/** query for a list of devices
+ * Enumerators are responsable for device creation and destruction.
+ * Upon request, ODP can build a list of devices belonging to a given 
enumerator
+ * and possibly having a specific address.
+ * This function builds this list.
+ * @param enumr The enumerator which created the device
+ * @param address The device address (or NULL if don't care)
+ * @return A malloc'd ODPDRV_DEVICE_INVALID terminated array of odpdrv_device_t
+ * This array MUST BE FREED by the caller!
+ */
+odpdrv_device_t *odpdrv_device_query(odpdrv_enumr_t enumr, const char 
*address);
+
 /**
 * Register an devio.
 * Each devio calls this function at init time.
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 08/23] drv: driver: change drv unbind function name and pass correct parameter

2017-03-22 Thread Christophe Milard
The driver removal function expects a device, of course...
Also unbind seems a better name to disconnect from a device
since remove has been used for removing the object itself for
enumerators.
Some extra parameters to allow for graceful unbinding are also added.

Signed-off-by: Christophe Milard 
---
 include/odp/drv/spec/driver.h | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/include/odp/drv/spec/driver.h b/include/odp/drv/spec/driver.h
index b08d7fb..8ff856c 100644
--- a/include/odp/drv/spec/driver.h
+++ b/include/odp/drv/spec/driver.h
@@ -300,14 +300,29 @@ struct odpdrv_driver_param_t {
 */
int (*probe)(odpdrv_device_t *dev);
 
-   /** Remove function:
+   /** unbind function:
 * Only called with devices whose probe() returned true
 *
+* dev: the device to unbind
+* callback: if flag ODPDRV_DRV_UNBIND_IMMEDIATE is not specified,
+*  unbind should be attempted gracefully, meaning that some IO may need
+*  to terminate before the driver is really unbound from the device:
+*  In this case (when the flag is not set), the driver is due to call
+*  the callback function when the driver is unbound from the device.
+*  This callback may occurs within the unbind() call if the driver
+*  does unbind immediately.
+*  If the ODPDRV_DRV_UNBIND_IMMEDIATE is specified, the driver is due
+*  to release the device immediately (poosibly less gracefully).
+*  The callback must be called immediately in this case.
 */
-   int (*remove)(odpdrv_device_param_t *dev);
-
+   int (*unbind)(odpdrv_device_t dev,
+ void (*callback)(odpdrv_device_t dev),
+ uint32_t flags);
 };
 
+/** The callback function must be called mmediately by the current ODP thread 
*/
+#define ODPDRV_DRV_UNBIND_IMMEDIATE0x0001
+
 /**
 * Register an enumerator class.
 * Each enumerator class calls this function at init time.
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 09/23] drv: driver: add callback function for device destruction

2017-03-22 Thread Christophe Milard
When a device is destroyed by an enumerator, odpdrv_device_destroy() is
called.
However, the complete device destruction may require waiting for IO to be
completed: the device destruction is therefore divided in 2 steps:
odpdrv_device_destroy() starts the device destruction, and the provided
callback function is called when the device can be fully removed, i.e.
when it no longer has any driver bound to it.
An extra flag is also added to select the destruction type:
The default is a graceful destruction, letting the time for any attached
driver to terminate. This may imply that the callback function is called
from another ODP thread, later on.
ODPDRV_DEV_DESTROY_IMMEDIATE forces an immediate device destruction,
possibly terminating things abrubtly, but it guarantees that the
callback is performed by the same ODP thread. This is to be used at ODP
terminaison time.

Signed-off-by: Christophe Milard 
---
 include/odp/drv/spec/driver.h   | 31 +++
 platform/linux-generic/drv_driver.c |  9 -
 2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/include/odp/drv/spec/driver.h b/include/odp/drv/spec/driver.h
index 8ff856c..9643268 100644
--- a/include/odp/drv/spec/driver.h
+++ b/include/odp/drv/spec/driver.h
@@ -357,12 +357,35 @@ odpdrv_device_t 
odpdrv_device_create(odpdrv_device_param_t *param);
 
 /**
 * Destroy a device
-* Called by each enumerator at probe time, or anytime later, for each
-* destroyed created device
+* Called by each enumerator after probe time, for each device to be
+* destroyed.
+* Destroying a device may require tearing down a driver and waiting for some IO
+* to terminate: The device destruction is therefore done in 2 steps:
+* Calling this function starts the device destruction: when the device has
+* no driver attached any longer, ODP calls the provided callback()
+* function  which should free the enumerator-allocated resources for
+* this device.
+* If the flag ODPDRV_DEV_DESTROY_IMMEDIATE is given, the device destruction
+* is immediate, i.e. the callback function is guaranteed to be called by the
+* same ODP thread: This might however not let the time for the bound driver
+* (if any) to terminate gracefully. This would typically be used at ODP
+* terminaison. By default, the callback may be called later, when the driver
+* has gracefully terminated, hence possibly from another ODP thread.
 * @param dev A odpdrv device handle as returned by odpdrv_device_create.
-* @return 0 on success or a negative value on error.
+* @param callback a pointer to a function to be called when the device is
+*freed (no more driver). The parameter to the callback function is
+*   the pointer to the enumerator specific part of the device as provided
+*   at device creation time (void *enum_dev). The callback function
+*   should release these resources.
+* @param flags 0 or ODPDRV_DEV_DESTROY_IMMEDIATE for immediate shut down
+* @return 0 on success or a negative value on error. On error, the callback
+* function is not called.
 */
-void odpdrv_device_destroy(odpdrv_device_t dev);
+int odpdrv_device_destroy(odpdrv_device_t dev,
+ void (*callback)(void *enum_dev), uint32_t flags);
+
+/** The callback function must be called by the current ODP thread */
+#define ODPDRV_DEV_DESTROY_IMMEDIATE   0x0001
 
 /**
 * Register an devio.
diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index 35473bd..4ade3c3 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -232,10 +232,17 @@ odpdrv_device_t 
odpdrv_device_create(odpdrv_device_param_t *param)
return ODPDRV_DEVICE_INVALID;
 }
 
-void odpdrv_device_destroy(odpdrv_device_t dev)
+int odpdrv_device_destroy(odpdrv_device_t dev,
+ void (*callback)(void *enum_dev), uint32_t flags)
 {
if (dev == ODPDRV_DEVICE_INVALID)
ODP_ERR("Invalid device\n");
+   if (callback != NULL)
+   ODP_ERR("Callback not supported yet\n");
+   if (flags != 0)
+   ODP_ERR("flags not supported yet\n");
+
+   return 0;
 }
 
 odpdrv_devio_t odpdrv_devio_register(odpdrv_devio_param_t *param)
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 07/23] test: drv: enumerator registration tests

2017-03-22 Thread Christophe Milard
making sure that enumerators are probed.

Signed-off-by: Christophe Milard 
---
 .../validation/drv/drvdriver/.gitignore|   1 +
 .../validation/drv/drvdriver/Makefile.am   |  11 +
 .../validation/drv/drvdriver/drvdriver_enumr.c | 303 +
 .../validation/drv/drvdriver/drvdriver_enumr.h |  24 ++
 .../drv/drvdriver/drvdriver_enumr_main.c   |  12 +
 test/linux-generic/Makefile.am |   1 +
 6 files changed, 352 insertions(+)
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_enumr.c
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_enumr.h
 create mode 100644 
test/common_plat/validation/drv/drvdriver/drvdriver_enumr_main.c

diff --git a/test/common_plat/validation/drv/drvdriver/.gitignore 
b/test/common_plat/validation/drv/drvdriver/.gitignore
index 9268315..a842448 100644
--- a/test/common_plat/validation/drv/drvdriver/.gitignore
+++ b/test/common_plat/validation/drv/drvdriver/.gitignore
@@ -1 +1,2 @@
 drvdriver_enumr_class_main
+drvdriver_enumr_main
diff --git a/test/common_plat/validation/drv/drvdriver/Makefile.am 
b/test/common_plat/validation/drv/drvdriver/Makefile.am
index 9e941ee..3476c50 100644
--- a/test/common_plat/validation/drv/drvdriver/Makefile.am
+++ b/test/common_plat/validation/drv/drvdriver/Makefile.am
@@ -14,3 +14,14 @@ drvdriver_enumr_class_main_LDADD = 
libtestdrvdriverenumrclass.la \
   $(LIBCUNIT_COMMON) $(LIBODP)
 
 EXTRA_DIST = drvdriver_enumr_class.h
+
+#tests for enumerator registration:
+noinst_LTLIBRARIES += libtestdrvdriverenumr.la
+libtestdrvdriverenumr_la_SOURCES = drvdriver_enumr.c
+
+test_PROGRAMS += drvdriver_enumr_main$(EXEEXT)
+dist_drvdriver_enumr_main_SOURCES = drvdriver_enumr_main.c
+drvdriver_enumr_main_LDADD = libtestdrvdriverenumr.la \
+  $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST += drvdriver_enumr.h
diff --git a/test/common_plat/validation/drv/drvdriver/drvdriver_enumr.c 
b/test/common_plat/validation/drv/drvdriver/drvdriver_enumr.c
new file mode 100644
index 000..38aac3d
--- /dev/null
+++ b/test/common_plat/validation/drv/drvdriver/drvdriver_enumr.c
@@ -0,0 +1,303 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include 
+#include 
+#include 
+#include "drvdriver_enumr.h"
+#include 
+
+static odp_instance_t odp_instance;
+static odpdrv_enumr_class_t enumr_class1, enumr_class2;
+
+/* markers showing that different stages have been run */
+static int enumr1_probed;
+static int enumr2_probed;
+static int enumr3_probed;
+static int enumr4_probed;
+
+/* forward declaration */
+static int enumr1_probe(void);
+static int enumr2_probe(void);
+static int enumr3_probe(void);
+static int enumr4_probe(void);
+
+static int enumr1_remove(void);
+static int enumr2_remove(void);
+static int enumr3_remove(void);
+static int enumr4_remove(void);
+
+static int enumr_class1_probe(void);
+static int enumr_class2_probe(void);
+
+static int enumr_class1_remove(void);
+static int enumr_class2_remove(void);
+
+/* because many things to be checked are performed during ODP initialisation,
+ * the initialisation functions have to be a part of the test
+ */
+static int tests_global_init(void)
+{
+   if (0 != odp_init_global(&odp_instance, NULL, NULL)) {
+   fprintf(stderr, "error: odp_init_global() failed.\n");
+   return -1;
+   }
+   if (0 != odp_init_local(odp_instance, ODP_THREAD_CONTROL)) {
+   fprintf(stderr, "error: odp_init_local() failed.\n");
+   return -1;
+   }
+
+   return 0;
+}
+
+static int tests_global_term(void)
+{
+   if (0 != odp_term_local()) {
+   fprintf(stderr, "error: odp_term_local() failed.\n");
+   return -1;
+   }
+
+   if (0 != odp_term_global(odp_instance)) {
+   fprintf(stderr, "error: odp_term_global() failed.\n");
+   return -1;
+   }
+
+   return 0;
+}
+
+/*enumerator register functions */
+static odpdrv_enumr_t enumr1_register(void)
+{
+   odpdrv_enumr_param_t param = {
+   .enumr_class = enumr_class1,
+   .api_name = "Enumerator_interface_1",
+   .api_version = 1,
+   .probe = enumr1_probe,
+   .remove = enumr1_remove,
+   .register_notifier = NULL
+   };
+
+   return odpdrv_enumr_register(¶m);
+}
+
+static odpdrv_enumr_t enumr2_register(void)
+{
+   odpdrv_enumr_param_t param = {
+   .enumr_class = enumr_class1,
+   .api_name = "Enumerator_interface_2",
+   .api_version = 1,
+   .probe = enumr2_probe,
+   .remove = enumr2_remove,
+   .register_notifier = NULL
+   };
+
+   return odpdrv_enumr_register(¶m);
+}
+
+static odpdrv_enumr_t enumr3_register(void)
+{
+   odpdrv_enumr_param_t param = {
+  

[lng-odp] [API-NEXT PATCHv2 06/23] linux-gen: drv: enumerator registration

2017-03-22 Thread Christophe Milard
The enumerator registration functions for the linux-gen ODP implementation.

Signed-off-by: Christophe Milard 
---
 platform/linux-generic/drv_driver.c | 139 +++-
 1 file changed, 136 insertions(+), 3 deletions(-)

diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index 50956a7..35473bd 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -24,6 +24,7 @@ static enum {UNDONE, IN_PROGRESS, DONE} init_global_status;
 static _odp_ishm_pool_t *list_elt_pool;
 
 typedef struct _odpdrv_enumr_class_s _odpdrv_enumr_class_t;
+typedef struct _odpdrv_enumr_s _odpdrv_enumr_t;
 
 /* an enumerator class (list element) */
 struct _odpdrv_enumr_class_s {
@@ -40,6 +41,20 @@ typedef struct _odpdrv_enumr_class_lst_t {
 } _odpdrv_enumr_class_lst_t;
 static struct _odpdrv_enumr_class_lst_t enumr_class_lst;
 
+/* an enumerator (list element) */
+struct _odpdrv_enumr_s {
+   odpdrv_enumr_param_t param;
+   int probed;
+   struct _odpdrv_enumr_s *next;
+};
+
+/* the enumerator list: */
+typedef struct _odpdrv_enumr_lst_t {
+   odp_rwlock_recursive_t lock;
+   _odpdrv_enumr_t *head;
+} _odpdrv_enumr_lst_t;
+static struct _odpdrv_enumr_lst_t enumr_lst;
+
 /* some driver elements (such as enumeraor classes, drivers, devio) may
  * register before init_global and init_local complete. Mutex will fail
  * in this cases but should be used later on.
@@ -69,6 +84,35 @@ static void enumr_class_list_write_unlock(void)
odp_rwlock_recursive_write_unlock(&enumr_class_lst.lock);
 }
 
+static void enumr_list_read_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_lock(&enumr_lst.lock);
+}
+
+static void enumr_list_read_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_unlock(&enumr_lst.lock);
+}
+
+static void enumr_list_write_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_lock(&enumr_lst.lock);
+}
+
+static void enumr_list_write_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_unlock(&enumr_lst.lock);
+}
+
+/* some functions to get internal pointers from handles... */
+static inline _odpdrv_enumr_class_t *get_enumr_class(odpdrv_enumr_class_t 
class)
+{
+   return (_odpdrv_enumr_class_t *)(void *)class;
+}
 
 odpdrv_enumr_class_t odpdrv_enumr_class_register(odpdrv_enumr_class_param_t
 *param)
@@ -133,10 +177,52 @@ odpdrv_enumr_class_t 
odpdrv_enumr_class_register(odpdrv_enumr_class_param_t
 
 odpdrv_enumr_t odpdrv_enumr_register(odpdrv_enumr_param_t *param)
 {
-   ODP_ERR("NOT Supported yet! Enumerator API %s Registration!\n.",
-   param->api_name);
+   _odpdrv_enumr_t *enumr;
+   _odpdrv_enumr_class_t *enumr_c;
+   int found_class = 0;
 
-   return ODPDRV_ENUMR_INVALID;
+   /* make sure that the provided enumerator_class does indeed exist: */
+   enumr_class_list_read_lock();
+   enumr_c = enumr_class_lst.head;
+   while (enumr_c) {
+   if (get_enumr_class(param->enumr_class) == enumr_c) {
+   found_class = 1;
+   break;
+   }
+   enumr_c = enumr_c->next;
+   }
+   enumr_class_list_read_unlock();
+   if (!found_class) {
+   ODP_ERR("invalid enumerator class provided!\n");
+   return ODPDRV_ENUMR_INVALID;
+   }
+
+   /* allocate memory for the new enumerator:
+* If init_global has not been done yet, we have a big issue,
+* as none of the enumerator classes should be probed before that!
+* We cannot even issue an error as ODP_* functions have not been
+* initialised yet, but this is no good...
+*/
+
+   if (init_global_status == UNDONE)
+   return ODPDRV_ENUMR_INVALID;
+
+   enumr = _odp_ishm_pool_alloc(list_elt_pool,
+sizeof(_odpdrv_enumr_t));
+   if (!enumr) {
+   ODP_ERR("_odp_ishm_pool_alloc failed!\n");
+   return ODPDRV_ENUMR_INVALID;
+   }
+
+   /* save init parameters and insert enumerator in list */
+   enumr->param = *param;
+   enumr->probed = 0;
+   enumr_list_write_lock();
+   enumr->next = enumr_lst.head;
+   enumr_lst.head = enumr;
+   enumr_list_write_unlock();
+
+   return (odpdrv_enumr_t)enumr;
 }
 
 odpdrv_device_t odpdrv_device_create(odpdrv_device_param_t *param)
@@ -174,6 +260,7 @@ odpdrv_driver_t 
odpdrv_driver_register(odpdrv_driver_param_t *param)
 void _odpdrv_driver_probe_drv_items(void)
 {
_odpdrv_enumr_class_t *enumr_c;
+   _odpdrv_enumr_t *enumr;
 
/* probe unprobed enumerators: */
enumr_class_list_read_lock();
@@ -186,11 +273,26 @@ void _odpdrv_driver_probe_drv_items(void)
   

[lng-odp] [API-NEXT PATCHv2 05/23] test: drv: enumerator_class registration tests

2017-03-22 Thread Christophe Milard
Testing that enumerators classes can register properly.
Saddly restricted to statically linked enumerators classes, as testing with
modules in autotools seems to be an issue so far.

Signed-off-by: Christophe Milard 
---
 test/common_plat/m4/configure.m4   |   1 +
 test/common_plat/validation/drv/Makefile.am|   1 +
 .../validation/drv/drvdriver/.gitignore|   1 +
 .../validation/drv/drvdriver/Makefile.am   |  16 ++
 .../drv/drvdriver/drvdriver_enumr_class.c  | 174 +
 .../drv/drvdriver/drvdriver_enumr_class.h  |  24 +++
 .../drv/drvdriver/drvdriver_enumr_class_main.c |  12 ++
 test/linux-generic/Makefile.am |   1 +
 8 files changed, 230 insertions(+)
 create mode 100644 test/common_plat/validation/drv/drvdriver/.gitignore
 create mode 100644 test/common_plat/validation/drv/drvdriver/Makefile.am
 create mode 100644 
test/common_plat/validation/drv/drvdriver/drvdriver_enumr_class.c
 create mode 100644 
test/common_plat/validation/drv/drvdriver/drvdriver_enumr_class.h
 create mode 100644 
test/common_plat/validation/drv/drvdriver/drvdriver_enumr_class_main.c

diff --git a/test/common_plat/m4/configure.m4 b/test/common_plat/m4/configure.m4
index 13a13bd..400750c 100644
--- a/test/common_plat/m4/configure.m4
+++ b/test/common_plat/m4/configure.m4
@@ -34,4 +34,5 @@ AC_CONFIG_FILES([test/common_plat/Makefile
 test/common_plat/validation/api/traffic_mngr/Makefile
 test/common_plat/validation/drv/Makefile
 test/common_plat/validation/drv/drvatomic/Makefile
+test/common_plat/validation/drv/drvdriver/Makefile
 test/common_plat/validation/drv/drvshmem/Makefile])
diff --git a/test/common_plat/validation/drv/Makefile.am 
b/test/common_plat/validation/drv/Makefile.am
index bcdb92e..7329a89 100644
--- a/test/common_plat/validation/drv/Makefile.am
+++ b/test/common_plat/validation/drv/Makefile.am
@@ -1,4 +1,5 @@
 ODPDRV_MODULES = drvatomic \
+drvdriver \
 drvshmem
 
 SUBDIRS = $(ODPDRV_MODULES)
diff --git a/test/common_plat/validation/drv/drvdriver/.gitignore 
b/test/common_plat/validation/drv/drvdriver/.gitignore
new file mode 100644
index 000..9268315
--- /dev/null
+++ b/test/common_plat/validation/drv/drvdriver/.gitignore
@@ -0,0 +1 @@
+drvdriver_enumr_class_main
diff --git a/test/common_plat/validation/drv/drvdriver/Makefile.am 
b/test/common_plat/validation/drv/drvdriver/Makefile.am
new file mode 100644
index 000..9e941ee
--- /dev/null
+++ b/test/common_plat/validation/drv/drvdriver/Makefile.am
@@ -0,0 +1,16 @@
+include ../Makefile.inc
+
+# because most of driver activity occurs at init time, and due to the
+# fact that many sequential ODP runs are not allowed from the same process,
+# we need different binaries for each things being tested (as API init)
+
+#tests for enumerator class registration:
+noinst_LTLIBRARIES = libtestdrvdriverenumrclass.la
+libtestdrvdriverenumrclass_la_SOURCES = drvdriver_enumr_class.c
+
+test_PROGRAMS = drvdriver_enumr_class_main$(EXEEXT)
+dist_drvdriver_enumr_class_main_SOURCES = drvdriver_enumr_class_main.c
+drvdriver_enumr_class_main_LDADD = libtestdrvdriverenumrclass.la \
+  $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST = drvdriver_enumr_class.h
diff --git a/test/common_plat/validation/drv/drvdriver/drvdriver_enumr_class.c 
b/test/common_plat/validation/drv/drvdriver/drvdriver_enumr_class.c
new file mode 100644
index 000..f7dd42c
--- /dev/null
+++ b/test/common_plat/validation/drv/drvdriver/drvdriver_enumr_class.c
@@ -0,0 +1,174 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include 
+#include 
+#include 
+#include "drvdriver_enumr_class.h"
+#include 
+
+static odp_instance_t odp_instance;
+
+static int enumr_class1_probed;
+static int enumr_class2_probed;
+
+/* forward declaration */
+static int enumr_class1_probe(void);
+static int enumr_class2_probe(void);
+
+static int enumr_class1_remove(void);
+static int enumr_class2_remove(void);
+
+/* because many things to be checked are performed during ODP initialisation,
+ * the initialisation functions have to be a part of the test
+ */
+static int tests_global_init(void)
+{
+   if (0 != odp_init_global(&odp_instance, NULL, NULL)) {
+   fprintf(stderr, "error: odp_init_global() failed.\n");
+   return -1;
+   }
+   if (0 != odp_init_local(odp_instance, ODP_THREAD_CONTROL)) {
+   fprintf(stderr, "error: odp_init_local() failed.\n");
+   return -1;
+   }
+
+   return 0;
+}
+
+static int tests_global_term(void)
+{
+   if (0 != odp_term_local()) {
+   fprintf(stderr, "error: odp_term_local() failed.\n");
+   return -1;
+   }
+
+   if (0 != odp_term_global(odp_instance)) {
+   fprintf(stderr, "error: o

[lng-odp] [API-NEXT PATCHv2 04/23] linux-gen: drv: enumerator_class registration

2017-03-22 Thread Christophe Milard
The functions to register and probe enumerator classes are added.

Signed-off-by: Christophe Milard 
---
 platform/linux-generic/Makefile.am |   1 +
 platform/linux-generic/_modules.c  |   4 +
 platform/linux-generic/drv_driver.c| 212 -
 .../linux-generic/include/drv_driver_internal.h|  22 +++
 platform/linux-generic/include/odp_internal.h  |   5 +
 platform/linux-generic/odp_init.c  |  21 +-
 6 files changed, 260 insertions(+), 5 deletions(-)
 create mode 100644 platform/linux-generic/include/drv_driver_internal.h

diff --git a/platform/linux-generic/Makefile.am 
b/platform/linux-generic/Makefile.am
index deab284..02f13fe 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -133,6 +133,7 @@ noinst_HEADERS = \
  ${srcdir}/include/_ishm_internal.h \
  ${srcdir}/include/_ishmphy_internal.h \
  ${srcdir}/include/_ishmpool_internal.h \
+ ${srcdir}/include/drv_driver_internal.h\
  ${srcdir}/include/odp_align_internal.h \
  ${srcdir}/include/odp_atomic_internal.h \
  ${srcdir}/include/odp_buffer_inlines.h \
diff --git a/platform/linux-generic/_modules.c 
b/platform/linux-generic/_modules.c
index 6bb854e..b23c81f 100644
--- a/platform/linux-generic/_modules.c
+++ b/platform/linux-generic/_modules.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -40,6 +41,9 @@ static int load_modules(void)
ODP_DBG("module %s loaded.\n", module_name);
}
 
+   /* give a chance top the driver interface to probe for new things: */
+   _odpdrv_driver_probe_drv_items();
+
return 0;
 }
 
diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index 529da48..50956a7 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -4,20 +4,131 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include 
+
 #include 
+#include <_ishmpool_internal.h>
 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
+#include 
+
+static enum {UNDONE, IN_PROGRESS, DONE} init_global_status;
+
+/* pool from which different list elements are alocated: */
+#define ELT_POOL_SIZE (1 << 20)  /* 1Mb */
+static _odp_ishm_pool_t *list_elt_pool;
+
+typedef struct _odpdrv_enumr_class_s _odpdrv_enumr_class_t;
+
+/* an enumerator class (list element) */
+struct _odpdrv_enumr_class_s {
+   odpdrv_enumr_class_param_t param;
+   int probed;
+   _odp_ishm_pool_t *pool;
+   struct _odpdrv_enumr_class_s *next;
+};
+
+/* the enumerator class list: */
+typedef struct _odpdrv_enumr_class_lst_t {
+   odp_rwlock_recursive_t lock;
+   _odpdrv_enumr_class_t *head;
+} _odpdrv_enumr_class_lst_t;
+static struct _odpdrv_enumr_class_lst_t enumr_class_lst;
+
+/* some driver elements (such as enumeraor classes, drivers, devio) may
+ * register before init_global and init_local complete. Mutex will fail
+ * in this cases but should be used later on.
+ * These functions disable the usage of Mutex while it is global init i.e.
+ * while single threaded*/
+static void enumr_class_list_read_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_lock(&enumr_class_lst.lock);
+}
+
+static void enumr_class_list_read_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_read_unlock(&enumr_class_lst.lock);
+}
+
+static void enumr_class_list_write_lock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_lock(&enumr_class_lst.lock);
+}
+
+static void enumr_class_list_write_unlock(void)
+{
+   if (init_global_status == DONE)
+   odp_rwlock_recursive_write_unlock(&enumr_class_lst.lock);
+}
+
 
 odpdrv_enumr_class_t odpdrv_enumr_class_register(odpdrv_enumr_class_param_t
 *param)
 {
-   ODP_ERR("NOT Supported yet! Enumerator Class %s Registration!\n.",
-   param->name);
+   _odpdrv_enumr_class_t *enumr_c;
 
-   return ODPDRV_ENUMR_CLASS_INVALID;
+   /* parse the list of already registered enumerator class to make
+* sure no enumerator with identical name already exists:
+*/
+   enumr_class_list_read_lock();
+   enumr_c = enumr_class_lst.head;
+   while (enumr_c) {
+   if (strncmp(param->name, enumr_c->param.name,
+   ODPDRV_NAME_SIZE) == 0) {
+   ODP_ERR("enumerator class %s already exists!\n",
+   param->name);
+   enumr_class_list_read_unlock();
+   return ODPDRV_ENUMR_CLASS_INVALID;
+   }
+   enumr_c = enumr_c->next;
+   }
+   enumr_class_list_read_unlock();
+
+   /* allocate memory for the 

[lng-odp] [API-NEXT PATCHv2 03/23] drv: making parameter strings dynamically computable

2017-03-22 Thread Christophe Milard
Declaring strings as const in the driver API prevents dynamic calculation
of these strings, which is a drawback. For instance,
the device addresses (string) are typically calculated by enumerators,
and should therefore not be const... Other strings may also be the result
of a computation. This change is made to allow this.

Signed-off-by: Christophe Milard 
---
 include/odp/drv/spec/driver.h | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/odp/drv/spec/driver.h b/include/odp/drv/spec/driver.h
index d83e907..b08d7fb 100644
--- a/include/odp/drv/spec/driver.h
+++ b/include/odp/drv/spec/driver.h
@@ -170,7 +170,7 @@ struct odpdrv_enumr_class_param_t {
/** Enumerator name: mostly used for debug purpose.
 * Name must be unique (e.g. "PCI-DPAA2")
 */
-   const char name[ODPDRV_NAME_SIZE];
+   char name[ODPDRV_NAME_SIZE];
 
/** Probe function:
 * Called by ODP to get the enumerator class instances registered
@@ -198,7 +198,7 @@ struct odpdrv_enumr_param_t {
 * The format of the enum_dev part for the odpdrv_device_param_t
 * structure is identified by the api-name and version below
 */
-   const char api_name[ODPDRV_NAME_SIZE];
+   char api_name[ODPDRV_NAME_SIZE];
uint32_t api_version; /**<< the version of the provided API */
 
/** Probe function:
@@ -240,7 +240,7 @@ struct odpdrv_device_param_t {
 * e.g. ".23.12.1" for PCI domain 0, bus 23, device 12, function 1.
 * This string identifies the device uniquely.
 */
-   const char  address[ODPDRV_NAME_ADDR_SZ];
+   char address[ODPDRV_NAME_ADDR_SZ];
 
/** Enumerator dependent part
 * This part is allocated by the enumerator and is enumerator dependent
@@ -260,13 +260,13 @@ struct odpdrv_devio_param_t {
 * with same provided interface should refer to a common enumerator
 * class)
 */
-   const char api_name[ODPDRV_NAME_SIZE];
+   char api_name[ODPDRV_NAME_SIZE];
uint32_t api_version; /**<< the version of the provided API */
 
/** Enumerator interface name and version
 * The enumerator interface this devio needs.
 */
-   const char enumr_api_name[ODPDRV_NAME_SIZE];
+   char enumr_api_name[ODPDRV_NAME_SIZE];
uint32_t enumr_api_version; /**<< required enumerator API version */
 
/** Ops
@@ -283,14 +283,14 @@ struct odpdrv_driver_param_t {
 * The driver name (the pair {driver-name, enum-api-name} must
 * be unique)
 */
-   const char name[ODPDRV_NAME_SIZE];
+   char name[ODPDRV_NAME_SIZE];
 
/** Supported devios:
 * The list of supported devio: one of the following devio
 * (with correct version) must be available for the driver to work:
 */
struct {
-   const char api_name[ODPDRV_NAME_SIZE]; /**<< devio API name */
+   char api_name[ODPDRV_NAME_SIZE]; /**<< devio API name */
uint32_t   api_version; /**<< devio API version */
} devios[ODPDRV_MAX_DEVIOS];
 
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 02/23] linux-gen: adding compiler hints in the driver interface

2017-03-22 Thread Christophe Milard
Just including the spec file from the linux-generic side, as usual.

Signed-off-by: Christophe Milard 
---
 include/odp_drv.h  |  1 +
 platform/linux-generic/include/odp/drv/hints.h | 34 ++
 2 files changed, 35 insertions(+)
 create mode 100644 platform/linux-generic/include/odp/drv/hints.h

diff --git a/include/odp_drv.h b/include/odp_drv.h
index 96d81ba..cdba226 100644
--- a/include/odp_drv.h
+++ b/include/odp_drv.h
@@ -24,6 +24,7 @@ extern C {
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/platform/linux-generic/include/odp/drv/hints.h 
b/platform/linux-generic/include/odp/drv/hints.h
new file mode 100644
index 000..808c22c
--- /dev/null
+++ b/platform/linux-generic/include/odp/drv/hints.h
@@ -0,0 +1,34 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODPDRV compiler hints
+ */
+
+#ifndef ODPDRV_PLAT_HINTS_H_
+#define ODPDRV_PLAT_HINTS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @ingroup odpdrv_compiler_optim
+ *  @{
+ */
+
+/**
+ * @}
+ */
+
+#include 
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
-- 
2.7.4



[lng-odp] [API-NEXT PATCHv2 00/23] driver items registration and probing

2017-03-22 Thread Christophe Milard
This patch series can be pulled from:
https://git.linaro.org/people/christophe.milard/odp.git/log/?h=drv_framework_v2

Since V1: Fixes following Bill's comments.

Note: I am not really sure this is still in phase with what was discussed
at connect, since I couldn't attend. But, at least I did the changes following
the comments I recieved. Hope that still makes sence.
Also, I am aware that patch 1 generates a warning: I copied this part from the
north API so I assume this is an agreed decision.

This patch series implements the driver interface, i.e.
enumerator class, enumerator, devio and drivers registration and probing.
This interface is depicted in:
https://docs.google.com/document/d/1eCKPJF6uSlOllXi_sKDvRwUD2BXm-ZzxZoKT0nVEsl4/edit
The associated tests are testing these mechanisms. Note that these tests
are testing staticaly linked modules only (hence avoiding the
module/platform/test debate). Also note that these tests are gathering
all the elements (enumerators, enumerator classes, devio, drivers) making
up the driver interface so as their interactions can be checked.
Real elements (pci enumerators, drivers...) will likely be written in a much
more stand-alone way.

Christophe Milard (23):
  drv: adding compiler hints in the driver interface
  linux-gen: adding compiler hints in the driver interface
  drv: making parameter strings dynamically computable
  linux-gen: drv: enumerator_class registration
  test: drv: enumerator_class registration tests
  linux-gen: drv: enumerator registration
  test: drv: enumerator registration tests
  drv: driver: change drv unbind function name and pass correct
parameter
  drv: driver: add callback function for device destruction
  linux-gen: drv: device creation and deletion
  drv: driver: adding device query function
  linux-gen: drv: driver: adding device querry function
  test: drv: device creation and destruction
  drv: driver: adding a probe and remove callback for devio
  linux-gen: drv: devio registration
  test: drv: devio creation and destruction
  drv: adding driver remove function
  drv: complement parameters to the driver probe() function
  linux-gen: driver registration and probing
  test: drv: driver registration and probing
  drv: driver: adding functions to attach driver's data to the device
  linux-gen: adding functions to attach driver's data to the device
  test: drv: test for setting and retrieving driver's data

 include/odp/drv/spec/driver.h  |  132 ++-
 include/odp/drv/spec/hints.h   |  119 +++
 include/odp_drv.h  |1 +
 platform/Makefile.inc  |1 +
 platform/linux-generic/Makefile.am |1 +
 platform/linux-generic/_modules.c  |4 +
 platform/linux-generic/drv_driver.c| 1051 +++-
 .../linux-generic/include/drv_driver_internal.h|   22 +
 platform/linux-generic/include/odp/drv/hints.h |   34 +
 platform/linux-generic/include/odp_internal.h  |5 +
 platform/linux-generic/odp_init.c  |   21 +-
 test/common_plat/m4/configure.m4   |1 +
 test/common_plat/validation/drv/Makefile.am|1 +
 .../validation/drv/drvdriver/.gitignore|5 +
 .../validation/drv/drvdriver/Makefile.am   |   60 ++
 .../validation/drv/drvdriver/drvdriver_device.c|  218 
 .../validation/drv/drvdriver/drvdriver_device.h|   24 +
 .../drv/drvdriver/drvdriver_device_main.c  |   12 +
 .../validation/drv/drvdriver/drvdriver_devio.c |  209 
 .../validation/drv/drvdriver/drvdriver_devio.h |   24 +
 .../drv/drvdriver/drvdriver_devio_main.c   |   12 +
 .../validation/drv/drvdriver/drvdriver_driver.c|  518 ++
 .../validation/drv/drvdriver/drvdriver_driver.h|   24 +
 .../drv/drvdriver/drvdriver_driver_main.c  |   12 +
 .../validation/drv/drvdriver/drvdriver_enumr.c |  303 ++
 .../validation/drv/drvdriver/drvdriver_enumr.h |   24 +
 .../drv/drvdriver/drvdriver_enumr_class.c  |  174 
 .../drv/drvdriver/drvdriver_enumr_class.h  |   24 +
 .../drv/drvdriver/drvdriver_enumr_class_main.c |   12 +
 .../drv/drvdriver/drvdriver_enumr_main.c   |   12 +
 test/linux-generic/Makefile.am |5 +
 31 files changed, 3030 insertions(+), 35 deletions(-)
 create mode 100644 include/odp/drv/spec/hints.h
 create mode 100644 platform/linux-generic/include/drv_driver_internal.h
 create mode 100644 platform/linux-generic/include/odp/drv/hints.h
 create mode 100644 test/common_plat/validation/drv/drvdriver/.gitignore
 create mode 100644 test/common_plat/validation/drv/drvdriver/Makefile.am
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_device.c
 create mode 100644 test/common_plat/validation/drv/drvdriver/drvdriver_device.h
 create mode 100644 
test/common_plat/validation/drv/drvdriver/drvdriver_device_main.c

[lng-odp] [API-NEXT PATCHv2 01/23] drv: adding compiler hints in the driver interface

2017-03-22 Thread Christophe Milard
Largely inspired from its north api counterpart, the drv/spec/hint.h
file is added. Also includes the __constructor__ attributes that many
driver interface items will need.

Signed-off-by: Christophe Milard 
---
 include/odp/drv/spec/hints.h | 119 +++
 platform/Makefile.inc|   1 +
 2 files changed, 120 insertions(+)
 create mode 100644 include/odp/drv/spec/hints.h

diff --git a/include/odp/drv/spec/hints.h b/include/odp/drv/spec/hints.h
new file mode 100644
index 000..ddae22e
--- /dev/null
+++ b/include/odp/drv/spec/hints.h
@@ -0,0 +1,119 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODPDRV compiler hints
+ */
+
+#ifndef ODPDRV_API_HINTS_H_
+#define ODPDRV_API_HINTS_H_
+#include 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup odpdrv_compiler_optim
+ *  Macros that will give hints to the compiler.
+ *  @{
+ */
+
+#ifdef __GNUC__
+
+/** Define a function that should be run at early init (constructor)
+ */
+#define ODPDRV_CONSTRUCTOR __attribute__((__constructor__))
+
+/** Define a function that does not return
+ */
+#define ODPDRV_NORETURN __attribute__((__noreturn__))
+
+/** Define a weak symbol
+ * This is primarily useful in defining library functions that can be
+ * overridden in user code.
+ */
+#define ODPDRV_WEAK_SYMBOL __attribute__((__weak__))
+
+/**
+ * Hot code section
+ */
+#define ODPDRV_HOT_CODE__attribute__((__hot__))
+
+/**
+ * Cold code section
+ */
+#define ODPDRV_COLD_CODE   __attribute__((__cold__))
+
+/**
+ * Printf format attribute
+ */
+#define ODPDRV_PRINTF_FORMAT(x, y) __attribute__((format(printf, (x), (y
+
+/**
+ * Indicate deprecated variables, functions or types
+ */
+#define ODPDRV_DEPRECATED __attribute__((__deprecated__))
+
+/**
+ * Intentionally unused variables of functions
+ */
+#define ODPDRV_UNUSED __attribute__((__unused__))
+
+/**
+ * Branch likely taken
+ */
+#define odpdrv_likely(x)   __builtin_expect((x), 1)
+
+/**
+ * Branch unlikely taken
+ */
+#define odpdrv_unlikely(x) __builtin_expect((x), 0)
+
+/*
+ * __builtin_prefetch (const void *addr, rw, locality)
+ *
+ * rw 0..1   (0: read, 1: write)
+ * locality 0..3 (0: don't leave to cache, 3: leave on all cache levels)
+ */
+
+/**
+ * Cache prefetch address
+ */
+#define odpdrv_prefetch(x) __builtin_prefetch((x), 0, 3)
+
+/**
+ * Cache prefetch address for storing
+ */
+#define odpdrv_prefetch_store(x)   __builtin_prefetch((x), 1, 3)
+
+#else
+
+#define ODPDRV_CONSTRUCTOR
+#define ODPDRV_NORETURN
+#define ODPDRV_WEAK_SYMBOL
+#define ODPDRV_HOT_CODE
+#define ODPDRV_COLD_CODE
+#define ODPDRV_DEPRECATED
+#define ODPDRV_UNUSED
+#define odpdrv_likely(x)
+#define odpdrv_unlikely(x)
+#define odpdrv_prefetch(x)
+#define odpdrv_prefetch_store(x)
+
+#endif
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#include 
+#endif
diff --git a/platform/Makefile.inc b/platform/Makefile.inc
index 874cf88..e439e3c 100644
--- a/platform/Makefile.inc
+++ b/platform/Makefile.inc
@@ -69,6 +69,7 @@ odpdrvspecinclude_HEADERS = \
  $(top_srcdir)/include/odp/drv/spec/byteorder.h \
  $(top_srcdir)/include/odp/drv/spec/compiler.h \
  $(top_srcdir)/include/odp/drv/spec/driver.h \
+ $(top_srcdir)/include/odp/drv/spec/hints.h \
  $(top_srcdir)/include/odp/drv/spec/shm.h \
  $(top_srcdir)/include/odp/drv/spec/spinlock.h \
  $(top_srcdir)/include/odp/drv/spec/std_types.h \
-- 
2.7.4



Re: [lng-odp] [PATCHv3 0/5] test: generator: improve performance

2017-03-22 Thread Maxim Uvarov

CHECK: Alignment should match open parenthesis
#99: FILE: example/generator/odp_generator.c:254:
+   odp_memcpy(buf, odp_packet_data(pkt_ref),
+   args->appl.payload + ODPH_UDPHDR_LEN +

CHECK: Alignment should match open parenthesis
#189: FILE: example/generator/odp_generator.c:348:
+   odp_memcpy(buf, odp_packet_data(pkt_ref),
+   args->appl.payload + ODPH_ICMPHDR_LEN +

CHECK: braces {} should be used on all arms of this statement
#215: FILE: example/generator/odp_generator.c:456:
+   if (args->appl.mode == APPL_MODE_UDP)
[...]
+   else if (args->appl.mode == APPL_MODE_PING)
[...]
+   else {
[...]


On 03/20/17 10:28, Bogdan Pricope wrote:
> Improve performance of "odp_generator" example application.
> 
> Bogdan Pricope (5):
>   test: generator: compose sending packets from reference packet plus
> differences
>   test: generator: send UDP packets in bursts
>   test: generator: receive packets in bursts
>   test: generator: use multiple RX queue in receiving mode
>   test: generator: use multiple TX queues in send UDP mode
> 
>  example/generator/odp_generator.c | 366 
> +-
>  1 file changed, 277 insertions(+), 89 deletions(-)
> 



Re: [lng-odp] [PATCH] Fix memory ordering in ring dequeue

2017-03-22 Thread Bill Fischofer
On Tue, Mar 21, 2017 at 11:54 PM, Brian Brooks  wrote:
>
> Acquire ordering is needed to maintain proper release consistency with
> the ring enqueue operation. This issue presented itself as deadlock when
> running on an ARM-based chip.
>
> Signed-off-by: Brian Brooks 

Reviewed-by: Bill Fischofer 

> ---
>  platform/linux-generic/include/odp_ring_internal.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/platform/linux-generic/include/odp_ring_internal.h 
> b/platform/linux-generic/include/odp_ring_internal.h
> index 55fedeb3..44b83c60 100644
> --- a/platform/linux-generic/include/odp_ring_internal.h
> +++ b/platform/linux-generic/include/odp_ring_internal.h
> @@ -57,7 +57,7 @@ static inline uint32_t ring_deq(ring_t *ring, uint32_t mask)
>
> /* Move reader head. This thread owns data at the new head. */
> do {
> -   tail = odp_atomic_load_u32(&ring->w_tail);
> +   tail = odp_atomic_load_acq_u32(&ring->w_tail);
>
> if (head == tail)
> return RING_EMPTY;
> @@ -90,7 +90,7 @@ static inline uint32_t ring_deq_multi(ring_t *ring, 
> uint32_t mask,
>
> /* Move reader head. This thread owns data at the new head. */
> do {
> -   tail = odp_atomic_load_u32(&ring->w_tail);
> +   tail = odp_atomic_load_acq_u32(&ring->w_tail);
>
> /* Ring is empty */
> if (head == tail)
> --
> 2.12.0
>


Re: [lng-odp] [API-NEXT PATCH v2 2/3] api: ipsec: add inline IPSEC support

2017-03-22 Thread Bill Fischofer
On Wed, Mar 22, 2017 at 6:37 AM, Peltonen, Janne (Nokia - FI/Espoo) <
janne.pelto...@nokia.com> wrote:

> Hi,
>
> > > +
> > > +   /** Outer headers for inline output operation
> > > +*
> > > +*  Outbound inline IPSEC operation uses this information to
> > > prepend
> > > +*  outer headers to the IPSEC packet before sending it out.
> > > +*/
> > > +   struct {
> > > +   /** Points to first byte of outer headers to be copied
> in
> > > +*  front of the outgoing IPSEC packet. Implementation
> > > copies
> > > +*  the headers during odp_ipsec_out_inline() call. */
> > > +   uint8_t *ptr;
> > >
> >
> > Should this be an odp_packet_t rather than a raw set of bytes? The
> > rationale for making this an odp_packet_t is that this could then be a
> > packet reference which can be used for (re)transmit tracking. For input
>
> If it were odp_packet_t, the IPsec implementation would have to be
> prepared for the data to be segmented in arbitrary ways, which probably
> would not improve performance. And to me it is not really a packet anyway.
>

It's as much of a packet as the hdr passed to odp_packet_ref_pkt() to be
prefixed to the created reference. An odp_packet_t is how we represent
packets (complete and partial) in ODP, so it makes sense to be consistent
here. We already have minimum segment sizes in the packet definition so I
don't see this being a concern here any more than in any other ODP packet
APIs.


>
> I did not quite understand the point about retransmit tracking in this
> context.
>

One of the main use cases for references is to permit easy retransmit
processing via constructs like:

odp_pktout_send(outq, odp_packet_ref_static(pkt));

That allows the caller to hold onto a reference to the packet being
transmitted both for retransmit purposes as well as to be able to determine
that that transmit has been successful, indicated by
odp_packet_has_ref(pkt) returning from 1 to 0. You can't really pass a
reference to the IPsec routines since references have read-only payloads
and IPsec is transforming the payload, however if you have a separate
header that can be a reference since all you're asking is that this be
prefixed to the result prior to transmission, so it would seem the same
capabilities would result.


>
> One thing we already discussed with Petri is that to enable IP and UDP
> based tunneling protocols (e.g. IPIP, GRE, VxLAN) outside the IPsec
> packet in the inline output case, the right packet length would have
> to be inserted in the right place of the added header. There is the
> same issue with L2 protocols that would contain the total packet
> length (e.g. some proprietary fabric encapsulation). In this case
> the outer header is rather like a template. This is something to be
> considered in some future versions of the API but one possible
> way to accommodate some of these cases is to have an offset that
> specifies which word of the complete packet shall be incremented
> by the resulting packet size after IPsec encapsulation.
>

I agree this is a direction we want to go, but I'd want to see this done
via a generalized tunnel acceleration set of APIs the permit general
encapsulation/decapsulation services. Given the flexibility inherent in
this sort of processing, I see this as one area where synergy with the P4
project is most promising. P4 excels at offering highly efficient
descriptions of bit-level packet structures and manipulations that can be
implemented in soft logic like FPGAs. The idea would be that the
application would either select from a library of predefined P4 templates
or be able to specify its own unique formats without requiring a new ODP
API for every such variant. Something worth exploring.


>
> > having this be raw bytes makes sense since the ODP implementation is
> > controlling their allocation and placement, however for output how is the
> > application going to allocate these? Presumably it would create a header
> > via odp_packet_alloc() and then use odp_packet_data() to get this
> address,
> > but that seems cumbersome compared to simply passing the odp_packet_t
> > directly. The alternative would seem to require that the application use
> > some sort of odp_shm_reserve() call, but that gets awkward and is far
> less
> > efficient than packet allocation, which is a fastpath operation.
> >
>
> I do not think applications would dynamically allocate the storage for the
> header (through packet alloc or shm alloc or whatever) for every packet
> sent
> but would just have the pointer point to a cached header somewhere (e.g.
> ready-made L2 header cached in the next hop structure found by L3 route
> search). If the header or part of it does have to be constructed on the
> fly, the application can use the stack or other thread specific storage
> that does not have to be allocated separately for every output operation.
> Or maybe even some existing per-packet memory like the 

Re: [lng-odp] [API-NEXT PATCH v2 2/3] api: ipsec: add inline IPSEC support

2017-03-22 Thread Savolainen, Petri (Nokia - FI/Espoo)

NO HTML mails to the ODP list please. Indentation is lost due to HTML.


 /**
+ * Protocol layers in IPSEC configuration
+ */
+typedef enum odp_ipsec_proto_layer_t {
+       /** No layers */
+       ODP_IPSEC_LAYER_NONE = 0,
+
+       /** Layer L2 protocols (Ethernet, VLAN, etc) */
+       ODP_IPSEC_LAYER_L2,
+
+       /** Layer L3 protocols (IPv4, IPv6, ICMP, IPSec, etc) */

Nit: Correct spelling is IPsec, not IPSec, per RFC 4301.

+       /** Parse packet headers in IPSEC payload
+        *
+        *  Select header parsing level after inbound processing. Packet headers
+        *  in IPSEC payload must be parsed (at least) up to this level.
+        *  Default value is ODP_IPSEC_LAYER_NONE.
+        *
+        *  Note that IPSec payload is never a L2 packet (ODP_IPSEC_LAYER_L2

IPsec


OK. I'll correct it to IPSEC, which is used throughout this file.

" All other capitalizations of IPsec (e.g., IPSEC, IPSec, ipsec) are 
deprecated. However, any capitalization of the  sequence of letters "IPsec" 
should be understood to refer to the IPsec protocols. "

 
+/**
  * IPSEC Security Association (SA) parameters
  */
 typedef struct odp_ipsec_sa_param_t {
@@ -426,6 +610,17 @@ typedef struct odp_ipsec_sa_param_t {
        /** SPI value */
        uint32_t spi;

+       /** Additional inbound SA lookup parameters. Values are considered
+        *  only in ODP_IPSEC_LOOKUP_IN_DSTADDR_UNIQUE_SPI lookup mode. */
+       struct {
+               /* v4 or v6 */
+               uint8_t ip_version;

Is this an enum? If not perhaps doc this as 4 = IPv4, 6 = IPv6.

OK. I'll document it.

 

 /**
+ * Outbound inline IPSEC operation parameters
+ */
+typedef struct odp_ipsec_inline_op_param_t {
+       /** Packet output interface for inline output operation
+        *
+        *  Outbound inline IPSEC operation uses this packet IO interface to
+        *  output the packet after a successful IPSEC transformation. The pktio
+        *  must have been configured to operate in inline IPSEC mode.
+        */
+       odp_pktio_t pktio;

Shouldn't we have an option for this to be output to an odp_tm_queue_t instead 
of a pktio? 
Also, for output are there any controls over which odp_pktout_queue_t is used, 
or is this undefined?


TM is not supported at this stage. Destination TM queue will be added here when 
TM support is added.

Pktout queues are for application use, there's no benefit from those to an 
accelerator (IPSEC may use whatever  implementation specific way to deliver 
packet to pktio).

 
+
+       /** Outer headers for inline output operation
+        *
+        *  Outbound inline IPSEC operation uses this information to prepend
+        *  outer headers to the IPSEC packet before sending it out.
+        */
+       struct {
+               /** Points to first byte of outer headers to be copied in
+                *  front of the outgoing IPSEC packet. Implementation copies
+                *  the headers during odp_ipsec_out_inline() call. */
+               uint8_t *ptr;

Should this be an odp_packet_t rather than a raw set of bytes? The rationale 
for making this an odp_packet_t is that this could then be a packet reference 
which can be used for (re)transmit tracking. For input having this be raw bytes 
makes sense since the ODP implementation is controlling their allocation and 
placement, however for output how is the application going to allocate these? 
Presumably it would create a header via odp_packet_alloc() and then use 
odp_packet_data() to get this address, but that seems cumbersome compared to 
simply passing the odp_packet_t directly. The alternative would seem to require 
that the application use some sort of odp_shm_reserve() call, but that gets 
awkward and is far less efficient than packet allocation, which is a fastpath 
operation.
 

Packet is not needed for l2 hdr storage. Application will store headers to e.g. 
SA context, etc convenient memory location and pass only a pointer to there. 
Implementation copies those (few) bytes during odp_ipsec_out_inline() call. 
Since headers are copied, there's no special requirement for the memory - also 
stack can be used. Most likely application would not store the headers into a 
packet - since there's no benefit on doing so. The payload packet would be more 
likely target for reference counting (than l2 hdr bytes).


 /**
@@ -773,18 +1045,14 @@ typedef struct odp_ipsec_op_result_t {
         *  at least 'num_pkt' elements.
         *
         *  Each successfully transformed packet has a valid value for these
-        *  meta-data:
+        *  meta-data regardless of the inner packet parse configuration.

Vestigial typo. It's metadata, not meta-data. Might as well clean up here.

OK.

+
+       /** Outbound IPSEC inlined with packet output
+        *
+        *  Enable/disable inline outbound IPSEC operation. When enabled IPSEC
+        *  outbound processing can send outgoing IPSEC packets directly
+        *  to the pktio interface for output. IPSEC

Re: [lng-odp] [API-NEXT PATCH v2 2/3] api: ipsec: add inline IPSEC support

2017-03-22 Thread Peltonen, Janne (Nokia - FI/Espoo)
Hi,

> > +
> > +   /** Outer headers for inline output operation
> > +*
> > +*  Outbound inline IPSEC operation uses this information to
> > prepend
> > +*  outer headers to the IPSEC packet before sending it out.
> > +*/
> > +   struct {
> > +   /** Points to first byte of outer headers to be copied in
> > +*  front of the outgoing IPSEC packet. Implementation
> > copies
> > +*  the headers during odp_ipsec_out_inline() call. */
> > +   uint8_t *ptr;
> >
> 
> Should this be an odp_packet_t rather than a raw set of bytes? The
> rationale for making this an odp_packet_t is that this could then be a
> packet reference which can be used for (re)transmit tracking. For input

If it were odp_packet_t, the IPsec implementation would have to be
prepared for the data to be segmented in arbitrary ways, which probably
would not improve performance. And to me it is not really a packet anyway.

I did not quite understand the point about retransmit tracking in this
context.

One thing we already discussed with Petri is that to enable IP and UDP
based tunneling protocols (e.g. IPIP, GRE, VxLAN) outside the IPsec
packet in the inline output case, the right packet length would have
to be inserted in the right place of the added header. There is the
same issue with L2 protocols that would contain the total packet
length (e.g. some proprietary fabric encapsulation). In this case
the outer header is rather like a template. This is something to be
considered in some future versions of the API but one possible
way to accommodate some of these cases is to have an offset that
specifies which word of the complete packet shall be incremented
by the resulting packet size after IPsec encapsulation.

> having this be raw bytes makes sense since the ODP implementation is
> controlling their allocation and placement, however for output how is the
> application going to allocate these? Presumably it would create a header
> via odp_packet_alloc() and then use odp_packet_data() to get this address,
> but that seems cumbersome compared to simply passing the odp_packet_t
> directly. The alternative would seem to require that the application use
> some sort of odp_shm_reserve() call, but that gets awkward and is far less
> efficient than packet allocation, which is a fastpath operation.
>

I do not think applications would dynamically allocate the storage for the
header (through packet alloc or shm alloc or whatever) for every packet sent
but would just have the pointer point to a cached header somewhere (e.g.
ready-made L2 header cached in the next hop structure found by L3 route
search). If the header or part of it does have to be constructed on the
fly, the application can use the stack or other thread specific storage
that does not have to be allocated separately for every output operation.
Or maybe even some existing per-packet memory like the user area.

Btw, the API should make it clear if the header data can be in the headroom
or the user area of the packet being enqueued (I suppose the latter should
be fine).
 
Janne


> -Original Message-
> From: lng-odp [mailto:lng-odp-boun...@lists.linaro.org] On Behalf Of Bill 
> Fischofer
> Sent: Wednesday, March 22, 2017 12:17 AM
> To: Petri Savolainen 
> Cc: lng-odp-forward 
> Subject: Re: [lng-odp] [API-NEXT PATCH v2 2/3] api: ipsec: add inline IPSEC 
> support
> 
> On Tue, Mar 21, 2017 at 9:17 AM, Petri Savolainen <
> petri.savolai...@linaro.org> wrote:
> 
> > Added support for inline IPSEC processing on packet input and
> > output. Inline mode IPSEC and traffic manager cannot be enabled
> > (currently) on the same pktio interface.
> >
> > Signed-off-by: Petri Savolainen 
> > ---
> >  include/odp/api/spec/ipsec.h | 348 ++
> > ++---
> >  include/odp/api/spec/packet_io.h |  32 
> >  2 files changed, 355 insertions(+), 25 deletions(-)
> >
> > diff --git a/include/odp/api/spec/ipsec.h b/include/odp/api/spec/ipsec.h
> > index e951e49..23d02cf 100644
> > --- a/include/odp/api/spec/ipsec.h
> > +++ b/include/odp/api/spec/ipsec.h
> > @@ -19,6 +19,8 @@ extern "C" {
> >  #endif
> >
> >  #include 
> > +#include 
> > +#include 
> >
> >  /** @defgroup odp_ipsec ODP IPSEC
> >   *  Operations of IPSEC API.
> > @@ -51,11 +53,43 @@ typedef enum odp_ipsec_op_mode_t {
> >   * Application uses asynchronous IPSEC operations,
> >   * which return results via events.
> >   */
> > -   ODP_IPSEC_OP_MODE_ASYNC
> > +   ODP_IPSEC_OP_MODE_ASYNC,
> > +
> > +   /** Inline IPSEC operation
> > + *
> > + * Packet input/output is connected directly to IPSEC
> > inbound/outbound
> > + * processing. Application uses asynchronous or inline IPSEC
> > + * operations.
> > + */
> > +   ODP_IPSEC_OP_MODE_INLINE,
> > +
> > +   /** IPSEC is disabled in inbound / outbound direction */
> > +   ODP_IPSEC

Re: [lng-odp] [RFC, API-NEXT v1 1/1] comp:compression interface

2017-03-22 Thread Bogdan Pricope
Hi,

My understanding is that:
 - compression can be used in stateless or statefull mode. How can we
differentiate between the two configurations: by specifying a special
algorithm on session creation or by setting "last" field to "true" for
every operation? Do we need this setting per operation or per session?
 - stateless mode may be used by IPComp (RFC3173) - it will be
application job to add IPComp header between IP header and payload
 - statefull mode requires a connection oriented protocol (TCP)
support to take care of delivering date in order and without drops.
How will receiver know if payload is clear text or compressed? Should
use a well-known port?

- on statefull mode, it will always be an output for every input or
algorithm may decide to concat consecutive packets and output fewer?
- in-place vs. new packet: in-place processing will be added later -
you should take care on what you to copy between input and output
packets - user area, pkt user pointer, etc.

Is my understanding correct?

BR,
Bogdan

On 17 March 2017 at 14:20, Mahipal Challa  wrote:
> From: Shally Verma 
>
> An API set to add compression/decompression support in ODP
> interface.
>
> Signed-off-by: Shally Verma 
> Signed-off-by: Mahipal Challa 
> ---
>  include/odp/api/spec/comp.h | 668 
> 
>  1 file changed, 668 insertions(+)
>
> diff --git a/include/odp/api/spec/comp.h b/include/odp/api/spec/comp.h
> new file mode 100644
> index 000..d8f6c68
> --- /dev/null
> +++ b/include/odp/api/spec/comp.h
> @@ -0,0 +1,668 @@
> +/* Copyright (c) 2017, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:BSD-3-Clause
> + */
> +
> +/**
> + * @file
> + *
> + * ODP Compression
> + */
> +
> +#ifndef ODP_API_COMP_H_
> +#define ODP_API_COMP_H_
> +#include 
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/** @defgroup odp_compression ODP COMP
> + *  ODP Compression defines interface to compress/decompress and authenticate
> + *  data.
> + *
> + *  Compression here implicilty refer to both compression and decompression.
> + *  Example, compression algo 'deflate' mean both 'deflate' and 'inflate'.
> + *
> + *  if opcode = ODP_COMP_COMPRESS, then it will Compress,
> + *  if opcode = ODP_COMP_DECOMPRESS, then it will Decompress.
> + *
> + *  Current version of Interface allow Compression ONLY,Authentication ONLY 
> or
> + *  both Compression + Auth ONLY sessions.
> + *
> + *  Macros, enums, types and operations to utilise compression.
> + *  @{
> + */
> +
> +/**
> + * @def ODP_COMP_SESSION_INVALID
> + * Invalid session handle
> + */
> +
> +/**
> + * @typedef odp_comp_session_t (platform dependent)
> + * Comp API opaque session handle
> + */
> +
> +/**
> + * @typedef odp_comp_compl_t
> +* Compression API completion event (platform dependent)
> +*/
> +
> +/**
> + * Compression API operation mode
> + */
> +typedef enum {
> +   /** Synchronous, return results immediately */
> +   ODP_COMP_SYNC,
> +   /** Asynchronous, return results via event */
> +   ODP_COMP_ASYNC,
> +} odp_comp_op_mode_t;
> +
> +/**
> + * Comp API operation type
> + */
> +typedef enum {
> +   /** Compress and/or Compute ICV  */
> +   ODP_COMP_OP_COMPRESS,
> +   /** Decompress and/or Compute ICV */
> +   ODP_COMP_OP_DECOMPRESS,
> +} odp_comp_op_t;
> +
> +/**
> + * Comp API compression algorithm
> + *
> + *  Enum listing support Compression algo. Currently one
> + *  Compressor corresponds to 1 compliant decompressor.
> + *
> + */
> +typedef enum {
> +   /** No algorithm specified */
> +   ODP_COMP_ALG_NULL,
> +   /** DEFLATE -
> +   *
> +   * implicit Inflate in case of decode operation
> +   *
> +   */
> +   ODP_COMP_ALG_DEFLATE,
> +   /** ZLIB */
> +   ODP_COMP_ALG_ZLIB,
> +   /** LZS*/
> +   ODP_COMP_ALG_LZS,
> +   /** SHA1
> +   *
> +   * When given, imply Authentication ONLY operation
> +   *
> +   */
> +   ODP_COMP_ALG_SHA1,
> +   /** SHA256
> +   *
> +   * When given, imply Authentication ONLY operation
> +   *
> +   */
> +   ODP_COMP_ALG_SHA256,
> +   /** DEFLATE+SHA1  */
> +   ODP_COMP_ALG_DEFLATE_SHA1,
> +   /** DEFLATE+SHA256   */
> +   ODP_COMP_ALG_DEFLATE_SHA256,
> +   /** ZLIB+SHA  */
> +   ODP_COMP_ALG_ZLIB_SHA1,
> +   /** ZLIB+SHA256 */
> +   ODP_COMP_ALG_ZLIB_SHA256,
> +   /** LZS+SHA1   */
> +   ODP_COMP_ALG_LZS_SHA1,
> +   /** LZS+SHA256 */
> +   ODP_COMP_ALG_LZS_SHA256
> +} odp_comp_alg_t;
> +
> +/**
> + * Comp API session creation return code
> + */
> +typedef enum {
> +   /** Session created */
> +   ODP_COMP_SES_CREATE_ERR_NONE,
> +   /** Creation failed, no resources */
> +   ODP_COMP_SES_CREATE_ERR_ENOMEM,
> +   /** Creation failed, bad compression params */
> +   ODP_COMP_SES_CREATE_ERR_INV_COMP,
> +   /** Creation failed,requested configuration not supported*/
> +