wct4xxp: Atomically perform some read/modify/write operations
There are read/modify/write operations on the framer that were not protected by any locks. While I didn't notice any code paths that would result in simultaneous accesses to these registers, this change will hopefully save someone else some time in the future verifying that the accesses are safe. A side effect is that the reglock is acquired only once for each read/modify/write cycle as opposed to twice previously. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Acked-by: Michael Spiceland <mspiceland@digium.com> Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10248 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
parent
a81fb56b5f
commit
b7485aa383
@ -808,6 +808,7 @@ static void hdlc_stop(struct t4 *wc, unsigned int span)
|
|||||||
{
|
{
|
||||||
struct t4_span *t = wc->tspans[span];
|
struct t4_span *t = wc->tspans[span];
|
||||||
unsigned char imr0, imr1, mode;
|
unsigned char imr0, imr1, mode;
|
||||||
|
unsigned long flags;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (debug & DEBUG_FRAMER)
|
if (debug & DEBUG_FRAMER)
|
||||||
@ -820,19 +821,21 @@ static void hdlc_stop(struct t4 *wc, unsigned int span)
|
|||||||
t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00);
|
t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
imr0 = t4_framer_in(wc, span, FRMR_IMR0);
|
spin_lock_irqsave(&wc->reglock, flags);
|
||||||
imr1 = t4_framer_in(wc, span, FRMR_IMR1);
|
imr0 = __t4_framer_in(wc, span, FRMR_IMR0);
|
||||||
|
imr1 = __t4_framer_in(wc, span, FRMR_IMR1);
|
||||||
|
|
||||||
/* Disable HDLC interrupts */
|
/* Disable HDLC interrupts */
|
||||||
imr0 |= HDLC_IMR0_MASK;
|
imr0 |= HDLC_IMR0_MASK;
|
||||||
t4_framer_out(wc, span, FRMR_IMR0, imr0);
|
__t4_framer_out(wc, span, FRMR_IMR0, imr0);
|
||||||
|
|
||||||
imr1 |= HDLC_IMR1_MASK;
|
imr1 |= HDLC_IMR1_MASK;
|
||||||
t4_framer_out(wc, span, FRMR_IMR1, imr1);
|
__t4_framer_out(wc, span, FRMR_IMR1, imr1);
|
||||||
|
|
||||||
mode = t4_framer_in(wc, span, FRMR_MODE);
|
mode = __t4_framer_in(wc, span, FRMR_MODE);
|
||||||
mode &= ~FRMR_MODE_HRAC;
|
mode &= ~FRMR_MODE_HRAC;
|
||||||
t4_framer_out(wc, span, FRMR_MODE, mode);
|
__t4_framer_out(wc, span, FRMR_MODE, mode);
|
||||||
|
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||||
|
|
||||||
t->sigactive = 0;
|
t->sigactive = 0;
|
||||||
}
|
}
|
||||||
@ -879,29 +882,33 @@ static int hdlc_start(struct t4 *wc, unsigned int span, struct dahdi_chan *chan,
|
|||||||
|
|
||||||
mode |= FRMR_MODE_HRAC;
|
mode |= FRMR_MODE_HRAC;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&wc->reglock, flags);
|
||||||
|
|
||||||
/* Make sure we're in the right mode */
|
/* Make sure we're in the right mode */
|
||||||
t4_framer_out(wc, span, FRMR_MODE, mode);
|
__t4_framer_out(wc, span, FRMR_MODE, mode);
|
||||||
t4_framer_out(wc, span, FRMR_TSEO, 0x00);
|
__t4_framer_out(wc, span, FRMR_TSEO, 0x00);
|
||||||
t4_framer_out(wc, span, FRMR_TSBS1, hardhdlcmode);
|
__t4_framer_out(wc, span, FRMR_TSBS1, hardhdlcmode);
|
||||||
|
|
||||||
/* Set the interframe gaps, etc */
|
/* Set the interframe gaps, etc */
|
||||||
t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS);
|
__t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS);
|
||||||
|
|
||||||
t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC);
|
__t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC);
|
||||||
|
|
||||||
/* Set up the time slot that we want to tx/rx on */
|
/* Set up the time slot that we want to tx/rx on */
|
||||||
t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
|
__t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
|
||||||
t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
|
__t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
|
||||||
|
|
||||||
imr0 = t4_framer_in(wc, span, FRMR_IMR0);
|
imr0 = __t4_framer_in(wc, span, FRMR_IMR0);
|
||||||
imr1 = t4_framer_in(wc, span, FRMR_IMR1);
|
imr1 = __t4_framer_in(wc, span, FRMR_IMR1);
|
||||||
|
|
||||||
/* Enable our interrupts again */
|
/* Enable our interrupts again */
|
||||||
imr0 &= ~HDLC_IMR0_MASK;
|
imr0 &= ~HDLC_IMR0_MASK;
|
||||||
t4_framer_out(wc, span, FRMR_IMR0, imr0);
|
__t4_framer_out(wc, span, FRMR_IMR0, imr0);
|
||||||
|
|
||||||
imr1 &= ~HDLC_IMR1_MASK;
|
imr1 &= ~HDLC_IMR1_MASK;
|
||||||
t4_framer_out(wc, span, FRMR_IMR1, imr1);
|
__t4_framer_out(wc, span, FRMR_IMR1, imr1);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||||
|
|
||||||
/* Reset the signaling controller */
|
/* Reset the signaling controller */
|
||||||
t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES);
|
t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES);
|
||||||
@ -1789,6 +1796,7 @@ static void init_spans(struct t4 *wc)
|
|||||||
int gen2;
|
int gen2;
|
||||||
struct t4_span *ts;
|
struct t4_span *ts;
|
||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN);
|
gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN);
|
||||||
for (x = 0; x < wc->numspans; x++) {
|
for (x = 0; x < wc->numspans; x++) {
|
||||||
@ -1861,11 +1869,13 @@ static void init_spans(struct t4 *wc)
|
|||||||
ts->alarmcheck_time = jiffies + msecs_to_jiffies(250);
|
ts->alarmcheck_time = jiffies + msecs_to_jiffies(250);
|
||||||
|
|
||||||
/* Enable 1sec timer interrupt */
|
/* Enable 1sec timer interrupt */
|
||||||
reg = t4_framer_in(wc, x, FMR1_T);
|
spin_lock_irqsave(&wc->reglock, flags);
|
||||||
t4_framer_out(wc, x, FMR1_T, (reg | FMR1_ECM));
|
reg = __t4_framer_in(wc, x, FMR1_T);
|
||||||
|
__t4_framer_out(wc, x, FMR1_T, (reg | FMR1_ECM));
|
||||||
|
|
||||||
/* Enable Errored Second interrupt */
|
/* Enable Errored Second interrupt */
|
||||||
t4_framer_out(wc, x, ESM, 0);
|
__t4_framer_out(wc, x, ESM, 0);
|
||||||
|
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||||
|
|
||||||
t4_reset_counters(&ts->span);
|
t4_reset_counters(&ts->span);
|
||||||
|
|
||||||
@ -3924,6 +3934,7 @@ static int t4_hardware_init_2(struct t4 *wc)
|
|||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
unsigned int regval;
|
unsigned int regval;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (t4_pci_in(wc, WC_VERSION) >= 0xc01a0165) {
|
if (t4_pci_in(wc, WC_VERSION) >= 0xc01a0165) {
|
||||||
wc->tspans[0]->spanflags |= FLAG_OCTOPT;
|
wc->tspans[0]->spanflags |= FLAG_OCTOPT;
|
||||||
@ -3941,10 +3952,13 @@ static int t4_hardware_init_2(struct t4 *wc)
|
|||||||
if (t4_framer_in(wc, 0, 0x4a) != 0x05)
|
if (t4_framer_in(wc, 0, 0x4a) != 0x05)
|
||||||
dev_info(&wc->dev->dev, "WARNING: FALC framer not intialized "
|
dev_info(&wc->dev->dev, "WARNING: FALC framer not intialized "
|
||||||
"in compatibility mode.\n");
|
"in compatibility mode.\n");
|
||||||
regval = t4_framer_in(wc, 0 ,0xd6);
|
spin_lock_irqsave(&wc->reglock, flags);
|
||||||
|
regval = __t4_framer_in(wc, 0, 0xd6);
|
||||||
regval |= (1 << 5); /* set COMP_DIS*/
|
regval |= (1 << 5); /* set COMP_DIS*/
|
||||||
t4_framer_out(wc, 0, 0xd6, regval);
|
__t4_framer_out(wc, 0, 0xd6, regval);
|
||||||
regval = t4_framer_in(wc, 0, 0x4a);
|
regval = __t4_framer_in(wc, 0, 0x4a);
|
||||||
|
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||||
|
|
||||||
if (regval == 0x05)
|
if (regval == 0x05)
|
||||||
dev_info(&wc->dev->dev, "FALC Framer Version: 2.1 or "
|
dev_info(&wc->dev->dev, "FALC Framer Version: 2.1 or "
|
||||||
"earlier\n");
|
"earlier\n");
|
||||||
@ -3954,11 +3968,14 @@ static int t4_hardware_init_2(struct t4 *wc)
|
|||||||
} else
|
} else
|
||||||
dev_info(&wc->dev->dev, "FALC Framer Version: Unknown "
|
dev_info(&wc->dev->dev, "FALC Framer Version: Unknown "
|
||||||
"(VSTR = 0x%02x)\n", regval);
|
"(VSTR = 0x%02x)\n", regval);
|
||||||
regval = t4_framer_in(wc, 0 ,0xd6);
|
|
||||||
regval &= ~(1 << 5); /* clear COMP_DIS*/
|
|
||||||
t4_framer_out(wc, 0, 0xd6, regval);
|
|
||||||
|
|
||||||
t4_framer_out(wc, 0, 0x4a, 0xaa);
|
spin_lock_irqsave(&wc->reglock, flags);
|
||||||
|
regval = __t4_framer_in(wc, 0, 0xd6);
|
||||||
|
regval &= ~(1 << 5); /* clear COMP_DIS*/
|
||||||
|
__t4_framer_out(wc, 0, 0xd6, regval);
|
||||||
|
__t4_framer_out(wc, 0, 0x4a, 0xaa);
|
||||||
|
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
dev_info(&wc->dev->dev, "Board ID: %02x\n", wc->order);
|
dev_info(&wc->dev->dev, "Board ID: %02x\n", wc->order);
|
||||||
for (x = 0; x < 11; x++) {
|
for (x = 0; x < 11; x++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user