aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2010-03-18 06:26:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-03-23 16:50:23 -0400
commit1b72aecd950c4c3cec2d66dbe5436c9e25a487b7 (patch)
tree1111ab6e6733300a6dd7dfe35f9a0d59c599dfcf /drivers
parent4695dc917d9ec7a38cb4f91fceb2b78aaec1f945 (diff)
wl1271: Fix MAC address handling
This patch fixes MAC address handling. To achieve this, firmware booting had to be delayed from the previous op_start to op_add_interface, which is the point when the driver gets to know the configured MAC address. As the wl1271 only supports one virtual interface, this even seems quite logical. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Kalle Valo <kalle.valo@nokia.com> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_boot.c8
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c149
2 files changed, 68 insertions, 89 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index f88d52e87e82..41c6affbee29 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -228,6 +228,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
228 nvs_len = sizeof(wl->nvs->nvs); 228 nvs_len = sizeof(wl->nvs->nvs);
229 nvs_ptr = (u8 *)wl->nvs->nvs; 229 nvs_ptr = (u8 *)wl->nvs->nvs;
230 230
231 /* update current MAC address to NVS */
232 nvs_ptr[11] = wl->mac_addr[0];
233 nvs_ptr[10] = wl->mac_addr[1];
234 nvs_ptr[6] = wl->mac_addr[2];
235 nvs_ptr[5] = wl->mac_addr[3];
236 nvs_ptr[4] = wl->mac_addr[4];
237 nvs_ptr[3] = wl->mac_addr[5];
238
231 /* 239 /*
232 * Layout before the actual NVS tables: 240 * Layout before the actual NVS tables:
233 * 1 byte : burst length. 241 * 1 byte : burst length.
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 037a4f4036fd..d8cb51410b2f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -570,40 +570,6 @@ out:
570 return ret; 570 return ret;
571} 571}
572 572
573static int wl1271_update_mac_addr(struct wl1271 *wl)
574{
575 int ret = 0;
576 u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
577
578 /* get mac address from the NVS */
579 wl->mac_addr[0] = nvs_ptr[11];
580 wl->mac_addr[1] = nvs_ptr[10];
581 wl->mac_addr[2] = nvs_ptr[6];
582 wl->mac_addr[3] = nvs_ptr[5];
583 wl->mac_addr[4] = nvs_ptr[4];
584 wl->mac_addr[5] = nvs_ptr[3];
585
586 /* FIXME: if it is a zero-address, we should bail out. Now, instead,
587 we randomize an address */
588 if (is_zero_ether_addr(wl->mac_addr)) {
589 static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
590 memcpy(wl->mac_addr, nokia_oui, 3);
591 get_random_bytes(wl->mac_addr + 3, 3);
592
593 /* update this address to the NVS */
594 nvs_ptr[11] = wl->mac_addr[0];
595 nvs_ptr[10] = wl->mac_addr[1];
596 nvs_ptr[6] = wl->mac_addr[2];
597 nvs_ptr[5] = wl->mac_addr[3];
598 nvs_ptr[4] = wl->mac_addr[4];
599 nvs_ptr[3] = wl->mac_addr[5];
600 }
601
602 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
603
604 return ret;
605}
606
607static int wl1271_fetch_nvs(struct wl1271 *wl) 573static int wl1271_fetch_nvs(struct wl1271 *wl)
608{ 574{
609 const struct firmware *fw; 575 const struct firmware *fw;
@@ -633,8 +599,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
633 599
634 memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); 600 memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file));
635 601
636 ret = wl1271_update_mac_addr(wl);
637
638out: 602out:
639 release_firmware(fw); 603 release_firmware(fw);
640 604
@@ -952,13 +916,58 @@ static struct notifier_block wl1271_dev_notifier = {
952 916
953static int wl1271_op_start(struct ieee80211_hw *hw) 917static int wl1271_op_start(struct ieee80211_hw *hw)
954{ 918{
919 wl1271_debug(DEBUG_MAC80211, "mac80211 start");
920
921 /*
922 * We have to delay the booting of the hardware because
923 * we need to know the local MAC address before downloading and
924 * initializing the firmware. The MAC address cannot be changed
925 * after boot, and without the proper MAC address, the firmware
926 * will not function properly.
927 *
928 * The MAC address is first known when the corresponding interface
929 * is added. That is where we will initialize the hardware.
930 */
931
932 return 0;
933}
934
935static void wl1271_op_stop(struct ieee80211_hw *hw)
936{
937 wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
938}
939
940static int wl1271_op_add_interface(struct ieee80211_hw *hw,
941 struct ieee80211_vif *vif)
942{
955 struct wl1271 *wl = hw->priv; 943 struct wl1271 *wl = hw->priv;
956 int retries = WL1271_BOOT_RETRIES; 944 int retries = WL1271_BOOT_RETRIES;
957 int ret = 0; 945 int ret = 0;
958 946
959 wl1271_debug(DEBUG_MAC80211, "mac80211 start"); 947 wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
948 vif->type, vif->addr);
960 949
961 mutex_lock(&wl->mutex); 950 mutex_lock(&wl->mutex);
951 if (wl->vif) {
952 ret = -EBUSY;
953 goto out;
954 }
955
956 wl->vif = vif;
957
958 switch (vif->type) {
959 case NL80211_IFTYPE_STATION:
960 wl->bss_type = BSS_TYPE_STA_BSS;
961 break;
962 case NL80211_IFTYPE_ADHOC:
963 wl->bss_type = BSS_TYPE_IBSS;
964 break;
965 default:
966 ret = -EOPNOTSUPP;
967 goto out;
968 }
969
970 memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
962 971
963 if (wl->state != WL1271_STATE_OFF) { 972 if (wl->state != WL1271_STATE_OFF) {
964 wl1271_error("cannot start because not in off state: %d", 973 wl1271_error("cannot start because not in off state: %d",
@@ -1014,20 +1023,20 @@ out:
1014 return ret; 1023 return ret;
1015} 1024}
1016 1025
1017static void wl1271_op_stop(struct ieee80211_hw *hw) 1026static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
1027 struct ieee80211_vif *vif)
1018{ 1028{
1019 struct wl1271 *wl = hw->priv; 1029 struct wl1271 *wl = hw->priv;
1020 int i; 1030 int i;
1021 1031
1022 wl1271_info("down"); 1032 mutex_lock(&wl->mutex);
1033 wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
1023 1034
1024 wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); 1035 wl1271_info("down");
1025 1036
1026 unregister_inetaddr_notifier(&wl1271_dev_notifier); 1037 unregister_inetaddr_notifier(&wl1271_dev_notifier);
1027 list_del(&wl->list); 1038 list_del(&wl->list);
1028 1039
1029 mutex_lock(&wl->mutex);
1030
1031 WARN_ON(wl->state != WL1271_STATE_ON); 1040 WARN_ON(wl->state != WL1271_STATE_ON);
1032 1041
1033 if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { 1042 if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) {
@@ -1070,6 +1079,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
1070 wl->rate_set = CONF_TX_RATE_MASK_BASIC; 1079 wl->rate_set = CONF_TX_RATE_MASK_BASIC;
1071 wl->sta_rate_set = 0; 1080 wl->sta_rate_set = 0;
1072 wl->flags = 0; 1081 wl->flags = 0;
1082 wl->vif = NULL;
1073 1083
1074 for (i = 0; i < NUM_TX_QUEUES; i++) 1084 for (i = 0; i < NUM_TX_QUEUES; i++)
1075 wl->tx_blocks_freed[i] = 0; 1085 wl->tx_blocks_freed[i] = 0;
@@ -1078,53 +1088,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
1078 mutex_unlock(&wl->mutex); 1088 mutex_unlock(&wl->mutex);
1079} 1089}
1080 1090
1081static int wl1271_op_add_interface(struct ieee80211_hw *hw,
1082 struct ieee80211_vif *vif)
1083{
1084 struct wl1271 *wl = hw->priv;
1085 int ret = 0;
1086
1087 wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
1088 vif->type, vif->addr);
1089
1090 mutex_lock(&wl->mutex);
1091 if (wl->vif) {
1092 ret = -EBUSY;
1093 goto out;
1094 }
1095
1096 wl->vif = vif;
1097
1098 switch (vif->type) {
1099 case NL80211_IFTYPE_STATION:
1100 wl->bss_type = BSS_TYPE_STA_BSS;
1101 break;
1102 case NL80211_IFTYPE_ADHOC:
1103 wl->bss_type = BSS_TYPE_IBSS;
1104 break;
1105 default:
1106 ret = -EOPNOTSUPP;
1107 goto out;
1108 }
1109
1110 /* FIXME: what if conf->mac_addr changes? */
1111
1112out:
1113 mutex_unlock(&wl->mutex);
1114 return ret;
1115}
1116
1117static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
1118 struct ieee80211_vif *vif)
1119{
1120 struct wl1271 *wl = hw->priv;
1121
1122 mutex_lock(&wl->mutex);
1123 wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
1124 wl->vif = NULL;
1125 mutex_unlock(&wl->mutex);
1126}
1127
1128#if 0 1091#if 0
1129static int wl1271_op_config_interface(struct ieee80211_hw *hw, 1092static int wl1271_op_config_interface(struct ieee80211_hw *hw,
1130 struct ieee80211_vif *vif, 1093 struct ieee80211_vif *vif,
@@ -2114,6 +2077,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
2114 struct ieee80211_hw *hw; 2077 struct ieee80211_hw *hw;
2115 struct wl1271 *wl; 2078 struct wl1271 *wl;
2116 int i, ret; 2079 int i, ret;
2080 static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
2117 2081
2118 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); 2082 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
2119 if (!hw) { 2083 if (!hw) {
@@ -2155,6 +2119,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
2155 wl->state = WL1271_STATE_OFF; 2119 wl->state = WL1271_STATE_OFF;
2156 mutex_init(&wl->mutex); 2120 mutex_init(&wl->mutex);
2157 2121
2122 /*
2123 * FIXME: we should use a zero MAC address here, but for now we
2124 * generate a random Nokia address.
2125 */
2126 memcpy(wl->mac_addr, nokia_oui, 3);
2127 get_random_bytes(wl->mac_addr + 3, 3);
2128
2158 /* Apply default driver configuration. */ 2129 /* Apply default driver configuration. */
2159 wl1271_conf_init(wl); 2130 wl1271_conf_init(wl);
2160 2131