2008-04-15 04:16:15

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 0/12] iwlwifi driver updates

This patch series contains a few iwlwifi driver updates.

Patches 3 to 7 introduces support for WEP HW encryption
acceleration. It supports default and dynamic keys both PSK and 1X
No changes in mac80211 were required. It also reorganizes security
related code into a new file iwl-sta.c

Please note that patch "iwlwifi: perform bss_info_changed post
association work right away" depends on recent mac80211 patch:
mac80211: no BSS changes to driver from beacons processed during scanning


[PATCH 01/12] iwlwifi: generalize iwlwifi init flow
[PATCH 02/12] iwlwifi: replace sprintf with scnprintf for debugfs output
[PATCH 03/12] iwlwifi: add default WEP key host command
[PATCH 04/12] iwlwifi: default WEP HW encryption
[PATCH 05/12] iwlwifi: add 1X HW WEP support
[PATCH 06/12] iwlwifi: maintain uCode key table state
[PATCH 07/12] iwlwifi: moves security functions to iwl-sta.c
[PATCH 08/12] iwlwifi: Fix byte count table for fragmented packets
[PATCH 09/12] iwl4965: make iwl4956_send_rxon_assoc asynchronous
[PATCH 10/12] iwlwifi: make Makefile more concise
[PATCH 11/12] iwlwifi: perform bss_info_changed post association work right away
[PATCH 12/12] iwlwifi: move shared pointers to iwl_priv

Thank you

Reinette


2008-04-15 16:17:15

by Pavel Roskin

[permalink] [raw]
Subject: Re: [PATCH 09/12] iwl4965: make iwl4956_send_rxon_assoc asynchronous

On Mon, 2008-04-14 at 21:16 -0700, Reinette Chatre wrote:
> Signed-off-by: Reinette Chatre <[email protected]>
> Acked-by: Tomas Winkler <[email protected]>
> ---
> drivers/net/wireless/iwlwifi/iwl4965-base.c | 27 ++++++---------------------
> 1 files changed, 6 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
> index 60c0b83..9fb9857 100644
> --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
> @@ -758,15 +758,8 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv)
>
> static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)

Wrong patch description. Please swap 5 and 6 :-)

--
Regards,
Pavel Roskin

2008-04-15 04:16:16

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 02/12] iwlwifi: replace sprintf with scnprintf for debugfs output

From: Abhijeet Kolekar <[email protected]>

The buffersize allocated is not accurate.
Writing to these buffers with scnprintf is safer.

Signed-off-by: Abhijeet Kolekar <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-debugfs.c | 71 +++++++++++++++++-----------
1 files changed, 43 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 23632e5..cbea477 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -102,10 +102,14 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char buf[256];
int pos = 0;
+ const size_t bufsz = sizeof(buf);

- pos += sprintf(buf+pos, "mgmt: %u\n", priv->tx_stats[0].cnt);
- pos += sprintf(buf+pos, "ctrl: %u\n", priv->tx_stats[1].cnt);
- pos += sprintf(buf+pos, "data: %u\n", priv->tx_stats[2].cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
+ priv->tx_stats[0].cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
+ priv->tx_stats[1].cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
+ priv->tx_stats[2].cnt);

return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -117,10 +121,14 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char buf[256];
int pos = 0;
+ const size_t bufsz = sizeof(buf);

- pos += sprintf(buf+pos, "mgmt: %u\n", priv->rx_stats[0].cnt);
- pos += sprintf(buf+pos, "ctrl: %u\n", priv->rx_stats[1].cnt);
- pos += sprintf(buf+pos, "data: %u\n", priv->rx_stats[2].cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
+ priv->rx_stats[0].cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
+ priv->rx_stats[1].cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
+ priv->rx_stats[2].cnt);

return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -138,6 +146,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
int i;
int pos = 0;
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ const size_t bufsz = sizeof(buf);

printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n",
priv->dbgfs->sram_offset, priv->dbgfs->sram_len);
@@ -159,9 +168,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
break;
}
}
- pos += sprintf(buf+pos, "0x%08x ", val);
+ pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
}
- pos += sprintf(buf+pos, "\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "\n");
iwl_release_nic_access(priv);

ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
@@ -210,44 +219,50 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
if(!buf)
return -ENOMEM;

- pos += sprintf(buf+pos, "num of stations: %d\n\n",
+ pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
priv->num_stations);

for (i = 0; i < max_sta; i++) {
station = &priv->stations[i];
if (station->used) {
- pos += sprintf(buf+pos, "station %d:\ngeneral data:\n",
- i+1);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "station %d:\ngeneral data:\n", i+1);
print_mac(mac, station->sta.sta.addr);
- pos += sprintf(buf+pos, "id: %u\n",
+ pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
station->sta.sta.sta_id);
- pos += sprintf(buf+pos, "mode: %u\n",
+ pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
station->sta.mode);
- pos += sprintf(buf+pos, "flags: 0x%x\n",
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "flags: 0x%x\n",
station->sta.station_flags_msk);
- pos += sprintf(buf+pos, "ps_status: %u\n",
- station->ps_status);
-
- pos += sprintf(buf+pos, "tid data:\n");
-
- pos += sprintf(buf+pos, "seq_num\t\ttxq_id\t");
- pos += sprintf(buf+pos, "frame_count\twait_for_ba\t");
- pos += sprintf(buf+pos, "start_idx\tbitmap0\t");
- pos += sprintf(buf+pos, "bitmap1\trate_n_flags\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "ps_status: %u\n", station->ps_status);
+ pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "seq_num\t\ttxq_id\t");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "frame_count\twait_for_ba\t");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "start_idx\tbitmap0\t");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "bitmap1\trate_n_flags\n");

for (j = 0; j < MAX_TID_COUNT; j++) {
- pos += sprintf(buf+pos, "[%d]:\t\t%u\t",
- j, station->tid[j].seq_number);
- pos += sprintf(buf+pos, "%u\t\t%u\t\t%u\t\t",
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "[%d]:\t\t%u\t", j,
+ station->tid[j].seq_number);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "%u\t\t%u\t\t%u\t\t",
station->tid[j].agg.txq_id,
station->tid[j].agg.frame_count,
station->tid[j].agg.wait_for_ba);
- pos += sprintf(buf+pos, "%u\t%llu\t%u\n",
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "%u\t%llu\t%u\n",
station->tid[j].agg.start_idx,
(unsigned long long)station->tid[j].agg.bitmap,
station->tid[j].agg.rate_n_flags);
}
- pos += sprintf(buf+pos, "\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "\n");
}
}

--
1.5.3.4


2008-04-15 04:16:16

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 01/12] iwlwifi: generalize iwlwifi init flow

From: Tomas Winkler <[email protected]>

This patch creates handlers to support
iwlwifi init flow for multiple HWs

Signed-off-by: Tomas Winkler <[email protected]>
Signed-off-by: Ron Rindjunsky <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 149 ++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-core.h | 11 ++-
drivers/net/wireless/iwlwifi/iwl4965-base.c | 179 +++------------------------
3 files changed, 174 insertions(+), 165 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 472ca3d..822169e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -114,6 +114,151 @@ static const u16 default_tid_to_tx_fifo[] = {

#endif /*CONFIG_IWL4965_HT */

+/* check contents of special bootstrap uCode SRAM */
+static int iwl4965_verify_bsm(struct iwl_priv *priv)
+{
+ __le32 *image = priv->ucode_boot.v_addr;
+ u32 len = priv->ucode_boot.len;
+ u32 reg;
+ u32 val;
+
+ IWL_DEBUG_INFO("Begin verify bsm\n");
+
+ /* verify BSM SRAM contents */
+ val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
+ for (reg = BSM_SRAM_LOWER_BOUND;
+ reg < BSM_SRAM_LOWER_BOUND + len;
+ reg += sizeof(u32), image++) {
+ val = iwl_read_prph(priv, reg);
+ if (val != le32_to_cpu(*image)) {
+ IWL_ERROR("BSM uCode verification failed at "
+ "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
+ BSM_SRAM_LOWER_BOUND,
+ reg - BSM_SRAM_LOWER_BOUND, len,
+ val, le32_to_cpu(*image));
+ return -EIO;
+ }
+ }
+
+ IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
+
+ return 0;
+}
+
+/**
+ * iwl4965_load_bsm - Load bootstrap instructions
+ *
+ * BSM operation:
+ *
+ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+ * in special SRAM that does not power down during RFKILL. When powering back
+ * up after power-saving sleeps (or during initial uCode load), the BSM loads
+ * the bootstrap program into the on-board processor, and starts it.
+ *
+ * The bootstrap program loads (via DMA) instructions and data for a new
+ * program from host DRAM locations indicated by the host driver in the
+ * BSM_DRAM_* registers. Once the new program is loaded, it starts
+ * automatically.
+ *
+ * When initializing the NIC, the host driver points the BSM to the
+ * "initialize" uCode image. This uCode sets up some internal data, then
+ * notifies host via "initialize alive" that it is complete.
+ *
+ * The host then replaces the BSM_DRAM_* pointer values to point to the
+ * normal runtime uCode instructions and a backup uCode data cache buffer
+ * (filled initially with starting data values for the on-board processor),
+ * then triggers the "initialize" uCode to load and launch the runtime uCode,
+ * which begins normal operation.
+ *
+ * When doing a power-save shutdown, runtime uCode saves data SRAM into
+ * the backup data cache in DRAM before SRAM is powered down.
+ *
+ * When powering back up, the BSM loads the bootstrap program. This reloads
+ * the runtime uCode instructions and the backup data cache into SRAM,
+ * and re-launches the runtime uCode from where it left off.
+ */
+static int iwl4965_load_bsm(struct iwl_priv *priv)
+{
+ __le32 *image = priv->ucode_boot.v_addr;
+ u32 len = priv->ucode_boot.len;
+ dma_addr_t pinst;
+ dma_addr_t pdata;
+ u32 inst_len;
+ u32 data_len;
+ int i;
+ u32 done;
+ u32 reg_offset;
+ int ret;
+
+ IWL_DEBUG_INFO("Begin load bsm\n");
+
+ /* make sure bootstrap program is no larger than BSM's SRAM size */
+ if (len > IWL_MAX_BSM_SIZE)
+ return -EINVAL;
+
+ /* Tell bootstrap uCode where to find the "Initialize" uCode
+ * in host DRAM ... host DRAM physical address bits 35:4 for 4965.
+ * NOTE: iwl4965_initialize_alive_start() will replace these values,
+ * after the "initialize" uCode has run, to point to
+ * runtime/protocol instructions and backup data cache. */
+ pinst = priv->ucode_init.p_addr >> 4;
+ pdata = priv->ucode_init_data.p_addr >> 4;
+ inst_len = priv->ucode_init.len;
+ data_len = priv->ucode_init_data.len;
+
+ ret = iwl_grab_nic_access(priv);
+ if (ret)
+ return ret;
+
+ iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+ iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+ iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+ iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+
+ /* Fill BSM memory with bootstrap instructions */
+ for (reg_offset = BSM_SRAM_LOWER_BOUND;
+ reg_offset < BSM_SRAM_LOWER_BOUND + len;
+ reg_offset += sizeof(u32), image++)
+ _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image));
+
+ ret = iwl4965_verify_bsm(priv);
+ if (ret) {
+ iwl_release_nic_access(priv);
+ return ret;
+ }
+
+ /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+ iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+ iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND);
+ iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+
+ /* Load bootstrap code into instruction SRAM now,
+ * to prepare to load "initialize" uCode */
+ iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
+
+ /* Wait for load of bootstrap uCode to finish */
+ for (i = 0; i < 100; i++) {
+ done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
+ if (!(done & BSM_WR_CTRL_REG_BIT_START))
+ break;
+ udelay(10);
+ }
+ if (i < 100)
+ IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
+ else {
+ IWL_ERROR("BSM write did not complete!\n");
+ return -EIO;
+ }
+
+ /* Enable future boot loads whenever power management unit triggers it
+ * (e.g. when powering back up after power-save shutdown) */
+ iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
+
+ iwl_release_nic_access(priv);
+
+ return 0;
+}
+
static int iwl4965_init_drv(struct iwl_priv *priv)
{
int ret;
@@ -4789,6 +4934,10 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {

static struct iwl_lib_ops iwl4965_lib = {
.init_drv = iwl4965_init_drv,
+ .hw_nic_init = iwl4965_hw_nic_init,
+ .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
+ .alive_notify = iwl4965_alive_notify,
+ .load_ucode = iwl4965_load_bsm,
.eeprom_ops = {
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 6d82376..889fdba 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -89,9 +89,18 @@ struct iwl_hcmd_utils_ops {
struct iwl_lib_ops {
/* iwlwifi driver (priv) init */
int (*init_drv)(struct iwl_priv *priv);
+ /* nic init */
+ int (*hw_nic_init)(struct iwl_priv *priv);
+ /* alive notification */
+ int (*alive_notify)(struct iwl_priv *priv);
+ /* check validity of rtc data address */
+ int (*is_valid_rtc_data_addr)(u32 addr);
+ /* 1st ucode load */
+ int (*load_ucode)(struct iwl_priv *priv);
+ /* rfkill */
+ void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio);
/* eeprom operations (as defined in iwl-eeprom.h) */
struct iwl_eeprom_ops eeprom_ops;
- void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio);
};

struct iwl_ops {
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 06e44da..ecc9cba 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -4305,7 +4305,7 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)

base = le32_to_cpu(priv->card_alive.error_event_table_ptr);

- if (!iwl4965_hw_valid_rtc_data_addr(base)) {
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
return;
}
@@ -4400,7 +4400,7 @@ static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
u32 size; /* # entries that we'll print */

base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (!iwl4965_hw_valid_rtc_data_addr(base)) {
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
return;
}
@@ -5175,156 +5175,6 @@ static int iwl4965_verify_ucode(struct iwl_priv *priv)
return rc;
}

-
-/* check contents of special bootstrap uCode SRAM */
-static int iwl4965_verify_bsm(struct iwl_priv *priv)
-{
- __le32 *image = priv->ucode_boot.v_addr;
- u32 len = priv->ucode_boot.len;
- u32 reg;
- u32 val;
-
- IWL_DEBUG_INFO("Begin verify bsm\n");
-
- /* verify BSM SRAM contents */
- val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
- for (reg = BSM_SRAM_LOWER_BOUND;
- reg < BSM_SRAM_LOWER_BOUND + len;
- reg += sizeof(u32), image ++) {
- val = iwl_read_prph(priv, reg);
- if (val != le32_to_cpu(*image)) {
- IWL_ERROR("BSM uCode verification failed at "
- "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
- BSM_SRAM_LOWER_BOUND,
- reg - BSM_SRAM_LOWER_BOUND, len,
- val, le32_to_cpu(*image));
- return -EIO;
- }
- }
-
- IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
-
- return 0;
-}
-
-/**
- * iwl4965_load_bsm - Load bootstrap instructions
- *
- * BSM operation:
- *
- * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
- * in special SRAM that does not power down during RFKILL. When powering back
- * up after power-saving sleeps (or during initial uCode load), the BSM loads
- * the bootstrap program into the on-board processor, and starts it.
- *
- * The bootstrap program loads (via DMA) instructions and data for a new
- * program from host DRAM locations indicated by the host driver in the
- * BSM_DRAM_* registers. Once the new program is loaded, it starts
- * automatically.
- *
- * When initializing the NIC, the host driver points the BSM to the
- * "initialize" uCode image. This uCode sets up some internal data, then
- * notifies host via "initialize alive" that it is complete.
- *
- * The host then replaces the BSM_DRAM_* pointer values to point to the
- * normal runtime uCode instructions and a backup uCode data cache buffer
- * (filled initially with starting data values for the on-board processor),
- * then triggers the "initialize" uCode to load and launch the runtime uCode,
- * which begins normal operation.
- *
- * When doing a power-save shutdown, runtime uCode saves data SRAM into
- * the backup data cache in DRAM before SRAM is powered down.
- *
- * When powering back up, the BSM loads the bootstrap program. This reloads
- * the runtime uCode instructions and the backup data cache into SRAM,
- * and re-launches the runtime uCode from where it left off.
- */
-static int iwl4965_load_bsm(struct iwl_priv *priv)
-{
- __le32 *image = priv->ucode_boot.v_addr;
- u32 len = priv->ucode_boot.len;
- dma_addr_t pinst;
- dma_addr_t pdata;
- u32 inst_len;
- u32 data_len;
- int rc;
- int i;
- u32 done;
- u32 reg_offset;
-
- IWL_DEBUG_INFO("Begin load bsm\n");
-
- /* make sure bootstrap program is no larger than BSM's SRAM size */
- if (len > IWL_MAX_BSM_SIZE)
- return -EINVAL;
-
- /* Tell bootstrap uCode where to find the "Initialize" uCode
- * in host DRAM ... host DRAM physical address bits 35:4 for 4965.
- * NOTE: iwl4965_initialize_alive_start() will replace these values,
- * after the "initialize" uCode has run, to point to
- * runtime/protocol instructions and backup data cache. */
- pinst = priv->ucode_init.p_addr >> 4;
- pdata = priv->ucode_init_data.p_addr >> 4;
- inst_len = priv->ucode_init.len;
- data_len = priv->ucode_init_data.len;
-
- rc = iwl_grab_nic_access(priv);
- if (rc)
- return rc;
-
- iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
- iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
- iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
- iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
-
- /* Fill BSM memory with bootstrap instructions */
- for (reg_offset = BSM_SRAM_LOWER_BOUND;
- reg_offset < BSM_SRAM_LOWER_BOUND + len;
- reg_offset += sizeof(u32), image++)
- _iwl_write_prph(priv, reg_offset,
- le32_to_cpu(*image));
-
- rc = iwl4965_verify_bsm(priv);
- if (rc) {
- iwl_release_nic_access(priv);
- return rc;
- }
-
- /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
- iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
- iwl_write_prph(priv, BSM_WR_MEM_DST_REG,
- RTC_INST_LOWER_BOUND);
- iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-
- /* Load bootstrap code into instruction SRAM now,
- * to prepare to load "initialize" uCode */
- iwl_write_prph(priv, BSM_WR_CTRL_REG,
- BSM_WR_CTRL_REG_BIT_START);
-
- /* Wait for load of bootstrap uCode to finish */
- for (i = 0; i < 100; i++) {
- done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
- if (!(done & BSM_WR_CTRL_REG_BIT_START))
- break;
- udelay(10);
- }
- if (i < 100)
- IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
- else {
- IWL_ERROR("BSM write did not complete!\n");
- return -EIO;
- }
-
- /* Enable future boot loads whenever power management unit triggers it
- * (e.g. when powering back up after power-save shutdown) */
- iwl_write_prph(priv, BSM_WR_CTRL_REG,
- BSM_WR_CTRL_REG_BIT_START_EN);
-
- iwl_release_nic_access(priv);
-
- return 0;
-}
-
static void iwl4965_nic_start(struct iwl_priv *priv)
{
/* Remove all resets to allow NIC to operate */
@@ -5634,7 +5484,7 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv)
*/
static void iwl4965_alive_start(struct iwl_priv *priv)
{
- int rc = 0;
+ int ret = 0;

IWL_DEBUG_INFO("Runtime Alive received.\n");

@@ -5657,10 +5507,10 @@ static void iwl4965_alive_start(struct iwl_priv *priv)

iwlcore_clear_stations_table(priv);

- rc = iwl4965_alive_notify(priv);
- if (rc) {
+ ret = priv->cfg->ops->lib->alive_notify(priv);
+ if (ret) {
IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
- rc);
+ ret);
goto restart;
}

@@ -5835,7 +5685,8 @@ static void iwl4965_down(struct iwl_priv *priv)

static int __iwl4965_up(struct iwl_priv *priv)
{
- int rc, i;
+ int i;
+ int ret;

if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_WARNING("Exit pending; will not bring the NIC up\n");
@@ -5870,10 +5721,10 @@ static int __iwl4965_up(struct iwl_priv *priv)
iwl_rfkill_set_hw_state(priv);
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);

- rc = iwl4965_hw_nic_init(priv);
- if (rc) {
- IWL_ERROR("Unable to int nic\n");
- return rc;
+ ret = priv->cfg->ops->lib->hw_nic_init(priv);
+ if (ret) {
+ IWL_ERROR("Unable to init nic\n");
+ return ret;
}

/* make sure rfkill handshake bits are cleared */
@@ -5906,10 +5757,10 @@ static int __iwl4965_up(struct iwl_priv *priv)
/* load bootstrap state machine,
* load bootstrap program into processor's memory,
* prepare to load the "initialize" uCode */
- rc = iwl4965_load_bsm(priv);
+ ret = priv->cfg->ops->lib->load_ucode(priv);

- if (rc) {
- IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
+ if (ret) {
+ IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret);
continue;
}

--
1.5.3.4


2008-04-15 04:16:19

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 11/12] iwlwifi: perform bss_info_changed post association work right away

Do not use workqueue for bss_info_changed post association work.
When driver is notified of association the upper layer will be notified
right after that the association is complete. Doing the post association
work in a workqueue introduces a race condition where the upper layer may
want to make use of the association, but it is not yet complete.

Signed-off-by: Reinette Chatre <[email protected]>
Acked-by: Tomas Winkler <[email protected]>
---
This patch depends on "mac80211: no BSS changes to driver from beacons
processed during scanning"

drivers/net/wireless/iwlwifi/iwl4965-base.c | 31 +++++++++++++++++++-------
1 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 9fb9857..1f34340 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1840,7 +1840,7 @@ static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv,
| RXON_FLG_CCK_MSK);
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
} else {
- /* Copied from iwl4965_bg_post_associate() */
+ /* Copied from iwl4965_post_associate() */
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
@@ -6004,10 +6004,8 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data)

#define IWL_DELAY_NEXT_SCAN (HZ*2)

-static void iwl4965_bg_post_associate(struct work_struct *data)
+static void iwl4965_post_associate(struct iwl_priv *priv)
{
- struct iwl_priv *priv = container_of(data, struct iwl_priv,
- post_associate.work);
struct ieee80211_conf *conf = NULL;
int ret = 0;
DECLARE_MAC_BUF(mac);
@@ -6025,12 +6023,10 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;

- mutex_lock(&priv->mutex);

- if (!priv->vif || !priv->is_open) {
- mutex_unlock(&priv->mutex);
+ if (!priv->vif || !priv->is_open)
return;
- }
+
iwl4965_scan_cancel_timeout(priv, 200);

conf = ieee80211_get_hw_conf(priv->hw);
@@ -6114,7 +6110,18 @@ static void iwl4965_bg_post_associate(struct work_struct *data)

/* we have just associated, don't start scan too early */
priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
+}
+
+
+static void iwl4965_bg_post_associate(struct work_struct *data)
+{
+ struct iwl_priv *priv = container_of(data, struct iwl_priv,
+ post_associate.work);
+
+ mutex_lock(&priv->mutex);
+ iwl4965_post_associate(priv);
mutex_unlock(&priv->mutex);
+
}

static void iwl4965_bg_abort_scan(struct work_struct *work)
@@ -6736,6 +6743,10 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,

if (changes & BSS_CHANGED_ASSOC) {
IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc);
+ /* This should never happen as this function should
+ * never be called from interrupt context. */
+ if (WARN_ON_ONCE(in_interrupt()))
+ return;
if (bss_conf->assoc) {
priv->assoc_id = bss_conf->aid;
priv->beacon_int = bss_conf->beacon_int;
@@ -6743,7 +6754,9 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
priv->assoc_capability = bss_conf->assoc_capability;
priv->next_scan_jiffies = jiffies +
IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
- queue_work(priv->workqueue, &priv->post_associate.work);
+ mutex_lock(&priv->mutex);
+ iwl4965_post_associate(priv);
+ mutex_unlock(&priv->mutex);
} else {
priv->assoc_id = 0;
IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc);
--
1.5.3.4


2008-04-15 04:16:17

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 08/12] iwlwifi: Fix byte count table for fragmented packets

From: Tomas Winkler <[email protected]>

This patch fix byte count table update. Table must be updated for each
fragment

Signed-off-by: Tomas Winkler <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 13 +++++--------
drivers/net/wireless/iwlwifi/iwl-core.h | 4 ++++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 6 +++---
3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 822169e..04fed5e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -3141,18 +3141,16 @@ static void iwl4965_hw_card_show_info(struct iwl_priv *priv)
#define IWL_TX_DELIMITER_SIZE 4

/**
- * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array
+ * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/
-int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq, u16 byte_cnt)
+static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq,
+ u16 byte_cnt)
{
int len;
int txq_id = txq->q.id;
struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;

- if (txq->need_update == 0)
- return 0;
-
len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;

/* Set up byte count within first 256 entries */
@@ -3164,8 +3162,6 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr],
byte_cnt, len);
-
- return 0;
}

/**
@@ -4934,6 +4930,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {

static struct iwl_lib_ops iwl4965_lib = {
.init_drv = iwl4965_init_drv,
+ .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
.hw_nic_init = iwl4965_hw_nic_init,
.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
.alive_notify = iwl4965_alive_notify,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 889fdba..23c21e3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -89,6 +89,10 @@ struct iwl_hcmd_utils_ops {
struct iwl_lib_ops {
/* iwlwifi driver (priv) init */
int (*init_drv)(struct iwl_priv *priv);
+
+ void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq,
+ u16 byte_cnt);
/* nic init */
int (*hw_nic_init)(struct iwl_priv *priv);
/* alive notification */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index bfefb05..60c0b83 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -575,11 +575,11 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
txq->need_update = 1;

/* Set up entry in queue's byte count circular buffer */
- ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0);
+ priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);

/* Increment and update queue's write index */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- iwl4965_tx_queue_update_write_ptr(priv, txq);
+ ret = iwl4965_tx_queue_update_write_ptr(priv, txq);

spin_unlock_irqrestore(&priv->hcmd_lock, flags);
return ret ? ret : idx;
@@ -2392,7 +2392,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
ieee80211_get_hdrlen(fc));

/* Set up entry for this TFD in Tx byte-count array */
- iwl4965_tx_queue_update_wr_ptr(priv, txq, len);
+ priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len);

/* Tell device the write index *just past* this latest filled TFD */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
--
1.5.3.4


2008-04-15 04:16:19

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 10/12] iwlwifi: make Makefile more concise

Also change CONFIG_IWLCORE_RFKILL to CONFIG_IWLWIFI_RFKILL to
be more consistent with other config variables.

Signed-off-by: Reinette Chatre <[email protected]>
Acked-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/Kconfig | 2 +-
drivers/net/wireless/iwlwifi/Makefile | 29 ++++++++---------------------
drivers/net/wireless/iwlwifi/iwl-4965.h | 2 +-
drivers/net/wireless/iwlwifi/iwl-rfkill.h | 2 +-
4 files changed, 11 insertions(+), 24 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index bcaa61b..f844b73 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -6,7 +6,7 @@ config IWLWIFI_LEDS
bool
default n

-config IWLCORE_RFKILL
+config IWLWIFI_RFKILL
boolean "IWLWIFI RF kill support"
depends on IWLCORE
select RFKILL
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 741ea34..4f3e88b 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -1,26 +1,13 @@
-obj-$(CONFIG_IWLCORE) += iwlcore.o
-iwlcore-objs = iwl-core.o iwl-eeprom.o iwl-hcmd.o
-
-ifeq ($(CONFIG_IWLWIFI_DEBUGFS),y)
- iwlcore-objs += iwl-debugfs.o
-endif
-
-ifeq ($(CONFIG_IWLWIFI_LEDS),y)
- iwlcore-objs += iwl-led.o
-endif
-
-ifeq ($(CONFIG_IWLCORE_RFKILL),y)
- iwlcore-objs += iwl-rfkill.o
-endif
+obj-$(CONFIG_IWLCORE) := iwlcore.o
+iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o
+iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
+iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
+iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o

obj-$(CONFIG_IWL3945) += iwl3945.o
-iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o
-
-ifeq ($(CONFIG_IWL3945_LEDS),y)
- iwl3945-objs += iwl-3945-led.o
-endif
-
+iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o
+iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o

obj-$(CONFIG_IWL4965) += iwl4965.o
-iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o
+iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index daf157a..17c4bcf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -1034,7 +1034,7 @@ struct iwl_priv {
* 4965's initialize alive response contains some calibration data. */
struct iwl4965_init_alive_resp card_alive_init;
struct iwl4965_alive_resp card_alive;
-#ifdef CONFIG_IWLCORE_RFKILL
+#ifdef CONFIG_IWLWIFI_RFKILL
struct iwl_rfkill_mngr rfkill_mngr;
#endif

diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
index e7aa51a..a7f04b8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
@@ -34,7 +34,7 @@ struct iwl_priv;
#include <linux/input.h>


-#ifdef CONFIG_IWLCORE_RFKILL
+#ifdef CONFIG_IWLWIFI_RFKILL
struct iwl_rfkill_mngr {
struct rfkill *rfkill;
struct input_dev *input_dev;
--
1.5.3.4


2008-04-15 04:16:17

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 06/12] iwlwifi: maintain uCode key table state

From: Emmanuel Grumbach <[email protected]>

This patch fix book keeping of key table in the driver
to be synchronized with uCode

Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.h | 1 +
drivers/net/wireless/iwlwifi/iwl-sta.c | 28 ++++++++++++++++++++++++--
drivers/net/wireless/iwlwifi/iwl-sta.h | 1 +
drivers/net/wireless/iwlwifi/iwl4965-base.c | 10 ++++++--
4 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index 23ab523..daf157a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -1116,6 +1116,7 @@ struct iwl_priv {
struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
u8 default_wep_key;
u8 key_mapping_key;
+ unsigned long ucode_key_table;

/* Indication if ieee80211_ops->open has been called */
u8 is_open;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index cb96419..41238f2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -36,6 +36,18 @@
#include "iwl-io.h"
#include "iwl-helpers.h"
#include "iwl-4965.h"
+#include "iwl-sta.h"
+
+int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < STA_KEY_MAX_NUM; i++)
+ if (test_and_set_bit(i, &priv->ucode_key_table))
+ return i;
+
+ return -1;
+}

int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
{
@@ -81,14 +93,19 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
}

int iwl_remove_default_wep_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *key)
+ struct ieee80211_key_conf *keyconf)
{
int ret;
unsigned long flags;

spin_lock_irqsave(&priv->sta_lock, flags);
+
+ if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table))
+ IWL_ERROR("index %d not used in uCode key table.\n",
+ keyconf->keyidx);
+
priv->default_wep_key--;
- memset(&priv->wep_keys[key->keyidx], 0, sizeof(priv->wep_keys[0]));
+ memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
ret = iwl_send_static_wepkey_cmd(priv, 1);
spin_unlock_irqrestore(&priv->sta_lock, flags);

@@ -108,6 +125,10 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
spin_lock_irqsave(&priv->sta_lock, flags);
priv->default_wep_key++;

+ if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table))
+ IWL_ERROR("index %d already used in uCode key table.\n",
+ keyconf->keyidx);
+
priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
keyconf->keylen);
@@ -151,7 +172,8 @@ int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
memcpy(&priv->stations[sta_id].sta.key.key[3],
keyconf->key, keyconf->keylen);

- priv->stations[sta_id].sta.key.key_offset = sta_id % 8; /* FIXME */
+ priv->stations[sta_id].sta.key.key_offset =
+ iwl_get_free_ucode_key_index(priv);
priv->stations[sta_id].sta.key.key_flags = key_flags;

priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 78e0254..3f1b205 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -37,6 +37,7 @@
#include "iwl-io.h"
#include "iwl-helpers.h"

+int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty);
int iwl_remove_default_wep_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 37ab1c5..da01896 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1140,8 +1140,8 @@ static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
keyconf->keylen);

- priv->stations[sta_id].sta.key.key_offset
- = (sta_id % STA_KEY_MAX_NUM);/*FIXME*/
+ priv->stations[sta_id].sta.key.key_offset =
+ iwl_get_free_ucode_key_index(priv);
priv->stations[sta_id].sta.key.key_flags = key_flags;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
@@ -1187,6 +1187,10 @@ static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
priv->key_mapping_key = 0;

spin_lock_irqsave(&priv->sta_lock, flags);
+ if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
+ &priv->ucode_key_table))
+ IWL_ERROR("index %d not used in uCode key table.\n",
+ priv->stations[sta_id].sta.key.key_offset);
memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key));
memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo));
priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
@@ -6971,7 +6975,7 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
spin_lock_irqsave(&priv->sta_lock, flags);

priv->stations[sta_id].sta.key.key_offset =
- (sta_id % STA_KEY_MAX_NUM);/* FIXME */
+ iwl_get_free_ucode_key_index(priv);
priv->stations[sta_id].sta.key.key_flags = key_flags;
priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;

--
1.5.3.4


2008-04-15 04:16:20

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 12/12] iwlwifi: move shared pointers to iwl_priv

From: Tomas Winkler <[email protected]>

This patch moves shared memory structure to iwl_priv

Signed-off-by: Tomas Winkler <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 12 +++---
drivers/net/wireless/iwlwifi/iwl-4965.c | 55 ++++++++++++--------------
drivers/net/wireless/iwlwifi/iwl-4965.h | 11 +++--
drivers/net/wireless/iwlwifi/iwl4965-base.c | 6 +-
4 files changed, 40 insertions(+), 44 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index de7bac1..3d098da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -1554,29 +1554,29 @@ struct iwl4965_sched_queue_byte_cnt_tbl {
struct iwl4965_shared {
struct iwl4965_sched_queue_byte_cnt_tbl
queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES];
- __le32 val0;
+ __le32 rb_closed;

/* __le32 rb_closed_stts_rb_num:12; */
#define IWL_rb_closed_stts_rb_num_POS 0
#define IWL_rb_closed_stts_rb_num_LEN 12
-#define IWL_rb_closed_stts_rb_num_SYM val0
+#define IWL_rb_closed_stts_rb_num_SYM rb_closed
/* __le32 rsrv1:4; */
/* __le32 rb_closed_stts_rx_frame_num:12; */
#define IWL_rb_closed_stts_rx_frame_num_POS 16
#define IWL_rb_closed_stts_rx_frame_num_LEN 12
-#define IWL_rb_closed_stts_rx_frame_num_SYM val0
+#define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed
/* __le32 rsrv2:4; */

- __le32 val1;
+ __le32 frm_finished;
/* __le32 frame_finished_stts_rb_num:12; */
#define IWL_frame_finished_stts_rb_num_POS 0
#define IWL_frame_finished_stts_rb_num_LEN 12
-#define IWL_frame_finished_stts_rb_num_SYM val1
+#define IWL_frame_finished_stts_rb_num_SYM frm_finished
/* __le32 rsrv3:4; */
/* __le32 frame_finished_stts_rx_frame_num:12; */
#define IWL_frame_finished_stts_rx_frame_num_POS 16
#define IWL_frame_finished_stts_rx_frame_num_LEN 12
-#define IWL_frame_finished_stts_rx_frame_num_SYM val1
+#define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished
/* __le32 rsrv4:4; */

__le32 padding1; /* so that allocation will be aligned to 16B */
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 04fed5e..a10a6e8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -274,6 +274,18 @@ static int iwl4965_init_drv(struct iwl_priv *priv)
spin_lock_init(&priv->hcmd_lock);
spin_lock_init(&priv->lq_mngr.lock);

+ priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
+ sizeof(struct iwl4965_shared),
+ &priv->shared_phys);
+
+ if (!priv->shared_virt) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared));
+
+
for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);

@@ -546,15 +558,15 @@ static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)

static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
{
- int rc;
+ int ret;
unsigned long flags;
unsigned int rb_size;

spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_nic_access(priv);
- if (rc) {
+ ret = iwl_grab_nic_access(priv);
+ if (ret) {
spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
+ return ret;
}

if (priv->cfg->mod_params->amsdu_size_8K)
@@ -574,15 +586,15 @@ static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)

/* Tell device where in DRAM to update its Rx status */
iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
- (priv->hw_setting.shared_phys +
- offsetof(struct iwl4965_shared, val0)) >> 4);
+ (priv->shared_phys +
+ offsetof(struct iwl4965_shared, rb_closed)) >> 4);

/* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
rb_size |
- /*0x10 << 4 | */
+ /* 0x10 << 4 | */
(RX_QUEUE_SIZE_LOG <<
FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));

@@ -1966,7 +1978,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv)

/* Tel 4965 where to find Tx byte count tables */
iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
- (priv->hw_setting.shared_phys +
+ (priv->shared_phys +
offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10);

/* Disable chain mode for all queues */
@@ -2024,29 +2036,14 @@ int iwl4965_alive_notify(struct iwl_priv *priv)
*/
int iwl4965_hw_set_hw_setting(struct iwl_priv *priv)
{
- int ret = 0;

if ((priv->cfg->mod_params->num_of_queues > IWL_MAX_NUM_QUEUES) ||
(priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
IWL_ERROR("invalid queues_num, should be between %d and %d\n",
IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
- ret = -EINVAL;
- goto out;
- }
-
- /* Allocate area for Tx byte count tables and Rx queue status */
- priv->hw_setting.shared_virt =
- pci_alloc_consistent(priv->pci_dev,
- sizeof(struct iwl4965_shared),
- &priv->hw_setting.shared_phys);
-
- if (!priv->hw_setting.shared_virt) {
- ret = -ENOMEM;
- goto out;
+ return -EINVAL;
}

- memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared));
-
priv->hw_setting.max_txq_num = priv->cfg->mod_params->num_of_queues;
priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;
@@ -2061,8 +2058,7 @@ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv)

priv->hw_setting.tx_ant_num = 2;

-out:
- return ret;
+ return 0;
}

/**
@@ -3014,9 +3010,8 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,

int iwl4965_hw_get_rx_read(struct iwl_priv *priv)
{
- struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
-
- return IWL_GET_BITS(*shared_data, rb_closed_stts_rb_num);
+ struct iwl4965_shared *s = priv->shared_virt;
+ return le32_to_cpu(s->rb_closed) & 0xFFF;
}

int iwl4965_hw_get_temperature(struct iwl_priv *priv)
@@ -3149,7 +3144,7 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
{
int len;
int txq_id = txq->q.id;
- struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
+ struct iwl4965_shared *shared_data = priv->shared_virt;

len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index 17c4bcf..e5ab4c0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -576,8 +576,6 @@ struct iwl4965_ibss_seq {
* @max_rxq_log: Log-base-2 of max_rxq_size
* @max_stations:
* @bcast_sta_id:
- * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status
- * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status
*/
struct iwl4965_driver_hw_info {
u16 max_txq_num;
@@ -589,8 +587,6 @@ struct iwl4965_driver_hw_info {
u16 max_rxq_log;
u8 max_stations;
u8 bcast_sta_id;
- void *shared_virt;
- dma_addr_t shared_phys;
};

#define HT_SHORT_GI_20MHZ_ONLY (1 << 0)
@@ -1147,9 +1143,14 @@ struct iwl_priv {
/* Last Rx'd beacon timestamp */
u64 timestamp;
u16 beacon_int;
- struct iwl4965_driver_hw_info hw_setting;
struct ieee80211_vif *vif;

+ struct iwl4965_driver_hw_info hw_setting;
+ /* driver/uCode shared Tx Byte Counts and Rx status */
+ void *shared_virt;
+ /* Physical Pointer to Tx Byte Counts and Rx status */
+ dma_addr_t shared_phys;
+
/* Current association information needed to configure the
* hardware */
u16 assoc_id;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 1f34340..5ec0af4 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1219,11 +1219,11 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)

static void iwl4965_unset_hw_setting(struct iwl_priv *priv)
{
- if (priv->hw_setting.shared_virt)
+ if (priv->shared_virt)
pci_free_consistent(priv->pci_dev,
sizeof(struct iwl4965_shared),
- priv->hw_setting.shared_virt,
- priv->hw_setting.shared_phys);
+ priv->shared_virt,
+ priv->shared_phys);
}

/**
--
1.5.3.4


2008-04-15 04:16:19

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 09/12] iwl4965: make iwl4956_send_rxon_assoc asynchronous

Signed-off-by: Reinette Chatre <[email protected]>
Acked-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl4965-base.c | 27 ++++++---------------------
1 files changed, 6 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 60c0b83..9fb9857 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -758,15 +758,8 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv)

static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
{
- int rc = 0;
- struct iwl4965_rx_packet *res = NULL;
+ int ret = 0;
struct iwl4965_rxon_assoc_cmd rxon_assoc;
- struct iwl_host_cmd cmd = {
- .id = REPLY_RXON_ASSOC,
- .len = sizeof(rxon_assoc),
- .meta.flags = CMD_WANT_SKB,
- .data = &rxon_assoc,
- };
const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon;
const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon;

@@ -794,20 +787,12 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;

- rc = iwl_send_cmd_sync(priv, &cmd);
- if (rc)
- return rc;
-
- res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
- if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
- IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
- rc = -EIO;
- }
-
- priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
+ ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
+ sizeof(rxon_assoc), &rxon_assoc, NULL);
+ if (ret)
+ return ret;

- return rc;
+ return ret;
}

/**
--
1.5.3.4


2008-04-15 04:16:16

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 03/12] iwlwifi: add default WEP key host command

From: Emmanuel Grumbach <[email protected]>

This patch adds declaration for static WEP host command. This command will
be used for default WEP group keys when no key mapping keys are used.

Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 27 ++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-hcmd.c | 1 +
2 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
index 7e36ecb..65cd8ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
@@ -84,6 +84,9 @@ enum {
REPLY_REMOVE_STA = 0x19, /* not used */
REPLY_REMOVE_ALL_STA = 0x1a, /* not used */

+ /* Security */
+ REPLY_WEPKEY = 0x20,
+
/* RX, TX, LEDs */
REPLY_TX = 0x1c,
REPLY_RATE_SCALE = 0x47, /* 3945 only */
@@ -850,6 +853,30 @@ struct iwl4965_add_sta_resp {
u8 status; /* ADD_STA_* */
} __attribute__ ((packed));

+/*
+ * REPLY_WEP_KEY = 0x20
+ */
+struct iwl_wep_key {
+ u8 key_index;
+ u8 key_offset;
+ u8 reserved1[2];
+ u8 key_size;
+ u8 reserved2[3];
+ u8 key[16];
+} __attribute__ ((packed));
+
+struct iwl_wep_cmd {
+ u8 num_keys;
+ u8 global_key_type;
+ u8 flags;
+ u8 reserved;
+ struct iwl_wep_key key[0];
+} __attribute__ ((packed));
+
+#define WEP_KEY_WEP_TYPE 1
+#define WEP_KEYS_MAX 4
+#define WEP_INVALID_OFFSET 0xff
+#define WEP_KEY_LEN_128 13

/******************************************************************************
* (4)
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 1f8c299..fdb27f1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -51,6 +51,7 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(REPLY_ADD_STA);
IWL_CMD(REPLY_REMOVE_STA);
IWL_CMD(REPLY_REMOVE_ALL_STA);
+ IWL_CMD(REPLY_WEPKEY);
IWL_CMD(REPLY_TX);
IWL_CMD(REPLY_RATE_SCALE);
IWL_CMD(REPLY_LEDS_CMD);
--
1.5.3.4


2008-04-15 04:16:19

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 07/12] iwlwifi: moves security functions to iwl-sta.c

From: Emmanuel Grumbach <[email protected]>

This patch moves security related functions to iwl-sta.c.
Note that iwl4965_mac_update_tkip_key is still in iwl4965-base.c since it
is a mac80211 handler.

Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-sta.c | 119 ++++++++++++++++++++++++++-
drivers/net/wireless/iwlwifi/iwl-sta.h | 7 +-
drivers/net/wireless/iwlwifi/iwl4965-base.c | 120 +--------------------------
3 files changed, 123 insertions(+), 123 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 41238f2..8765358 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -139,7 +139,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
return ret;
}

-int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
+static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf,
u8 sta_id)
{
@@ -186,3 +186,120 @@ int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,

return ret;
}
+
+static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id)
+{
+ unsigned long flags;
+ __le16 key_flags = 0;
+
+ key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+ key_flags &= ~STA_KEY_FLG_INVALID;
+
+ if (sta_id == priv->hw_setting.bcast_sta_id)
+ key_flags |= STA_KEY_MULTICAST_MSK;
+
+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ keyconf->hw_key_idx = keyconf->keyidx;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].keyinfo.alg = keyconf->alg;
+ priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+
+ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
+ keyconf->keylen);
+
+ memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
+ keyconf->keylen);
+
+ priv->stations[sta_id].sta.key.key_offset =
+ iwl_get_free_ucode_key_index(priv);
+ priv->stations[sta_id].sta.key.key_flags = key_flags;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
+ return iwl4965_send_add_station(priv,
+ &priv->stations[sta_id].sta, CMD_ASYNC);
+}
+
+static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ keyconf->hw_key_idx = keyconf->keyidx;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ priv->stations[sta_id].keyinfo.alg = keyconf->alg;
+ priv->stations[sta_id].keyinfo.conf = keyconf;
+ priv->stations[sta_id].keyinfo.keylen = 16;
+
+ /* This copy is acutally not needed: we get the key with each TX */
+ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
+
+ memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return ret;
+}
+
+int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id)
+{
+ unsigned long flags;
+
+ priv->key_mapping_key = 0;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
+ &priv->ucode_key_table))
+ IWL_ERROR("index %d not used in uCode key table.\n",
+ priv->stations[sta_id].sta.key.key_offset);
+ memset(&priv->stations[sta_id].keyinfo, 0,
+ sizeof(struct iwl4965_hw_key));
+ memset(&priv->stations[sta_id].sta.key, 0,
+ sizeof(struct iwl4965_keyinfo));
+ priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
+ return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+}
+
+int iwl_set_dynamic_key(struct iwl_priv *priv,
+ struct ieee80211_key_conf *key, u8 sta_id)
+{
+ int ret;
+
+ priv->key_mapping_key = 1;
+
+ switch (key->alg) {
+ case ALG_CCMP:
+ ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id);
+ break;
+ case ALG_TKIP:
+ ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id);
+ break;
+ case ALG_WEP:
+ ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id);
+ break;
+ default:
+ IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 3f1b205..44f272e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -43,8 +43,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key);
int iwl_set_default_wep_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key);
-int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id);
-
+int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id);
+int iwl_set_dynamic_key(struct iwl_priv *priv,
+ struct ieee80211_key_conf *key, u8 sta_id);
#endif /* __iwl_sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index da01896..bfefb05 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1112,122 +1112,6 @@ int iwl4965_send_add_station(struct iwl_priv *priv,
return rc;
}

-static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id)
-{
- unsigned long flags;
- __le16 key_flags = 0;
-
- key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
- key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-
- if (sta_id == priv->hw_setting.bcast_sta_id)
- key_flags |= STA_KEY_MULTICAST_MSK;
-
- keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- keyconf->hw_key_idx = keyconf->keyidx;
-
- key_flags &= ~STA_KEY_FLG_INVALID;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].keyinfo.alg = keyconf->alg;
- priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-
- memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
- keyconf->keylen);
-
- memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
- keyconf->keylen);
-
- priv->stations[sta_id].sta.key.key_offset =
- iwl_get_free_ucode_key_index(priv);
- priv->stations[sta_id].sta.key.key_flags = key_flags;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
- return iwl4965_send_add_station(priv,
- &priv->stations[sta_id].sta, CMD_ASYNC);
-}
-
-static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id)
-{
- unsigned long flags;
- int ret = 0;
-
- keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- keyconf->hw_key_idx = keyconf->keyidx;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- priv->stations[sta_id].keyinfo.alg = keyconf->alg;
- priv->stations[sta_id].keyinfo.conf = keyconf;
- priv->stations[sta_id].keyinfo.keylen = 16;
-
- /* This copy is acutally not needed: we get the key with each TX */
- memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
-
- memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return ret;
-}
-
-static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
-{
- unsigned long flags;
-
- priv->key_mapping_key = 0;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
- &priv->ucode_key_table))
- IWL_ERROR("index %d not used in uCode key table.\n",
- priv->stations[sta_id].sta.key.key_offset);
- memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key));
- memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo));
- priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
- return 0;
-}
-
-static int iwl4965_set_dynamic_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *key, u8 sta_id)
-{
- int ret;
-
- priv->key_mapping_key = 1;
-
- switch (key->alg) {
- case ALG_CCMP:
- ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id);
- break;
- case ALG_TKIP:
- ret = iwl4965_set_tkip_dynamic_key_info(priv, key, sta_id);
- break;
- case ALG_WEP:
- ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id);
- break;
- default:
- IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
static void iwl4965_clear_free_frames(struct iwl_priv *priv)
{
struct list_head *element;
@@ -7043,7 +6927,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (is_default_wep_key)
ret = iwl_set_default_wep_key(priv, key);
else
- ret = iwl4965_set_dynamic_key(priv, key, sta_id);
+ ret = iwl_set_dynamic_key(priv, key, sta_id);

IWL_DEBUG_MAC80211("enable hwcrypto key\n");
break;
@@ -7051,7 +6935,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (is_default_wep_key)
ret = iwl_remove_default_wep_key(priv, key);
else
- ret = iwl4965_clear_sta_key_info(priv, sta_id);
+ ret = iwl_remove_dynamic_key(priv, sta_id);

IWL_DEBUG_MAC80211("disable hwcrypto key\n");
break;
--
1.5.3.4


2008-04-15 04:16:18

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 05/12] iwlwifi: add 1X HW WEP support

From: Emmanuel Grumbach <[email protected]>

This patch adds support for HW encryption/decryption in 1X WEP.

Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-4965.h | 1 +
drivers/net/wireless/iwlwifi/iwl-sta.c | 47 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-sta.h | 3 ++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 9 ++++-
4 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index 93df29e..23ab523 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -461,6 +461,7 @@ struct iwl4965_tid_data {
struct iwl4965_hw_key {
enum ieee80211_key_alg alg;
int keylen;
+ u8 keyidx;
struct ieee80211_key_conf *conf;
u8 key[32];
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index a48e228..cb96419 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -35,6 +35,7 @@
#include "iwl-sta.h"
#include "iwl-io.h"
#include "iwl-helpers.h"
+#include "iwl-4965.h"

int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
{
@@ -117,3 +118,49 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
return ret;
}

+int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id)
+{
+ unsigned long flags;
+ __le16 key_flags = 0;
+ int ret;
+
+ keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+ keyconf->hw_key_idx = keyconf->keyidx;
+
+ key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+ key_flags &= ~STA_KEY_FLG_INVALID;
+
+ if (keyconf->keylen == WEP_KEY_LEN_128)
+ key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
+
+ if (sta_id == priv->hw_setting.bcast_sta_id)
+ key_flags |= STA_KEY_MULTICAST_MSK;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ priv->stations[sta_id].keyinfo.alg = keyconf->alg;
+ priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+ priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
+
+ memcpy(priv->stations[sta_id].keyinfo.key,
+ keyconf->key, keyconf->keylen);
+
+ memcpy(&priv->stations[sta_id].sta.key.key[3],
+ keyconf->key, keyconf->keylen);
+
+ priv->stations[sta_id].sta.key.key_offset = sta_id % 8; /* FIXME */
+ priv->stations[sta_id].sta.key.key_flags = key_flags;
+
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+ ret = iwl4965_send_add_station(priv,
+ &priv->stations[sta_id].sta, CMD_ASYNC);
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return ret;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 50e9f14..78e0254 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -42,5 +42,8 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key);
int iwl_set_default_wep_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key);
+int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id);

#endif /* __iwl_sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index dfd2b75..37ab1c5 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1214,7 +1214,7 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv,
ret = iwl4965_set_tkip_dynamic_key_info(priv, key, sta_id);
break;
case ALG_WEP:
- ret = -EOPNOTSUPP;
+ ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id);
break;
default:
IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
@@ -2138,7 +2138,12 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
if (wepkey->key_size == WEP_KEY_LEN_128)
cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
} else {
- IWL_ERROR("No support for WEP key mappings key\n");
+ /* the WEP key was sent as dynamic */
+ keyidx = keyinfo->keyidx;
+ memcpy(&cmd->cmd.tx.key[3], keyinfo->key,
+ keyinfo->keylen);
+ if (keyinfo->keylen == WEP_KEY_LEN_128)
+ cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
}

cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
--
1.5.3.4


2008-04-15 04:16:17

by Reinette Chatre

[permalink] [raw]
Subject: [PATCH 04/12] iwlwifi: default WEP HW encryption

From: Emmanuel Grumbach <[email protected]>

This patch adds HW encryption support in default WEP mode.
When no key mapping key/pairwise key is used. The key is broadcast key
is used as default/global/static key.
This code assumes that group cast key is added after pairwise key.

Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
drivers/net/wireless/iwlwifi/Makefile | 2 +-
drivers/net/wireless/iwlwifi/iwl-4965.h | 3 +
drivers/net/wireless/iwlwifi/iwl-sta.c | 119 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-sta.h | 46 ++++++++++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 90 ++++++++++++---------
5 files changed, 220 insertions(+), 40 deletions(-)
create mode 100644 drivers/net/wireless/iwlwifi/iwl-sta.c
create mode 100644 drivers/net/wireless/iwlwifi/iwl-sta.h

diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 2751e8a..741ea34 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -22,5 +22,5 @@ endif


obj-$(CONFIG_IWL4965) += iwl4965.o
-iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o
+iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index 65e5367..93df29e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -1112,6 +1112,9 @@ struct iwl_priv {
spinlock_t sta_lock;
int num_stations;
struct iwl4965_station_entry stations[IWL_STATION_COUNT];
+ struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
+ u8 default_wep_key;
+ u8 key_mapping_key;

/* Indication if ieee80211_ops->open has been called */
u8 is_open;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
new file mode 100644
index 0000000..a48e228
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -0,0 +1,119 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * James P. Ketrenos <[email protected]>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-4965.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+
+int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
+{
+ int i, not_empty = 0;
+ u8 buff[sizeof(struct iwl_wep_cmd) +
+ sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
+ struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
+ size_t cmd_size = sizeof(struct iwl_wep_cmd);
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_WEPKEY,
+ .data = wep_cmd,
+ .meta.flags = CMD_ASYNC,
+ };
+
+ memset(wep_cmd, 0, cmd_size +
+ (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
+
+ for (i = 0; i < WEP_KEYS_MAX ; i++) {
+ wep_cmd->key[i].key_index = i;
+ if (priv->wep_keys[i].key_size) {
+ wep_cmd->key[i].key_offset = i;
+ not_empty = 1;
+ } else {
+ wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
+ }
+
+ wep_cmd->key[i].key_size = priv->wep_keys[i].key_size;
+ memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key,
+ priv->wep_keys[i].key_size);
+ }
+
+ wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
+ wep_cmd->num_keys = WEP_KEYS_MAX;
+
+ cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
+
+ cmd.len = cmd_size;
+
+ if (not_empty || send_if_empty)
+ return iwl_send_cmd(priv, &cmd);
+ else
+ return 0;
+}
+
+int iwl_remove_default_wep_key(struct iwl_priv *priv,
+ struct ieee80211_key_conf *key)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->default_wep_key--;
+ memset(&priv->wep_keys[key->keyidx], 0, sizeof(priv->wep_keys[0]));
+ ret = iwl_send_static_wepkey_cmd(priv, 1);
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return ret;
+}
+
+int iwl_set_default_wep_key(struct iwl_priv *priv,
+ struct ieee80211_key_conf *keyconf)
+{
+ int ret;
+ unsigned long flags;
+
+ keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+ keyconf->hw_key_idx = keyconf->keyidx;
+ priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->default_wep_key++;
+
+ priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
+ memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
+ keyconf->keylen);
+
+ ret = iwl_send_static_wepkey_cmd(priv, 0);
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return ret;
+}
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
new file mode 100644
index 0000000..50e9f14
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * James P. Ketrenos <[email protected]>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#ifndef __iwl_sta_h__
+#define __iwl_sta_h__
+
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-core.h"
+#include "iwl-4965.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+
+int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty);
+int iwl_remove_default_wep_key(struct iwl_priv *priv,
+ struct ieee80211_key_conf *key);
+int iwl_set_default_wep_key(struct iwl_priv *priv,
+ struct ieee80211_key_conf *key);
+
+#endif /* __iwl_sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index ecc9cba..dfd2b75 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -50,6 +50,7 @@
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-helpers.h"
+#include "iwl-sta.h"

static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
struct iwl4965_tx_queue *txq);
@@ -941,6 +942,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
return -EIO;
}
priv->assoc_station_added = 1;
+ if (priv->default_wep_key &&
+ iwl_send_static_wepkey_cmd(priv, 0))
+ IWL_ERROR("Could not send WEP static key.\n");
}

return 0;
@@ -1180,6 +1184,8 @@ static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
{
unsigned long flags;

+ priv->key_mapping_key = 0;
+
spin_lock_irqsave(&priv->sta_lock, flags);
memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key));
memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo));
@@ -1198,6 +1204,8 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv,
{
int ret;

+ priv->key_mapping_key = 1;
+
switch (key->alg) {
case ALG_CCMP:
ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id);
@@ -1216,23 +1224,6 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv,
return ret;
}

-static int iwl4965_remove_static_key(struct iwl_priv *priv)
-{
- int ret = -EOPNOTSUPP;
-
- return ret;
-}
-
-static int iwl4965_set_static_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *key)
-{
- if (key->alg == ALG_WEP)
- return -EOPNOTSUPP;
-
- IWL_ERROR("Static key invalid: alg %d\n", key->alg);
- return -EINVAL;
-}
-
static void iwl4965_clear_free_frames(struct iwl_priv *priv)
{
struct list_head *element;
@@ -2115,6 +2106,10 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
int sta_id)
{
struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
+ struct iwl_wep_key *wepkey;
+ int keyidx = 0;
+
+ BUG_ON(ctl->key_idx > 3);

switch (keyinfo->alg) {
case ALG_CCMP:
@@ -2133,16 +2128,24 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
break;

case ALG_WEP:
- cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP |
- (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
-
- if (keyinfo->keylen == 13)
- cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
+ wepkey = &priv->wep_keys[ctl->key_idx];
+ cmd->cmd.tx.sec_ctl = 0;
+ if (priv->default_wep_key) {
+ /* the WEP key was sent as static */
+ keyidx = ctl->key_idx;
+ memcpy(&cmd->cmd.tx.key[3], wepkey->key,
+ wepkey->key_size);
+ if (wepkey->key_size == WEP_KEY_LEN_128)
+ cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
+ } else {
+ IWL_ERROR("No support for WEP key mappings key\n");
+ }

- memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
+ cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
+ (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);

IWL_DEBUG_TX("Configuring packet for WEP encryption "
- "with key %d\n", ctl->key_idx);
+ "with key %d\n", keyidx);
break;

default:
@@ -6989,7 +6992,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
DECLARE_MAC_BUF(mac);
int ret = 0;
u8 sta_id = IWL_INVALID_STATION;
- u8 static_key;
+ u8 is_default_wep_key = 0;

IWL_DEBUG_MAC80211("enter\n");

@@ -7002,33 +7005,42 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
/* only support pairwise keys */
return -EOPNOTSUPP;

- /* FIXME: need to differenciate between static and dynamic key
- * in the level of mac80211 */
- static_key = !iwl_is_associated(priv);
+ sta_id = iwl4965_hw_find_station(priv, addr);
+ if (sta_id == IWL_INVALID_STATION) {
+ IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
+ print_mac(mac, addr));
+ return -EINVAL;

- if (!static_key) {
- sta_id = iwl4965_hw_find_station(priv, addr);
- if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
- print_mac(mac, addr));
- return -EINVAL;
- }
}

+ mutex_lock(&priv->mutex);
iwl4965_scan_cancel_timeout(priv, 100);
+ mutex_unlock(&priv->mutex);
+
+ /* If we are getting WEP group key and we didn't receive any key mapping
+ * so far, we are in legacy wep mode (group key only), otherwise we are
+ * in 1X mode.
+ * In legacy wep mode, we use another host command to the uCode */
+ if (key->alg == ALG_WEP && sta_id == priv->hw_setting.bcast_sta_id &&
+ priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ if (cmd == SET_KEY)
+ is_default_wep_key = !priv->key_mapping_key;
+ else
+ is_default_wep_key = priv->default_wep_key;
+ }

switch (cmd) {
case SET_KEY:
- if (static_key)
- ret = iwl4965_set_static_key(priv, key);
+ if (is_default_wep_key)
+ ret = iwl_set_default_wep_key(priv, key);
else
ret = iwl4965_set_dynamic_key(priv, key, sta_id);

IWL_DEBUG_MAC80211("enable hwcrypto key\n");
break;
case DISABLE_KEY:
- if (static_key)
- ret = iwl4965_remove_static_key(priv);
+ if (is_default_wep_key)
+ ret = iwl_remove_default_wep_key(priv, key);
else
ret = iwl4965_clear_sta_key_info(priv, sta_id);

--
1.5.3.4


2008-04-15 16:38:24

by Reinette Chatre

[permalink] [raw]
Subject: RE: [PATCH 09/12] iwl4965: make iwl4956_send_rxon_assocasynchronous

On Tuesday, April 15, 2008 9:35 AM, Pavel Roskin wrote:

> On Tue, 2008-04-15 at 09:22 -0700, Chatre, Reinette wrote:
>>>> static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
>>>
>>> Wrong patch description. Please swap 5 and 6 :-)
>>
>> Sorry - I do not understand your comment. Could you please elaborate?
>
> The subject was:
> iwl4965: make iwl4956_send_rxon_assoc asynchronous
> (you also lost a space in this reply, but it was there)
>
> It should be:
> iwl4965: make iwl4965_send_rxon_assoc asynchronous
>
> In other words, replace 4956 with 4965 in the subject. I hope John
> can do it while applying.

oh no - great catch.

John, could you please fix the typo in the patch description when you
apply this one?

Thank you very much

Reinette

2008-04-15 16:35:19

by Pavel Roskin

[permalink] [raw]
Subject: RE: [PATCH 09/12] iwl4965: make iwl4956_send_rxon_assocasynchronous

On Tue, 2008-04-15 at 09:22 -0700, Chatre, Reinette wrote:
> >> static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
> >
> > Wrong patch description. Please swap 5 and 6 :-)
>
> Sorry - I do not understand your comment. Could you please elaborate?

The subject was:
iwl4965: make iwl4956_send_rxon_assoc asynchronous
(you also lost a space in this reply, but it was there)

It should be:
iwl4965: make iwl4965_send_rxon_assoc asynchronous

In other words, replace 4956 with 4965 in the subject. I hope John can
do it while applying.

--
Regards,
Pavel Roskin

2008-04-15 16:22:34

by Reinette Chatre

[permalink] [raw]
Subject: RE: [PATCH 09/12] iwl4965: make iwl4956_send_rxon_assocasynchronous

On Tuesday, April 15, 2008 9:17 AM, Pavel Roskin wrote:

> On Mon, 2008-04-14 at 21:16 -0700, Reinette Chatre wrote:
>> Signed-off-by: Reinette Chatre <[email protected]>
>> Acked-by: Tomas Winkler <[email protected]>
>> ---
>> drivers/net/wireless/iwlwifi/iwl4965-base.c | 27
>> ++++++--------------------- 1 files changed, 6 insertions(+), 21
>> deletions(-)
>>
>> diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c
> b/drivers/net/wireless/iwlwifi/iwl4965-base.c
>> index 60c0b83..9fb9857 100644
>> --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
>> +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
>> @@ -758,15 +758,8 @@ static int
> iwl4965_full_rxon_required(struct iwl_priv *priv)
>>
>> static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
>
> Wrong patch description. Please swap 5 and 6 :-)

Sorry - I do not understand your comment. Could you please elaborate?

Thanks

Reinette