diff options
Diffstat (limited to 'drivers/net/wireless/libertas/cmd.c')
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index c4b32a05de10..bb940cce3a73 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "dev.h" | 11 | #include "dev.h" |
12 | #include "join.h" | 12 | #include "join.h" |
13 | #include "wext.h" | 13 | #include "wext.h" |
14 | #include "cmd.h" | ||
14 | 15 | ||
15 | static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode); | 16 | static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode); |
16 | struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); | 17 | struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); |
@@ -36,18 +37,78 @@ static u8 is_command_allowed_in_ps(u16 cmd) | |||
36 | return 0; | 37 | return 0; |
37 | } | 38 | } |
38 | 39 | ||
39 | static int lbs_cmd_hw_spec(struct lbs_private *priv, struct cmd_ds_command *cmd) | 40 | /** |
41 | * @brief Updates the hardware details like MAC address and regulatory region | ||
42 | * | ||
43 | * @param priv A pointer to struct lbs_private structure | ||
44 | * | ||
45 | * @return 0 on success, error on failure | ||
46 | */ | ||
47 | int lbs_update_hw_spec(struct lbs_private *priv) | ||
40 | { | 48 | { |
41 | struct cmd_ds_get_hw_spec *hwspec = &cmd->params.hwspec; | 49 | struct cmd_ds_get_hw_spec cmd; |
50 | int ret = -1; | ||
51 | u32 i; | ||
52 | DECLARE_MAC_BUF(mac); | ||
42 | 53 | ||
43 | lbs_deb_enter(LBS_DEB_CMD); | 54 | lbs_deb_enter(LBS_DEB_CMD); |
44 | 55 | ||
45 | cmd->command = cpu_to_le16(CMD_GET_HW_SPEC); | 56 | memset(&cmd, 0, sizeof(cmd)); |
46 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN); | 57 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
47 | memcpy(hwspec->permanentaddr, priv->current_addr, ETH_ALEN); | 58 | memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN); |
59 | ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, cmd); | ||
60 | if (ret) | ||
61 | goto out; | ||
62 | |||
63 | priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo); | ||
64 | memcpy(priv->fwreleasenumber, cmd.fwreleasenumber, 4); | ||
65 | |||
66 | lbs_deb_cmd("GET_HW_SPEC: firmware release %u.%u.%up%u\n", | ||
67 | priv->fwreleasenumber[2], priv->fwreleasenumber[1], | ||
68 | priv->fwreleasenumber[0], priv->fwreleasenumber[3]); | ||
69 | lbs_deb_cmd("GET_HW_SPEC: MAC addr %s\n", | ||
70 | print_mac(mac, cmd.permanentaddr)); | ||
71 | lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", | ||
72 | cmd.hwifversion, cmd.version); | ||
73 | |||
74 | /* Clamp region code to 8-bit since FW spec indicates that it should | ||
75 | * only ever be 8-bit, even though the field size is 16-bit. Some firmware | ||
76 | * returns non-zero high 8 bits here. | ||
77 | */ | ||
78 | priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF; | ||
79 | |||
80 | for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { | ||
81 | /* use the region code to search for the index */ | ||
82 | if (priv->regioncode == lbs_region_code_to_index[i]) | ||
83 | break; | ||
84 | } | ||
48 | 85 | ||
86 | /* if it's unidentified region code, use the default (USA) */ | ||
87 | if (i >= MRVDRV_MAX_REGION_CODE) { | ||
88 | priv->regioncode = 0x10; | ||
89 | lbs_pr_info("unidentified region code; using the default (USA)\n"); | ||
90 | } | ||
91 | |||
92 | if (priv->current_addr[0] == 0xff) | ||
93 | memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); | ||
94 | |||
95 | memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN); | ||
96 | if (priv->mesh_dev) | ||
97 | memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); | ||
98 | |||
99 | if (lbs_set_regiontable(priv, priv->regioncode, 0)) { | ||
100 | ret = -1; | ||
101 | goto out; | ||
102 | } | ||
103 | |||
104 | if (lbs_set_universaltable(priv, 0)) { | ||
105 | ret = -1; | ||
106 | goto out; | ||
107 | } | ||
108 | |||
109 | out: | ||
49 | lbs_deb_leave(LBS_DEB_CMD); | 110 | lbs_deb_leave(LBS_DEB_CMD); |
50 | return 0; | 111 | return ret; |
51 | } | 112 | } |
52 | 113 | ||
53 | static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv, | 114 | static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv, |
@@ -1223,9 +1284,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1223 | cmdptr->result = 0; | 1284 | cmdptr->result = 0; |
1224 | 1285 | ||
1225 | switch (cmd_no) { | 1286 | switch (cmd_no) { |
1226 | case CMD_GET_HW_SPEC: | ||
1227 | ret = lbs_cmd_hw_spec(priv, cmdptr); | ||
1228 | break; | ||
1229 | case CMD_802_11_PS_MODE: | 1287 | case CMD_802_11_PS_MODE: |
1230 | ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action); | 1288 | ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action); |
1231 | break; | 1289 | break; |