summaryrefslogtreecommitdiffstats
path: root/bsps/shared/grlib/1553/gr1553rt.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/shared/grlib/1553/gr1553rt.c')
-rw-r--r--bsps/shared/grlib/1553/gr1553rt.c123
1 files changed, 79 insertions, 44 deletions
diff --git a/bsps/shared/grlib/1553/gr1553rt.c b/bsps/shared/grlib/1553/gr1553rt.c
index 339e856c76..7f35138376 100644
--- a/bsps/shared/grlib/1553/gr1553rt.c
+++ b/bsps/shared/grlib/1553/gr1553rt.c
@@ -147,7 +147,6 @@ static int gr1553rt_list_reg(struct gr1553rt_list *list)
return -1;
}
-#if 0 /* unused for now */
/* Unregister List from device */
static void gr1553rt_list_unreg(struct gr1553rt_list *list)
{
@@ -156,16 +155,15 @@ static void gr1553rt_list_unreg(struct gr1553rt_list *list)
priv->lists[list->listid] = NULL;
list->listid = -1;
}
-#endif
static int gr1553rt_bdid(void *rt, struct gr1553rt_sw_bd *bd)
{
struct gr1553rt_priv *priv = rt;
-
+
unsigned short index;
/* Get Index of Software BD */
- index = ((unsigned int)bd - (unsigned int)&priv->swbds[0]) /
+ index = ((unsigned int)bd - (unsigned int)&priv->swbds[0]) /
sizeof(struct gr1553rt_sw_bd);
return index;
@@ -197,10 +195,9 @@ static int gr1553rt_bd_alloc(void *rt, struct gr1553rt_sw_bd **bd, int cnt)
}
*bd = &priv->swbds[priv->swbd_free];
+ curr = &priv->swbds[priv->swbd_free];
for (i=0; i<cnt; i++) {
- if ( i == 0) {
- curr = &priv->swbds[priv->swbd_free];
- } else {
+ if ( i != 0) {
curr = &priv->swbds[curr->this_next];
}
if ( curr->this_next == 0xffff ) {
@@ -240,7 +237,7 @@ int gr1553rt_list_init
{
struct gr1553rt_priv *priv = rt;
size_t size;
- int i;
+ int i, malloc_used;
struct gr1553rt_sw_bd *swbd;
unsigned short index;
struct gr1553rt_list *list;
@@ -251,6 +248,7 @@ int gr1553rt_list_init
* If the IN/OUT plist argument points to NULL a list
* dynamically allocated here.
*/
+ malloc_used = 0;
list = *plist;
if ( list == NULL ) {
/* Dynamically allocate LIST */
@@ -258,20 +256,27 @@ int gr1553rt_list_init
(cfg->bd_cnt * sizeof(list->bds[0]));
list = grlib_malloc(size);
if ( list == NULL )
- return -1;
+ return -1; /* Out of Memory */
*plist = list;
+ malloc_used = 1;
}
list->rt = rt;
list->subadr = -1;
list->listid = gr1553rt_list_reg(list);
- if ( list->listid == -1 )
+ if ( list->listid == -1 ) {
+ if (malloc_used)
+ free(list);
return -2; /* Too many lists */
+ }
list->cfg = cfg;
list->bd_cnt = cfg->bd_cnt;
/* Allocate all BDs needed by list */
if ( gr1553rt_bd_alloc(rt, &swbd, list->bd_cnt) ) {
+ gr1553rt_list_unreg(list);
+ if (malloc_used)
+ free(list);
return -3; /* Too few descriptors */
}
@@ -352,7 +357,7 @@ int gr1553rt_bd_init(
bd->next = nextbd;
SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
- return 0;
+ return 0;
}
int gr1553rt_bd_update(
@@ -410,7 +415,7 @@ int gr1553rt_bd_update(
}
*dptr = (uint16_t *)tmp;
}
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
+ SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
return 0;
}
@@ -727,7 +732,7 @@ void gr1553rt_hw_stop(struct gr1553rt_priv *priv)
GR1553RT_WRITE_REG(&priv->regs->rt_cfg, GR1553RT_KEY);
/* Stop BC if not already stopped: BC can not be used simultaneously
- * as the RT anyway
+ * as the RT anyway
*/
GR1553RT_WRITE_REG(&priv->regs->bc_ctrl, GR1553BC_KEY | 0x0204);
@@ -766,17 +771,17 @@ void gr1553rt_sw_free(struct gr1553rt_priv *priv)
}
}
-/* Free dynamically allocated buffers, if any */
static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
{
int size;
+ int retval = 0;
/* Allocate Event log */
if ((unsigned int)priv->cfg.evlog_buffer & 1) {
/* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */
- priv->evlog_hw_base = (unsigned int *)
+ priv->evlog_buffer = (void *)
((unsigned int)priv->cfg.evlog_buffer & ~0x1);
- priv->evlog_buffer = priv->cfg.evlog_buffer;
+ priv->evlog_hw_base = (unsigned int*)priv->evlog_buffer;
drvmgr_translate_check(
*priv->pdev,
DMAMEM_TO_CPU,
@@ -788,16 +793,19 @@ static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
if (priv->cfg.evlog_buffer == NULL) {
priv->evlog_buffer = grlib_malloc(
priv->cfg.evlog_size * 2);
- if (priv->evlog_buffer == NULL)
- return -1;
+ if (priv->evlog_buffer == NULL) {
+ retval = -1;
+ goto err;
+ }
+ /* Align to SIZE bytes boundary */
+ priv->evlog_cpu_base = (unsigned int *)
+ (((unsigned int)priv->evlog_buffer +
+ (priv->cfg.evlog_size-1)) & ~(priv->cfg.evlog_size-1));
} else {
/* Addess already CPU-LOCAL */
priv->evlog_buffer = priv->cfg.evlog_buffer;
+ priv->evlog_cpu_base = (unsigned int *)priv->evlog_buffer;
}
- /* Align to SIZE bytes boundary */
- priv->evlog_cpu_base = (unsigned int *)
- (((unsigned int)priv->evlog_buffer +
- (priv->cfg.evlog_size-1)) & ~(priv->cfg.evlog_size-1));
drvmgr_translate_check(
*priv->pdev,
@@ -807,6 +815,11 @@ static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
priv->cfg.evlog_size
);
}
+ /* Verify alignment */
+ if ((unsigned int)priv->evlog_hw_base & (priv->cfg.evlog_size-1)) {
+ retval = -2;
+ goto err;
+ }
priv->evlog_cpu_end = priv->evlog_cpu_base +
priv->cfg.evlog_size/sizeof(unsigned int *);
@@ -815,9 +828,9 @@ static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
size = priv->bds_cnt * sizeof(struct gr1553rt_bd);
if ((unsigned int)priv->cfg.bd_buffer & 1) {
/* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */
- priv->bds_hw = (struct gr1553rt_bd *)
+ priv->bd_buffer = (void *)
((unsigned int)priv->cfg.bd_buffer & ~0x1);
- priv->bd_buffer = priv->cfg.bd_buffer;
+ priv->bds_hw = (struct gr1553rt_bd *)priv->bd_buffer;
drvmgr_translate_check(
*priv->pdev,
DMAMEM_TO_CPU,
@@ -828,15 +841,18 @@ static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
} else {
if ( priv->cfg.bd_buffer == NULL ) {
priv->bd_buffer = grlib_malloc(size + 0xf);
- if (priv->bd_buffer == NULL)
- return -1;
+ if (priv->bd_buffer == NULL) {
+ retval = -1;
+ goto err;
+ }
+ /* Align to 16 bytes boundary */
+ priv->bds_cpu = (struct gr1553rt_bd *)
+ (((unsigned int)priv->bd_buffer + 0xf) & ~0xf);
} else {
/* Addess already CPU-LOCAL */
priv->bd_buffer = priv->cfg.bd_buffer;
+ priv->bds_cpu = (struct gr1553rt_bd *)priv->bd_buffer;
}
- /* Align to 16 bytes boundary */
- priv->bds_cpu = (struct gr1553rt_bd *)
- (((unsigned int)priv->bd_buffer + 0xf) & ~0xf);
/* Translate from CPU address to hardware address */
drvmgr_translate_check(
@@ -847,21 +863,28 @@ static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
size
);
}
+ /* Verify alignment */
+ if ((unsigned int)priv->bds_hw & (0xf)) {
+ retval = -2;
+ goto err;
+ }
#if (RTBD_MAX == 0)
/* Allocate software description of */
priv->swbds = grlib_malloc(priv->cfg.bd_count * sizeof(*priv->swbds));
if ( priv->swbds == NULL ) {
- return -1;
+ retval = -1;
+ goto err;
}
#endif
/* Allocate Sub address table */
if ((unsigned int)priv->cfg.satab_buffer & 1) {
/* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */
- priv->sas_hw = (struct gr1553rt_sa *)
+ priv->satab_buffer = (void *)
((unsigned int)priv->cfg.satab_buffer & ~0x1);
- priv->satab_buffer = priv->cfg.satab_buffer;
+ priv->sas_hw = (struct gr1553rt_sa *)priv->satab_buffer;
+
drvmgr_translate_check(
*priv->pdev,
DMAMEM_TO_CPU,
@@ -871,16 +894,18 @@ static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
} else {
if (priv->cfg.satab_buffer == NULL) {
priv->satab_buffer = grlib_malloc((16 * 32) * 2);
- if (priv->satab_buffer == NULL)
- return -1;
+ if (priv->satab_buffer == NULL) {
+ retval = -1;
+ goto err;
+ }
+ /* Align to 512 bytes boundary */
+ priv->sas_cpu = (struct gr1553rt_sa *)
+ (((unsigned int)priv->satab_buffer + 0x1ff) & ~0x1ff);
} else {
/* Addess already CPU-LOCAL */
priv->satab_buffer = priv->cfg.satab_buffer;
+ priv->sas_cpu = (struct gr1553rt_sa *)priv->satab_buffer;
}
- /* Align to 512 bytes boundary */
- priv->sas_cpu = (struct gr1553rt_sa *)
- (((unsigned int)priv->satab_buffer + 0x1ff) &
- ~0x1ff);
/* Translate Address from CPU-LOCAL to HARDWARE (REMOTE) */
drvmgr_translate_check(
@@ -890,8 +915,17 @@ static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
(void **)&priv->sas_hw,
16 * 32);
}
+ /* Verify alignment */
+ if ((unsigned int)priv->sas_hw & (0x1ff)) {
+ retval = -2;
+ goto err;
+ }
- return 0;
+err:
+ if (retval) {
+ gr1553rt_sw_free(priv);
+ }
+ return retval;
}
void gr1553rt_sw_init(struct gr1553rt_priv *priv)
@@ -937,7 +971,7 @@ void gr1553rt_sw_init(struct gr1553rt_priv *priv)
int gr1553rt_config(void *rt, struct gr1553rt_cfg *cfg)
{
struct gr1553rt_priv *priv = rt;
-
+ int retval = 0;
if ( priv->started )
return -1;
@@ -949,9 +983,9 @@ int gr1553rt_config(void *rt, struct gr1553rt_cfg *cfg)
if ( cfg->rtaddress > 30 )
return -1;
if ( (cfg->evlog_size & (cfg->evlog_size-1)) != 0)
- return -1; /* SIZE: Not aligned to a power of 2 */
+ return -2; /* SIZE: Not aligned to a power of 2 */
if ( ((unsigned int)priv->cfg.evlog_buffer & (cfg->evlog_size-1)) != 0 )
- return -1; /* Buffer: Not aligned to size */
+ return -2; /* Buffer: Not aligned to size */
#if (RTBD_MAX > 0)
if ( cfg->bd_count > RTBD_MAX )
return -1;
@@ -962,8 +996,9 @@ int gr1553rt_config(void *rt, struct gr1553rt_cfg *cfg)
/*** Adapt to new config ***/
- if ( gr1553rt_sw_alloc(priv) != 0 )
- return -1;
+ if ( (retval=gr1553rt_sw_alloc(priv)) != 0 ) {
+ return retval;
+ }
gr1553rt_sw_init(priv);