Commit 8a48b711 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] drivers/atm/horizon.c delousing

Same as with ambassador.c - same authors, same braindamage.
parent 5917ab47
...@@ -599,33 +599,14 @@ static inline u16 rx_q_entry_to_rx_channel (u32 x) { ...@@ -599,33 +599,14 @@ static inline u16 rx_q_entry_to_rx_channel (u32 x) {
#define CR_MAXPEXP 4 #define CR_MAXPEXP 4
static int make_rate (const hrz_dev * dev, u32 c, rounding r, static int make_rate (const hrz_dev * dev, u32 c, rounding r,
u16 * bits, unsigned int * actual) { u16 * bits, unsigned int * actual)
{
// note: rounding the rate down means rounding 'p' up // note: rounding the rate down means rounding 'p' up
const unsigned long br = test_bit(ultra, &dev->flags) ? BR_ULT : BR_HRZ; const unsigned long br = test_bit(ultra, &dev->flags) ? BR_ULT : BR_HRZ;
u32 div = CR_MIND; u32 div = CR_MIND;
u32 pre; u32 pre;
// local fn to build the timer bits
int set_cr (void) {
// paranoia
if (div > CR_MAXD || (!pre) || pre > 1<<CR_MAXPEXP) {
PRINTD (DBG_QOS, "set_cr internal failure: d=%u p=%u",
div, pre);
return -EINVAL;
} else {
if (bits)
*bits = (div<<CLOCK_SELECT_SHIFT) | (pre-1);
if (actual) {
*actual = (br + (pre<<div) - 1) / (pre<<div);
PRINTD (DBG_QOS, "actual rate: %u", *actual);
}
return 0;
}
}
// br_exp and br_man are used to avoid overflowing (c*maxp*2^d) in // br_exp and br_man are used to avoid overflowing (c*maxp*2^d) in
// the tests below. We could think harder about exact possibilities // the tests below. We could think harder about exact possibilities
// of failure... // of failure...
...@@ -634,7 +615,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r, ...@@ -634,7 +615,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
unsigned int br_exp = 0; unsigned int br_exp = 0;
PRINTD (DBG_QOS|DBG_FLOW, "make_rate b=%lu, c=%u, %s", br, c, PRINTD (DBG_QOS|DBG_FLOW, "make_rate b=%lu, c=%u, %s", br, c,
(r == round_up) ? "up" : (r == round_down) ? "down" : "nearest"); r == round_up ? "up" : r == round_down ? "down" : "nearest");
// avoid div by zero // avoid div by zero
if (!c) { if (!c) {
...@@ -665,15 +646,14 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r, ...@@ -665,15 +646,14 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
if (!pre) if (!pre)
pre = 1; pre = 1;
break; break;
case round_up: default: /* round_up */
pre = br/(c<<div); pre = br/(c<<div);
// but p must be non-zero // but p must be non-zero
if (!pre) if (!pre)
return -EINVAL; return -EINVAL;
break;
} }
PRINTD (DBG_QOS, "A: p=%u, d=%u", pre, div); PRINTD (DBG_QOS, "A: p=%u, d=%u", pre, div);
return set_cr (); goto got_it;
} }
// at this point we have // at this point we have
...@@ -693,30 +673,36 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r, ...@@ -693,30 +673,36 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
case round_nearest: case round_nearest:
pre = (br+(c<<div)/2)/(c<<div); pre = (br+(c<<div)/2)/(c<<div);
break; break;
case round_up: default: /* round_up */
pre = br/(c<<div); pre = br/(c<<div);
break;
} }
PRINTD (DBG_QOS, "B: p=%u, d=%u", pre, div); PRINTD (DBG_QOS, "B: p=%u, d=%u", pre, div);
return set_cr (); goto got_it;
} }
} }
// at this point we have // at this point we have
// d == MAXD and (c << (MAXPEXP+MAXD)) < B // d == MAXD and (c << (MAXPEXP+MAXD)) < B
// but we cannot go any higher // but we cannot go any higher
// take care of rounding // take care of rounding
switch (r) { if (r == round_down)
case round_down:
return -EINVAL; return -EINVAL;
break;
case round_nearest:
break;
case round_up:
break;
}
pre = 1 << CR_MAXPEXP; pre = 1 << CR_MAXPEXP;
PRINTD (DBG_QOS, "C: p=%u, d=%u", pre, div); PRINTD (DBG_QOS, "C: p=%u, d=%u", pre, div);
return set_cr (); got_it:
// paranoia
if (div > CR_MAXD || (!pre) || pre > 1<<CR_MAXPEXP) {
PRINTD (DBG_QOS, "set_cr internal failure: d=%u p=%u",
div, pre);
return -EINVAL;
} else {
if (bits)
*bits = (div<<CLOCK_SELECT_SHIFT) | (pre-1);
if (actual) {
*actual = (br + (pre<<div) - 1) / (pre<<div);
PRINTD (DBG_QOS, "actual rate: %u", *actual);
}
return 0;
}
} }
static int make_rate_with_tolerance (const hrz_dev * dev, u32 c, rounding r, unsigned int tol, static int make_rate_with_tolerance (const hrz_dev * dev, u32 c, rounding r, unsigned int tol,
...@@ -1823,22 +1809,22 @@ static void hrz_reset (const hrz_dev * dev) { ...@@ -1823,22 +1809,22 @@ static void hrz_reset (const hrz_dev * dev) {
/********** read the burnt in address **********/ /********** read the burnt in address **********/
static u16 __init read_bia (const hrz_dev * dev, u16 addr) { static inline void WRITE_IT_WAIT (const hrz_dev *dev, u32 ctrl)
{
u32 ctrl = rd_regl (dev, CONTROL_0_REG);
void WRITE_IT_WAIT (void) {
wr_regl (dev, CONTROL_0_REG, ctrl); wr_regl (dev, CONTROL_0_REG, ctrl);
udelay (5); udelay (5);
} }
void CLOCK_IT (void) { static inline void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
{
// DI must be valid around rising SK edge // DI must be valid around rising SK edge
ctrl &= ~SEEPROM_SK; WRITE_IT_WAIT(dev, ctrl & ~SEEPROM_SK);
WRITE_IT_WAIT(); WRITE_IT_WAIT(dev, ctrl | SEEPROM_SK);
ctrl |= SEEPROM_SK; }
WRITE_IT_WAIT();
} static u16 __init read_bia (const hrz_dev * dev, u16 addr)
{
u32 ctrl = rd_regl (dev, CONTROL_0_REG);
const unsigned int addr_bits = 6; const unsigned int addr_bits = 6;
const unsigned int data_bits = 16; const unsigned int data_bits = 16;
...@@ -1848,17 +1834,17 @@ static u16 __init read_bia (const hrz_dev * dev, u16 addr) { ...@@ -1848,17 +1834,17 @@ static u16 __init read_bia (const hrz_dev * dev, u16 addr) {
u16 res; u16 res;
ctrl &= ~(SEEPROM_CS | SEEPROM_SK | SEEPROM_DI); ctrl &= ~(SEEPROM_CS | SEEPROM_SK | SEEPROM_DI);
WRITE_IT_WAIT(); WRITE_IT_WAIT(dev, ctrl);
// wake Serial EEPROM and send 110 (READ) command // wake Serial EEPROM and send 110 (READ) command
ctrl |= (SEEPROM_CS | SEEPROM_DI); ctrl |= (SEEPROM_CS | SEEPROM_DI);
CLOCK_IT(); CLOCK_IT(dev, ctrl);
ctrl |= SEEPROM_DI; ctrl |= SEEPROM_DI;
CLOCK_IT(); CLOCK_IT(dev, ctrl);
ctrl &= ~SEEPROM_DI; ctrl &= ~SEEPROM_DI;
CLOCK_IT(); CLOCK_IT(dev, ctrl);
for (i=0; i<addr_bits; i++) { for (i=0; i<addr_bits; i++) {
if (addr & (1 << (addr_bits-1))) if (addr & (1 << (addr_bits-1)))
...@@ -1866,7 +1852,7 @@ static u16 __init read_bia (const hrz_dev * dev, u16 addr) { ...@@ -1866,7 +1852,7 @@ static u16 __init read_bia (const hrz_dev * dev, u16 addr) {
else else
ctrl &= ~SEEPROM_DI; ctrl &= ~SEEPROM_DI;
CLOCK_IT(); CLOCK_IT(dev, ctrl);
addr = addr << 1; addr = addr << 1;
} }
...@@ -1878,14 +1864,14 @@ static u16 __init read_bia (const hrz_dev * dev, u16 addr) { ...@@ -1878,14 +1864,14 @@ static u16 __init read_bia (const hrz_dev * dev, u16 addr) {
for (i=0;i<data_bits;i++) { for (i=0;i<data_bits;i++) {
res = res >> 1; res = res >> 1;
CLOCK_IT(); CLOCK_IT(dev, ctrl);
if (rd_regl (dev, CONTROL_0_REG) & SEEPROM_DO) if (rd_regl (dev, CONTROL_0_REG) & SEEPROM_DO)
res |= (1 << (data_bits-1)); res |= (1 << (data_bits-1));
} }
ctrl &= ~(SEEPROM_SK | SEEPROM_CS); ctrl &= ~(SEEPROM_SK | SEEPROM_CS);
WRITE_IT_WAIT(); WRITE_IT_WAIT(dev, ctrl);
return res; return res;
} }
......
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