diff options
author | sruffell <sruffell@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2008-01-02 20:30:58 +0000 |
---|---|---|
committer | sruffell <sruffell@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2008-01-02 20:30:58 +0000 |
commit | 9099095634b7c959954a1d420c277b743e6ee7f6 (patch) | |
tree | 50cc73d7844e503e879812a5afc60e8423ddb481 /wcte12xp | |
parent | df19a0df6dab13f2be16680f039f0fe68a778198 (diff) |
VPMADT032 stability changes for wctdm24xxp and wcte12xp:
- Remove double reads.
- Wait for writes to complete before starting reads.
- Optimize reads of multi-word register.
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@3592 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wcte12xp')
-rw-r--r-- | wcte12xp/vpmadt032.c | 155 |
1 files changed, 105 insertions, 50 deletions
diff --git a/wcte12xp/vpmadt032.c b/wcte12xp/vpmadt032.c index 9050c6e..68455b8 100644 --- a/wcte12xp/vpmadt032.c +++ b/wcte12xp/vpmadt032.c @@ -289,7 +289,7 @@ static struct vpm150m_cmd * vpm150m_empty_slot(struct t1 *wc) { unsigned int x; - for (x = 0; x < sizeof(wc->vpm150m->cmdq) / sizeof(wc->vpm150m->cmdq[0]); x++) { + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { if (!wc->vpm150m->cmdq[x].flags) { return &wc->vpm150m->cmdq[x]; } @@ -297,50 +297,92 @@ static struct vpm150m_cmd * vpm150m_empty_slot(struct t1 *wc) return NULL; } -unsigned short t1_vpm150m_getreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) +/* Wait for any outstanding commands to be completed. */ +static inline int vpm150m_io_wait(struct t1 *wc) +{ + int x; + int ret=0; + for (x=0; x < VPM150M_MAX_COMMANDS;) { + if (wc->vpm150m->cmdq[x].flags) { + if ((ret=schluffen(&wc->regq))) { + return ret; + } + x=0; + } + else { + ++x; + } + } + return ret; +} + +int t1_vpm150m_getreg_full_async(struct t1 *wc, int pagechange, unsigned int len, + unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) { + int ret=0; unsigned long flags; - volatile struct vpm150m_cmd *hit; - unsigned short ret = 0; - int i; + BUG_ON(!hit_p); + spin_lock_irqsave(&wc->reglock, flags); + (*hit_p) = vpm150m_empty_slot(wc); + if (*hit_p) { + (*hit_p)->flags = __VPM150M_RD; + if (pagechange) { + (*hit_p)->flags |= __VPM150M_RWPAGE; + } + (*hit_p)->datalen = len; + (*hit_p)->address = addr; + memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); + } + else { + ret = -EBUSY; + } + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} +int t1_vpm150m_getreg_full_return(struct t1 *wc, int pagechange, unsigned int len, + unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) +{ + int ret = 0; + unsigned long flags; + BUG_ON(!hit_p); + spin_lock_irqsave(&wc->reglock, flags); do { - spin_lock_irqsave(&wc->reglock, flags); - hit = vpm150m_empty_slot(wc); - if (hit) { - hit->flags = __VPM150M_RD; - if(pagechange) - hit->flags |= __VPM150M_RWPAGE; - hit->datalen = len; - hit->address = addr; - for (i=0; i < hit->datalen; i++) - hit->data[i] = 0x0000; + if ((*hit_p)->flags & __VPM150M_FIN) { + memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); + (*hit_p)->flags = 0; + (*hit_p) = NULL; + ret = 0; } - spin_unlock_irqrestore(&wc->reglock, flags); - if (!hit) { - if ((ret = schluffen(&wc->regq))) + else { + spin_unlock_irqrestore(&wc->reglock, flags); + if ((ret=schluffen(&wc->regq))) { return ret; + } + spin_lock_irqsave(&wc->reglock, flags); + ret = -EBUSY; } - } while (!hit); + } while (-EBUSY == ret); + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} -#if 1 +int t1_vpm150m_getreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) +{ + struct vpm150m_cmd *hit = 0; + int ret = 0; do { - spin_lock_irqsave(&wc->reglock, flags); - if (hit->flags & __VPM150M_FIN) { - for (i = 0; i < hit->datalen; i++) - outbuf[i] = hit->data[i]; - hit->flags = 0; - hit=NULL; - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (hit) { - if ((ret = schluffen(&wc->regq))) - return ret; + ret = t1_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); + if (!hit) { + if ( -EBUSY == ret ) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + BUG_ON( 0 != ret); } - } while (hit); - -#endif + } while (!hit); + ret = t1_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); return ret; } @@ -403,20 +445,10 @@ int t1_vpm150m_setreg(struct t1 *wc, unsigned int len, unsigned int addr, unsign unsigned short t1_vpm150m_getreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) { unsigned short res; - unsigned short count=0; - unsigned short first_data=0; - do { - t1_vpm150m_setpage(wc, addr >> 16); - if ((addr >> 16) != ((addr + len) >> 16)) - module_printk("getreg: You found it!\n"); - if (count > 0) { - first_data = *data; - } - res = t1_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); - } while (((0==count++) || (first_data != *data)) && (count < 100)); - if (count >= 100) { - module_printk(" %s:%d\n", __FILE__, __LINE__); - } + t1_vpm150m_setpage(wc, addr >> 16); + if ((addr >> 16) != ((addr + len) >> 16)) + module_printk("getreg: You found it!\n"); + res = t1_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); return res; } @@ -985,8 +1017,31 @@ void gpakReadDspMemory( struct t1 *wc = wc_find_iface(DspId); int i; int transcount; - - if (wc && wc->vpm150m) { + int ret; + + vpm150m_io_wait(wc); + if ( NumWords < VPM150M_MAX_COMMANDS ) { + struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0}; + t1_vpm150m_setpage(wc, DspAddress >> 16); + DspAddress &= 0xffff; + for (i=0; i < NumWords; ++i) { + ret = t1_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], + &cmds[i]); + if (0 != ret) { + dump_stack(); + return; + } + } + for (i=NumWords-1; i >=0; --i) { + ret = t1_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], + &cmds[i]); + if (0 != ret) { + dump_stack(); + return; + } + } + } + else { for (i = 0; i < NumWords;) { if ((NumWords - i) > VPM150M_MAX_DATA) transcount = VPM150M_MAX_DATA; |