Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: net/mac80211/pm.c
This commit is contained in:
@@ -1964,6 +1964,194 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
|
||||
{
|
||||
int rc = 0;
|
||||
struct iwl_rx_packet *res = NULL;
|
||||
struct iwl3945_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 iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
|
||||
const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
|
||||
|
||||
if ((rxon1->flags == rxon2->flags) &&
|
||||
(rxon1->filter_flags == rxon2->filter_flags) &&
|
||||
(rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
|
||||
(rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
|
||||
IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rxon_assoc.flags = priv->staging_rxon.flags;
|
||||
rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
|
||||
rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
|
||||
rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
|
||||
rxon_assoc.reserved = 0;
|
||||
|
||||
rc = iwl_send_cmd_sync(priv, &cmd);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
|
||||
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
|
||||
rc = -EIO;
|
||||
}
|
||||
|
||||
priv->alloc_rxb_skb--;
|
||||
dev_kfree_skb_any(cmd.meta.u.skb);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl3945_commit_rxon - commit staging_rxon to hardware
|
||||
*
|
||||
* The RXON command in staging_rxon is committed to the hardware and
|
||||
* the active_rxon structure is updated with the new data. This
|
||||
* function correctly transitions out of the RXON_ASSOC_MSK state if
|
||||
* a HW tune is required based on the RXON structure changes.
|
||||
*/
|
||||
static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
||||
{
|
||||
/* cast away the const for active_rxon in this function */
|
||||
struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
|
||||
struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
|
||||
int rc = 0;
|
||||
bool new_assoc =
|
||||
!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -1;
|
||||
|
||||
/* always get timestamp with Rx frame */
|
||||
staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
|
||||
|
||||
/* select antenna */
|
||||
staging_rxon->flags &=
|
||||
~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
|
||||
staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
|
||||
|
||||
rc = iwl_check_rxon_cmd(priv);
|
||||
if (rc) {
|
||||
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If we don't need to send a full RXON, we can use
|
||||
* iwl3945_rxon_assoc_cmd which is used to reconfigure filter
|
||||
* and other flags for the current radio configuration. */
|
||||
if (!iwl_full_rxon_required(priv)) {
|
||||
rc = iwl_send_rxon_assoc(priv);
|
||||
if (rc) {
|
||||
IWL_ERR(priv, "Error setting RXON_ASSOC "
|
||||
"configuration (%d).\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we are currently associated and the new config requires
|
||||
* an RXON_ASSOC and the new config wants the associated mask enabled,
|
||||
* we must clear the associated from the active configuration
|
||||
* before we apply the new config */
|
||||
if (iwl_is_associated(priv) && new_assoc) {
|
||||
IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
|
||||
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
/*
|
||||
* reserved4 and 5 could have been filled by the iwlcore code.
|
||||
* Let's clear them before pushing to the 3945.
|
||||
*/
|
||||
active_rxon->reserved4 = 0;
|
||||
active_rxon->reserved5 = 0;
|
||||
rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
|
||||
sizeof(struct iwl3945_rxon_cmd),
|
||||
&priv->active_rxon);
|
||||
|
||||
/* If the mask clearing failed then we set
|
||||
* active_rxon back to what it was previously */
|
||||
if (rc) {
|
||||
active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
|
||||
"configuration (%d).\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Sending RXON\n"
|
||||
"* with%s RXON_FILTER_ASSOC_MSK\n"
|
||||
"* channel = %d\n"
|
||||
"* bssid = %pM\n",
|
||||
(new_assoc ? "" : "out"),
|
||||
le16_to_cpu(staging_rxon->channel),
|
||||
staging_rxon->bssid_addr);
|
||||
|
||||
/*
|
||||
* reserved4 and 5 could have been filled by the iwlcore code.
|
||||
* Let's clear them before pushing to the 3945.
|
||||
*/
|
||||
staging_rxon->reserved4 = 0;
|
||||
staging_rxon->reserved5 = 0;
|
||||
|
||||
iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
|
||||
|
||||
/* Apply the new configuration */
|
||||
rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
|
||||
sizeof(struct iwl3945_rxon_cmd),
|
||||
staging_rxon);
|
||||
if (rc) {
|
||||
IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
|
||||
|
||||
priv->cfg->ops->smgmt->clear_station_table(priv);
|
||||
|
||||
/* If we issue a new RXON command which required a tune then we must
|
||||
* send a new TXPOWER command or we won't be able to Tx any frames */
|
||||
rc = priv->cfg->ops->lib->send_tx_power(priv);
|
||||
if (rc) {
|
||||
IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Add the broadcast address so we can send broadcast frames */
|
||||
if (priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0, NULL) ==
|
||||
IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* If we have set the ASSOC_MSK and we are in BSS mode then
|
||||
* add the IWL_AP_ID to the station rate table */
|
||||
if (iwl_is_associated(priv) &&
|
||||
(priv->iw_mode == NL80211_IFTYPE_STATION))
|
||||
if (priv->cfg->ops->smgmt->add_station(priv,
|
||||
priv->active_rxon.bssid_addr, 1, 0, NULL)
|
||||
== IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Error adding AP address for transmit\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Init the hardware's rate fallback order based on the band */
|
||||
rc = iwl3945_init_hw_rate_table(priv);
|
||||
if (rc) {
|
||||
IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* will add 3945 channel switch cmd handling later */
|
||||
int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
{
|
||||
@@ -2729,6 +2917,11 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct iwl_hcmd_ops iwl3945_hcmd = {
|
||||
.rxon_assoc = iwl3945_send_rxon_assoc,
|
||||
.commit_rxon = iwl3945_commit_rxon,
|
||||
};
|
||||
|
||||
static struct iwl_lib_ops iwl3945_lib = {
|
||||
.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
|
||||
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
|
||||
@@ -2758,6 +2951,17 @@ static struct iwl_lib_ops iwl3945_lib = {
|
||||
},
|
||||
.send_tx_power = iwl3945_send_tx_power,
|
||||
.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
|
||||
.post_associate = iwl3945_post_associate,
|
||||
.config_ap = iwl3945_config_ap,
|
||||
};
|
||||
|
||||
static struct iwl_station_mgmt_ops iwl3945_station_mgmt = {
|
||||
.add_station = iwl3945_add_station,
|
||||
#if 0
|
||||
.remove_station = iwl3945_remove_station,
|
||||
#endif
|
||||
.find_station = iwl3945_hw_find_station,
|
||||
.clear_station_table = iwl3945_clear_stations_table,
|
||||
};
|
||||
|
||||
static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
|
||||
@@ -2767,7 +2971,9 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
|
||||
|
||||
static struct iwl_ops iwl3945_ops = {
|
||||
.lib = &iwl3945_lib,
|
||||
.hcmd = &iwl3945_hcmd,
|
||||
.utils = &iwl3945_hcmd_utils,
|
||||
.smgmt = &iwl3945_station_mgmt,
|
||||
};
|
||||
|
||||
static struct iwl_cfg iwl3945_bg_cfg = {
|
||||
|
Reference in New Issue
Block a user