aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/zd1211rw/zd_mac.c
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2007-07-01 18:22:32 +0100
committerJohn W. Linville <linville@tuxdriver.com>2007-07-10 14:14:56 -0400
commit74553aedd46b3a2cae986f909cf2a3f99369decc (patch)
tree6904945b36c017c58249b1900fbbd531f3286e49 /drivers/net/wireless/zd1211rw/zd_mac.c
parent93f510bbac64f552ef6872a39ae12afa06c4e999 (diff)
downloadkernel_samsung_smdk4412-74553aedd46b3a2cae986f909cf2a3f99369decc.zip
kernel_samsung_smdk4412-74553aedd46b3a2cae986f909cf2a3f99369decc.tar.gz
kernel_samsung_smdk4412-74553aedd46b3a2cae986f909cf2a3f99369decc.tar.bz2
[PATCH] zd1211rw: Defer firmware load until first ifup
While playing with the firmware a while back, I discovered a way to access the device's entire address space before the firmware has been loaded. Previously we were loading the firmware early on (during probe) so that we could read the MAC address from the EEPROM and register a netdevice. Now that we can read the EEPROM without having firmware, we can defer firmware loading until later while still reading the MAC address early on. This has the advantage that zd1211rw can now be built into the kernel -- previously if this was the case, zd1211rw would be loaded before the filesystem is available and firmware loading would fail. Firmware load and other device initialization operations now happen the first time the interface is brought up. Some architectural changes were needed: handling of the is_zd1211b flag was moved into the zd_usb structure, MAC address handling was obviously changed, and a preinit_hw stage was added (the order is now: init, preinit_hw, init_hw). Signed-off-by: Daniel Drake <dsd@gentoo.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_mac.c')
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 522de3f..f6c487a 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -86,28 +86,33 @@ out:
return r;
}
-int zd_mac_init_hw(struct zd_mac *mac, u8 device_type)
+int zd_mac_preinit_hw(struct zd_mac *mac)
{
int r;
- struct zd_chip *chip = &mac->chip;
u8 addr[ETH_ALEN];
+
+ r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
+ if (r)
+ return r;
+
+ memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
+ return 0;
+}
+
+int zd_mac_init_hw(struct zd_mac *mac)
+{
+ int r;
+ struct zd_chip *chip = &mac->chip;
u8 default_regdomain;
r = zd_chip_enable_int(chip);
if (r)
goto out;
- r = zd_chip_init_hw(chip, device_type);
+ r = zd_chip_init_hw(chip);
if (r)
goto disable_int;
- zd_get_e2p_mac_addr(chip, addr);
- r = zd_write_mac_addr(chip, addr);
- if (r)
- goto disable_int;
ZD_ASSERT(!irqs_disabled());
- spin_lock_irq(&mac->lock);
- memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
- spin_unlock_irq(&mac->lock);
r = zd_read_regdomain(chip, &default_regdomain);
if (r)
@@ -167,14 +172,25 @@ int zd_mac_open(struct net_device *netdev)
{
struct zd_mac *mac = zd_netdev_mac(netdev);
struct zd_chip *chip = &mac->chip;
+ struct zd_usb *usb = &chip->usb;
int r;
+ if (!usb->initialized) {
+ r = zd_usb_init_hw(usb);
+ if (r)
+ goto out;
+ }
+
tasklet_enable(&mac->rx_tasklet);
r = zd_chip_enable_int(chip);
if (r < 0)
goto out;
+ r = zd_write_mac_addr(chip, netdev->dev_addr);
+ if (r)
+ goto disable_int;
+
r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
if (r < 0)
goto disable_int;
@@ -254,9 +270,11 @@ int zd_mac_set_mac_address(struct net_device *netdev, void *p)
dev_dbg_f(zd_mac_dev(mac),
"Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data));
- r = zd_write_mac_addr(chip, addr->sa_data);
- if (r)
- return r;
+ if (netdev->flags & IFF_UP) {
+ r = zd_write_mac_addr(chip, addr->sa_data);
+ if (r)
+ return r;
+ }
spin_lock_irqsave(&mac->lock, flags);
memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -858,7 +876,7 @@ static int fill_ctrlset(struct zd_mac *mac,
/* ZD1211B: Computing the length difference this way, gives us
* flexibility to compute the packet length.
*/
- cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ?
+ cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
packet_length - frag_len : packet_length);
/*