X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fwl1251%2Fcmd.c;h=eaaebb7b8b7203dd4840c16c31ab24bd4f3db7a6;hp=6822b845efc15d5e2305bf468cf76c6bd83e1dce;hb=d93eda2f03c2b1ae007033aee80d573285b66b9e;hpb=eb497bef403c18e1e4ef1906e1f75010b325d87a diff --git a/drivers/net/wireless/wl1251/cmd.c b/drivers/net/wireless/wl1251/cmd.c index 6822b845efc1..eaaebb7b8b72 100644 --- a/drivers/net/wireless/wl1251/cmd.c +++ b/drivers/net/wireless/wl1251/cmd.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "wl1251.h" #include "reg.h" @@ -22,6 +23,7 @@ int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len) { struct wl1251_cmd_header *cmd; unsigned long timeout; + u32 poll_count = 0; u32 intr; int ret = 0; @@ -45,11 +47,20 @@ int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len) goto out; } - msleep(1); + poll_count++; + if (poll_count < 30) + udelay(1); + else + msleep(1); intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); } + wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); + + if (cmd->status != CMD_STATUS_SUCCESS) + wl1251_error("command %d returned %d", id, cmd->status); + wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, WL1251_ACX_INTR_CMD_COMPLETE); @@ -203,11 +214,11 @@ out: return ret; } -int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) +int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable) { struct cmd_enabledisable_path *cmd; int ret; - u16 cmd_rx, cmd_tx; + u16 cmd_rx; wl1251_debug(DEBUG_CMD, "cmd data path"); @@ -219,13 +230,10 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) cmd->channel = channel; - if (enable) { + if (enable) cmd_rx = CMD_ENABLE_RX; - cmd_tx = CMD_ENABLE_TX; - } else { + else cmd_rx = CMD_DISABLE_RX; - cmd_tx = CMD_DISABLE_TX; - } ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); if (ret < 0) { @@ -237,17 +245,38 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d", enable ? "start" : "stop", channel); +out: + kfree(cmd); + return ret; +} + +int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable) +{ + struct cmd_enabledisable_path *cmd; + int ret; + u16 cmd_tx; + + wl1251_debug(DEBUG_CMD, "cmd data path"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->channel = channel; + + if (enable) + cmd_tx = CMD_ENABLE_TX; + else + cmd_tx = CMD_DISABLE_TX; + ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); - if (ret < 0) { + if (ret < 0) wl1251_error("tx %s cmd for channel %d failed", enable ? "start" : "stop", channel); - goto out; - } - - wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d", - enable ? "start" : "stop", channel); + else + wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d", + enable ? "start" : "stop", channel); -out: kfree(cmd); return ret; } @@ -297,6 +326,28 @@ out: return ret; } +int wl1251_cmd_disconnect(struct wl1251 *wl) +{ + struct wl1251_cmd_disconnect *cmd; + int ret; + + wl1251_debug(DEBUG_CMD, "cmd disconnect"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->rx_config_options = wl->rx_config; + cmd->rx_filter_options = 0; + + ret = wl1251_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd)); + if (ret < 0) + wl1251_error("cmd disconnect failed: %d", ret); + + kfree(cmd); + return ret; +} + int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode) { struct wl1251_cmd_ps_params *ps_params = NULL; @@ -314,7 +365,8 @@ int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode) ps_params->send_null_data = 1; ps_params->retries = 5; ps_params->hang_over_period = 128; - ps_params->null_data_rate = 1; /* 1 Mbps */ + ps_params->null_data_rate = RATE_MASK_1MBPS | RATE_MASK_2MBPS | + RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params, sizeof(*ps_params)); @@ -410,7 +462,9 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, struct wl1251_cmd_scan *cmd; int i, ret = 0; - wl1251_debug(DEBUG_CMD, "cmd scan"); + wl1251_debug(DEBUG_CMD, "cmd scan channels %d", n_channels); + + WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) @@ -421,6 +475,13 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, CFG_RX_MGMT_EN | CFG_RX_BCN_EN); cmd->params.scan_options = 0; + /* + * Use high priority scan when not associated to prevent fw issue + * causing never-ending scans (sometimes 20+ minutes). + * Note: This bug may be caused by the fw's DTIM handling. + */ + if (is_zero_ether_addr(wl->bssid)) + cmd->params.scan_options |= cpu_to_le16(WL1251_SCAN_OPT_PRIORITY_HIGH); cmd->params.num_channels = n_channels; cmd->params.num_probe_requests = n_probes; cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */