Commit 4c4d6160 authored by Federico Vaga's avatar Federico Vaga

kernel: do not use embedded function to avoid kernel panic

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 5ac4e38e
...@@ -18,10 +18,11 @@ ...@@ -18,10 +18,11 @@
#include "fine-delay.h" #include "fine-delay.h"
typedef int (*sdb_traverse_cb) (uint32_t address, uint32_t size, uint64_t vid, uint32_t did); typedef int (*sdb_traverse_cb) (uint32_t address, uint32_t size, uint64_t vid, uint32_t did, void *data);
static int traverse_sdb_devices(struct sdb_array *tree, static int traverse_sdb_devices(struct sdb_array *tree,
sdb_traverse_cb cb) sdb_traverse_cb cb,
void *data)
{ {
union sdb_record *r; union sdb_record *r;
struct sdb_product *p; struct sdb_product *p;
...@@ -38,11 +39,11 @@ static int traverse_sdb_devices(struct sdb_array *tree, ...@@ -38,11 +39,11 @@ static int traverse_sdb_devices(struct sdb_array *tree,
if (!IS_ERR(tree->subtree[i])) if (!IS_ERR(tree->subtree[i]))
{ {
rv = traverse_sdb_devices ( tree->subtree[i], cb ); rv = traverse_sdb_devices ( tree->subtree[i], cb, data );
if(rv > 0) if(rv > 0)
return 1; return 1;
} }
if (r->empty.record_type != sdb_type_device) if (r->empty.record_type != sdb_type_device)
continue; continue;
...@@ -52,51 +53,64 @@ static int traverse_sdb_devices(struct sdb_array *tree, ...@@ -52,51 +53,64 @@ static int traverse_sdb_devices(struct sdb_array *tree,
vid = __be64_to_cpu(p->vendor_id); vid = __be64_to_cpu(p->vendor_id);
did = __be32_to_cpu(p->device_id); did = __be32_to_cpu(p->device_id);
size = (uint32_t) (last + 1 - first); size = (uint32_t) (last + 1 - first);
if (cb (first + tree->baseaddr, size, vid, did)) if (cb (first + tree->baseaddr, size, vid, did, data))
return 1; return 1;
} }
return 0; return 0;
} }
/* Finds the Nth SDB device that matches (vid/did) pair, where N <= *ordinal. struct callback_state {
If N < *ordinal, the value of N is stored at *ordinal. int n;
This magic is used to handle hybrid bistreams (with two or more different int *ordinal;
mezzanines). */
signed long fmc_sdb_find_nth_device (struct sdb_array *tree, uint64_t vid, uint32_t did, int *ordinal, uint32_t *size )
{
int n = -1;
uint32_t current_address; uint32_t current_address;
uint32_t current_size; uint32_t current_size;
uint64_t did;
int callback (uint32_t address, uint32_t size, uint64_t vid_, uint32_t did_) uint32_t vid;
{ };
if(vid_ == vid && did_ == did)
static int callback (uint32_t address, uint32_t size, uint64_t vid_, uint32_t did_, void *data)
{
struct callback_state *st = (struct callback_state *) data;
if(vid_ == st->vid && did_ == st->did)
{ {
n++; st->n++;
current_address = address; st->current_address = address;
current_size = size; st->current_size = size;
if(!ordinal || n == *ordinal) if(!st->ordinal || st->n == *st->ordinal)
{ {
return 1; return 1;
} }
} }
return 0; /* continue scanning */ return 0; /* continue scanning */
} }
traverse_sdb_devices (tree, callback); /* Finds the Nth SDB device that matches (vid/did) pair, where N <= *ordinal.
If N < *ordinal, the value of N is stored at *ordinal.
This magic is used to handle hybrid bistreams (with two or more different
mezzanines). */
if (n >= 0) signed long fmc_sdb_find_nth_device (struct sdb_array *tree, uint64_t vid, uint32_t did, int *ordinal, uint32_t *size )
{
struct callback_state st;
st.n = -1;
st.ordinal = ordinal;
st.vid = vid;
st.did = did;
traverse_sdb_devices (tree, callback, &st);
if (st.n >= 0)
{ {
if(size) if(size)
*size = current_size; *size = st.current_size;
if(ordinal) if(ordinal)
*ordinal = n; *ordinal = st.n;
return current_address; return st.current_address;
} }
return -ENODEV; return -ENODEV;
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment