Subject: [RFC] Try to improve RTL8187B initialization time

As reported before, we know that the initialization of rtl8187b interfaces is
slow. There were some strange sleeps from vendor driver that were imported too
just to be sure, but they don't seem to be needed. After looking at r8180 code,
I think they really aren't needed, and using it as reference, I did a similar
initialization now for rtl8187b, on quick tests seems to work well.

Another thing I got is a RTL818X_CONFIG3_ANAPARAM_WRITE being enabled without
writing any ANAPARAM value (this came from vendor driver also), I changed it to
write ANAPARAM_ON like on other places and disable config3 write, but in my
tests didn't seem to make any noticeable difference.

diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index f981fdb..25d9a0e 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -634,8 +634,6 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF4, 0, 1);
rtl818x_iowrite8_idx(priv, (u8 *)0xFFF8, 0, 1);

- rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001);
-
rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x569A, 2);

rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD,
@@ -643,14 +641,13 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
reg |= RTL818X_CONFIG3_ANAPARAM_WRITE;
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
+ RTL8187B_RTL8225_ANAPARAM_ON);
+ reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE;
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD,
RTL818X_EEPROM_CMD_NORMAL);

- rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
- rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488);
- rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
- msleep(1100);
-
priv->rf->init(dev);

reg = RTL818X_CMD_TX_ENABLE | RTL818X_CMD_RX_ENABLE;
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
index 1bae899..9549e33 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -835,6 +835,15 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
struct rtl8187_priv *priv = dev->priv;
int i;

+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+ msleep(200);
+ rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001);
+ rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+
rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
rtl8225_write(dev, 0x2, 0x44D); msleep(1);
@@ -850,25 +859,36 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
rtl8225_write(dev, 0xc, 0x850); msleep(1);
rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
rtl8225_write(dev, 0xe, 0x02B); msleep(1);
- rtl8225_write(dev, 0xf, 0x114); msleep(1);
+ rtl8225_write(dev, 0xf, 0x114); msleep(100);

- rtl8225_write(dev, 0x0, 0x1B7); msleep(1);
+ if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+ rtl8225_write(dev, 0x02, 0x0C4D);
+ msleep(200);
+ rtl8225_write(dev, 0x02, 0x044D);
+ msleep(100);
+ /* TODO: detect calibration failure? */
+ }
+
+ rtl8225_write(dev, 0x0, 0x1B7);
+ rtl8225_write(dev, 0x3, 0x002);
+ rtl8225_write(dev, 0x5, 0x004);

for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
- rtl8225_write(dev, 0x1, i + 1); msleep(1);
- rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); msleep(1);
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
}

- rtl8225_write(dev, 0x3, 0x080); msleep(1);
- rtl8225_write(dev, 0x5, 0x004); msleep(1);
- rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
- msleep(3000);
+ rtl8225_write(dev, 0x0, 0x0B7);
+ msleep(100);
+ rtl8225_write(dev, 0x2, 0xC4D);
+ msleep(200);
+ rtl8225_write(dev, 0x2, 0x44D);
+ msleep(100);

- rtl8225_write(dev, 0x2, 0xC4D); msleep(1);
- msleep(2000);
+ rtl8225_write(dev, 0x00, 0x2BF);
+ rtl8225_write(dev, 0xFF, 0xFFFF);

- rtl8225_write(dev, 0x2, 0x44D); msleep(1);
- rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);

rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);


--
[]'s
Herton


Subject: Re: [RFC] Try to improve RTL8187B initialization time

Em Thursday 10 July 2008 19:51:18 Hin-Tak Leung escreveu:
> Herton Ronaldo Krzesinski wrote:
> > As reported before, we know that the initialization of rtl8187b interfaces is
> > slow. There were some strange sleeps from vendor driver that were imported too
> > just to be sure, but they don't seem to be needed. After looking at r8180 code,
> > I think they really aren't needed, and using it as reference, I did a similar
> > initialization now for rtl8187b, on quick tests seems to work well.
>
> Most of the change is minor - mainly 6 secs is removed in 3 big chunks, but
> a fraction of a sec here and there is added back elsewhere, so the net effect
> is probably 4-5 sec, or less, since you also added some new code.
> How about just removing the 3 chunks as below?
>
> I am wondering also if some of the delays is simply that some of the init
> numbers is wrong and the firmware gets thrown into some mini-recovery over-ride
> routine.

I think it's something needed for hardware/RF chip to "settle down" or have
time to save the rf parameter after the given command. Removing the msleeps is
another option, testing here it worked (in fact I think it lowered the net
traffic quality a bit but nothing much noticeable, could be some noise), but
this could hide something or introduce random bug due to timing issue (like
lower tx/rx quality or interface not working sometimes). Doing something
similar like RTL8180/R8185 was the idea to avoid some problem basing on a known
to work code for the same radio chip (although risking to have something
specific to 8185/8180 brought in...).

>
> I also have another "theory" - the windows driver is sensitive to the hardware
> switch and the linux driver not, so obviously the effect of the hardware switch
> can be overrided in software. To give the *appearance* of fast initialization,
> maybe the windows driver simply initialize everything on load (i.e. when windows
> starts), then switch the radio on and off when the user asks to shut off the
> interface, etc. I have never got ndiswrapper to work on x86_64 (ifconfig up
> stuck) - how does timing of ifconfig up/down with ndiswrapper compare?

I didn't written down the full time, but it's much faster, ie. not this huge
delay compared to the linux driver.

>
> BTW, ndiswrapper won't even build with 2.6.26-rc9.

On a 2.6.26-rc9 builds ok here (i386), I don't remember to have any extra patch
needed.

>
> > diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
> > index f981fdb..25d9a0e 100644
> > --- a/drivers/net/wireless/rtl8187_dev.c
> > +++ b/drivers/net/wireless/rtl8187_dev.c
>
> > @@ -643,14 +641,13 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
>
> > - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
> > - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488);
> > - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
> > - msleep(1100);
> > -
>
> 1st one.
>
> > diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
> > index 1bae899..9549e33 100644
> > --- a/drivers/net/wireless/rtl8187_rtl8225.c
> > +++ b/drivers/net/wireless/rtl8187_rtl8225.c
>
> > @@ -850,25 +859,36 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
>
> > - rtl8225_write(dev, 0x3, 0x080); msleep(1);
> > - rtl8225_write(dev, 0x5, 0x004); msleep(1);
> > - rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
> > - msleep(3000);
>
> 2nd
>
>
> > + rtl8225_write(dev, 0x0, 0x0B7);
> > + msleep(100);
> > + rtl8225_write(dev, 0x2, 0xC4D);
> > + msleep(200);
> > + rtl8225_write(dev, 0x2, 0x44D);
> > + msleep(100);
> >
> > - rtl8225_write(dev, 0x2, 0xC4D); msleep(1);
> > - msleep(2000);
>
> 3rd, but some are added as above.
>
>

--
[]'s
Herton

2008-07-10 22:43:41

by Hin-Tak Leung

[permalink] [raw]
Subject: Re: [RFC] Try to improve RTL8187B initialization time

Herton Ronaldo Krzesinski wrote:
> As reported before, we know that the initialization of rtl8187b interfaces is
> slow. There were some strange sleeps from vendor driver that were imported too
> just to be sure, but they don't seem to be needed. After looking at r8180 code,
> I think they really aren't needed, and using it as reference, I did a similar
> initialization now for rtl8187b, on quick tests seems to work well.

Most of the change is minor - mainly 6 secs is removed in 3 big chunks, but
a fraction of a sec here and there is added back elsewhere, so the net effect
is probably 4-5 sec, or less, since you also added some new code.
How about just removing the 3 chunks as below?

I am wondering also if some of the delays is simply that some of the init
numbers is wrong and the firmware gets thrown into some mini-recovery over-ride
routine.

I also have another "theory" - the windows driver is sensitive to the hardware
switch and the linux driver not, so obviously the effect of the hardware switch
can be overrided in software. To give the *appearance* of fast initialization,
maybe the windows driver simply initialize everything on load (i.e. when windows
starts), then switch the radio on and off when the user asks to shut off the
interface, etc. I have never got ndiswrapper to work on x86_64 (ifconfig up
stuck) - how does timing of ifconfig up/down with ndiswrapper compare?

BTW, ndiswrapper won't even build with 2.6.26-rc9.

> diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
> index f981fdb..25d9a0e 100644
> --- a/drivers/net/wireless/rtl8187_dev.c
> +++ b/drivers/net/wireless/rtl8187_dev.c

> @@ -643,14 +641,13 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)

> - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
> - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488);
> - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
> - msleep(1100);
> -

1st one.

> diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
> index 1bae899..9549e33 100644
> --- a/drivers/net/wireless/rtl8187_rtl8225.c
> +++ b/drivers/net/wireless/rtl8187_rtl8225.c

> @@ -850,25 +859,36 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)

> - rtl8225_write(dev, 0x3, 0x080); msleep(1);
> - rtl8225_write(dev, 0x5, 0x004); msleep(1);
> - rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
> - msleep(3000);

2nd


> + rtl8225_write(dev, 0x0, 0x0B7);
> + msleep(100);
> + rtl8225_write(dev, 0x2, 0xC4D);
> + msleep(200);
> + rtl8225_write(dev, 0x2, 0x44D);
> + msleep(100);
>
> - rtl8225_write(dev, 0x2, 0xC4D); msleep(1);
> - msleep(2000);

3rd, but some are added as above.


2008-07-11 16:51:32

by Hin-Tak Leung

[permalink] [raw]
Subject: Re: [RFC] Try to improve RTL8187B initialization time

Herton Ronaldo Krzesinski wrote:
> Em Thursday 10 July 2008 19:51:18 Hin-Tak Leung escreveu:
<snipped>
>> BTW, ndiswrapper won't even build with 2.6.26-rc9.
>
> On a 2.6.26-rc9 builds ok here (i386), I don't remember to have any extra patch
> needed.

I was looking for more developer-oriented info for ndiswrapper to see if I can
fix the XP 64-bit realtek driver on x86_64 linux to see how it compares with the
new native driver, and found two other places Pavel spends his time on (broadcom
firmware cutter and ndiswrapper). He just committed a patch within the last day
or two to ndiswrapper trunk to fix the build problem I saw - apparently it is
WEXT change scheduled for 2.6.27. I saw it sooner than I should because I
was testing John's new redhat rawhide 2.6.26-rc9 kernel with the new rtl8187b
driver.

If ndiswrapper trunk doesn't work with 64-bit realtek, I am probably going to
dig in to see what's wrong with it. Wish me luck!