From 3fa507386dc4cdf731344cb9361e9cca373cedb9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 4 May 2011 07:50:38 -0700 Subject: iwlagn: prepare for multi-TB commands In a subsequent patch, I want to make commands use multiple TBs in a TFD. This is a simple change to prepare the data structures for this, with as of now still just a single TB supported. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 89b8da7..9f34cd7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -195,9 +195,9 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = sizeof(cmd), + .len = { sizeof(cmd), }, .flags = CMD_SYNC, - .data = &cmd, + .data = { &cmd, }, }; cmd.band = priv->band == IEEE80211_BAND_2GHZ; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 98f81df..09751f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -282,9 +282,9 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = sizeof(cmd), + .len = { sizeof(cmd), }, .flags = CMD_SYNC, - .data = &cmd, + .data = { &cmd, }, }; cmd.band = priv->band == IEEE80211_BAND_2GHZ; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a7921f9a..860c26e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -221,9 +221,9 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = sizeof(cmd), + .len = { sizeof(cmd), }, .flags = CMD_SYNC, - .data = &cmd, + .data = { &cmd, }, }; cmd.band = priv->band == IEEE80211_BAND_2GHZ; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 0f6bb9b..30e11c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -93,8 +93,8 @@ int iwl_send_calib_results(struct iwl_priv *priv) for (i = 0; i < IWL_CALIB_MAX; i++) { if ((BIT(i) & priv->hw_params.calib_init_cfg) && priv->calib_results[i].buf) { - hcmd.len = priv->calib_results[i].buf_len; - hcmd.data = priv->calib_results[i].buf; + hcmd.len[0] = priv->calib_results[i].buf_len; + hcmd.data[0] = priv->calib_results[i].buf; ret = iwl_send_cmd_sync(priv, &hcmd); if (ret) { IWL_ERR(priv, "Error %d iteration %d\n", @@ -456,9 +456,9 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) struct iwl_sensitivity_data *data = NULL; struct iwl_host_cmd cmd_out = { .id = SENSITIVITY_CMD, - .len = sizeof(struct iwl_sensitivity_cmd), + .len = { sizeof(struct iwl_sensitivity_cmd), }, .flags = CMD_ASYNC, - .data = &cmd, + .data = { &cmd, }, }; data = &(priv->sensitivity_data); @@ -491,9 +491,9 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) struct iwl_sensitivity_data *data = NULL; struct iwl_host_cmd cmd_out = { .id = SENSITIVITY_CMD, - .len = sizeof(struct iwl_enhance_sensitivity_cmd), + .len = { sizeof(struct iwl_enhance_sensitivity_cmd), }, .flags = CMD_ASYNC, - .data = &cmd, + .data = { &cmd, }, }; data = &(priv->sensitivity_data); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 8e79653..576f45e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1140,7 +1140,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) { struct iwl_host_cmd cmd = { .id = REPLY_SCAN_CMD, - .len = sizeof(struct iwl_scan_cmd), + .len = { sizeof(struct iwl_scan_cmd), }, .flags = CMD_SIZE_HUGE, }; struct iwl_scan_cmd *scan; @@ -1425,10 +1425,10 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) return -EIO; } - cmd.len += le16_to_cpu(scan->tx_cmd.len) + + cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) + scan->channel_count * sizeof(struct iwl_scan_channel); - cmd.data = scan; - scan->len = cpu_to_le16(cmd.len); + cmd.data[0] = scan; + scan->len = cpu_to_le16(cmd.len[0]); /* set scan bit here for PAN params */ set_bit(STATUS_SCAN_HW, &priv->status); @@ -1520,9 +1520,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) struct iwl_txfifo_flush_cmd flush_cmd; struct iwl_host_cmd cmd = { .id = REPLY_TXFIFO_FLUSH, - .len = sizeof(struct iwl_txfifo_flush_cmd), + .len = { sizeof(struct iwl_txfifo_flush_cmd), }, .flags = CMD_SYNC, - .data = &flush_cmd, + .data = { &flush_cmd, }, }; might_sleep(); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 079275f..0bd722c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -144,7 +144,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, size_t cmd_size = sizeof(struct iwl_wep_cmd); struct iwl_host_cmd cmd = { .id = ctx->wep_key_cmd, - .data = wep_cmd, + .data = { wep_cmd, }, .flags = CMD_SYNC, }; @@ -172,7 +172,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX; - cmd.len = cmd_size; + cmd.len[0] = cmd_size; if (not_empty || send_if_empty) return iwl_send_cmd(priv, &cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 8bda0e8..e35755c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -217,8 +217,8 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) struct iwl_calib_cfg_cmd calib_cfg_cmd; struct iwl_host_cmd cmd = { .id = CALIBRATION_CFG_CMD, - .len = sizeof(struct iwl_calib_cfg_cmd), - .data = &calib_cfg_cmd, + .len = { sizeof(struct iwl_calib_cfg_cmd), }, + .data = { &calib_cfg_cmd, }, }; memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3ecc319..2713081 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -189,8 +189,8 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) rate_flags); /* Submit command */ - cmd.len = sizeof(*tx_beacon_cmd) + frame_size; - cmd.data = tx_beacon_cmd; + cmd.len[0] = sizeof(*tx_beacon_cmd) + frame_size; + cmd.data[0] = tx_beacon_cmd; err = iwl_send_cmd_sync(priv, &cmd); @@ -2114,8 +2114,8 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) struct iwl_calib_cfg_cmd calib_cfg_cmd; struct iwl_host_cmd cmd = { .id = CALIBRATION_CFG_CMD, - .len = sizeof(struct iwl_calib_cfg_cmd), - .data = &calib_cfg_cmd, + .len = { sizeof(struct iwl_calib_cfg_cmd), }, + .data = { &calib_cfg_cmd, }, }; memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 214e465..9daf964 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -277,15 +277,16 @@ struct iwl_device_cmd { #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) +#define IWL_MAX_CMD_TFDS 1 struct iwl_host_cmd { - const void *data; + const void *data[IWL_MAX_CMD_TFDS]; unsigned long reply_page; void (*callback)(struct iwl_priv *priv, struct iwl_device_cmd *cmd, struct iwl_rx_packet *pkt); u32 flags; - u16 len; + u16 len[IWL_MAX_CMD_TFDS]; u8 id; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 8f0beb9..1ff1f31 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -264,8 +264,8 @@ int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) { struct iwl_host_cmd cmd = { .id = id, - .len = len, - .data = data, + .len = { len, }, + .data = { data, }, }; return iwl_send_cmd_sync(priv, &cmd); @@ -279,8 +279,8 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, { struct iwl_host_cmd cmd = { .id = id, - .len = len, - .data = data, + .len = { len, }, + .data = { data, }, }; cmd.flags |= CMD_ASYNC; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 439187f..7c23beb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -107,8 +107,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) { struct iwl_host_cmd cmd = { .id = REPLY_LEDS_CMD, - .len = sizeof(struct iwl_led_cmd), - .data = led_cmd, + .len = { sizeof(struct iwl_led_cmd), }, + .data = { led_cmd, }, .flags = CMD_ASYNC, .callback = NULL, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 3c8cebd..7df2814 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -141,7 +141,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_host_cmd cmd = { .id = REPLY_ADD_STA, .flags = flags, - .data = data, + .data = { data, }, }; u8 sta_id __maybe_unused = sta->sta.sta_id; @@ -155,7 +155,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, might_sleep(); } - cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); + cmd.len[0] = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); ret = iwl_send_cmd(priv, &cmd); if (ret || (flags & CMD_ASYNC)) @@ -401,9 +401,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv, struct iwl_host_cmd cmd = { .id = REPLY_REMOVE_STA, - .len = sizeof(struct iwl_rem_sta_cmd), + .len = { sizeof(struct iwl_rem_sta_cmd), }, .flags = CMD_SYNC, - .data = &rm_sta_cmd, + .data = { &rm_sta_cmd, }, }; memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); @@ -760,9 +760,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_host_cmd cmd = { .id = REPLY_TX_LINK_QUALITY_CMD, - .len = sizeof(struct iwl_link_quality_cmd), + .len = { sizeof(struct iwl_link_quality_cmd), }, .flags = flags, - .data = lq, + .data = { lq, }, }; if (WARN_ON(lq->sta_id == IWL_INVALID_STATION)) diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 89b6696..01a8ec9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -198,10 +198,10 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) } cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); - cmd.data = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); - cmd.len = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," - " len %d\n", cmd.id, cmd.flags, cmd.len); + " len %d\n", cmd.id, cmd.flags, cmd.len[0]); /* ok, let's submit the command to ucode */ return iwl_send_cmd(priv, &cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index e69597e..7843195 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -446,7 +446,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) u16 fix_size; bool is_ct_kill = false; - fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); + fix_size = (u16)(cmd->len[0] + sizeof(out_cmd->hdr)); /* * If any of the command structures end up being larger than @@ -506,7 +506,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) out_meta->callback = cmd->callback; out_cmd->hdr.cmd = cmd->id; - memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len); + memcpy(&out_cmd->cmd.payload, cmd->data[0], cmd->len[0]); /* At this point, the out_cmd now has all of the incoming cmd * information */ @@ -555,7 +555,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, phys_addr, fix_size, 1, - U32_PAD(cmd->len)); + U32_PAD(cmd->len[0])); /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); -- cgit v0.10.2 From 214d14d4d323aab5d455b409e279f9e1e6631123 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 4 May 2011 07:50:44 -0700 Subject: iwlagn: clean up TXQ indirection All of these functions no longer need to be accessed indirectly since they're shared in all AGN devices. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index b4c8193..61d4a11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -171,10 +171,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) static struct iwl_lib_ops iwl1000_lib = { .set_hw_params = iwl1000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 9f34cd7..86feec8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -252,10 +252,6 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv, static struct iwl_lib_ops iwl2000_lib = { .set_hw_params = iwl2000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 09751f2..a70b8cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -339,10 +339,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, static struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, @@ -374,10 +370,6 @@ static struct iwl_lib_ops iwl5000_lib = { static struct iwl_lib_ops iwl5150_lib = { .set_hw_params = iwl5150_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 860c26e..f8c710d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -278,10 +278,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, static struct iwl_lib_ops iwl6000_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, @@ -314,10 +310,6 @@ static struct iwl_lib_ops iwl6000_lib = { static struct iwl_lib_ops iwl6030_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_bt_rx_handler_setup, .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 7c1becf..d34e103 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -750,12 +750,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_unlock(&priv->sta_lock); /* Attach buffers to TFD */ - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - txcmd_phys, firstlen, 1, 0); + iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1, 0); if (secondlen > 0) - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, secondlen, - 0, 0); + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, + secondlen, 0, 0); scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); @@ -911,7 +909,7 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); /* Turn off all Tx DMA fifos */ - priv->cfg->ops->lib->txq_set_sched(priv, 0); + iwlagn_txq_set_sched(priv, 0); /* Tell NIC where to find the "keep warm" buffer */ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); @@ -949,7 +947,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); /* Turn off all Tx DMA fifos */ - priv->cfg->ops->lib->txq_set_sched(priv, 0); + iwlagn_txq_set_sched(priv, 0); /* Tell NIC where to find the "keep warm" buffer */ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); @@ -975,7 +973,7 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) /* Turn off all Tx DMA fifos */ spin_lock_irqsave(&priv->lock, flags); - priv->cfg->ops->lib->txq_set_sched(priv, 0); + iwlagn_txq_set_sched(priv, 0); /* Stop each Tx DMA channel, and wait for it to be idle */ for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { @@ -1258,7 +1256,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) iwlagn_txq_inval_byte_cnt_tbl(priv, txq); - priv->cfg->ops->lib->txq_free_tfd(priv, txq); + iwlagn_txq_free_tfd(priv, txq); } return nfreed; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index e35755c..97de5d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -440,7 +440,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) IWL_MASK(0, priv->hw_params.max_txq_num)); /* Activate all Tx DMA/FIFO channels */ - priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); + iwlagn_txq_set_sched(priv, IWL_MASK(0, 7)); /* map queues to FIFOs */ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2713081..2bb08d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -200,155 +200,6 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) return err; } -static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - - dma_addr_t addr = get_unaligned_le32(&tb->lo); - if (sizeof(dma_addr_t) > sizeof(u32)) - addr |= - ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16; - - return addr; -} - -static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - - return le16_to_cpu(tb->hi_n_len) >> 4; -} - -static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, - dma_addr_t addr, u16 len) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - u16 hi_n_len = len << 4; - - put_unaligned_le32(addr, &tb->lo); - if (sizeof(dma_addr_t) > sizeof(u32)) - hi_n_len |= ((addr >> 16) >> 16) & 0xF; - - tb->hi_n_len = cpu_to_le16(hi_n_len); - - tfd->num_tbs = idx + 1; -} - -static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) -{ - return tfd->num_tbs & 0x1f; -} - -/** - * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] - * @priv - driver private data - * @txq - tx queue - * - * Does NOT advance any TFD circular buffer read/write indexes - * Does NOT free the TFD itself (which is within circular buffer) - */ -void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) -{ - struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds; - struct iwl_tfd *tfd; - struct pci_dev *dev = priv->pci_dev; - int index = txq->q.read_ptr; - int i; - int num_tbs; - - tfd = &tfd_tmp[index]; - - /* Sanity check on number of chunks */ - num_tbs = iwl_tfd_get_num_tbs(tfd); - - if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); - /* @todo issue fatal error, it is quite serious situation */ - return; - } - - /* Unmap tx_cmd */ - if (num_tbs) - pci_unmap_single(dev, - dma_unmap_addr(&txq->meta[index], mapping), - dma_unmap_len(&txq->meta[index], len), - PCI_DMA_BIDIRECTIONAL); - - /* Unmap chunks, if any. */ - for (i = 1; i < num_tbs; i++) - pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), - iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); - - /* free SKB */ - if (txq->txb) { - struct sk_buff *skb; - - skb = txq->txb[txq->q.read_ptr].skb; - - /* can be called from irqs-disabled context */ - if (skb) { - dev_kfree_skb_any(skb); - txq->txb[txq->q.read_ptr].skb = NULL; - } - } -} - -int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, - u8 reset, u8 pad) -{ - struct iwl_queue *q; - struct iwl_tfd *tfd, *tfd_tmp; - u32 num_tbs; - - q = &txq->q; - tfd_tmp = (struct iwl_tfd *)txq->tfds; - tfd = &tfd_tmp[q->write_ptr]; - - if (reset) - memset(tfd, 0, sizeof(*tfd)); - - num_tbs = iwl_tfd_get_num_tbs(tfd); - - /* Each TFD can point to a maximum 20 Tx buffers */ - if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Error can not send more than %d chunks\n", - IWL_NUM_OF_TBS); - return -EINVAL; - } - - if (WARN_ON(addr & ~DMA_BIT_MASK(36))) - return -EINVAL; - - if (unlikely(addr & ~IWL_TX_DMA_MASK)) - IWL_ERR(priv, "Unaligned address = %llx\n", - (unsigned long long)addr); - - iwl_tfd_set_tb(tfd, num_tbs, addr, len); - - return 0; -} - -/* - * Tell nic where to find circular buffer of Tx Frame Descriptors for - * given Tx queue, and enable the DMA channel used for that queue. - * - * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA - * channels supported in hardware. - */ -int iwl_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - int txq_id = txq->q.id; - - /* Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), - txq->q.dma_addr >> 8); - - return 0; -} - static void iwl_bg_beacon_update(struct work_struct *work) { struct iwl_priv *priv = diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index fe33fe8..269e0c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -191,12 +191,10 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); void iwl_setup_rx_handlers(struct iwl_priv *priv); /* tx */ -void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); -int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); +int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset, u8 pad); -int iwl_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq); void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 5b5b0cce..3bb76f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -127,16 +127,6 @@ struct iwl_temp_ops { struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); - /* Handling TX */ - void (*txq_set_sched)(struct iwl_priv *priv, u32 mask); - int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, - u16 len, u8 reset, u8 pad); - void (*txq_free_tfd)(struct iwl_priv *priv, - struct iwl_tx_queue *txq); - int (*txq_init)(struct iwl_priv *priv, - struct iwl_tx_queue *txq); /* setup Rx handler */ void (*rx_handler_setup)(struct iwl_priv *priv); /* setup deferred work */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7843195..302284b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -32,6 +32,7 @@ #include #include #include "iwl-eeprom.h" +#include "iwl-agn.h" #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-sta.h" @@ -85,6 +86,154 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) txq->need_update = 0; } +static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + + dma_addr_t addr = get_unaligned_le32(&tb->lo); + if (sizeof(dma_addr_t) > sizeof(u32)) + addr |= + ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16; + + return addr; +} + +static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + + return le16_to_cpu(tb->hi_n_len) >> 4; +} + +static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, + dma_addr_t addr, u16 len) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + u16 hi_n_len = len << 4; + + put_unaligned_le32(addr, &tb->lo); + if (sizeof(dma_addr_t) > sizeof(u32)) + hi_n_len |= ((addr >> 16) >> 16) & 0xF; + + tb->hi_n_len = cpu_to_le16(hi_n_len); + + tfd->num_tbs = idx + 1; +} + +static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) +{ + return tfd->num_tbs & 0x1f; +} + +/** + * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] + * @priv - driver private data + * @txq - tx queue + * + * Does NOT advance any TFD circular buffer read/write indexes + * Does NOT free the TFD itself (which is within circular buffer) + */ +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) +{ + struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds; + struct iwl_tfd *tfd; + struct pci_dev *dev = priv->pci_dev; + int index = txq->q.read_ptr; + int i; + int num_tbs; + + tfd = &tfd_tmp[index]; + + /* Sanity check on number of chunks */ + num_tbs = iwl_tfd_get_num_tbs(tfd); + + if (num_tbs >= IWL_NUM_OF_TBS) { + IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); + /* @todo issue fatal error, it is quite serious situation */ + return; + } + + /* Unmap tx_cmd */ + if (num_tbs) + pci_unmap_single(dev, + dma_unmap_addr(&txq->meta[index], mapping), + dma_unmap_len(&txq->meta[index], len), + PCI_DMA_BIDIRECTIONAL); + + /* Unmap chunks, if any. */ + for (i = 1; i < num_tbs; i++) + pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), + iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); + + /* free SKB */ + if (txq->txb) { + struct sk_buff *skb; + + skb = txq->txb[txq->q.read_ptr].skb; + + /* can be called from irqs-disabled context */ + if (skb) { + dev_kfree_skb_any(skb); + txq->txb[txq->q.read_ptr].skb = NULL; + } + } +} + +int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + dma_addr_t addr, u16 len, + u8 reset, u8 pad) +{ + struct iwl_queue *q; + struct iwl_tfd *tfd, *tfd_tmp; + u32 num_tbs; + + q = &txq->q; + tfd_tmp = (struct iwl_tfd *)txq->tfds; + tfd = &tfd_tmp[q->write_ptr]; + + if (reset) + memset(tfd, 0, sizeof(*tfd)); + + num_tbs = iwl_tfd_get_num_tbs(tfd); + + /* Each TFD can point to a maximum 20 Tx buffers */ + if (num_tbs >= IWL_NUM_OF_TBS) { + IWL_ERR(priv, "Error can not send more than %d chunks\n", + IWL_NUM_OF_TBS); + return -EINVAL; + } + + if (WARN_ON(addr & ~DMA_BIT_MASK(36))) + return -EINVAL; + + if (unlikely(addr & ~IWL_TX_DMA_MASK)) + IWL_ERR(priv, "Unaligned address = %llx\n", + (unsigned long long)addr); + + iwl_tfd_set_tb(tfd, num_tbs, addr, len); + + return 0; +} + +/* + * Tell nic where to find circular buffer of Tx Frame Descriptors for + * given Tx queue, and enable the DMA channel used for that queue. + * + * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA + * channels supported in hardware. + */ +static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) +{ + int txq_id = txq->q.id; + + /* Circular buffer (TFD queue in DRAM) physical base address */ + iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), + txq->q.dma_addr >> 8); + + return 0; +} + /** * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's */ @@ -97,7 +246,7 @@ void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) return; while (q->write_ptr != q->read_ptr) { - priv->cfg->ops->lib->txq_free_tfd(priv, txq); + iwlagn_txq_free_tfd(priv, txq); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } } @@ -391,7 +540,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, return ret; /* Tell device where to find queue */ - priv->cfg->ops->lib->txq_init(priv, txq); + iwlagn_tx_queue_init(priv, txq); return 0; err: @@ -420,7 +569,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); /* Tell device where to find queue */ - priv->cfg->ops->lib->txq_init(priv, txq); + iwlagn_tx_queue_init(priv, txq); } /*************** HOST COMMAND QUEUE FUNCTIONS *****/ @@ -553,9 +702,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, fix_size, 1, - U32_PAD(cmd->len[0])); + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, fix_size, 1, + U32_PAD(cmd->len[0])); /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); -- cgit v0.10.2 From 4c42db0f04e55d48f0ea9f424144a5211b7a155c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 4 May 2011 07:50:48 -0700 Subject: iwlagn: remove unused pad argument The pad argument to iwlagn_txq_free_tfd isn't used, remove it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index d34e103..9acf0e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -750,10 +750,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_unlock(&priv->sta_lock); /* Attach buffers to TFD */ - iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1, 0); + iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1); if (secondlen > 0) iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, - secondlen, 0, 0); + secondlen, 0); scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 269e0c4..fc7dc06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -194,7 +194,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv); void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, u8 reset, u8 pad); + dma_addr_t addr, u16 len, u8 reset); void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9daf964..38254bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -48,8 +48,6 @@ #include "iwl-agn-rs.h" #include "iwl-agn-tt.h" -#define U32_PAD(n) ((4-(n))&0x3) - struct iwl_tx_queue; /* CT-KILL constants */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 302284b..a47558f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -182,7 +182,7 @@ void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, - u8 reset, u8 pad) + u8 reset) { struct iwl_queue *q; struct iwl_tfd *tfd, *tfd_tmp; @@ -702,8 +702,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); - iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, fix_size, 1, - U32_PAD(cmd->len[0])); + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, fix_size, 1); /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); -- cgit v0.10.2 From 4ce7cc2b09553a91d4aea014c39674685715173a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 May 2011 11:57:40 -0700 Subject: iwlagn: support multiple TBs per command The current "huge" command handling is a bit confusing, and very limited since only one command may be huge at a time. Additionally, we often copy data around quite pointlessly since we could instead map the existing scan buffer for example and use it directly. This patch makes that possible. The first change is that multiple buffers may be given to each command (this change was prepared earlier so callsites don't need to change). Each of those can be mapped attached to a TB in the TFD, and the command header can use a TB (the first one) in the TFD as well. Doing this allows getting rid of huge commands in favour of mapping existing buffers. The beacon transmission is also optimised to not copy the SKB at all but use multiple TBs. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 30e11c7..d39efcc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -87,7 +87,6 @@ int iwl_send_calib_results(struct iwl_priv *priv) struct iwl_host_cmd hcmd = { .id = REPLY_PHY_CALIBRATION_CMD, - .flags = CMD_SIZE_HUGE, }; for (i = 0; i < IWL_CALIB_MAX; i++) { @@ -95,6 +94,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) priv->calib_results[i].buf) { hcmd.len[0] = priv->calib_results[i].buf_len; hcmd.data[0] = priv->calib_results[i].buf; + hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; ret = iwl_send_cmd_sync(priv, &hcmd); if (ret) { IWL_ERR(priv, "Error %d iteration %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 576f45e..f803fb6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1141,7 +1141,6 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) struct iwl_host_cmd cmd = { .id = REPLY_SCAN_CMD, .len = { sizeof(struct iwl_scan_cmd), }, - .flags = CMD_SIZE_HUGE, }; struct iwl_scan_cmd *scan; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; @@ -1428,6 +1427,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) + scan->channel_count * sizeof(struct iwl_scan_channel); cmd.data[0] = scan; + cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; scan->len = cpu_to_le16(cmd.len[0]); /* set scan bit here for PAN params */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2bb08d7..675b9a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -134,12 +134,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) struct iwl_tx_beacon_cmd *tx_beacon_cmd; struct iwl_host_cmd cmd = { .id = REPLY_TX_BEACON, - .flags = CMD_SIZE_HUGE, }; u32 frame_size; u32 rate_flags; u32 rate; - int err; /* * We have to set up the TX command, the TX Beacon command, and the @@ -156,17 +154,15 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) if (WARN_ON(!priv->beacon_skb)) return -EINVAL; - /* Allocate beacon memory */ - tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len, - GFP_KERNEL); + /* Allocate beacon command */ + if (!priv->beacon_cmd) + priv->beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd), GFP_KERNEL); + tx_beacon_cmd = priv->beacon_cmd; if (!tx_beacon_cmd) return -ENOMEM; frame_size = priv->beacon_skb->len; - /* Set up TX beacon contents */ - memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size); - /* Set up TX command fields */ tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; @@ -175,7 +171,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; /* Set up TX beacon command fields */ - iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame, + iwl_set_beacon_tim(priv, tx_beacon_cmd, priv->beacon_skb->data, frame_size); /* Set up packet rate and flags */ @@ -189,15 +185,14 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) rate_flags); /* Submit command */ - cmd.len[0] = sizeof(*tx_beacon_cmd) + frame_size; + cmd.len[0] = sizeof(*tx_beacon_cmd); cmd.data[0] = tx_beacon_cmd; + cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; + cmd.len[1] = frame_size; + cmd.data[1] = priv->beacon_skb->data; + cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; - err = iwl_send_cmd_sync(priv, &cmd); - - /* Free temporary storage */ - kfree(tx_beacon_cmd); - - return err; + return iwl_send_cmd_sync(priv, &cmd); } static void iwl_bg_beacon_update(struct work_struct *work) @@ -3246,6 +3241,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv) iwlcore_free_geos(priv); iwl_free_channel_map(priv); kfree(priv->scan_cmd); + kfree(priv->beacon_cmd); } struct ieee80211_ops iwlagn_hw_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 5fdad65..6ee5f1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -205,7 +205,6 @@ enum { #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) #define SEQ_TO_INDEX(s) ((s) & 0xff) #define INDEX_TO_SEQ(i) ((i) & 0xff) -#define SEQ_HUGE_FRAME cpu_to_le16(0x4000) #define SEQ_RX_FRAME cpu_to_le16(0x8000) /** @@ -234,9 +233,7 @@ struct iwl_cmd_header { * * 0:7 tfd index - position within TX queue * 8:12 TX queue id - * 13 reserved - * 14 huge - driver sets this to indicate command is in the - * 'huge' storage at the end of the command buffers + * 13:14 reserved * 15 unsolicited RX or uCode-originated notification */ __le16 sequence; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 38254bd..3e3b8b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -110,8 +110,6 @@ struct iwl_cmd_meta { struct iwl_device_cmd *cmd, struct iwl_rx_packet *pkt); - /* The CMD_SIZE_HUGE flag bit indicates that the command - * structure is stored at the end of the shared queue memory. */ u32 flags; DEFINE_DMA_UNMAP_ADDR(mapping); @@ -121,7 +119,23 @@ struct iwl_cmd_meta { /* * Generic queue structure * - * Contains common data for Rx and Tx queues + * Contains common data for Rx and Tx queues. + * + * Note the difference between n_bd and n_window: the hardware + * always assumes 256 descriptors, so n_bd is always 256 (unless + * there might be HW changes in the future). For the normal TX + * queues, n_window, which is the size of the software queue data + * is also 256; however, for the command queue, n_window is only + * 32 since we don't need so many commands pending. Since the HW + * still uses 256 BDs for DMA though, n_bd stays 256. As a result, + * the software buffers (in the variables @meta, @txb in struct + * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds + * in the same struct) have 256. + * This means that we end up with the following: + * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 | + * SW entries: | 0 | ... | 31 | + * where N is a number between 0 and 7. This means that the SW + * data is a window overlayed over the HW queue. */ struct iwl_queue { int n_bd; /* number of BDs in this queue */ @@ -163,7 +177,7 @@ struct iwl_tx_info { struct iwl_tx_queue { struct iwl_queue q; - void *tfds; + struct iwl_tfd *tfds; struct iwl_device_cmd **cmd; struct iwl_cmd_meta *meta; struct iwl_tx_info *txb; @@ -245,7 +259,6 @@ enum { CMD_SYNC = 0, CMD_SIZE_NORMAL = 0, CMD_NO_SKB = 0, - CMD_SIZE_HUGE = (1 << 0), CMD_ASYNC = (1 << 1), CMD_WANT_SKB = (1 << 2), CMD_MAPPED = (1 << 3), @@ -257,8 +270,8 @@ enum { * struct iwl_device_cmd * * For allocation of the command and tx queues, this establishes the overall - * size of the largest command we send to uCode, except for a scan command - * (which is relatively huge; space is allocated separately). + * size of the largest command we send to uCode, except for commands that + * aren't fully copied and use other TFD space. */ struct iwl_device_cmd { struct iwl_cmd_header hdr; /* uCode API */ @@ -275,7 +288,11 @@ struct iwl_device_cmd { #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) -#define IWL_MAX_CMD_TFDS 1 +#define IWL_MAX_CMD_TFDS 2 + +enum iwl_hcmd_dataflag { + IWL_HCMD_DFL_NOCOPY = BIT(0), +}; struct iwl_host_cmd { const void *data[IWL_MAX_CMD_TFDS]; @@ -285,6 +302,7 @@ struct iwl_host_cmd { struct iwl_rx_packet *pkt); u32 flags; u16 len[IWL_MAX_CMD_TFDS]; + u8 dataflags[IWL_MAX_CMD_TFDS]; u8 id; }; @@ -687,17 +705,8 @@ static inline int iwl_queue_used(const struct iwl_queue *q, int i) } -static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) +static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) { - /* - * This is for init calibration result and scan command which - * required buffer > TFD_MAX_PAYLOAD_SIZE, - * the big buffer at end of command array - */ - if (is_huge) - return q->n_window; /* must be power of 2 */ - - /* Otherwise, use normal size buffers */ return index & (q->n_window - 1); } @@ -1451,6 +1460,7 @@ struct iwl_priv { struct work_struct beacon_update; struct iwl_rxon_context *beacon_ctx; struct sk_buff *beacon_skb; + void *beacon_cmd; struct work_struct tt_work; struct work_struct ct_enter; diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index f00172c..fc13186 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -137,20 +137,27 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, #define TRACE_SYSTEM iwlwifi TRACE_EVENT(iwlwifi_dev_hcmd, - TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags), - TP_ARGS(priv, hcmd, len, flags), + TP_PROTO(struct iwl_priv *priv, u32 flags, + const void *hcmd0, size_t len0, + const void *hcmd1, size_t len1, + const void *hcmd2, size_t len2), + TP_ARGS(priv, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2), TP_STRUCT__entry( PRIV_ENTRY - __dynamic_array(u8, hcmd, len) + __dynamic_array(u8, hcmd0, len0) + __dynamic_array(u8, hcmd1, len1) + __dynamic_array(u8, hcmd2, len2) __field(u32, flags) ), TP_fast_assign( PRIV_ASSIGN; - memcpy(__get_dynamic_array(hcmd), hcmd, len); + memcpy(__get_dynamic_array(hcmd0), hcmd0, len0); + memcpy(__get_dynamic_array(hcmd1), hcmd1, len1); + memcpy(__get_dynamic_array(hcmd2), hcmd2, len2); __entry->flags = flags; ), TP_printk("[%p] hcmd %#.2x (%ssync)", - __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0], + __entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0], __entry->flags & CMD_ASYNC ? "a" : "") ); diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 01a8ec9..dd2904a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -200,6 +200,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," " len %d\n", cmd.id, cmd.flags, cmd.len[0]); /* ok, let's submit the command to ucode */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index a47558f..2f6b38c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -125,25 +125,13 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) return tfd->num_tbs & 0x1f; } -/** - * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] - * @priv - driver private data - * @txq - tx queue - * - * Does NOT advance any TFD circular buffer read/write indexes - * Does NOT free the TFD itself (which is within circular buffer) - */ -void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) +static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, + struct iwl_tfd *tfd) { - struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds; - struct iwl_tfd *tfd; struct pci_dev *dev = priv->pci_dev; - int index = txq->q.read_ptr; int i; int num_tbs; - tfd = &tfd_tmp[index]; - /* Sanity check on number of chunks */ num_tbs = iwl_tfd_get_num_tbs(tfd); @@ -156,14 +144,30 @@ void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) /* Unmap tx_cmd */ if (num_tbs) pci_unmap_single(dev, - dma_unmap_addr(&txq->meta[index], mapping), - dma_unmap_len(&txq->meta[index], len), + dma_unmap_addr(meta, mapping), + dma_unmap_len(meta, len), PCI_DMA_BIDIRECTIONAL); /* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++) pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); +} + +/** + * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] + * @priv - driver private data + * @txq - tx queue + * + * Does NOT advance any TFD circular buffer read/write indexes + * Does NOT free the TFD itself (which is within circular buffer) + */ +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) +{ + struct iwl_tfd *tfd_tmp = txq->tfds; + int index = txq->q.read_ptr; + + iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index]); /* free SKB */ if (txq->txb) { @@ -189,7 +193,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, u32 num_tbs; q = &txq->q; - tfd_tmp = (struct iwl_tfd *)txq->tfds; + tfd_tmp = txq->tfds; tfd = &tfd_tmp[q->write_ptr]; if (reset) @@ -303,7 +307,7 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) return; while (q->read_ptr != q->write_ptr) { - i = get_cmd_index(q, q->read_ptr, 0); + i = get_cmd_index(q, q->read_ptr); if (txq->meta[i].flags & CMD_MAPPED) { pci_unmap_single(priv->pci_dev, @@ -315,15 +319,6 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } - - i = q->n_window; - if (txq->meta[i].flags & CMD_MAPPED) { - pci_unmap_single(priv->pci_dev, - dma_unmap_addr(&txq->meta[i], mapping), - dma_unmap_len(&txq->meta[i], len), - PCI_DMA_BIDIRECTIONAL); - txq->meta[i].flags = 0; - } } /** @@ -343,7 +338,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) iwl_cmd_queue_unmap(priv); /* De-alloc array of command/tx buffers */ - for (i = 0; i <= TFD_CMD_SLOTS; i++) + for (i = 0; i < TFD_CMD_SLOTS; i++) kfree(txq->cmd[i]); /* De-alloc circular buffer of TFDs */ @@ -483,33 +478,17 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, { int i, len; int ret; - int actual_slots = slots_num; - - /* - * Alloc buffer array for commands (Tx or other types of commands). - * For the command queue (#4/#9), allocate command space + one big - * command for scan, since scan command is very huge; the system will - * not have two scans at the same time, so only one is needed. - * For normal Tx queues (all other queues), no super-size command - * space is needed. - */ - if (txq_id == priv->cmd_queue) - actual_slots++; - txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots, + txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num, GFP_KERNEL); - txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots, + txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num, GFP_KERNEL); if (!txq->meta || !txq->cmd) goto out_free_arrays; len = sizeof(struct iwl_device_cmd); - for (i = 0; i < actual_slots; i++) { - /* only happens for cmd queue */ - if (i == slots_num) - len = IWL_MAX_CMD_SIZE; - + for (i = 0; i < slots_num; i++) { txq->cmd[i] = kmalloc(len, GFP_KERNEL); if (!txq->cmd[i]) goto err; @@ -544,7 +523,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, return 0; err: - for (i = 0; i < actual_slots; i++) + for (i = 0; i < slots_num; i++) kfree(txq->cmd[i]); out_free_arrays: kfree(txq->meta); @@ -592,23 +571,44 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) dma_addr_t phys_addr; unsigned long flags; u32 idx; - u16 fix_size; + u16 copy_size, cmd_size; bool is_ct_kill = false; + bool had_nocopy = false; + int i; + u8 *cmd_dest; +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING + const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {}; + int trace_lens[IWL_MAX_CMD_TFDS + 1] = {}; + int trace_idx; +#endif - fix_size = (u16)(cmd->len[0] + sizeof(out_cmd->hdr)); + copy_size = sizeof(out_cmd->hdr); + cmd_size = sizeof(out_cmd->hdr); + + /* need one for the header if the first is NOCOPY */ + BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); + + for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { + if (!cmd->len[i]) + continue; + if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { + had_nocopy = true; + } else { + /* NOCOPY must not be followed by normal! */ + if (WARN_ON(had_nocopy)) + return -EINVAL; + copy_size += cmd->len[i]; + } + cmd_size += cmd->len[i]; + } /* * If any of the command structures end up being larger than - * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then - * we will need to increase the size of the TFD entries - * Also, check to see if command buffer should not exceed the size - * of device_cmd and max_cmd_size. + * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically + * allocated into separate TFDs, then we will need to + * increase the size of the buffers. */ - if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && - !(cmd->flags & CMD_SIZE_HUGE))) - return -EINVAL; - - if (WARN_ON(fix_size > IWL_MAX_CMD_SIZE)) + if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) return -EINVAL; if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { @@ -617,14 +617,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -EIO; } - /* - * As we only have a single huge buffer, check that the command - * is synchronous (otherwise buffers could end up being reused). - */ - - if (WARN_ON((cmd->flags & CMD_ASYNC) && (cmd->flags & CMD_SIZE_HUGE))) - return -EINVAL; - spin_lock_irqsave(&priv->hcmd_lock, flags); if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { @@ -639,7 +631,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -ENOSPC; } - idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); + idx = get_cmd_index(q, q->write_ptr); out_cmd = txq->cmd[idx]; out_meta = &txq->meta[idx]; @@ -654,55 +646,84 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (cmd->flags & CMD_ASYNC) out_meta->callback = cmd->callback; - out_cmd->hdr.cmd = cmd->id; - memcpy(&out_cmd->cmd.payload, cmd->data[0], cmd->len[0]); - - /* At this point, the out_cmd now has all of the incoming cmd - * information */ + /* set up the header */ + out_cmd->hdr.cmd = cmd->id; out_cmd->hdr.flags = 0; out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | - INDEX_TO_SEQ(q->write_ptr)); - if (cmd->flags & CMD_SIZE_HUGE) - out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; - -#ifdef CONFIG_IWLWIFI_DEBUG - switch (out_cmd->hdr.cmd) { - case REPLY_TX_LINK_QUALITY_CMD: - case SENSITIVITY_CMD: - IWL_DEBUG_HC_DUMP(priv, "Sending command %s (#%x), seq: 0x%04X, " - "%d bytes at %d[%d]:%d\n", - get_cmd_string(out_cmd->hdr.cmd), - out_cmd->hdr.cmd, - le16_to_cpu(out_cmd->hdr.sequence), fix_size, - q->write_ptr, idx, priv->cmd_queue); - break; - default: - IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " - "%d bytes at %d[%d]:%d\n", - get_cmd_string(out_cmd->hdr.cmd), - out_cmd->hdr.cmd, - le16_to_cpu(out_cmd->hdr.sequence), fix_size, - q->write_ptr, idx, priv->cmd_queue); + INDEX_TO_SEQ(q->write_ptr)); + + /* and copy the data that needs to be copied */ + + cmd_dest = &out_cmd->cmd.payload[0]; + for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { + if (!cmd->len[i]) + continue; + if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) + break; + memcpy(cmd_dest, cmd->data[i], cmd->len[i]); + cmd_dest += cmd->len[i]; } -#endif + + IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " + "%d bytes at %d[%d]:%d\n", + get_cmd_string(out_cmd->hdr.cmd), + out_cmd->hdr.cmd, + le16_to_cpu(out_cmd->hdr.sequence), cmd_size, + q->write_ptr, idx, priv->cmd_queue); + phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, - fix_size, PCI_DMA_BIDIRECTIONAL); + copy_size, PCI_DMA_BIDIRECTIONAL); if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { idx = -ENOMEM; goto out; } dma_unmap_addr_set(out_meta, mapping, phys_addr); - dma_unmap_len_set(out_meta, len, fix_size); + dma_unmap_len_set(out_meta, len, copy_size); + + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1); +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING + trace_bufs[0] = &out_cmd->hdr; + trace_lens[0] = copy_size; + trace_idx = 1; +#endif + + for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { + if (!cmd->len[i]) + continue; + if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) + continue; + phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i], + cmd->len[i], PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) { + iwlagn_unmap_tfd(priv, out_meta, + &txq->tfds[q->write_ptr]); + idx = -ENOMEM; + goto out; + } + + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, + cmd->len[i], 0); +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING + trace_bufs[trace_idx] = cmd->data[i]; + trace_lens[trace_idx] = cmd->len[i]; + trace_idx++; +#endif + } out_meta->flags = cmd->flags | CMD_MAPPED; txq->need_update = 1; - trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); - - iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, fix_size, 1); + /* check that tracing gets all possible blocks */ + BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3); +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING + trace_iwlwifi_dev_hcmd(priv, cmd->flags, + trace_bufs[0], trace_lens[0], + trace_bufs[1], trace_lens[1], + trace_bufs[2], trace_lens[2]); +#endif /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); @@ -761,7 +782,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) int txq_id = SEQ_TO_QUEUE(sequence); int index = SEQ_TO_INDEX(sequence); int cmd_index; - bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; @@ -779,14 +799,11 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) return; } - cmd_index = get_cmd_index(&txq->q, index, huge); + cmd_index = get_cmd_index(&txq->q, index); cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; - pci_unmap_single(priv->pci_dev, - dma_unmap_addr(meta, mapping), - dma_unmap_len(meta, len), - PCI_DMA_BIDIRECTIONAL); + iwlagn_unmap_tfd(priv, meta, &txq->tfds[index]); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { -- cgit v0.10.2 From 5065054790b111bf677b1eccf3f8f76f20cc0ae6 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 4 May 2011 16:56:52 -0700 Subject: iwlagn: more ucode error log info No functional changes, just logging more information when uCode crash, also change change the format. Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 675b9a6..a7054a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1622,10 +1622,7 @@ static const char *desc_lookup(u32 num) void iwl_dump_nic_error_log(struct iwl_priv *priv) { - u32 data2, line; - u32 desc, time, count, base, data1; - u32 blink1, blink2, ilink1, ilink2; - u32 pc, hcmd; + u32 base; struct iwl_error_event_table table; base = priv->device_pointers.error_event_table; @@ -1648,37 +1645,40 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); - count = table.valid; - - if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { + if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { IWL_ERR(priv, "Start IWL Error Log Dump:\n"); IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", - priv->status, count); - } - - desc = table.error_id; - priv->isr_stats.err_code = desc; - pc = table.pc; - blink1 = table.blink1; - blink2 = table.blink2; - ilink1 = table.ilink1; - ilink2 = table.ilink2; - data1 = table.data1; - data2 = table.data2; - line = table.line; - time = table.tsf_low; - hcmd = table.hcmd; - - trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, - blink1, blink2, ilink1, ilink2); - - IWL_ERR(priv, "Desc Time " - "data1 data2 line\n"); - IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n", - desc_lookup(desc), desc, time, data1, data2, line); - IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); - IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", - pc, blink1, blink2, ilink1, ilink2, hcmd); + priv->status, table.valid); + } + + priv->isr_stats.err_code = table.error_id; + + trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, + table.data1, table.data2, table.line, + table.blink1, table.blink2, table.ilink1, + table.ilink2, table.bcon_time, table.gp1, + table.gp2, table.gp3, table.ucode_ver, + table.hw_ver, table.brd_ver); + IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, + desc_lookup(table.error_id)); + IWL_ERR(priv, "0x%08X | uPc\n", table.pc); + IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1); + IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2); + IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1); + IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2); + IWL_ERR(priv, "0x%08X | data1\n", table.data1); + IWL_ERR(priv, "0x%08X | data2\n", table.data2); + IWL_ERR(priv, "0x%08X | line\n", table.line); + IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time); + IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low); + IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi); + IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1); + IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2); + IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3); + IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver); + IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver); + IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver); + IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd); } #define EVENT_START_OFFSET (4 * sizeof(u32)) diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index fc13186..2c84ba95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -209,15 +209,18 @@ TRACE_EVENT(iwlwifi_dev_tx, ); TRACE_EVENT(iwlwifi_dev_ucode_error, - TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time, + TP_PROTO(struct iwl_priv *priv, u32 desc, u32 tsf_low, u32 data1, u32 data2, u32 line, u32 blink1, - u32 blink2, u32 ilink1, u32 ilink2), - TP_ARGS(priv, desc, time, data1, data2, line, - blink1, blink2, ilink1, ilink2), + u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time, + u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver, + u32 brd_ver), + TP_ARGS(priv, desc, tsf_low, data1, data2, line, + blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2, + gp3, ucode_ver, hw_ver, brd_ver), TP_STRUCT__entry( PRIV_ENTRY __field(u32, desc) - __field(u32, time) + __field(u32, tsf_low) __field(u32, data1) __field(u32, data2) __field(u32, line) @@ -225,11 +228,18 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, __field(u32, blink2) __field(u32, ilink1) __field(u32, ilink2) + __field(u32, bcon_time) + __field(u32, gp1) + __field(u32, gp2) + __field(u32, gp3) + __field(u32, ucode_ver) + __field(u32, hw_ver) + __field(u32, brd_ver) ), TP_fast_assign( PRIV_ASSIGN; __entry->desc = desc; - __entry->time = time; + __entry->tsf_low = tsf_low; __entry->data1 = data1; __entry->data2 = data2; __entry->line = line; @@ -237,12 +247,25 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, __entry->blink2 = blink2; __entry->ilink1 = ilink1; __entry->ilink2 = ilink2; + __entry->bcon_time = bcon_time; + __entry->gp1 = gp1; + __entry->gp2 = gp2; + __entry->gp3 = gp3; + __entry->ucode_ver = ucode_ver; + __entry->hw_ver = hw_ver; + __entry->brd_ver = brd_ver; ), TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, " - "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X", - __entry->priv, __entry->desc, __entry->time, __entry->data1, + "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X " + "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X " + "hw 0x%08X brd 0x%08X", + __entry->priv, __entry->desc, __entry->tsf_low, + __entry->data1, __entry->data2, __entry->line, __entry->blink1, - __entry->blink2, __entry->ilink1, __entry->ilink2) + __entry->blink2, __entry->ilink1, __entry->ilink2, + __entry->bcon_time, __entry->gp1, __entry->gp2, + __entry->gp3, __entry->ucode_ver, __entry->hw_ver, + __entry->brd_ver) ); TRACE_EVENT(iwlwifi_dev_ucode_event, -- cgit v0.10.2 From 7a4e5281d1b3335a3dc90841415390473cccebf3 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 6 May 2011 10:21:28 -0700 Subject: iwlagn: add testmode trace command Adding testmode trace/debug capability Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a7054a5..e027f99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3659,6 +3659,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) */ set_bit(STATUS_EXIT_PENDING, &priv->status); + iwl_testmode_cleanup(priv); iwl_leds_exit(priv); if (priv->mac80211_registered) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index fc7dc06..2495fe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -343,6 +343,7 @@ extern int iwl_alive_start(struct iwl_priv *priv); #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); extern void iwl_testmode_init(struct iwl_priv *priv); +extern void iwl_testmode_cleanup(struct iwl_priv *priv); #else static inline int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) @@ -353,6 +354,10 @@ static inline void iwl_testmode_init(struct iwl_priv *priv) { } +static inline +void iwl_testmode_cleanup(struct iwl_priv *priv) +{ +} #endif #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 3e3b8b8..12fb2f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1179,6 +1179,14 @@ enum iwl_scan_type { IWL_SCAN_OFFCH_TX, }; +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL +struct iwl_testmode_trace { + u8 *cpu_addr; + u8 *trace_addr; + dma_addr_t dma_addr; + bool trace_enabled; +}; +#endif struct iwl_priv { /* ieee device used by generic ieee processing code */ @@ -1510,6 +1518,9 @@ struct iwl_priv { struct led_classdev led; unsigned long blink_on, blink_off; bool led_registered; +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL + struct iwl_testmode_trace testmode_trace; +#endif }; /*iwl_priv */ static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index dd2904a..b778c3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -97,6 +97,10 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, + + [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, }, + }; /* @@ -167,6 +171,31 @@ nla_put_failure: void iwl_testmode_init(struct iwl_priv *priv) { priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; + priv->testmode_trace.trace_enabled = false; +} + +static void iwl_trace_cleanup(struct iwl_priv *priv) +{ + struct device *dev = &priv->pci_dev->dev; + + if (priv->testmode_trace.trace_enabled) { + if (priv->testmode_trace.cpu_addr && + priv->testmode_trace.dma_addr) + dma_free_coherent(dev, + TRACE_TOTAL_SIZE, + priv->testmode_trace.cpu_addr, + priv->testmode_trace.dma_addr); + priv->testmode_trace.trace_enabled = false; + priv->testmode_trace.cpu_addr = NULL; + priv->testmode_trace.trace_addr = NULL; + priv->testmode_trace.dma_addr = 0; + } +} + + +void iwl_testmode_cleanup(struct iwl_priv *priv) +{ + iwl_trace_cleanup(priv); } /* @@ -400,6 +429,102 @@ nla_put_failure: return -EMSGSIZE; } + +/* + * This function handles the user application commands for uCode trace + * + * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the + * handlers respectively. + * + * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned + * value of the actual command execution is replied to the user application. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + struct sk_buff *skb; + int status = 0; + struct device *dev = &priv->pci_dev->dev; + + switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: + if (priv->testmode_trace.trace_enabled) + return -EBUSY; + + priv->testmode_trace.cpu_addr = + dma_alloc_coherent(dev, + TRACE_TOTAL_SIZE, + &priv->testmode_trace.dma_addr, + GFP_KERNEL); + if (!priv->testmode_trace.cpu_addr) + return -ENOMEM; + priv->testmode_trace.trace_enabled = true; + priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN( + priv->testmode_trace.cpu_addr, 0x100); + memset(priv->testmode_trace.trace_addr, 0x03B, + TRACE_BUFF_SIZE); + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + sizeof(priv->testmode_trace.dma_addr) + 20); + if (!skb) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + iwl_trace_cleanup(priv); + return -ENOMEM; + } + NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR, + sizeof(priv->testmode_trace.dma_addr), + (u64 *)&priv->testmode_trace.dma_addr); + status = cfg80211_testmode_reply(skb); + if (status < 0) { + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", + status); + } + break; + + case IWL_TM_CMD_APP2DEV_END_TRACE: + iwl_trace_cleanup(priv); + break; + + case IWL_TM_CMD_APP2DEV_READ_TRACE: + if (priv->testmode_trace.trace_enabled && + priv->testmode_trace.trace_addr) { + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + 20 + TRACE_BUFF_SIZE); + if (skb == NULL) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA, + TRACE_BUFF_SIZE, + priv->testmode_trace.trace_addr); + status = cfg80211_testmode_reply(skb); + if (status < 0) { + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", status); + } + } else + return -EFAULT; + break; + + default: + IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n"); + return -ENOSYS; + } + return status; + +nla_put_failure: + kfree_skb(skb); + if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) == + IWL_TM_CMD_APP2DEV_BEGIN_TRACE) + iwl_trace_cleanup(priv); + return -EMSGSIZE; +} + /* The testmode gnl message handler that takes the gnl message from the * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then * invoke the corresponding handlers. @@ -459,6 +584,14 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); result = iwl_testmode_driver(hw, tb); break; + + case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: + case IWL_TM_CMD_APP2DEV_END_TRACE: + case IWL_TM_CMD_APP2DEV_READ_TRACE: + IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n"); + result = iwl_testmode_trace(hw, tb); + break; + default: IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); result = -ENOSYS; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 31f8949..34634ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -91,6 +91,10 @@ enum iwl_tm_cmd_t { /* if there is other new command for the driver layer operation, * append them here */ + /* commands fom user space for uCode trace operations */ + IWL_TM_CMD_APP2DEV_BEGIN_TRACE, + IWL_TM_CMD_APP2DEV_END_TRACE, + IWL_TM_CMD_APP2DEV_READ_TRACE, /* commands from kernel space to carry the synchronous response * to user application */ @@ -144,8 +148,19 @@ enum iwl_tm_attr_t { * application */ IWL_TM_ATTR_UCODE_RX_PKT, + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE, + * The mandatory fields are: + * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address + */ + IWL_TM_ATTR_TRACE_ADDR, + IWL_TM_ATTR_TRACE_DATA, + IWL_TM_ATTR_MAX, }; +/* uCode trace buffer */ +#define TRACE_BUFF_SIZE 0x20000 +#define TRACE_BUFF_PADD 0x2000 +#define TRACE_TOTAL_SIZE (TRACE_BUFF_SIZE + TRACE_BUFF_PADD) #endif -- cgit v0.10.2 From 4babc358c0a1bced6bed2c9d6c77fc8803b8a22f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 3 May 2011 18:05:12 -0700 Subject: iwlagn: add eeprom command to testmode Add the capability to dump eeprom through testmode request Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index b778c3f..e77ccaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -98,6 +98,8 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, }, @@ -418,6 +420,29 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) "Error starting the device: %d\n", status); break; + case IWL_TM_CMD_APP2DEV_GET_EEPROM: + if (priv->eeprom) { + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + priv->cfg->base_params->eeprom_size + 20); + if (!skb) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, + IWL_TM_CMD_DEV2APP_EEPROM_RSP); + NLA_PUT(skb, IWL_TM_ATTR_EEPROM, + priv->cfg->base_params->eeprom_size, + priv->eeprom); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", + status); + } else + return -EFAULT; + break; + default: IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); return -ENOSYS; @@ -581,6 +606,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: + case IWL_TM_CMD_APP2DEV_GET_EEPROM: IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); result = iwl_testmode_driver(hw, tb); break; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 34634ec..4171d29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -88,6 +88,7 @@ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_LOAD_INIT_FW, IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB, IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW, + IWL_TM_CMD_APP2DEV_GET_EEPROM, /* if there is other new command for the driver layer operation, * append them here */ @@ -103,6 +104,11 @@ enum iwl_tm_cmd_t { /* commands from kernel space to multicast the spontaneous messages * to user application */ IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, + + /* commands from kernel space to carry the eeprom response + * to user application */ + IWL_TM_CMD_DEV2APP_EEPROM_RSP, + IWL_TM_CMD_MAX, }; @@ -148,6 +154,12 @@ enum iwl_tm_attr_t { * application */ IWL_TM_ATTR_UCODE_RX_PKT, + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM, + * The mandatory fields are: + * IWL_TM_ATTR_EEPROM for the data content responging to the user + * application */ + IWL_TM_ATTR_EEPROM, + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE, * The mandatory fields are: * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address -- cgit v0.10.2 From 6489854b9cbc2faa6709532e61c3ea221cf8583b Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 3 May 2011 18:05:13 -0700 Subject: iwlagn: add testmode set fixed rate command Add support in testmode for setting fixed rate Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index dbe6295..432f839 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -335,6 +335,32 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, return tid; } +#if defined(CONFIG_MAC80211_DEBUGFS) || defined(CONFIG_IWLWIFI_DEVICE_SVTOOL) +static void rs_program_fix_rate(struct iwl_priv *priv, + struct iwl_lq_sta *lq_sta) +{ + struct iwl_station_priv *sta_priv = + container_of(lq_sta, struct iwl_station_priv, lq_sta); + struct iwl_rxon_context *ctx = sta_priv->common.ctx; + + lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ + lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ + lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ + lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ + + lq_sta->dbg_fixed_rate = priv->dbg_fixed_rate; + + IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", + lq_sta->lq.sta_id, priv->dbg_fixed_rate); + + if (priv->dbg_fixed_rate) { + rs_fill_link_cmd(NULL, lq_sta, priv->dbg_fixed_rate); + iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, + false); + } +} +#endif + /* get the traffic load value for tid */ @@ -1046,7 +1072,10 @@ done: /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); - +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL + if (priv->dbg_fixed_rate != lq_sta->dbg_fixed_rate) + rs_program_fix_rate(priv, lq_sta); +#endif if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) rs_bt_update_lq(priv, ctx, lq_sta); } @@ -2871,6 +2900,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_agg = 0; + priv->dbg_fixed_rate = 0; #ifdef CONFIG_MAC80211_DEBUGFS lq_sta->dbg_fixed_rate = 0; #endif @@ -3045,7 +3075,6 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, IWL_DEBUG_RATE(priv, "leave\n"); } - #ifdef CONFIG_MAC80211_DEBUGFS static int open_file_generic(struct inode *inode, struct file *file) { @@ -3070,6 +3099,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, IWL_DEBUG_RATE(priv, "Fixed rate ON\n"); } else { lq_sta->dbg_fixed_rate = 0; + priv->dbg_fixed_rate = 0; IWL_ERR(priv, "Invalid antenna selection 0x%X, Valid is 0x%X\n", ant_sel_tx, valid_tx_ant); @@ -3088,9 +3118,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, char buf[64]; int buf_size; u32 parsed_rate; - struct iwl_station_priv *sta_priv = - container_of(lq_sta, struct iwl_station_priv, lq_sta); - struct iwl_rxon_context *ctx = sta_priv->common.ctx; + priv = lq_sta->drv; memset(buf, 0, sizeof(buf)); @@ -3099,23 +3127,11 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, return -EFAULT; if (sscanf(buf, "%x", &parsed_rate) == 1) - lq_sta->dbg_fixed_rate = parsed_rate; + priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = parsed_rate; else - lq_sta->dbg_fixed_rate = 0; - - lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ - lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - - IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", - lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); + priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = 0; - if (lq_sta->dbg_fixed_rate) { - rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); - iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, - false); - } + rs_program_fix_rate(priv, lq_sta); return count; } @@ -3143,7 +3159,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, lq_sta->total_failed, lq_sta->total_success, lq_sta->active_legacy_rate); desc += sprintf(buff+desc, "fixed rate 0x%X\n", - lq_sta->dbg_fixed_rate); + priv->dbg_fixed_rate); desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 12fb2f4..ab29ab5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1521,6 +1521,8 @@ struct iwl_priv { #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL struct iwl_testmode_trace testmode_trace; #endif + u32 dbg_fixed_rate; + }; /*iwl_priv */ static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index e77ccaa..69b7e6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -103,6 +103,7 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, }; /* @@ -443,6 +444,15 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) return -EFAULT; break; + case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: + if (!tb[IWL_TM_ATTR_FIXRATE]) { + IWL_DEBUG_INFO(priv, + "Error finding fixrate setting\n"); + return -ENOMSG; + } + priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); + break; + default: IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); return -ENOSYS; @@ -607,6 +617,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: case IWL_TM_CMD_APP2DEV_GET_EEPROM: + case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); result = iwl_testmode_driver(hw, tb); break; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 4171d29..a88085e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -89,6 +89,7 @@ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB, IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW, IWL_TM_CMD_APP2DEV_GET_EEPROM, + IWL_TM_CMD_APP2DEV_FIXRATE_REQ, /* if there is other new command for the driver layer operation, * append them here */ @@ -167,6 +168,12 @@ enum iwl_tm_attr_t { IWL_TM_ATTR_TRACE_ADDR, IWL_TM_ATTR_TRACE_DATA, + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ, + * The mandatory fields are: + * IWL_TM_ATTR_FIXRATE for the fixed rate + */ + IWL_TM_ATTR_FIXRATE, + IWL_TM_ATTR_MAX, }; -- cgit v0.10.2 From dd5c940b42c1734e501d9494f7b99566b50a5a87 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 6 May 2011 17:06:43 -0700 Subject: iwlagn: clear STATUS_HCMD_ACTIVE bit if fail enqueue If fail to enqueue host command, clear the STATUS_hcmD_ACTIVE bit Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 1ff1f31..76f9966 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -188,6 +188,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) cmd_idx = iwl_enqueue_hcmd(priv, cmd); if (cmd_idx < 0) { ret = cmd_idx; + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; -- cgit v0.10.2 From 3083d03c215a2d1642dd12ede7ad61e24601b583 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 6 May 2011 17:06:44 -0700 Subject: iwlagn: alwasy send RXON with disassociate falge before associate Before send the RXON command with associated flag set, always do disassociate first to make sure uCode is in the correct state. Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 0238743..7d40e2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -389,11 +389,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * AP station must be done after the BSSID is set to correctly * set up filters in the device. */ - if ((old_assoc && new_assoc) || !new_assoc) { - ret = iwlagn_rxon_disconn(priv, ctx); - if (ret) - return ret; - } + ret = iwlagn_rxon_disconn(priv, ctx); + if (ret) + return ret; if (new_assoc) return iwlagn_rxon_connect(priv, ctx); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 2f6b38c..54a935f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -582,6 +582,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int trace_idx; #endif + if (test_bit(STATUS_FW_ERROR, &priv->status)) { + IWL_WARN(priv, "fw recovery, no hcmd send\n"); + return -EIO; + } + copy_size = sizeof(out_cmd->hdr); cmd_size = sizeof(out_cmd->hdr); -- cgit v0.10.2 From 70817b5e14760dad49a067fc3dd137bccd3c2960 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 May 2011 03:29:25 -0700 Subject: iwlagn: remove set but unused vars gcc is warning that a few variables in rate scaling are set but never otherwise used. This pointed out a few simplifications. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 432f839..c38ba7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2199,11 +2199,11 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) * setup rate table in uCode * return rate_n_flags as used in the table */ -static u32 rs_update_rate_tbl(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl, - int index, u8 is_green) +static void rs_update_rate_tbl(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + int index, u8 is_green) { u32 rate; @@ -2211,8 +2211,6 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); rs_fill_link_cmd(priv, lq_sta, rate); iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); - - return rate; } /* @@ -2241,7 +2239,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, u8 update_lq = 0; struct iwl_scale_tbl_info *tbl, *tbl1; u16 rate_scale_index_msk = 0; - u32 rate; u8 is_green = 0; u8 active_tbl = 0; u8 done_search = 0; @@ -2328,8 +2325,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); /* get "active" rate info */ index = iwl_hwrate_to_plcp_idx(tbl->current_rate); - rate = rs_update_rate_tbl(priv, ctx, lq_sta, - tbl, index, is_green); + rs_update_rate_tbl(priv, ctx, lq_sta, tbl, + index, is_green); } return; } @@ -2570,8 +2567,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, lq_update: /* Replace uCode's rate table for the destination station. */ if (update_lq) - rate = rs_update_rate_tbl(priv, ctx, lq_sta, - tbl, index, is_green); + rs_update_rate_tbl(priv, ctx, lq_sta, tbl, index, is_green); if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) { /* Should we stay with this modulation mode, @@ -3270,14 +3266,10 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = { static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - char buff[120]; - int desc = 0; - struct iwl_lq_sta *lq_sta = file->private_data; - struct iwl_priv *priv; struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl]; - - priv = lq_sta->drv; + char buff[120]; + int desc = 0; if (is_Ht(tbl->lq_type)) desc += sprintf(buff+desc, diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index c839796..47a56bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -216,15 +216,14 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv) static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) { - u32 otpgp; + iwl_read32(priv, CSR_OTP_GP_REG); - otpgp = iwl_read32(priv, CSR_OTP_GP_REG); if (mode == IWL_OTP_ACCESS_ABSOLUTE) iwl_clear_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_OTP_ACCESS_MODE); + CSR_OTP_GP_REG_OTP_ACCESS_MODE); else iwl_set_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_OTP_ACCESS_MODE); + CSR_OTP_GP_REG_OTP_ACCESS_MODE); } static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) -- cgit v0.10.2 From 51b7ef058c44c15af20ab4f7aed1dbb959cbd06d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 May 2011 08:17:20 -0700 Subject: iwlagn: change default beacon interval When the PAN context is active, but unused, it may still block scans that take more dwell time than its beacon interval (which is odd). Work around this problem by using a default beacon interval of 200 so scans will fit between. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ab29ab5..22a6e3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -81,7 +81,7 @@ struct iwl_tx_queue; #define MAX_RTS_THRESHOLD 2347U #define MAX_MSDU_SIZE 2304U #define MAX_MPDU_SIZE 2346U -#define DEFAULT_BEACON_INTERVAL 100U +#define DEFAULT_BEACON_INTERVAL 200U #define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_LONG_RETRY_LIMIT 4U -- cgit v0.10.2 From 6dc0c7fc7cc0f5ec3d92a3076dfe45028540e526 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 11 May 2011 08:33:55 -0700 Subject: iwlagn: remove unused old_assoc parameter old_assoc not used, remove it Signed-off-by: Wey-Yi Guy diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 7d40e2d..a95ad84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -289,7 +289,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) /* cast away the const for active_rxon in this function */ struct iwl_rxon_cmd *active = (void *)&ctx->active; bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); - bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK); int ret; lockdep_assert_held(&priv->mutex); -- cgit v0.10.2 From 9368a9a2378ab721f82f59430a135b4ce4ff5109 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 13 May 2011 21:47:23 +0200 Subject: p54usb: add zoom 4410 usbid Cc: Reported-by: Mark Davis Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index e183587..a8f3bc7 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -82,6 +82,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ + {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ -- cgit v0.10.2 From 011159a0a746e03ae42d559ce5c2a70138da3129 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 14 May 2011 00:12:48 +0300 Subject: airo: correct proc entry creation interfaces * use proc_mkdir_mode() instead of create_proc_entry(S_IFDIR|...), export proc_mkdir_mode() for that, oh well. * don't supply S_IFREG to proc_create_data(), it's unnecessary Signed-off-by: Alexey Dobriyan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 57a79b0..eb050ef 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -4500,17 +4500,15 @@ static int setup_proc_entry( struct net_device *dev, struct proc_dir_entry *entry; /* First setup the device directory */ strcpy(apriv->proc_name,dev->name); - apriv->proc_entry = create_proc_entry(apriv->proc_name, - S_IFDIR|airo_perm, - airo_entry); + apriv->proc_entry = proc_mkdir_mode(apriv->proc_name, airo_perm, + airo_entry); if (!apriv->proc_entry) goto fail; apriv->proc_entry->uid = proc_uid; apriv->proc_entry->gid = proc_gid; /* Setup the StatsDelta */ - entry = proc_create_data("StatsDelta", - S_IFREG | (S_IRUGO&proc_perm), + entry = proc_create_data("StatsDelta", S_IRUGO & proc_perm, apriv->proc_entry, &proc_statsdelta_ops, dev); if (!entry) goto fail_stats_delta; @@ -4518,8 +4516,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the Stats */ - entry = proc_create_data("Stats", - S_IFREG | (S_IRUGO&proc_perm), + entry = proc_create_data("Stats", S_IRUGO & proc_perm, apriv->proc_entry, &proc_stats_ops, dev); if (!entry) goto fail_stats; @@ -4527,8 +4524,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the Status */ - entry = proc_create_data("Status", - S_IFREG | (S_IRUGO&proc_perm), + entry = proc_create_data("Status", S_IRUGO & proc_perm, apriv->proc_entry, &proc_status_ops, dev); if (!entry) goto fail_status; @@ -4536,8 +4532,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the Config */ - entry = proc_create_data("Config", - S_IFREG | proc_perm, + entry = proc_create_data("Config", proc_perm, apriv->proc_entry, &proc_config_ops, dev); if (!entry) goto fail_config; @@ -4545,8 +4540,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the SSID */ - entry = proc_create_data("SSID", - S_IFREG | proc_perm, + entry = proc_create_data("SSID", proc_perm, apriv->proc_entry, &proc_SSID_ops, dev); if (!entry) goto fail_ssid; @@ -4554,8 +4548,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the APList */ - entry = proc_create_data("APList", - S_IFREG | proc_perm, + entry = proc_create_data("APList", proc_perm, apriv->proc_entry, &proc_APList_ops, dev); if (!entry) goto fail_aplist; @@ -4563,8 +4556,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the BSSList */ - entry = proc_create_data("BSSList", - S_IFREG | proc_perm, + entry = proc_create_data("BSSList", proc_perm, apriv->proc_entry, &proc_BSSList_ops, dev); if (!entry) goto fail_bsslist; @@ -4572,8 +4564,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the WepKey */ - entry = proc_create_data("WepKey", - S_IFREG | proc_perm, + entry = proc_create_data("WepKey", proc_perm, apriv->proc_entry, &proc_wepkey_ops, dev); if (!entry) goto fail_wepkey; @@ -5705,9 +5696,7 @@ static int __init airo_init_module( void ) { int i; - airo_entry = create_proc_entry("driver/aironet", - S_IFDIR | airo_perm, - NULL); + airo_entry = proc_mkdir_mode("driver/aironet", airo_perm, NULL); if (airo_entry) { airo_entry->uid = proc_uid; diff --git a/fs/proc/generic.c b/fs/proc/generic.c index f1281339..f1637f1 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -674,6 +674,7 @@ struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, } return ent; } +EXPORT_SYMBOL(proc_mkdir_mode); struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name, struct proc_dir_entry *parent) -- cgit v0.10.2 From d0df9eecf9f61f70fd847656f5eb113e06e46a03 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Fri, 13 May 2011 14:16:07 -0700 Subject: mac80211: Deactivate mesh path timers when freeing nodes Mesh paths are deleted via mesh_path_del() which properly deactivates the timer associated to a mesh path. But if paths were deleted by mesh_table_free(..., true) timers would not be deactivated. This fixes this case. Reported-by: Johannes Berg Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0aa96cd..f775202 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -719,8 +719,10 @@ static void mesh_path_node_free(struct hlist_node *p, bool free_leafs) struct mpath_node *node = hlist_entry(p, struct mpath_node, list); mpath = node->mpath; hlist_del_rcu(p); - if (free_leafs) + if (free_leafs) { + del_timer_sync(&mpath->timer); kfree(mpath); + } kfree(node); } -- cgit v0.10.2 From dedb1eb977d75f301b17190cc4b6e7d17dbf17db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 14 May 2011 00:04:38 +0200 Subject: b43: rename b43_wldev's field with ssb_device to sdev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We free name "dev" for something generic (like dev abstraction layer). Additionaly code is cleaner now, especially magic dev->dev-dev chains. Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index bd4cb75..fd69d6a 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -705,7 +705,7 @@ enum { /* Data structure for one wireless device (802.11 core) */ struct b43_wldev { - struct ssb_device *dev; + struct ssb_device *sdev; struct b43_wl *wl; /* The device initialization status. @@ -879,22 +879,22 @@ static inline enum ieee80211_band b43_current_band(struct b43_wl *wl) static inline u16 b43_read16(struct b43_wldev *dev, u16 offset) { - return ssb_read16(dev->dev, offset); + return ssb_read16(dev->sdev, offset); } static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value) { - ssb_write16(dev->dev, offset, value); + ssb_write16(dev->sdev, offset, value); } static inline u32 b43_read32(struct b43_wldev *dev, u16 offset) { - return ssb_read32(dev->dev, offset); + return ssb_read32(dev->sdev, offset); } static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) { - ssb_write32(dev->dev, offset, value); + ssb_write32(dev->sdev, offset, value); } static inline bool b43_using_pio_transfers(struct b43_wldev *dev) diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index ff0f5ba..10cfba3 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -80,7 +80,7 @@ static void op32_fill_descriptor(struct b43_dmaring *ring, addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK); addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addr |= ssb_dma_translation(ring->dev->dev); + addr |= ssb_dma_translation(ring->dev->sdev); ctl = bufsize & B43_DMA32_DCTL_BYTECNT; if (slot == ring->nr_slots - 1) ctl |= B43_DMA32_DCTL_DTABLEEND; @@ -174,7 +174,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring, addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addrhi |= (ssb_dma_translation(ring->dev->dev) << 1); + addrhi |= (ssb_dma_translation(ring->dev->sdev) << 1); if (slot == ring->nr_slots - 1) ctl0 |= B43_DMA64_DCTL0_DTABLEEND; if (start) @@ -333,10 +333,10 @@ static inline dma_addr_t dmaaddr; if (tx) { - dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + dmaaddr = dma_map_single(ring->dev->sdev->dma_dev, buf, len, DMA_TO_DEVICE); } else { - dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + dmaaddr = dma_map_single(ring->dev->sdev->dma_dev, buf, len, DMA_FROM_DEVICE); } @@ -348,10 +348,10 @@ static inline dma_addr_t addr, size_t len, int tx) { if (tx) { - dma_unmap_single(ring->dev->dev->dma_dev, + dma_unmap_single(ring->dev->sdev->dma_dev, addr, len, DMA_TO_DEVICE); } else { - dma_unmap_single(ring->dev->dev->dma_dev, + dma_unmap_single(ring->dev->sdev->dma_dev, addr, len, DMA_FROM_DEVICE); } } @@ -361,7 +361,7 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - dma_sync_single_for_cpu(ring->dev->dev->dma_dev, + dma_sync_single_for_cpu(ring->dev->sdev->dma_dev, addr, len, DMA_FROM_DEVICE); } @@ -370,7 +370,7 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - dma_sync_single_for_device(ring->dev->dev->dma_dev, + dma_sync_single_for_device(ring->dev->sdev->dma_dev, addr, len, DMA_FROM_DEVICE); } @@ -401,7 +401,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring) */ if (ring->type == B43_DMA_64BIT) flags |= GFP_DMA; - ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, + ring->descbase = dma_alloc_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE, &(ring->dmabase), flags); if (!ring->descbase) { @@ -415,7 +415,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring) static void free_ringmemory(struct b43_dmaring *ring) { - dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, + dma_free_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE, ring->descbase, ring->dmabase); } @@ -523,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, dma_addr_t addr, size_t buffersize, bool dma_to_device) { - if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr))) + if (unlikely(dma_mapping_error(ring->dev->sdev->dma_dev, addr))) return 1; switch (ring->type) { @@ -658,7 +658,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) int err = 0; u32 value; u32 addrext; - u32 trans = ssb_dma_translation(ring->dev->dev); + u32 trans = ssb_dma_translation(ring->dev->sdev); if (ring->tx) { if (ring->type == B43_DMA_64BIT) { @@ -869,7 +869,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, goto err_kfree_meta; /* test for ability to dma to txhdr_cache */ - dma_test = dma_map_single(dev->dev->dma_dev, + dma_test = dma_map_single(dev->sdev->dma_dev, ring->txhdr_cache, b43_txhdr_size(dev), DMA_TO_DEVICE); @@ -884,7 +884,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, if (!ring->txhdr_cache) goto err_kfree_meta; - dma_test = dma_map_single(dev->dev->dma_dev, + dma_test = dma_map_single(dev->sdev->dma_dev, ring->txhdr_cache, b43_txhdr_size(dev), DMA_TO_DEVICE); @@ -898,7 +898,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, } } - dma_unmap_single(dev->dev->dma_dev, + dma_unmap_single(dev->sdev->dma_dev, dma_test, b43_txhdr_size(dev), DMA_TO_DEVICE); } @@ -1013,9 +1013,9 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) /* Try to set the DMA mask. If it fails, try falling back to a * lower mask, as we can always also support a lower one. */ while (1) { - err = dma_set_mask(dev->dev->dma_dev, mask); + err = dma_set_mask(dev->sdev->dma_dev, mask); if (!err) { - err = dma_set_coherent_mask(dev->dev->dma_dev, mask); + err = dma_set_coherent_mask(dev->sdev->dma_dev, mask); if (!err) break; } @@ -1084,7 +1084,7 @@ int b43_dma_init(struct b43_wldev *dev) goto err_destroy_mcast; /* No support for the TX status DMA ring. */ - B43_WARN_ON(dev->dev->id.revision < 5); + B43_WARN_ON(dev->sdev->id.revision < 5); b43dbg(dev->wl, "%u-bit DMA initialized\n", (unsigned int)type); diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index c587115..0cafafe 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c @@ -138,7 +138,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, led->led_dev.default_trigger = default_trigger; led->led_dev.brightness_set = b43_led_brightness_set; - err = led_classdev_register(dev->dev->dev, &led->led_dev); + err = led_classdev_register(dev->sdev->dev, &led->led_dev); if (err) { b43warn(dev->wl, "LEDs: Failed to register %s\n", name); led->wl = NULL; @@ -215,7 +215,7 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev, enum b43_led_behaviour *behaviour, bool *activelow) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u8 sprom[4]; sprom[0] = bus->sprom.gpio0; diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index 94e4f13..2ef7d4b 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c @@ -98,7 +98,7 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev, rfover |= pga; rfover |= lna; rfover |= trsw_rx; - if ((dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) + if ((dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && phy->rev > 6) rfover |= B43_PHY_RFOVERVAL_EXTLNA; @@ -387,7 +387,7 @@ struct lo_g_saved_values { static void lo_measure_setup(struct b43_wldev *dev, struct lo_g_saved_values *sav) { - struct ssb_sprom *sprom = &dev->dev->bus->sprom; + struct ssb_sprom *sprom = &dev->sdev->bus->sprom; struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; struct b43_txpower_lo_control *lo = gphy->lo_control; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a96e05a..ea58e27 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -547,7 +547,7 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf) { u32 low, high; - B43_WARN_ON(dev->dev->id.revision < 3); + B43_WARN_ON(dev->sdev->id.revision < 3); /* The hardware guarantees us an atomic read, if we * read the low register first. */ @@ -585,7 +585,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf) { u32 low, high; - B43_WARN_ON(dev->dev->id.revision < 3); + B43_WARN_ON(dev->sdev->id.revision < 3); low = tsf; high = (tsf >> 32); @@ -713,7 +713,7 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on) b43_ram_write(dev, i * 4, buffer[i]); b43_write16(dev, 0x0568, 0x0000); - if (dev->dev->id.revision < 11) + if (dev->sdev->id.revision < 11) b43_write16(dev, 0x07C0, 0x0000); else b43_write16(dev, 0x07C0, 0x0100); @@ -1131,7 +1131,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) b43_write32(dev, B43_MMIO_MACCTL, macctl); /* Commit write */ b43_read32(dev, B43_MMIO_MACCTL); - if (awake && dev->dev->id.revision >= 5) { + if (awake && dev->sdev->id.revision >= 5) { /* Wait for the microcode to wake up. */ for (i = 0; i < 100; i++) { ucstat = b43_shm_read16(dev, B43_SHM_SHARED, @@ -1152,19 +1152,19 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) flags |= B43_TMSLOW_PHYRESET; if (dev->phy.type == B43_PHYTYPE_N) flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */ - ssb_device_enable(dev->dev, flags); + ssb_device_enable(dev->sdev, flags); msleep(2); /* Wait for the PLL to turn on. */ /* Now take the PHY out of Reset again */ - tmslow = ssb_read32(dev->dev, SSB_TMSLOW); + tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); tmslow |= SSB_TMSLOW_FGC; tmslow &= ~B43_TMSLOW_PHYRESET; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); - ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ + ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); + ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */ msleep(1); tmslow &= ~SSB_TMSLOW_FGC; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); - ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ + ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); + ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */ msleep(1); /* Turn Analog ON, but only if we already know the PHY-type. @@ -1214,7 +1214,7 @@ static void drain_txstatus_queue(struct b43_wldev *dev) { u32 dummy; - if (dev->dev->id.revision < 5) + if (dev->sdev->id.revision < 5) return; /* Read all entries from the microcode TXstatus FIFO * and throw them away. @@ -1420,9 +1420,9 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev, /* Get the mask of available antennas. */ if (dev->phy.gmode) - antenna_mask = dev->dev->bus->sprom.ant_available_bg; + antenna_mask = dev->sdev->bus->sprom.ant_available_bg; else - antenna_mask = dev->dev->bus->sprom.ant_available_a; + antenna_mask = dev->sdev->bus->sprom.ant_available_a; if (!(antenna_mask & (1 << (antenna_nr - 1)))) { /* This antenna is not available. Fall back to default. */ @@ -1637,7 +1637,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) mutex_lock(&wl->mutex); dev = wl->current_dev; if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { /* wl->mutex is enough. */ b43_do_beacon_update_trigger_work(dev); mmiowb(); @@ -1682,7 +1682,7 @@ static void b43_update_templates(struct b43_wl *wl) static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) { b43_time_lock(dev); - if (dev->dev->id.revision >= 3) { + if (dev->sdev->id.revision >= 3) { b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16)); b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10)); } else { @@ -2056,7 +2056,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, B43_WARN_ON(1); return -ENOSYS; } - err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); + err = request_firmware(&blob, ctx->fwname, ctx->dev->sdev->dev); if (err == -ENOENT) { snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), @@ -2106,13 +2106,13 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) { struct b43_wldev *dev = ctx->dev; struct b43_firmware *fw = &ctx->dev->fw; - const u8 rev = ctx->dev->dev->id.revision; + const u8 rev = ctx->dev->sdev->id.revision; const char *filename; u32 tmshigh; int err; /* Get microcode */ - tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); + tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); if ((rev >= 5) && (rev <= 10)) filename = "ucode5"; else if ((rev >= 11) && (rev <= 12)) @@ -2440,7 +2440,7 @@ static int b43_upload_microcode(struct b43_wldev *dev) snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u", dev->fw.rev, dev->fw.patch); - wiphy->hw_version = dev->dev->id.coreid; + wiphy->hw_version = dev->sdev->id.coreid; if (b43_is_old_txhdr_format(dev)) { /* We're over the deadline, but we keep support for old fw @@ -2558,7 +2558,7 @@ out: */ static int b43_gpio_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct ssb_device *gpiodev, *pcidev = NULL; u32 mask, set; @@ -2570,7 +2570,7 @@ static int b43_gpio_init(struct b43_wldev *dev) mask = 0x0000001F; set = 0x0000000F; - if (dev->dev->bus->chip_id == 0x4301) { + if (dev->sdev->bus->chip_id == 0x4301) { mask |= 0x0060; set |= 0x0060; } @@ -2581,14 +2581,14 @@ static int b43_gpio_init(struct b43_wldev *dev) mask |= 0x0180; set |= 0x0180; } - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) { + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) { b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) | 0x0200); mask |= 0x0200; set |= 0x0200; } - if (dev->dev->id.revision >= 2) + if (dev->sdev->id.revision >= 2) mask |= 0x0010; /* FIXME: This is redundant. */ #ifdef CONFIG_SSB_DRIVER_PCICORE @@ -2607,7 +2607,7 @@ static int b43_gpio_init(struct b43_wldev *dev) /* Turn off all GPIO stuff. Call this on module unload, for example. */ static void b43_gpio_cleanup(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct ssb_device *gpiodev, *pcidev = NULL; #ifdef CONFIG_SSB_DRIVER_PCICORE @@ -2688,12 +2688,12 @@ out: /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on) { - u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); + u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); if (on) tmslow |= B43_TMSLOW_MACPHYCLKEN; else tmslow &= ~B43_TMSLOW_MACPHYCLKEN; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); + ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); } static void b43_adjust_opmode(struct b43_wldev *dev) @@ -2732,15 +2732,15 @@ static void b43_adjust_opmode(struct b43_wldev *dev) /* Workaround: On old hardware the HW-MAC-address-filter * doesn't work properly, so always run promisc in filter * it in software. */ - if (dev->dev->id.revision <= 4) + if (dev->sdev->id.revision <= 4) ctl |= B43_MACCTL_PROMISC; b43_write32(dev, B43_MMIO_MACCTL, ctl); cfp_pretbtt = 2; if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) { - if (dev->dev->bus->chip_id == 0x4306 && - dev->dev->bus->chip_rev == 3) + if (dev->sdev->bus->chip_id == 0x4306 && + dev->sdev->bus->chip_rev == 3) cfp_pretbtt = 100; else cfp_pretbtt = 50; @@ -2898,7 +2898,7 @@ static int b43_chip_init(struct b43_wldev *dev) b43_write16(dev, 0x005E, value16); } b43_write32(dev, 0x0100, 0x01000000); - if (dev->dev->id.revision < 5) + if (dev->sdev->id.revision < 5) b43_write32(dev, 0x010C, 0x01000000); b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) @@ -2913,7 +2913,7 @@ static int b43_chip_init(struct b43_wldev *dev) /* Initially set the wireless operation mode. */ b43_adjust_opmode(dev); - if (dev->dev->id.revision < 3) { + if (dev->sdev->id.revision < 3) { b43_write16(dev, 0x060E, 0x0000); b43_write16(dev, 0x0610, 0x8000); b43_write16(dev, 0x0604, 0x0000); @@ -2933,7 +2933,7 @@ static int b43_chip_init(struct b43_wldev *dev) b43_mac_phy_clock_set(dev, true); b43_write16(dev, B43_MMIO_POWERUP_DELAY, - dev->dev->bus->chipco.fast_pwrup_delay); + dev->sdev->bus->chipco.fast_pwrup_delay); err = 0; b43dbg(dev->wl, "Chip initialized\n"); @@ -3096,7 +3096,7 @@ static int b43_validate_chipaccess(struct b43_wldev *dev) b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0); b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4); - if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) { + if ((dev->sdev->id.revision >= 3) && (dev->sdev->id.revision <= 10)) { /* The 32bit register shadows the two 16bit registers * with update sideeffects. Validate this. */ b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA); @@ -3449,7 +3449,7 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) static void b43_put_phy_into_reset(struct b43_wldev *dev) { - struct ssb_device *sdev = dev->dev; + struct ssb_device *sdev = dev->sdev; u32 tmslow; tmslow = ssb_read32(sdev, SSB_TMSLOW); @@ -3945,7 +3945,7 @@ redo: /* Disable interrupts on the device. */ b43_set_status(dev, B43_STAT_INITIALIZED); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { /* wl->mutex is locked. That is enough. */ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ @@ -3958,11 +3958,11 @@ redo: /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */ orig_dev = dev; mutex_unlock(&wl->mutex); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { b43_sdio_free_irq(dev); } else { - synchronize_irq(dev->dev->irq); - free_irq(dev->dev->irq, dev); + synchronize_irq(dev->sdev->irq); + free_irq(dev->sdev->irq, dev); } mutex_lock(&wl->mutex); dev = wl->current_dev; @@ -3995,18 +3995,19 @@ static int b43_wireless_core_start(struct b43_wldev *dev) B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); drain_txstatus_queue(dev); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler); if (err) { b43err(dev->wl, "Cannot request SDIO IRQ\n"); goto out; } } else { - err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, + err = request_threaded_irq(dev->sdev->irq, b43_interrupt_handler, b43_interrupt_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { - b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); + b43err(dev->wl, "Cannot request IRQ-%d\n", + dev->sdev->irq); goto out; } } @@ -4086,10 +4087,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) analog_type, phy_type, phy_rev); /* Get RADIO versioning */ - if (dev->dev->bus->chip_id == 0x4317) { - if (dev->dev->bus->chip_rev == 0) + if (dev->sdev->bus->chip_id == 0x4317) { + if (dev->sdev->bus->chip_rev == 0) tmp = 0x3205017F; - else if (dev->dev->bus->chip_rev == 1) + else if (dev->sdev->bus->chip_rev == 1) tmp = 0x4205017F; else tmp = 0x5205017F; @@ -4194,7 +4195,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev) static void b43_bluetooth_coext_enable(struct b43_wldev *dev) { - struct ssb_sprom *sprom = &dev->dev->bus->sprom; + struct ssb_sprom *sprom = &dev->sdev->bus->sprom; u64 hf; if (!modparam_btcoex) @@ -4221,16 +4222,16 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev) static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u32 tmp; if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) || (bus->chip_id == 0x4312)) { - tmp = ssb_read32(dev->dev, SSB_IMCFGLO); + tmp = ssb_read32(dev->sdev, SSB_IMCFGLO); tmp &= ~SSB_IMCFGLO_REQTO; tmp &= ~SSB_IMCFGLO_SERTO; tmp |= 0x3; - ssb_write32(dev->dev, SSB_IMCFGLO, tmp); + ssb_write32(dev->sdev, SSB_IMCFGLO, tmp); ssb_commit_settings(bus); } } @@ -4300,14 +4301,14 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) dev->wl->current_beacon = NULL; } - ssb_device_disable(dev->dev, 0); - ssb_bus_may_powerdown(dev->dev->bus); + ssb_device_disable(dev->sdev, 0); + ssb_bus_may_powerdown(dev->sdev->bus); } /* Initialize a wireless core */ static int b43_wireless_core_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct ssb_sprom *sprom = &bus->sprom; struct b43_phy *phy = &dev->phy; int err; @@ -4319,7 +4320,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) err = ssb_bus_powerup(bus, 0); if (err) goto out; - if (!ssb_device_is_enabled(dev->dev)) { + if (!ssb_device_is_enabled(dev->sdev)) { tmp = phy->gmode ? B43_TMSLOW_GMODE : 0; b43_wireless_core_reset(dev, tmp); } @@ -4329,7 +4330,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) phy->ops->prepare_structs(dev); /* Enable IRQ routing to this device. */ - ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); + ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev); b43_imcfglo_timeouts_workaround(dev); b43_bluetooth_coext_disable(dev); @@ -4342,7 +4343,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) if (err) goto err_busdown; b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_WLCOREREV, dev->dev->id.revision); + B43_SHM_SH_WLCOREREV, dev->sdev->id.revision); hf = b43_hf_read(dev); if (phy->type == B43_PHYTYPE_G) { hf |= B43_HF_SYMW; @@ -4389,8 +4390,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev) /* Maximum Contention Window */ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); - if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || - (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || + if ((dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA) || + (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) || dev->use_pio) { dev->__using_pio_transfers = 1; err = b43_pio_init(dev); @@ -4727,7 +4728,7 @@ static void b43_wireless_core_detach(struct b43_wldev *dev) static int b43_wireless_core_attach(struct b43_wldev *dev) { struct b43_wl *wl = dev->wl; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL; int err; bool have_2ghz_phy = 0, have_5ghz_phy = 0; @@ -4746,10 +4747,10 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) goto out; } /* Get the PHY type. */ - if (dev->dev->id.revision >= 5) { + if (dev->sdev->id.revision >= 5) { u32 tmshigh; - tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); + tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY); have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY); } else @@ -4822,7 +4823,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) INIT_WORK(&dev->restart_work, b43_chip_reset); dev->phy.ops->switch_analog(dev, 0); - ssb_device_disable(dev->dev, 0); + ssb_device_disable(dev->sdev, 0); ssb_bus_may_powerdown(bus); out: @@ -4863,7 +4864,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) goto out; wldev->use_pio = b43_modparam_pio; - wldev->dev = dev; + wldev->sdev = dev; wldev->wl = wl; b43_set_status(wldev, B43_STAT_UNINIT); wldev->bad_frames_preempt = modparam_bad_frames_preempt; diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c index b6428ec..b01c8ced 100644 --- a/drivers/net/wireless/b43/phy_a.c +++ b/drivers/net/wireless/b43/phy_a.c @@ -265,7 +265,7 @@ static void hardware_pctl_init_aphy(struct b43_wldev *dev) void b43_phy_inita(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; /* This lowlevel A-PHY init is also called from G-PHY init. @@ -311,7 +311,7 @@ void b43_phy_inita(struct b43_wldev *dev) } if ((phy->type == B43_PHYTYPE_G) && - (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) { + (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) { b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF); } } @@ -323,17 +323,17 @@ static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev) struct b43_phy_a *aphy = phy->a; s16 pab0, pab1, pab2; - pab0 = (s16) (dev->dev->bus->sprom.pa1b0); - pab1 = (s16) (dev->dev->bus->sprom.pa1b1); - pab2 = (s16) (dev->dev->bus->sprom.pa1b2); + pab0 = (s16) (dev->sdev->bus->sprom.pa1b0); + pab1 = (s16) (dev->sdev->bus->sprom.pa1b1); + pab2 = (s16) (dev->sdev->bus->sprom.pa1b2); if (pab0 != 0 && pab1 != 0 && pab2 != 0 && pab0 != -1 && pab1 != -1 && pab2 != -1) { /* The pabX values are set in SPROM. Use them. */ - if ((s8) dev->dev->bus->sprom.itssi_a != 0 && - (s8) dev->dev->bus->sprom.itssi_a != -1) + if ((s8) dev->sdev->bus->sprom.itssi_a != 0 && + (s8) dev->sdev->bus->sprom.itssi_a != -1) aphy->tgt_idle_tssi = - (s8) (dev->dev->bus->sprom.itssi_a); + (s8) (dev->sdev->bus->sprom.itssi_a); else aphy->tgt_idle_tssi = 62; aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index b5c5ce9..e46b2f4 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -168,7 +168,7 @@ void b43_phy_lock(struct b43_wldev *dev) B43_WARN_ON(dev->phy.phy_locked); dev->phy.phy_locked = 1; #endif - B43_WARN_ON(dev->dev->id.revision < 3); + B43_WARN_ON(dev->sdev->id.revision < 3); if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); @@ -180,7 +180,7 @@ void b43_phy_unlock(struct b43_wldev *dev) B43_WARN_ON(!dev->phy.phy_locked); dev->phy.phy_locked = 0; #endif - B43_WARN_ON(dev->dev->id.revision < 3); + B43_WARN_ON(dev->sdev->id.revision < 3); if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) b43_power_saving_ctl_bits(dev, 0); @@ -368,8 +368,8 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags) /* The next check will be needed in two seconds, or later. */ phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2)); - if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && - (dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306)) + if ((dev->sdev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && + (dev->sdev->bus->boardinfo.type == SSB_BOARD_BU4306)) return; /* No software txpower adjustment needed */ result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI)); diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index be48281..1758a28 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c @@ -718,7 +718,7 @@ static void b43_calc_nrssi_threshold(struct b43_wldev *dev) B43_WARN_ON(phy->type != B43_PHYTYPE_G); if (!phy->gmode || - !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { + !(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { tmp16 = b43_nrssi_hw_read(dev, 0x20); if (tmp16 >= 0x20) tmp16 -= 0x40; @@ -1114,7 +1114,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev, { struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); + struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); if (!phy->gmode) return 0; @@ -1491,7 +1491,7 @@ static u16 b43_radio_init2050(struct b43_wldev *dev) static void b43_phy_initb5(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; u16 offset, value; @@ -1620,7 +1620,7 @@ static void b43_phy_initb6(struct b43_wldev *dev) b43_radio_write16(dev, 0x5A, 0x88); b43_radio_write16(dev, 0x5B, 0x6B); b43_radio_write16(dev, 0x5C, 0x0F); - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) { + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) { b43_radio_write16(dev, 0x5D, 0xFA); b43_radio_write16(dev, 0x5E, 0xD8); } else { @@ -1787,7 +1787,7 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev) b43_phy_set(dev, B43_PHY_RFOVER, 0x0100); b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF); - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) { + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) { if (phy->rev >= 7) { b43_phy_set(dev, B43_PHY_RFOVER, 0x0800); b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000); @@ -1922,7 +1922,7 @@ static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev) /* Initialize B/G PHY power control */ static void b43_phy_init_pctl(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; struct b43_rfatt old_rfatt; @@ -2053,7 +2053,7 @@ static void b43_phy_initg(struct b43_wldev *dev) if (phy->rev >= 6) { b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12)); } - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075); else b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); @@ -2066,7 +2066,7 @@ static void b43_phy_initg(struct b43_wldev *dev) b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); } - if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { + if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { /* The specs state to update the NRSSI LT with * the value 0x7FFFFFFF here. I think that is some weird * compiler optimization in the original driver. @@ -2088,8 +2088,8 @@ static void b43_phy_initg(struct b43_wldev *dev) /* FIXME: The spec says in the following if, the 0 should be replaced 'if OFDM may not be used in the current locale' but OFDM is legal everywhere */ - if ((dev->dev->bus->chip_id == 0x4306 - && dev->dev->bus->chip_package == 2) || 0) { + if ((dev->sdev->bus->chip_id == 0x4306 + && dev->sdev->bus->chip_package == 2) || 0) { b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF); b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF); } @@ -2105,7 +2105,7 @@ void b43_gphy_channel_switch(struct b43_wldev *dev, b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel)); if (channel == 14) { - if (dev->dev->bus->sprom.country_code == + if (dev->sdev->bus->sprom.country_code == SSB_SPROM1CCODE_JAPAN) b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ACPR); @@ -2136,7 +2136,7 @@ static void default_baseband_attenuation(struct b43_wldev *dev, static void default_radio_attenuation(struct b43_wldev *dev, struct b43_rfatt *rf) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; rf->with_padmix = 0; @@ -2384,11 +2384,11 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev) struct b43_phy_g *gphy = phy->g; s16 pab0, pab1, pab2; - pab0 = (s16) (dev->dev->bus->sprom.pa0b0); - pab1 = (s16) (dev->dev->bus->sprom.pa0b1); - pab2 = (s16) (dev->dev->bus->sprom.pa0b2); + pab0 = (s16) (dev->sdev->bus->sprom.pa0b0); + pab1 = (s16) (dev->sdev->bus->sprom.pa0b1); + pab2 = (s16) (dev->sdev->bus->sprom.pa0b2); - B43_WARN_ON((dev->dev->bus->chip_id == 0x4301) && + B43_WARN_ON((dev->sdev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)); /* Not supported anymore */ gphy->dyn_tssi_tbl = 0; @@ -2396,10 +2396,10 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev) if (pab0 != 0 && pab1 != 0 && pab2 != 0 && pab0 != -1 && pab1 != -1 && pab2 != -1) { /* The pabX values are set in SPROM. Use them. */ - if ((s8) dev->dev->bus->sprom.itssi_bg != 0 && - (s8) dev->dev->bus->sprom.itssi_bg != -1) { + if ((s8) dev->sdev->bus->sprom.itssi_bg != 0 && + (s8) dev->sdev->bus->sprom.itssi_bg != -1) { gphy->tgt_idle_tssi = - (s8) (dev->dev->bus->sprom.itssi_bg); + (s8) (dev->sdev->bus->sprom.itssi_bg); } else gphy->tgt_idle_tssi = 62; gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, @@ -2840,7 +2840,7 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev) B43_TXCTL_TXMIX; rfatt += 2; bbatt += 2; - } else if (dev->dev->bus->sprom. + } else if (dev->sdev->bus->sprom. boardflags_lo & B43_BFL_PACTRL) { bbatt += 4 * (rfatt - 2); @@ -2914,14 +2914,14 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi); B43_WARN_ON(phy->type != B43_PHYTYPE_G); - max_pwr = dev->dev->bus->sprom.maxpwr_bg; - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) + max_pwr = dev->sdev->bus->sprom.maxpwr_bg; + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) max_pwr -= 3; /* minus 0.75 */ if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) { b43warn(dev->wl, "Invalid max-TX-power value in SPROM.\n"); max_pwr = INT_TO_Q52(20); /* fake it */ - dev->dev->bus->sprom.maxpwr_bg = max_pwr; + dev->sdev->bus->sprom.maxpwr_bg = max_pwr; } /* Get desired power (in Q5.2) */ @@ -3014,7 +3014,7 @@ static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; - if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) + if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) return; b43_mac_suspend(dev); diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index fd50eb1..012c8da 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -86,7 +86,7 @@ static void b43_lpphy_op_free(struct b43_wldev *dev) static void lpphy_read_band_sprom(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u16 cckpo, maxpwr; u32 ofdmpo; int i; @@ -214,7 +214,7 @@ static void lpphy_table_init(struct b43_wldev *dev) static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy_lp *lpphy = dev->phy.lp; u16 tmp, tmp2; @@ -412,7 +412,7 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev) static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy_lp *lpphy = dev->phy.lp; b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50); @@ -519,7 +519,7 @@ struct b2062_freqdata { static void lpphy_2062_init(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u32 crystalfreq, tmp, ref; unsigned int i; const struct b2062_freqdata *fd = NULL; @@ -697,7 +697,7 @@ static void lpphy_radio_init(struct b43_wldev *dev) lpphy_sync_stx(dev); b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80); b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0); - if (dev->dev->bus->chip_id == 0x4325) { + if (dev->sdev->bus->chip_id == 0x4325) { // TODO SSB PMU recalibration } } @@ -1289,7 +1289,7 @@ finish: static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF; int i; @@ -1840,7 +1840,7 @@ static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains, static void lpphy_papd_cal_txpwr(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct lpphy_tx_gains gains, oldgains; int old_txpctl, old_afe_ovr, old_rf, old_bbmult; @@ -1870,7 +1870,7 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx, bool rx, bool pa, struct lpphy_tx_gains *gains) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; const struct lpphy_rx_iq_comp *iqcomp = NULL; struct lpphy_tx_gains nogains, oldgains; u16 tmp; @@ -2408,7 +2408,7 @@ static const struct b206x_channel b2063_chantbl[] = { static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF); udelay(20); @@ -2432,7 +2432,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev, unsigned int channel) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; const struct b206x_channel *chandata = NULL; u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; @@ -2522,7 +2522,7 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev) static int lpphy_b2063_tune(struct b43_wldev *dev, unsigned int channel) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; static const struct b206x_channel *chandata = NULL; u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index b075a3f..9ed6515 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -299,7 +299,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) static void b43_nphy_tx_power_fix(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); + struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); u8 txpi[2], bbmult, i; u16 tmp, radio_gain, dac_gain; @@ -423,8 +423,8 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev) static void b43_radio_init2055_post(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); - struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); + struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); + struct ssb_boardinfo *binfo = &(dev->sdev->bus->boardinfo); int i; u16 val; bool workaround = false; @@ -609,12 +609,12 @@ static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) if (dev->phy.type != B43_PHYTYPE_N) return; - tmslow = ssb_read32(dev->dev, SSB_TMSLOW); + tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); if (force) tmslow |= SSB_TMSLOW_FGC; else tmslow &= ~SSB_TMSLOW_FGC; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); + ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ @@ -959,7 +959,7 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0); b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0); - ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00, + ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00, 0xFC00); b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) & @@ -983,7 +983,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) { u16 tmp; - if (dev->dev->id.revision == 16) + if (dev->sdev->id.revision == 16) b43_mac_suspend(dev); tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL); @@ -993,7 +993,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) tmp |= (val & mask); b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp); - if (dev->dev->id.revision == 16) + if (dev->sdev->id.revision == 16) b43_mac_enable(dev); return tmp; @@ -1168,7 +1168,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); + struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); /* PHY rev 0, 1, 2 */ u8 i, j; @@ -1373,7 +1373,7 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ static void b43_nphy_workarounds(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = phy->n; @@ -3586,7 +3586,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) */ int b43_phy_initn(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = phy->n; u8 tx_pwr_state; @@ -3601,7 +3601,7 @@ int b43_phy_initn(struct b43_wldev *dev) if ((dev->phy.rev >= 3) && (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) { - chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40); + chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40); } nphy->deaf_count = 0; b43_nphy_tables_init(dev); diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index aa12273..af0596d 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -111,7 +111,7 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev, B43_MMIO_PIO11_BASE5, }; - if (dev->dev->id.revision >= 11) { + if (dev->sdev->id.revision >= 11) { B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11)); return bases_rev11[index]; } @@ -121,14 +121,14 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev, static u16 pio_txqueue_offset(struct b43_wldev *dev) { - if (dev->dev->id.revision >= 11) + if (dev->sdev->id.revision >= 11) return 0x18; return 0; } static u16 pio_rxqueue_offset(struct b43_wldev *dev) { - if (dev->dev->id.revision >= 11) + if (dev->sdev->id.revision >= 11) return 0x38; return 8; } @@ -144,7 +144,7 @@ static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev, if (!q) return NULL; q->dev = dev; - q->rev = dev->dev->id.revision; + q->rev = dev->sdev->id.revision; q->mmio_base = index_to_pioqueue_base(dev, index) + pio_txqueue_offset(dev); q->index = index; @@ -178,7 +178,7 @@ static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev, if (!q) return NULL; q->dev = dev; - q->rev = dev->dev->id.revision; + q->rev = dev->sdev->id.revision; q->mmio_base = index_to_pioqueue_base(dev, index) + pio_rxqueue_offset(dev); @@ -339,7 +339,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI; b43_piotx_write16(q, B43_PIO_TXCTL, ctl); - ssb_block_write(dev->dev, data, (data_len & ~1), + ssb_block_write(dev->sdev, data, (data_len & ~1), q->mmio_base + B43_PIO_TXDATA, sizeof(u16)); if (data_len & 1) { @@ -351,7 +351,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, b43_piotx_write16(q, B43_PIO_TXCTL, ctl); tail[0] = data[data_len - 1]; tail[1] = 0; - ssb_block_write(dev->dev, tail, 2, + ssb_block_write(dev->sdev, tail, 2, q->mmio_base + B43_PIO_TXDATA, sizeof(u16)); } @@ -393,7 +393,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31; b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); - ssb_block_write(dev->dev, data, (data_len & ~3), + ssb_block_write(dev->sdev, data, (data_len & ~3), q->mmio_base + B43_PIO8_TXDATA, sizeof(u32)); if (data_len & 3) { @@ -421,7 +421,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, break; } b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); - ssb_block_write(dev->dev, tail, 4, + ssb_block_write(dev->sdev, tail, 4, q->mmio_base + B43_PIO8_TXDATA, sizeof(u32)); } @@ -657,11 +657,11 @@ data_ready: /* Get the preamble (RX header) */ if (q->rev >= 8) { - ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr), + ssb_block_read(dev->sdev, rxhdr, sizeof(*rxhdr), q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); } else { - ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr), + ssb_block_read(dev->sdev, rxhdr, sizeof(*rxhdr), q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); } @@ -697,7 +697,7 @@ data_ready: skb_reserve(skb, 2); skb_put(skb, len + padding); if (q->rev >= 8) { - ssb_block_read(dev->dev, skb->data + padding, (len & ~3), + ssb_block_read(dev->sdev, skb->data + padding, (len & ~3), q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); if (len & 3) { @@ -705,7 +705,7 @@ data_ready: BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4); /* Read the last few bytes. */ - ssb_block_read(dev->dev, tail, 4, + ssb_block_read(dev->sdev, tail, 4, q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); switch (len & 3) { @@ -724,7 +724,7 @@ data_ready: } } } else { - ssb_block_read(dev->dev, skb->data + padding, (len & ~1), + ssb_block_read(dev->sdev, skb->data + padding, (len & ~1), q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); if (len & 1) { @@ -732,7 +732,7 @@ data_ready: BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2); /* Read the last byte. */ - ssb_block_read(dev->dev, tail, 2, + ssb_block_read(dev->sdev, tail, 2, q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); skb->data[len + padding - 1] = tail[0]; diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 86bc0a0..a617efe 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -37,7 +37,7 @@ void b43_rfkill_poll(struct ieee80211_hw *hw) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; bool enabled; bool brought_up = false; @@ -47,7 +47,7 @@ void b43_rfkill_poll(struct ieee80211_hw *hw) mutex_unlock(&wl->mutex); return; } - ssb_device_enable(dev->dev, 0); + ssb_device_enable(dev->sdev, 0); brought_up = true; } @@ -63,7 +63,7 @@ void b43_rfkill_poll(struct ieee80211_hw *hw) } if (brought_up) { - ssb_device_disable(dev->dev, 0); + ssb_device_disable(dev->sdev, 0); ssb_bus_may_powerdown(bus); } diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c index 09e2dfd..808e25b 100644 --- a/drivers/net/wireless/b43/sdio.c +++ b/drivers/net/wireless/b43/sdio.c @@ -66,7 +66,7 @@ static void b43_sdio_interrupt_dispatcher(struct sdio_func *func) int b43_sdio_request_irq(struct b43_wldev *dev, void (*handler)(struct b43_wldev *dev)) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct sdio_func *func = bus->host_sdio; struct b43_sdio *sdio = sdio_get_drvdata(func); int err; @@ -82,7 +82,7 @@ int b43_sdio_request_irq(struct b43_wldev *dev, void b43_sdio_free_irq(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct sdio_func *func = bus->host_sdio; struct b43_sdio *sdio = sdio_get_drvdata(func); diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c index f1ae4e0..57af619 100644 --- a/drivers/net/wireless/b43/sysfs.c +++ b/drivers/net/wireless/b43/sysfs.c @@ -140,7 +140,7 @@ static DEVICE_ATTR(interference, 0644, int b43_sysfs_register(struct b43_wldev *wldev) { - struct device *dev = wldev->dev->dev; + struct device *dev = wldev->sdev->dev; B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED); @@ -149,7 +149,7 @@ int b43_sysfs_register(struct b43_wldev *wldev) void b43_sysfs_unregister(struct b43_wldev *wldev) { - struct device *dev = wldev->dev->dev; + struct device *dev = wldev->sdev->dev; device_remove_file(dev, &dev_attr_interference); } diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c index 61027ee..59df3c6 100644 --- a/drivers/net/wireless/b43/tables_lpphy.c +++ b/drivers/net/wireless/b43/tables_lpphy.c @@ -2304,7 +2304,7 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev) void lpphy_rev2plus_table_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; int i; B43_WARN_ON(dev->phy.rev < 2); @@ -2416,7 +2416,7 @@ void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count, void lpphy_init_tx_gain_table(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; switch (dev->phy.rev) { case 0: diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c index 9a335da..8f4db44 100644 --- a/drivers/net/wireless/b43/wa.c +++ b/drivers/net/wireless/b43/wa.c @@ -458,7 +458,7 @@ static void b43_wa_rssi_adc(struct b43_wldev *dev) static void b43_wa_boards_a(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && bus->boardinfo.type == SSB_BOARD_BU4306 && @@ -486,7 +486,7 @@ static void b43_wa_boards_a(struct b43_wldev *dev) static void b43_wa_boards_g(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM || diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index e5be381..c8f99ae 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -547,7 +547,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev, else tmp -= 3; } else { - if (dev->dev->bus->sprom. + if (dev->sdev->bus->sprom. boardflags_lo & B43_BFL_RSSI) { if (in_rssi > 63) in_rssi = 63; -- cgit v0.10.2 From df64962f7d74877624442c059e7878fdf7ec3c22 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 14 May 2011 02:42:38 +0200 Subject: carl9170: advertise interface combinations In order to provide multiple interfaces for a single device, the driver will be required to advertise all possible interface configurations to the stack. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index beb725d..771c021 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -286,6 +286,10 @@ struct ar9170 { unsigned int tx_seq_table; } fw; + /* interface configuration combinations */ + struct ieee80211_iface_limit if_comb_limits[1]; + struct ieee80211_iface_combination if_combs[1]; + /* reset / stuck frames/queue detection */ struct work_struct restart_work; struct work_struct ping_work; diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index 9517ede..221957c 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c @@ -151,6 +151,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) const struct carl9170fw_chk_desc *chk_desc; const struct carl9170fw_last_desc *last_desc; const struct carl9170fw_txsq_desc *txsq_desc; + u16 if_comb_types; last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC, sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER); @@ -268,6 +269,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) if (SUPP(CARL9170FW_WOL)) device_set_wakeup_enable(&ar->udev->dev, true); + if_comb_types = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_P2P_CLIENT); + ar->fw.vif_num = otus_desc->vif_num; ar->fw.cmd_bufs = otus_desc->cmd_bufs; ar->fw.address = le32_to_cpu(otus_desc->fw_address); @@ -294,12 +298,25 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); if (SUPP(CARL9170FW_WLANTX_CAB)) { - ar->hw->wiphy->interface_modes |= + if_comb_types |= BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO); } } + ar->if_comb_limits[0].max = ar->fw.vif_num; + ar->if_comb_limits[0].types = if_comb_types; + + ar->if_combs[0].num_different_channels = 1; + ar->if_combs[0].max_interfaces = ar->fw.vif_num; + ar->if_combs[0].limits = ar->if_comb_limits; + ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits); + + ar->hw->wiphy->iface_combinations = ar->if_combs; + ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs); + + ar->hw->wiphy->interface_modes |= if_comb_types; + txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC, sizeof(*txsq_desc), CARL9170FW_TXSQ_DESC_CUR_VER); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 7d5c65e..54d093c 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1570,14 +1570,8 @@ void *carl9170_alloc(size_t priv_size) INIT_LIST_HEAD(&ar->vif_list); init_completion(&ar->tx_flush); - /* - * Note: - * IBSS/ADHOC and AP mode are only enabled, if the firmware - * supports these modes. The code which will add the - * additional interface_modes is in fw.c. - */ - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_P2P_CLIENT); + /* firmware decides which modes we support */ + hw->wiphy->interface_modes = 0; hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_REPORTS_TX_ACK_STATUS | -- cgit v0.10.2 From 8e621fc90b42fa2ca4ff65dd8d9cb21723e47837 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 14 May 2011 01:55:23 +0200 Subject: mac80211: verify IBSS in interface combinations Drivers shouldn't attempt to advertise support for more than one IBSS interface since mac80211 doesn't support that. Check and return an error from ieee80211_register_hw() in that case. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0d7b08d..96ab130 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -752,11 +752,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); - /* mac80211 doesn't support more than 1 channel */ - for (i = 0; i < hw->wiphy->n_iface_combinations; i++) - if (hw->wiphy->iface_combinations[i].num_different_channels > 1) + /* + * mac80211 doesn't support more than 1 channel, and also not more + * than one IBSS interface + */ + for (i = 0; i < hw->wiphy->n_iface_combinations; i++) { + const struct ieee80211_iface_combination *c; + int j; + + c = &hw->wiphy->iface_combinations[i]; + + if (c->num_different_channels > 1) return -EINVAL; + for (j = 0; j < c->n_limits; j++) + if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && + c->limits[j].max > 1) + return -EINVAL; + } + #ifndef CONFIG_MAC80211_MESH /* mesh depends on Kconfig, but drivers should set it if they want */ local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT); -- cgit v0.10.2 From c29acf201007a6d73223f864f52406eb5ba19933 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 14 May 2011 09:43:28 +0530 Subject: mac80211: abort scan_work immediately when the device goes down As long as no delay is required b/w channel change, scan work is proceeding without scheduling a new work. In such case, we can not abort scan work when the card was unplugged. This patch completes the scanning immediately whenever the device goes down. Reviewed-by: Johannes Berg Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0d00ac9..dee30ae 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -384,11 +384,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, int i; enum nl80211_channel_type orig_ct; + clear_bit(SDATA_STATE_RUNNING, &sdata->state); + if (local->scan_sdata == sdata) ieee80211_scan_cancel(local); - clear_bit(SDATA_STATE_RUNNING, &sdata->state); - /* * Stop TX on this interface first. */ diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index d20046b..27af672 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -719,6 +719,11 @@ void ieee80211_scan_work(struct work_struct *work) * without scheduling a new work */ do { + if (!ieee80211_sdata_running(sdata)) { + aborted = true; + goto out_complete; + } + switch (local->next_scan_state) { case SCAN_DECISION: /* if no more bands/channels left, complete scan */ -- cgit v0.10.2 From 9594b56dbed8cecc4694ed2ab7cf36c66623910e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 14 May 2011 10:31:46 +0200 Subject: bcma: add PCI ID of the card found in Thinkpad X120e MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Gottfried Haider Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 99dd36e..ffd8797 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -171,6 +171,7 @@ static void bcma_host_pci_remove(struct pci_dev *dev) } static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, -- cgit v0.10.2 From d07c7cf49ae7c488e778c4d668f4cc10bd2fa971 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 14 May 2011 11:04:51 +0200 Subject: mac80211: add missing rcu_barrier mac80211 uses call_rcu() with functions that are defined in the module, so it must use rcu_barrier() at module exit time. Luckily, this seems to not be a problem in practice as module unload and unregistration takes a long time and probably does multiple synchronize_rcu(). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 96ab130..866f269 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1090,6 +1090,8 @@ static void __exit ieee80211_exit(void) ieee80211s_stop(); ieee80211_iface_exit(); + + rcu_barrier(); } -- cgit v0.10.2 From 1928ecab620907a0953f811316d05f367f3f4dba Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 14 May 2011 11:00:52 +0200 Subject: mac80211: fix and simplify mesh locking The locking in mesh_{mpath,mpp}_table_grow not only has an rcu_read_unlock() missing, it's also racy (though really only technically since it's invoked from a single function only) since it obtains the new size of the table without any locking, so two invocations of the function could attempt the same resize. Additionally, it uses synchronize_rcu() which is rather expensive and can be avoided trivially here. Modify the functions to only use the table lock and use call_rcu() instead of synchronize_rcu(). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index e7c5fdd..eb733c0 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -120,6 +120,7 @@ struct mesh_path { * buckets * @mean_chain_len: maximum average length for the hash buckets' list, if it is * reached, the table will grow + * rcu_head: RCU head to free the table */ struct mesh_table { /* Number of buckets will be 2^N */ @@ -132,6 +133,8 @@ struct mesh_table { int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); int size_order; int mean_chain_len; + + struct rcu_head rcu_head; }; /* Recent multicast cache */ diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index f775202..7402136 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -370,52 +370,52 @@ err_path_alloc: return err; } +static void mesh_table_free_rcu(struct rcu_head *rcu) +{ + struct mesh_table *tbl = container_of(rcu, struct mesh_table, rcu_head); + + mesh_table_free(tbl, false); +} + void mesh_mpath_table_grow(void) { struct mesh_table *oldtbl, *newtbl; - rcu_read_lock(); - newtbl = mesh_table_alloc(rcu_dereference(mesh_paths)->size_order + 1); - if (!newtbl) - return; write_lock_bh(&pathtbl_resize_lock); + newtbl = mesh_table_alloc(mesh_paths->size_order + 1); + if (!newtbl) + goto out; oldtbl = mesh_paths; if (mesh_table_grow(mesh_paths, newtbl) < 0) { - rcu_read_unlock(); __mesh_table_free(newtbl); - write_unlock_bh(&pathtbl_resize_lock); - return; + goto out; } - rcu_read_unlock(); rcu_assign_pointer(mesh_paths, newtbl); - write_unlock_bh(&pathtbl_resize_lock); - synchronize_rcu(); - mesh_table_free(oldtbl, false); + call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu); + + out: + write_unlock_bh(&pathtbl_resize_lock); } void mesh_mpp_table_grow(void) { struct mesh_table *oldtbl, *newtbl; - rcu_read_lock(); - newtbl = mesh_table_alloc(rcu_dereference(mpp_paths)->size_order + 1); - if (!newtbl) - return; write_lock_bh(&pathtbl_resize_lock); + newtbl = mesh_table_alloc(mpp_paths->size_order + 1); + if (!newtbl) + goto out; oldtbl = mpp_paths; if (mesh_table_grow(mpp_paths, newtbl) < 0) { - rcu_read_unlock(); __mesh_table_free(newtbl); - write_unlock_bh(&pathtbl_resize_lock); - return; + goto out; } - rcu_read_unlock(); rcu_assign_pointer(mpp_paths, newtbl); - write_unlock_bh(&pathtbl_resize_lock); + call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu); - synchronize_rcu(); - mesh_table_free(oldtbl, false); + out: + write_unlock_bh(&pathtbl_resize_lock); } int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) -- cgit v0.10.2 From 349eb8cf45aadd35836fdfde75b3265a01b2aaa1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 14 May 2011 11:56:16 +0200 Subject: mac80211: annotate and fix RCU in mesh code This adds proper RCU annotations to the mesh path table code, and fixes a number of bugs in the code that I found while checking the sparse warnings I got as a result of the annotations. Some things like the changes in mesh_path_add() or mesh_pathtbl_init() only serve to shut up sparse, but other changes like the changes surrounding the for_each_mesh_entry() macro fix real RCU bugs in the code. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index eb733c0..249e733 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -289,10 +289,6 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP; } -#define for_each_mesh_entry(x, p, node, i) \ - for (i = 0; i <= x->hash_mask; i++) \ - hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) - void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 7402136..2bda0ac 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -36,8 +36,8 @@ struct mpath_node { struct mesh_path *mpath; }; -static struct mesh_table *mesh_paths; -static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ +static struct mesh_table __rcu *mesh_paths; +static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */ int mesh_paths_generation; @@ -48,6 +48,29 @@ int mesh_paths_generation; static DEFINE_RWLOCK(pathtbl_resize_lock); +static inline struct mesh_table *resize_dereference_mesh_paths(void) +{ + return rcu_dereference_protected(mesh_paths, + lockdep_is_held(&pathtbl_resize_lock)); +} + +static inline struct mesh_table *resize_dereference_mpp_paths(void) +{ + return rcu_dereference_protected(mpp_paths, + lockdep_is_held(&pathtbl_resize_lock)); +} + +/* + * CAREFUL -- "tbl" must not be an expression, + * in particular not an rcu_dereference(), since + * it's used twice. So it is illegal to do + * for_each_mesh_entry(rcu_dereference(...), ...) + */ +#define for_each_mesh_entry(tbl, p, node, i) \ + for (i = 0; i <= tbl->hash_mask; i++) \ + hlist_for_each_entry_rcu(node, p, &tbl->hash_buckets[i], list) + + static struct mesh_table *mesh_table_alloc(int size_order) { int i; @@ -258,12 +281,13 @@ struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) */ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata) { + struct mesh_table *tbl = rcu_dereference(mesh_paths); struct mpath_node *node; struct hlist_node *p; int i; int j = 0; - for_each_mesh_entry(mesh_paths, p, node, i) { + for_each_mesh_entry(tbl, p, node, i) { if (sdata && node->mpath->sdata != sdata) continue; if (j++ == idx) { @@ -293,6 +317,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_local *local = sdata->local; + struct mesh_table *tbl; struct mesh_path *mpath, *new_mpath; struct mpath_node *node, *new_node; struct hlist_head *bucket; @@ -332,10 +357,12 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) spin_lock_init(&new_mpath->state_lock); init_timer(&new_mpath->timer); - hash_idx = mesh_table_hash(dst, sdata, mesh_paths); - bucket = &mesh_paths->hash_buckets[hash_idx]; + tbl = resize_dereference_mesh_paths(); - spin_lock_bh(&mesh_paths->hashwlock[hash_idx]); + hash_idx = mesh_table_hash(dst, sdata, tbl); + bucket = &tbl->hash_buckets[hash_idx]; + + spin_lock_bh(&tbl->hashwlock[hash_idx]); err = -EEXIST; hlist_for_each_entry(node, n, bucket, list) { @@ -345,13 +372,13 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) } hlist_add_head_rcu(&new_node->list, bucket); - if (atomic_inc_return(&mesh_paths->entries) >= - mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1)) + if (atomic_inc_return(&tbl->entries) >= + tbl->mean_chain_len * (tbl->hash_mask + 1)) grow = 1; mesh_paths_generation++; - spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]); + spin_unlock_bh(&tbl->hashwlock[hash_idx]); read_unlock_bh(&pathtbl_resize_lock); if (grow) { set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); @@ -360,7 +387,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) return 0; err_exists: - spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]); + spin_unlock_bh(&tbl->hashwlock[hash_idx]); read_unlock_bh(&pathtbl_resize_lock); kfree(new_node); err_node_alloc: @@ -382,11 +409,11 @@ void mesh_mpath_table_grow(void) struct mesh_table *oldtbl, *newtbl; write_lock_bh(&pathtbl_resize_lock); - newtbl = mesh_table_alloc(mesh_paths->size_order + 1); + oldtbl = resize_dereference_mesh_paths(); + newtbl = mesh_table_alloc(oldtbl->size_order + 1); if (!newtbl) goto out; - oldtbl = mesh_paths; - if (mesh_table_grow(mesh_paths, newtbl) < 0) { + if (mesh_table_grow(oldtbl, newtbl) < 0) { __mesh_table_free(newtbl); goto out; } @@ -403,11 +430,11 @@ void mesh_mpp_table_grow(void) struct mesh_table *oldtbl, *newtbl; write_lock_bh(&pathtbl_resize_lock); - newtbl = mesh_table_alloc(mpp_paths->size_order + 1); + oldtbl = resize_dereference_mpp_paths(); + newtbl = mesh_table_alloc(oldtbl->size_order + 1); if (!newtbl) goto out; - oldtbl = mpp_paths; - if (mesh_table_grow(mpp_paths, newtbl) < 0) { + if (mesh_table_grow(oldtbl, newtbl) < 0) { __mesh_table_free(newtbl); goto out; } @@ -422,6 +449,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_local *local = sdata->local; + struct mesh_table *tbl; struct mesh_path *mpath, *new_mpath; struct mpath_node *node, *new_node; struct hlist_head *bucket; @@ -456,10 +484,12 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) new_mpath->exp_time = jiffies; spin_lock_init(&new_mpath->state_lock); - hash_idx = mesh_table_hash(dst, sdata, mpp_paths); - bucket = &mpp_paths->hash_buckets[hash_idx]; + tbl = resize_dereference_mpp_paths(); - spin_lock_bh(&mpp_paths->hashwlock[hash_idx]); + hash_idx = mesh_table_hash(dst, sdata, tbl); + bucket = &tbl->hash_buckets[hash_idx]; + + spin_lock_bh(&tbl->hashwlock[hash_idx]); err = -EEXIST; hlist_for_each_entry(node, n, bucket, list) { @@ -469,11 +499,11 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) } hlist_add_head_rcu(&new_node->list, bucket); - if (atomic_inc_return(&mpp_paths->entries) >= - mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) + if (atomic_inc_return(&tbl->entries) >= + tbl->mean_chain_len * (tbl->hash_mask + 1)) grow = 1; - spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]); + spin_unlock_bh(&tbl->hashwlock[hash_idx]); read_unlock_bh(&pathtbl_resize_lock); if (grow) { set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); @@ -482,7 +512,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) return 0; err_exists: - spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]); + spin_unlock_bh(&tbl->hashwlock[hash_idx]); read_unlock_bh(&pathtbl_resize_lock); kfree(new_node); err_node_alloc: @@ -502,6 +532,7 @@ err_path_alloc: */ void mesh_plink_broken(struct sta_info *sta) { + struct mesh_table *tbl; static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct mesh_path *mpath; struct mpath_node *node; @@ -510,10 +541,11 @@ void mesh_plink_broken(struct sta_info *sta) int i; rcu_read_lock(); - for_each_mesh_entry(mesh_paths, p, node, i) { + tbl = rcu_dereference(mesh_paths); + for_each_mesh_entry(tbl, p, node, i) { mpath = node->mpath; spin_lock_bh(&mpath->state_lock); - if (mpath->next_hop == sta && + if (rcu_dereference(mpath->next_hop) == sta && mpath->flags & MESH_PATH_ACTIVE && !(mpath->flags & MESH_PATH_FIXED)) { mpath->flags &= ~MESH_PATH_ACTIVE; @@ -542,30 +574,38 @@ void mesh_plink_broken(struct sta_info *sta) */ void mesh_path_flush_by_nexthop(struct sta_info *sta) { + struct mesh_table *tbl; struct mesh_path *mpath; struct mpath_node *node; struct hlist_node *p; int i; - for_each_mesh_entry(mesh_paths, p, node, i) { + rcu_read_lock(); + tbl = rcu_dereference(mesh_paths); + for_each_mesh_entry(tbl, p, node, i) { mpath = node->mpath; - if (mpath->next_hop == sta) + if (rcu_dereference(mpath->next_hop) == sta) mesh_path_del(mpath->dst, mpath->sdata); } + rcu_read_unlock(); } void mesh_path_flush(struct ieee80211_sub_if_data *sdata) { + struct mesh_table *tbl; struct mesh_path *mpath; struct mpath_node *node; struct hlist_node *p; int i; - for_each_mesh_entry(mesh_paths, p, node, i) { + rcu_read_lock(); + tbl = rcu_dereference(mesh_paths); + for_each_mesh_entry(tbl, p, node, i) { mpath = node->mpath; if (mpath->sdata == sdata) mesh_path_del(mpath->dst, mpath->sdata); } + rcu_read_unlock(); } static void mesh_path_node_reclaim(struct rcu_head *rp) @@ -589,6 +629,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) */ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) { + struct mesh_table *tbl; struct mesh_path *mpath; struct mpath_node *node; struct hlist_head *bucket; @@ -597,19 +638,20 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) int err = 0; read_lock_bh(&pathtbl_resize_lock); - hash_idx = mesh_table_hash(addr, sdata, mesh_paths); - bucket = &mesh_paths->hash_buckets[hash_idx]; + tbl = resize_dereference_mesh_paths(); + hash_idx = mesh_table_hash(addr, sdata, tbl); + bucket = &tbl->hash_buckets[hash_idx]; - spin_lock_bh(&mesh_paths->hashwlock[hash_idx]); + spin_lock_bh(&tbl->hashwlock[hash_idx]); hlist_for_each_entry(node, n, bucket, list) { mpath = node->mpath; if (mpath->sdata == sdata && - memcmp(addr, mpath->dst, ETH_ALEN) == 0) { + memcmp(addr, mpath->dst, ETH_ALEN) == 0) { spin_lock_bh(&mpath->state_lock); mpath->flags |= MESH_PATH_RESOLVING; hlist_del_rcu(&node->list); call_rcu(&node->rcu, mesh_path_node_reclaim); - atomic_dec(&mesh_paths->entries); + atomic_dec(&tbl->entries); spin_unlock_bh(&mpath->state_lock); goto enddel; } @@ -618,7 +660,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) err = -ENXIO; enddel: mesh_paths_generation++; - spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]); + spin_unlock_bh(&tbl->hashwlock[hash_idx]); read_unlock_bh(&pathtbl_resize_lock); return err; } @@ -747,52 +789,60 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) int mesh_pathtbl_init(void) { - mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); - if (!mesh_paths) + struct mesh_table *tbl_path, *tbl_mpp; + + tbl_path = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); + if (!tbl_path) return -ENOMEM; - mesh_paths->free_node = &mesh_path_node_free; - mesh_paths->copy_node = &mesh_path_node_copy; - mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; + tbl_path->free_node = &mesh_path_node_free; + tbl_path->copy_node = &mesh_path_node_copy; + tbl_path->mean_chain_len = MEAN_CHAIN_LEN; - mpp_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); - if (!mpp_paths) { - mesh_table_free(mesh_paths, true); + tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); + if (!tbl_mpp) { + mesh_table_free(tbl_path, true); return -ENOMEM; } - mpp_paths->free_node = &mesh_path_node_free; - mpp_paths->copy_node = &mesh_path_node_copy; - mpp_paths->mean_chain_len = MEAN_CHAIN_LEN; + tbl_mpp->free_node = &mesh_path_node_free; + tbl_mpp->copy_node = &mesh_path_node_copy; + tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN; + + /* Need no locking since this is during init */ + RCU_INIT_POINTER(mesh_paths, tbl_path); + RCU_INIT_POINTER(mpp_paths, tbl_mpp); return 0; } void mesh_path_expire(struct ieee80211_sub_if_data *sdata) { + struct mesh_table *tbl; struct mesh_path *mpath; struct mpath_node *node; struct hlist_node *p; int i; - read_lock_bh(&pathtbl_resize_lock); - for_each_mesh_entry(mesh_paths, p, node, i) { + rcu_read_lock(); + tbl = rcu_dereference(mesh_paths); + for_each_mesh_entry(tbl, p, node, i) { if (node->mpath->sdata != sdata) continue; mpath = node->mpath; spin_lock_bh(&mpath->state_lock); if ((!(mpath->flags & MESH_PATH_RESOLVING)) && (!(mpath->flags & MESH_PATH_FIXED)) && - time_after(jiffies, - mpath->exp_time + MESH_PATH_EXPIRE)) { + time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) { spin_unlock_bh(&mpath->state_lock); mesh_path_del(mpath->dst, mpath->sdata); } else spin_unlock_bh(&mpath->state_lock); } - read_unlock_bh(&pathtbl_resize_lock); + rcu_read_unlock(); } void mesh_pathtbl_unregister(void) { - mesh_table_free(mesh_paths, true); - mesh_table_free(mpp_paths, true); + /* no need for locking during exit path */ + mesh_table_free(rcu_dereference_raw(mesh_paths), true); + mesh_table_free(rcu_dereference_raw(mpp_paths), true); } -- cgit v0.10.2 From 099fb8ab1e57e5d609ac686cc0ab6d1835a79155 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 14 May 2011 10:15:17 -0500 Subject: rtlwifi: rtl8192c-common: rtl8192ce: Fix for HT40 regression The changes that were made to rtl8192ce when rtl8192cu was added broke HT40. The errors included a typo in rtlwifi, a missing routine in rtl8192ce and a missing callback of that routine in rtl8192c-common. This patch fixes the regression reported in Bug #35082. Signed-off-by: Larry Finger Cc: stable@kernel.org Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 2bb7119..39b0297 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -190,7 +190,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) ppsc->swrf_processing = true; - if (ppsc->inactive_pwrstate == ERFOFF && + if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) { if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index c5424ca..d2cc815 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -728,7 +728,7 @@ void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, return; rtlphy->set_bwmode_inprogress = true; if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtlphy->set_bwmode_inprogress = false; + rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw); } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("FALSE driver sleep or unload\n")); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index 73ae8a4..abe0fcc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -366,6 +366,75 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, return true; } +void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + ("Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz")) + + if (is_hal_stop(rtlhal)) { + rtlphy->set_bwmode_inprogress = false; + return; + } + + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + reg_prsr_rsc = + (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); + + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); + break; + } + rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); +} + void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) { u8 tmpreg; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h index ad58085..be2c92a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h @@ -257,5 +257,6 @@ bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, u8 configtype); bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, u8 configtype); +void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 390bbb5..373dc78 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -232,6 +232,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile, .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile, .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, + .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, }; -- cgit v0.10.2 From 79d2b1570bcc31b846ccb2114a34e98ca87bf1d9 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 16 May 2011 18:23:23 +0530 Subject: ath9k: Fix power save wrappers in debug ops Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index bad1a87..7afe332 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -443,7 +443,9 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); len += snprintf(buf + len, sizeof(buf) - len, "addrmask: %pM\n", addr); + ath9k_ps_wakeup(sc); tmp = ath9k_hw_getrxfilter(sc->sc_ah); + ath9k_ps_restore(sc); len += snprintf(buf + len, sizeof(buf) - len, "rfilt: 0x%x", tmp); if (tmp & ATH9K_RX_FILTER_UCAST) @@ -725,6 +727,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, break; } + ath9k_ps_wakeup(sc); len += snprintf(buf + len, size - len, "curbssid: %pM\n" "OP-Mode: %s(%i)\n" @@ -734,6 +737,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, REG_READ(ah, AR_BEACON_PERIOD)); reg = REG_READ(ah, AR_TIMER_MODE); + ath9k_ps_restore(sc); len += snprintf(buf + len, size - len, "Timer-Mode-Register: 0x%x (", reg); if (reg & AR_TBTT_TIMER_EN) @@ -1050,7 +1054,9 @@ static ssize_t read_file_regval(struct file *file, char __user *user_buf, unsigned int len; u32 regval; + ath9k_ps_wakeup(sc); regval = REG_READ_D(ah, sc->debug.regidx); + ath9k_ps_restore(sc); len = sprintf(buf, "0x%08x\n", regval); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1072,7 +1078,9 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf, if (strict_strtoul(buf, 0, ®val)) return -EINVAL; + ath9k_ps_wakeup(sc); REG_WRITE_D(ah, sc->debug.regidx, regval); + ath9k_ps_restore(sc); return count; } -- cgit v0.10.2 From ed9d01026f156db2d638cbb045231c7a8fde877d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 May 2011 19:40:15 +0300 Subject: cfg80211: Use consistent BSS matching between scan and sme cfg80211 scan code adds separate BSS entries if the same BSS shows up on multiple channels. However, sme implementation does not use the frequency when fetching the BSS entry. Fix this by adding channel information to cfg80211_roamed() and include it in cfg80211_get_bss() calls. Please note that drivers using cfg80211_roamed() need to be modified to fully implement this fix. This commit includes only minimal changes to avoid compilation issues; it maintains the old (broken) behavior for most drivers. ath6kl was the only one that I could test, so I updated it to provide the operating frequency in the roamed event. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 5665a1a..a414768 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -565,7 +565,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) && iwm->conf.mode == UMAC_MODE_BSS) { cancel_delayed_work(&iwm->disconnect); - cfg80211_roamed(iwm_to_ndev(iwm), + cfg80211_roamed(iwm_to_ndev(iwm), NULL, complete->bssid, iwm->req_ie, iwm->req_ie_len, iwm->resp_ie, iwm->resp_ie_len, @@ -586,7 +586,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, WLAN_STATUS_SUCCESS, GFP_KERNEL); else - cfg80211_roamed(iwm_to_ndev(iwm), + cfg80211_roamed(iwm_to_ndev(iwm), NULL, complete->bssid, iwm->req_ie, iwm->req_ie_len, iwm->resp_ie, iwm->resp_ie_len, diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 518542b..29f9389 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2830,7 +2830,8 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) req_ie_len, resp_ie, resp_ie_len, 0, GFP_KERNEL); else - cfg80211_roamed(usbdev->net, bssid, req_ie, req_ie_len, + cfg80211_roamed(usbdev->net, NULL, bssid, + req_ie, req_ie_len, resp_ie, resp_ie_len, GFP_KERNEL); } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); diff --git a/drivers/staging/ath6kl/os/linux/cfg80211.c b/drivers/staging/ath6kl/os/linux/cfg80211.c index bcca394..5bda24e 100644 --- a/drivers/staging/ath6kl/os/linux/cfg80211.c +++ b/drivers/staging/ath6kl/os/linux/cfg80211.c @@ -570,7 +570,7 @@ ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel, WLAN_STATUS_SUCCESS, GFP_KERNEL); } else { /* inform roam event to cfg80211 */ - cfg80211_roamed(ar->arNetDev, bssid, + cfg80211_roamed(ar->arNetDev, ibss_channel, bssid, assocReqIe, assocReqLen, assocRespIe, assocRespLen, GFP_KERNEL); diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c index 555b056..7aaf99c 100644 --- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c @@ -2630,7 +2630,7 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, wl_get_assoc_ies(wl); memcpy(&wl->bssid, &e->addr, ETH_ALEN); wl_update_bss_info(wl); - cfg80211_roamed(ndev, + cfg80211_roamed(ndev, NULL, (u8 *)&wl->bssid, conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); @@ -2663,7 +2663,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, WL_DBG("Report connect result - connection %s\n", completed ? "succeeded" : "failed"); } else { - cfg80211_roamed(ndev, + cfg80211_roamed(ndev, NULL, (u8 *)&wl->bssid, conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 6a71f52..4734388 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -695,7 +695,7 @@ void prism2_disconnected(wlandevice_t *wlandev) void prism2_roamed(wlandevice_t *wlandev) { - cfg80211_roamed(wlandev->netdev, wlandev->bssid, + cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid, NULL, 0, NULL, 0, GFP_KERNEL); } diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index bfd6557..727131b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2878,6 +2878,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, * cfg80211_roamed - notify cfg80211 of roaming * * @dev: network device + * @channel: the channel of the new AP * @bssid: the BSSID of the new AP * @req_ie: association request IEs (maybe be %NULL) * @req_ie_len: association request IEs length @@ -2888,7 +2889,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, * It should be called by the underlying driver whenever it roamed * from one AP to another while connected. */ -void cfg80211_roamed(struct net_device *dev, const u8 *bssid, +void cfg80211_roamed(struct net_device *dev, + struct ieee80211_channel *channel, + const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); diff --git a/net/wireless/core.h b/net/wireless/core.h index bf0fb40..3dce1f1 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -245,6 +245,7 @@ struct cfg80211_event { u16 status; } cr; struct { + struct ieee80211_channel *channel; u8 bssid[ETH_ALEN]; const u8 *req_ie; const u8 *resp_ie; @@ -392,7 +393,9 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, int cfg80211_disconnect(struct cfg80211_registered_device *rdev, struct net_device *dev, u16 reason, bool wextev); -void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, +void __cfg80211_roamed(struct wireless_dev *wdev, + struct ieee80211_channel *channel, + const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len); int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/sme.c b/net/wireless/sme.c index e17b0be..b7b6ff8 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -250,7 +250,8 @@ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev) if (wdev->conn->params.privacy) capa |= WLAN_CAPABILITY_PRIVACY; - bss = cfg80211_get_bss(wdev->wiphy, NULL, wdev->conn->params.bssid, + bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel, + wdev->conn->params.bssid, wdev->conn->params.ssid, wdev->conn->params.ssid_len, WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, @@ -470,7 +471,10 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, } if (!bss) - bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, + bss = cfg80211_get_bss(wdev->wiphy, + wdev->conn ? wdev->conn->params.channel : + NULL, + bssid, wdev->ssid, wdev->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); @@ -538,7 +542,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, } EXPORT_SYMBOL(cfg80211_connect_result); -void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, +void __cfg80211_roamed(struct wireless_dev *wdev, + struct ieee80211_channel *channel, + const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len) { @@ -565,7 +571,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; - bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, + bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid, wdev->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); @@ -603,7 +609,9 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, #endif } -void cfg80211_roamed(struct net_device *dev, const u8 *bssid, +void cfg80211_roamed(struct net_device *dev, + struct ieee80211_channel *channel, + const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp) { @@ -619,6 +627,7 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid, return; ev->type = EVENT_ROAMED; + ev->rm.channel = channel; memcpy(ev->rm.bssid, bssid, ETH_ALEN); ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev); ev->rm.req_ie_len = req_ie_len; diff --git a/net/wireless/util.c b/net/wireless/util.c index f0536d4..4d7b83f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -746,7 +746,7 @@ static void cfg80211_process_wdev_events(struct wireless_dev *wdev) NULL); break; case EVENT_ROAMED: - __cfg80211_roamed(wdev, ev->rm.bssid, + __cfg80211_roamed(wdev, ev->rm.channel, ev->rm.bssid, ev->rm.req_ie, ev->rm.req_ie_len, ev->rm.resp_ie, ev->rm.resp_ie_len); break; -- cgit v0.10.2 From c6820f1e6c8273ca4b8f94c2354193d19e1a5c47 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 16 May 2011 23:22:00 +0200 Subject: ath9k: fix ad-hoc mode beacon selection In ad-hoc mode, beacon timers are configured differently compared to AP mode, and (depending on the scenario) can vary enough to make the beacon tasklet not detect slot 0 based on the TSF. Since staggered beacons are not (and cannot be) used in ad-hoc mode, it makes more sense to just hardcode slot 0 here, avoiding unnecessary TSF reads and calculations. Signed-off-by: Felix Fietkau Reported-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 637dbc5..c7f4679 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -351,9 +351,7 @@ void ath_beacon_tasklet(unsigned long data) struct ath_buf *bf = NULL; struct ieee80211_vif *vif; int slot; - u32 bfaddr, bc = 0, tsftu; - u64 tsf; - u16 intval; + u32 bfaddr, bc = 0; /* * Check if the previous beacon has gone out. If @@ -388,17 +386,27 @@ void ath_beacon_tasklet(unsigned long data) * on the tsf to safeguard against missing an swba. */ - intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; - tsf = ath9k_hw_gettsf64(ah); - tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); - tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); - slot = (tsftu % (intval * ATH_BCBUF)) / intval; - vif = sc->beacon.bslot[slot]; + if (ah->opmode == NL80211_IFTYPE_AP) { + u16 intval; + u32 tsftu; + u64 tsf; + + intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; + tsf = ath9k_hw_gettsf64(ah); + tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); + tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); + slot = (tsftu % (intval * ATH_BCBUF)) / intval; + vif = sc->beacon.bslot[slot]; + + ath_dbg(common, ATH_DBG_BEACON, + "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", + slot, tsf, tsftu / ATH_BCBUF, intval, vif); + } else { + slot = 0; + vif = sc->beacon.bslot[slot]; + } - ath_dbg(common, ATH_DBG_BEACON, - "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", - slot, tsf, tsftu / ATH_BCBUF, intval, vif); bfaddr = 0; if (vif) { -- cgit v0.10.2 From 7176ba23f8b589b1df3229574ff46fb904ce9ec5 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Mon, 16 May 2011 14:41:48 -0700 Subject: net: rfkill: add generic gpio rfkill driver This adds a new generic gpio rfkill driver to support rfkill switches which are controlled by gpios. The driver also supports passing in data about the clock for the radio, so that when rfkill is blocking, it can disable the clock. This driver assumes platform data is passed from the board files to configure it for specific devices. Original-patch-by: Anantha Idapalapati Signed-off-by: Rhyland Klein Signed-off-by: John W. Linville diff --git a/include/linux/rfkill-gpio.h b/include/linux/rfkill-gpio.h new file mode 100644 index 0000000..a175d05 --- /dev/null +++ b/include/linux/rfkill-gpio.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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-1301, USA. + */ + + +#ifndef __RFKILL_GPIO_H +#define __RFKILL_GPIO_H + +#include +#include + +/** + * struct rfkill_gpio_platform_data - platform data for rfkill gpio device. + * for unused gpio's, the expected value is -1. + * @name: name for the gpio rf kill instance + * @reset_gpio: GPIO which is used for reseting rfkill switch + * @shutdown_gpio: GPIO which is used for shutdown of rfkill switch + * @power_clk_name: [optional] name of clk to turn off while blocked + */ + +struct rfkill_gpio_platform_data { + char *name; + int reset_gpio; + int shutdown_gpio; + const char *power_clk_name; + enum rfkill_type type; +}; + +#endif /* __RFKILL_GPIO_H */ diff --git a/net/rfkill/Kconfig b/net/rfkill/Kconfig index 48464ca..78efe89 100644 --- a/net/rfkill/Kconfig +++ b/net/rfkill/Kconfig @@ -33,3 +33,12 @@ config RFKILL_REGULATOR To compile this driver as a module, choose M here: the module will be called rfkill-regulator. + +config RFKILL_GPIO + tristate "GPIO RFKILL driver" + depends on RFKILL && GPIOLIB && HAVE_CLK + default n + help + If you say yes here you get support of a generic gpio RFKILL + driver. The platform should fill in the appropriate fields in the + rfkill_gpio_platform_data structure and pass that to the driver. diff --git a/net/rfkill/Makefile b/net/rfkill/Makefile index d9a5a58..3117687 100644 --- a/net/rfkill/Makefile +++ b/net/rfkill/Makefile @@ -6,3 +6,4 @@ rfkill-y += core.o rfkill-$(CONFIG_RFKILL_INPUT) += input.o obj-$(CONFIG_RFKILL) += rfkill.o obj-$(CONFIG_RFKILL_REGULATOR) += rfkill-regulator.o +obj-$(CONFIG_RFKILL_GPIO) += rfkill-gpio.o diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c new file mode 100644 index 0000000..256c5dd --- /dev/null +++ b/net/rfkill/rfkill-gpio.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2011, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +enum rfkill_gpio_clk_state { + UNSPECIFIED = 0, + PWR_ENABLED, + PWR_DISABLED +}; + +#define PWR_CLK_SET(_RF, _EN) \ + ((_RF)->pwr_clk_enabled = (!(_EN) ? PWR_ENABLED : PWR_DISABLED)) +#define PWR_CLK_ENABLED(_RF) ((_RF)->pwr_clk_enabled == PWR_ENABLED) +#define PWR_CLK_DISABLED(_RF) ((_RF)->pwr_clk_enabled != PWR_ENABLED) + +struct rfkill_gpio_data { + struct rfkill_gpio_platform_data *pdata; + struct rfkill *rfkill_dev; + char *reset_name; + char *shutdown_name; + enum rfkill_gpio_clk_state pwr_clk_enabled; + struct clk *pwr_clk; +}; + +static int rfkill_gpio_set_power(void *data, bool blocked) +{ + struct rfkill_gpio_data *rfkill = data; + + if (blocked) { + if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) + gpio_direction_output(rfkill->pdata->shutdown_gpio, 0); + if (gpio_is_valid(rfkill->pdata->reset_gpio)) + gpio_direction_output(rfkill->pdata->reset_gpio, 0); + if (rfkill->pwr_clk && PWR_CLK_ENABLED(rfkill)) + clk_disable(rfkill->pwr_clk); + } else { + if (rfkill->pwr_clk && PWR_CLK_DISABLED(rfkill)) + clk_enable(rfkill->pwr_clk); + if (gpio_is_valid(rfkill->pdata->reset_gpio)) + gpio_direction_output(rfkill->pdata->reset_gpio, 1); + if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) + gpio_direction_output(rfkill->pdata->shutdown_gpio, 1); + } + + if (rfkill->pwr_clk) + PWR_CLK_SET(rfkill, blocked); + + return 0; +} + +static const struct rfkill_ops rfkill_gpio_ops = { + .set_block = rfkill_gpio_set_power, +}; + +static int rfkill_gpio_probe(struct platform_device *pdev) +{ + struct rfkill_gpio_data *rfkill; + struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; + int ret = 0; + int len = 0; + + if (!pdata) { + pr_warn("%s: No platform data specified\n", __func__); + return -EINVAL; + } + + /* make sure at-least one of the GPIO is defined and that + * a name is specified for this instance */ + if (!pdata->name || (!gpio_is_valid(pdata->reset_gpio) && + !gpio_is_valid(pdata->shutdown_gpio))) { + pr_warn("%s: invalid platform data\n", __func__); + return -EINVAL; + } + + rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); + if (!rfkill) + return -ENOMEM; + + rfkill->pdata = pdata; + + len = strlen(pdata->name); + rfkill->reset_name = kzalloc(len + 7, GFP_KERNEL); + if (!rfkill->reset_name) { + ret = -ENOMEM; + goto fail_alloc; + } + + rfkill->shutdown_name = kzalloc(len + 10, GFP_KERNEL); + if (!rfkill->shutdown_name) { + ret = -ENOMEM; + goto fail_reset_name; + } + + snprintf(rfkill->reset_name, len + 6 , "%s_reset", pdata->name); + snprintf(rfkill->shutdown_name, len + 9, "%s_shutdown", pdata->name); + + if (pdata->power_clk_name) { + rfkill->pwr_clk = clk_get(&pdev->dev, pdata->power_clk_name); + if (IS_ERR(rfkill->pwr_clk)) { + pr_warn("%s: can't find pwr_clk.\n", __func__); + goto fail_shutdown_name; + } + } + + if (gpio_is_valid(pdata->reset_gpio)) { + ret = gpio_request(pdata->reset_gpio, rfkill->reset_name); + if (ret) { + pr_warn("%s: failed to get reset gpio.\n", __func__); + goto fail_clock; + } + } + + if (gpio_is_valid(pdata->shutdown_gpio)) { + ret = gpio_request(pdata->shutdown_gpio, rfkill->shutdown_name); + if (ret) { + pr_warn("%s: failed to get shutdown gpio.\n", __func__); + goto fail_reset; + } + } + + rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type, + &rfkill_gpio_ops, rfkill); + if (!rfkill->rfkill_dev) + goto fail_shutdown; + + ret = rfkill_register(rfkill->rfkill_dev); + if (ret < 0) + goto fail_rfkill; + + platform_set_drvdata(pdev, rfkill); + + dev_info(&pdev->dev, "%s device registered.\n", pdata->name); + + return 0; + +fail_rfkill: + rfkill_destroy(rfkill->rfkill_dev); +fail_shutdown: + if (gpio_is_valid(pdata->shutdown_gpio)) + gpio_free(pdata->shutdown_gpio); +fail_reset: + if (gpio_is_valid(pdata->reset_gpio)) + gpio_free(pdata->reset_gpio); +fail_clock: + if (rfkill->pwr_clk) + clk_put(rfkill->pwr_clk); +fail_shutdown_name: + kfree(rfkill->shutdown_name); +fail_reset_name: + kfree(rfkill->reset_name); +fail_alloc: + kfree(rfkill); + + return ret; +} + +static int rfkill_gpio_remove(struct platform_device *pdev) +{ + struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); + + rfkill_unregister(rfkill->rfkill_dev); + rfkill_destroy(rfkill->rfkill_dev); + if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) + gpio_free(rfkill->pdata->shutdown_gpio); + if (gpio_is_valid(rfkill->pdata->reset_gpio)) + gpio_free(rfkill->pdata->reset_gpio); + if (rfkill->pwr_clk && PWR_CLK_ENABLED(rfkill)) + clk_disable(rfkill->pwr_clk); + if (rfkill->pwr_clk) + clk_put(rfkill->pwr_clk); + kfree(rfkill->shutdown_name); + kfree(rfkill->reset_name); + kfree(rfkill); + + return 0; +} + +static struct platform_driver rfkill_gpio_driver = { + .probe = rfkill_gpio_probe, + .remove = __devexit_p(rfkill_gpio_remove), + .driver = { + .name = "rfkill_gpio", + .owner = THIS_MODULE, + }, +}; + +static int __init rfkill_gpio_init(void) +{ + return platform_driver_register(&rfkill_gpio_driver); +} + +static void __exit rfkill_gpio_exit(void) +{ + platform_driver_unregister(&rfkill_gpio_driver); +} + +module_init(rfkill_gpio_init); +module_exit(rfkill_gpio_exit); + +MODULE_DESCRIPTION("gpio rfkill"); +MODULE_AUTHOR("NVIDIA"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From f699254c7126d7df94491dfd4c3648f8ec0c0d51 Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Mon, 16 May 2011 19:17:49 -0700 Subject: mwifiex: reduce CPU usage by tracking tx_pkts_queued This patch adds tx_pkts_queued to track number of packets being enqueued & dequeued so that mwifiex_wmm_lists_empty() evaluation is lightweight. Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index d3d5e08..f807447 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -196,6 +196,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, if (skb_src) pra_list->total_pkts_size -= skb_src->len; + atomic_dec(&priv->wmm.tx_pkts_queued); + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); @@ -257,6 +259,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, pra_list->total_pkts_size += skb_aggr->len; + atomic_inc(&priv->wmm.tx_pkts_queued); + tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 672701d..537b40d 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -213,7 +213,8 @@ struct mwifiex_wmm_desc { u32 drv_pkt_delay_max; u8 queue_priority[IEEE80211_MAX_QUEUES]; u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ - + /* Number of transmit packets queued */ + atomic_t tx_pkts_queued; }; struct mwifiex_802_11_security { diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index faa09e3..52d2185 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -399,6 +399,8 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; + + atomic_set(&priv->wmm.tx_pkts_queued, 0); } } @@ -408,17 +410,13 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) { - int i, j; + int i; struct mwifiex_private *priv; - for (j = 0; j < adapter->priv_num; ++j) { - priv = adapter->priv[j]; - if (priv) { - for (i = 0; i < MAX_NUM_TID; i++) - if (!mwifiex_wmm_is_ra_list_empty( - &priv->wmm.tid_tbl_ptr[i].ra_list)) - return false; - } + for (i = 0; i < adapter->priv_num; ++i) { + priv = adapter->priv[i]; + if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) + return false; } return true; @@ -468,6 +466,8 @@ static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) for (i = 0; i < MAX_NUM_TID; i++) mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. ra_list); + + atomic_set(&priv->wmm.tx_pkts_queued, 0); } /* @@ -638,6 +638,8 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, ra_list->total_pkts_size += skb->len; + atomic_inc(&priv->wmm.tx_pkts_queued); + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); } @@ -1028,6 +1030,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, .bss_prio_cur->list, struct mwifiex_bss_prio_node, list); + atomic_dec(&priv->wmm.tx_pkts_queued); spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); } @@ -1134,6 +1137,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, .bss_prio_cur->list, struct mwifiex_bss_prio_node, list); + atomic_dec(&priv->wmm.tx_pkts_queued); spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); } -- cgit v0.10.2 From 49729ff616547d7abcb96924d14aa860320e7352 Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Mon, 16 May 2011 19:17:50 -0700 Subject: mwifiex: reduce CPU usage by tracking highest_queued_prio This patch adds highest_queued_prio to track priority of packets as they are enqueued so that mwifiex_wmm_get_highest_priolist_ptr() starts checking at the first level where we have packets, instead of the highest. The function also lowers priority value to the level where first packet is found. Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 537b40d..ea3184d 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -215,6 +215,8 @@ struct mwifiex_wmm_desc { u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ /* Number of transmit packets queued */ atomic_t tx_pkts_queued; + /* Tracks highest priority with a packet queued */ + atomic_t highest_queued_prio; }; struct mwifiex_802_11_security { diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 52d2185..f3d5f23 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -177,14 +177,20 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) * This function map ACs to TIDs. */ static void -mwifiex_wmm_queue_priorities_tid(u8 queue_priority[]) +mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm) { + u8 *queue_priority = wmm->queue_priority; int i; for (i = 0; i < 4; ++i) { tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; } + + for (i = 0; i < MAX_NUM_TID; ++i) + tos_to_tid_inv[tos_to_tid[i]] = (u8)i; + + atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); } /* @@ -246,7 +252,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, } } - mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority); + mwifiex_wmm_queue_priorities_tid(&priv->wmm); } /* @@ -401,6 +407,7 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; atomic_set(&priv->wmm.tx_pkts_queued, 0); + atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } } @@ -468,6 +475,7 @@ static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) ra_list); atomic_set(&priv->wmm.tx_pkts_queued, 0); + atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } /* @@ -640,6 +648,11 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, atomic_inc(&priv->wmm.tx_pkts_queued); + if (atomic_read(&priv->wmm.highest_queued_prio) < + tos_to_tid_inv[tid_down]) + atomic_set(&priv->wmm.highest_queued_prio, + tos_to_tid_inv[tid_down]); + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); } @@ -865,9 +878,14 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, } do { + atomic_t *hqp; + spinlock_t *lock; + priv_tmp = bssprio_node->priv; + hqp = &priv_tmp->wmm.highest_queued_prio; + lock = &priv_tmp->wmm.ra_list_spinlock; - for (i = HIGH_PRIO_TID; i >= LOW_PRIO_TID; --i) { + for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { tid_ptr = &(priv_tmp)->wmm. tid_tbl_ptr[tos_to_tid[i]]; @@ -905,6 +923,11 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, is_list_empty = skb_queue_empty(&ptr->skb_head); if (!is_list_empty) { + spin_lock_irqsave(lock, flags); + if (atomic_read(hqp) > i) + atomic_set(hqp, i); + spin_unlock_irqrestore(lock, + flags); *priv = priv_tmp; *tid = tos_to_tid[i]; return ptr; -- cgit v0.10.2 From 93968147874508e6dd534af1e236a7353269da3f Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Mon, 16 May 2011 19:17:51 -0700 Subject: mwifiex: check mwifiex_wmm_lists_empty() before dequeue add checks to mwifiex_wmm_process_tx() loop so it doesn't re-enter mwifiex_dequeue_tx_packet() to find it can't send. Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index f3d5f23..784ad4c 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -1254,5 +1254,5 @@ mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) if (mwifiex_dequeue_tx_packet(adapter)) break; - } while (true); + } while (!mwifiex_wmm_lists_empty(adapter)); } -- cgit v0.10.2 From 17e8cec87586c26b953c6541c8a045e906ea046c Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Mon, 16 May 2011 19:17:52 -0700 Subject: mwifiex: CPU mips optimization with NO_PKT_PRIO_TID If we go through the entire for loop in mwifiex_wmm_get_highest_priolist_ptr() and don't find any packets, set highest_queued_prio to NO_PKT_PRIO_TID (< LOW_PRIO_TID). Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index ea3184d..3154b0a 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -202,6 +202,7 @@ struct mwifiex_tid_tbl { #define WMM_HIGHEST_PRIORITY 7 #define HIGH_PRIO_TID 7 #define LOW_PRIO_TID 0 +#define NO_PKT_PRIO_TID (-1) struct mwifiex_wmm_desc { struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 784ad4c..91634da 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -946,6 +946,12 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, } while (ptr != head); } + /* No packet at any TID for this priv. Mark as such + * to skip checking TIDs for this priv (until pkt is + * added). + */ + atomic_set(hqp, NO_PKT_PRIO_TID); + /* Get next bss priority node */ bssprio_node = list_first_entry(&bssprio_node->list, struct mwifiex_bss_prio_node, -- cgit v0.10.2 From 62a5b7dcee00c8e64e61ed98541c95fd38583116 Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Mon, 16 May 2011 19:17:53 -0700 Subject: mwifiex: adjust high/low water marks for tx_pending queue This is to fix an issue that the throughput of the higher priority stream gets dropped when a lower priority stream is present. Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 3154b0a..8316b3c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -69,7 +69,8 @@ struct mwifiex_drv_mode { #define MWIFIEX_TIMER_10S 10000 #define MWIFIEX_TIMER_1S 1000 -#define MAX_TX_PENDING 60 +#define MAX_TX_PENDING 100 +#define LOW_TX_PENDING 80 #define MWIFIEX_UPLD_SIZE (2312) diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 2101208..aaa50c0 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -140,7 +140,9 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, } else { priv->stats.tx_errors++; } - atomic_dec(&adapter->tx_pending); + + if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING) + goto done; for (i = 0; i < adapter->priv_num; i++) { -- cgit v0.10.2 From 20ba2861b09ae942398eda6d2dc0bf1019a97ddb Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Mon, 16 May 2011 21:46:28 -0700 Subject: iwlwifi: remove unused parameter from iwl_hcmd_queue_reclaim cmd_index is never used. Signed-off-by: Daniel Halperin Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 54a935f..686e176 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -746,8 +746,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) * need to be reclaimed. As result, some free space forms. If there is * enough free space (> low mark), wake the stack that feeds us. */ -static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, - int idx, int cmd_idx) +static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; @@ -819,7 +818,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) spin_lock_irqsave(&priv->hcmd_lock, flags); - iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); + iwl_hcmd_queue_reclaim(priv, txq_id, index); if (!(meta->flags & CMD_ASYNC)) { clear_bit(STATUS_HCMD_ACTIVE, &priv->status); -- cgit v0.10.2 From c75197a779b6f5ee4c5b859423a0d5257475ebee Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 17 May 2011 12:41:20 +0530 Subject: ath9k_htc: Fix mode selection Remove all the unsupported modes like FH, TURBO etc. Since this requires a FW update, increase the fw version to 1.3 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 2bdcdbc..0d6ff79 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -18,7 +18,7 @@ #define HTC_USB_H #define MAJOR_VERSION_REQ 1 -#define MINOR_VERSION_REQ 2 +#define MINOR_VERSION_REQ 3 #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index dfc7a98..5ec214c 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -46,15 +46,8 @@ extern struct ieee80211_ops ath9k_htc_ops; extern int htc_modparam_nohwcrypt; enum htc_phymode { - HTC_MODE_AUTO = 0, - HTC_MODE_11A = 1, - HTC_MODE_11B = 2, - HTC_MODE_11G = 3, - HTC_MODE_FH = 4, - HTC_MODE_TURBO_A = 5, - HTC_MODE_TURBO_G = 6, - HTC_MODE_11NA = 7, - HTC_MODE_11NG = 8 + HTC_MODE_11NA = 0, + HTC_MODE_11NG = 1 }; enum htc_opmode { diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 5aa104fe..6065c2f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -26,7 +26,7 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, { enum htc_phymode mode; - mode = HTC_MODE_AUTO; + mode = -EINVAL; switch (ichan->chanmode) { case CHANNEL_G: @@ -45,6 +45,8 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, break; } + WARN_ON(mode < 0); + return mode; } -- cgit v0.10.2 From 84dfa7308ccba190ad7efe655c25ca80793c029e Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 17 May 2011 12:41:31 +0530 Subject: ath9k_htc: Fix station flags The FW does absolutely nothing with the station flags, so remove them. But keep the field around since it might come in handy in the future. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 5ec214c..29dfdf8 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -116,18 +116,13 @@ struct ath9k_htc_target_vif { u8 pad; } __packed; -#define ATH_HTC_STA_AUTH 0x0001 -#define ATH_HTC_STA_QOS 0x0002 -#define ATH_HTC_STA_ERP 0x0004 -#define ATH_HTC_STA_HT 0x0008 - struct ath9k_htc_target_sta { u8 macaddr[ETH_ALEN]; u8 bssid[ETH_ALEN]; u8 sta_index; u8 vif_index; u8 is_vif_sta; - __be16 flags; /* ATH_HTC_STA_* */ + __be16 flags; __be16 htcap; __be16 maxampdu; u8 pad; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 6065c2f..b1b8613 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -502,9 +502,6 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, tsta.maxampdu = cpu_to_be16(maxampdu); } - if (sta && sta->ht_cap.ht_supported) - tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); - WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); if (ret) { if (sta) -- cgit v0.10.2 From db32124a3f463e551ebffe3b4c6045924d3dfafd Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 17 May 2011 12:41:41 +0530 Subject: ath9k_htc: Recalculate the BSSID mask on interface Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index b1b8613..8a82e82 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1164,6 +1164,8 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, ath9k_htc_set_opmode(priv); + ath9k_htc_set_bssid_mask(priv, vif); + /* * Stop ANI only if there are no associated station interfaces. */ -- cgit v0.10.2 From 33a5315f97e5b3964183f0cf74768ac47eabe631 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 17 May 2011 12:41:52 +0530 Subject: ath9k_htc: Fix RX filter calculation Choose the MY_BEACON filter only in case of a single interface. Also, set the ATH9K_RX_FILTER_MCAST_BCAST_ALL filter in case of interfaces. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index a898dac..0ecc242 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -875,6 +875,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) rfilt |= ATH9K_RX_FILTER_CONTROL; if ((ah->opmode == NL80211_IFTYPE_STATION) && + (priv->nvifs <= 1) && !(priv->rxfilter & FIF_BCN_PRBRESP_PROMISC)) rfilt |= ATH9K_RX_FILTER_MYBEACON; else @@ -888,6 +889,9 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) if (priv->rxfilter & FIF_PSPOLL) rfilt |= ATH9K_RX_FILTER_PSPOLL; + if (priv->nvifs > 1) + rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; + return rfilt; #undef RX_FILTER_PRESERVE -- cgit v0.10.2 From 0cd075d74b319b88bbaad666c2b9b911859a5b0e Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 17 May 2011 12:42:03 +0530 Subject: ath9k_htc: Fix BSSID calculation The BSSID/AID has to be set for the first associated station interface. Subsequent interfaces may move out of assoc/disassoc status, in which case, the BSSID has to be re-calculated from the available interfaces. Also, ANI should be enabled or disabled based on the current opmode. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 29dfdf8..fa5bb39 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -438,6 +438,7 @@ struct ath9k_htc_priv { u8 vif_sta_pos[ATH9K_HTC_MAX_VIF]; u8 num_ibss_vif; u8 num_sta_vif; + u8 num_sta_assoc_vif; u8 num_ap_vif; u16 op_flags; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 8a82e82..6eedabb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1436,6 +1436,37 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, return ret; } +static void ath9k_htc_set_bssid(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + + ath9k_hw_write_associd(priv->ah); + ath_dbg(common, ATH_DBG_CONFIG, + "BSSID: %pM aid: 0x%x\n", + common->curbssid, common->curaid); +} + +static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + + if ((vif->type == NL80211_IFTYPE_STATION) && bss_conf->assoc) { + common->curaid = bss_conf->aid; + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + } +} + +static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv) +{ + if (priv->num_sta_assoc_vif == 1) { + ieee80211_iterate_active_interfaces_atomic(priv->hw, + ath9k_htc_bss_iter, priv); + ath9k_htc_set_bssid(priv); + } +} + static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -1444,43 +1475,32 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); - bool set_assoc; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); - /* - * Set the HW AID/BSSID only for the first station interface - * or in IBSS mode. - */ - set_assoc = !!((priv->ah->opmode == NL80211_IFTYPE_ADHOC) || - ((priv->ah->opmode == NL80211_IFTYPE_STATION) && - (priv->num_sta_vif == 1))); - - if (changed & BSS_CHANGED_ASSOC) { - if (set_assoc) { - ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", - bss_conf->assoc); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + bss_conf->assoc); - common->curaid = bss_conf->assoc ? - bss_conf->aid : 0; + bss_conf->assoc ? + priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; - if (bss_conf->assoc) + if (priv->ah->opmode == NL80211_IFTYPE_STATION) { + if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1)) ath9k_htc_start_ani(priv); - else + else if (priv->num_sta_assoc_vif == 0) ath9k_htc_stop_ani(priv); } } if (changed & BSS_CHANGED_BSSID) { - if (set_assoc) { + if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { + common->curaid = bss_conf->aid; memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - ath9k_hw_write_associd(ah); - - ath_dbg(common, ATH_DBG_CONFIG, - "BSSID: %pM aid: 0x%x\n", - common->curbssid, common->curaid); + ath9k_htc_set_bssid(priv); + } else if (priv->ah->opmode == NL80211_IFTYPE_STATION) { + ath9k_htc_choose_set_bssid(priv); } } -- cgit v0.10.2 From bd54879958f3e7efe249f69c75718cc9ee915cf8 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 17 May 2011 12:42:14 +0530 Subject: ath9k_htc: Fix max subframe handling Commit "ath9k_htc: Fix AMPDU subframe handling" registered the maximum subframe limit of the driver with mac80211, which was used in ADDBA negotiation. While technically correct, this causes inter-operability issues with a few APs. Revert to the older behavior to fix this. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index bfdc8a8..d222456 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -769,11 +769,6 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, hw->channel_change_time = 5000; hw->max_listen_interval = 10; - if (AR_SREV_9271(priv->ah)) - hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_9271; - else - hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_7010; - hw->vif_data_size = sizeof(struct ath9k_htc_vif); hw->sta_data_size = sizeof(struct ath9k_htc_sta); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 6eedabb..bee100e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -581,7 +581,7 @@ int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); tcap.ampdu_limit = cpu_to_be32(0xffff); - tcap.ampdu_subframes = priv->hw->max_tx_aggregation_subframes; + tcap.ampdu_subframes = 0xff; tcap.enable_coex = enable_coex; tcap.tx_chainmask = priv->ah->caps.tx_chainmask; -- cgit v0.10.2 From d108e8b9320b77e3fa165757fd40f298bdd89d1c Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 17 May 2011 12:42:24 +0530 Subject: ath9k_htc: Change credit limit for UB94/95 Reduce the credit size for UB94/95 to fix target hangs. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index d222456..8657d26 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -258,7 +258,7 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid, */ if (IS_AR7010_DEVICE(drv_info)) - priv->htc->credits = 48; + priv->htc->credits = 45; else priv->htc->credits = 33; -- cgit v0.10.2 From 89ea674565611908e11f92f57b15bf50d82f1f22 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 17 May 2011 12:42:34 +0530 Subject: ath9k_htc: Fix packet timeout The WMI tx status event timeout was not aligning with the TX cleanup timer threshold value. Fix this to handle dropped packets. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index fa5bb39..e09b20f 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -273,9 +273,9 @@ struct ath9k_htc_rx { }; #define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ -#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 2500 /* ms */ +#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 3000 /* ms */ #define ATH9K_HTC_TX_RESERVE 10 -#define ATH9K_HTC_TX_TIMEOUT_COUNT 20 +#define ATH9K_HTC_TX_TIMEOUT_COUNT 40 #define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) #define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) -- cgit v0.10.2 From a455c57ed3e4b2166c42286dd7987f36b5e00612 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 17 May 2011 13:05:05 +0530 Subject: ath_hw: Fix bssid mask documentation Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index 183c282..eda470b 100644 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c @@ -43,7 +43,7 @@ * set of ~ ( MAC XOR BSSID ) for all bssids we handle. * * When you do this you are essentially computing the common bits of all your - * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with + * BSSes. Later it is assumed the hardware will "and" (&) the BSSID mask with * the MAC address to obtain the relevant bits and compare the result with * (frame's BSSID & mask) to see if they match. * @@ -71,8 +71,8 @@ * On loop iteration for BSSID-02: * bssid_mask &= ~(0001 ^ 1001) * bssid_mask = (1010) & ~(0001 ^ 1001) - * bssid_mask = (1010) & ~(1001) - * bssid_mask = (1010) & (0110) + * bssid_mask = (1010) & ~(1000) + * bssid_mask = (1010) & (0111) * bssid_mask = 0010 * * A bssid_mask of 0010 means "only pay attention to the second least @@ -102,11 +102,9 @@ * * IFRAME-02: 0001 (we should allow) * - * allow = (0001 & 1010) == 1010 - * * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; - * --> allow = (0010) == (0010) + * --> allow = (0000) == (0000) * --> allow = 1 * * Other examples: -- cgit v0.10.2 From 5b68138e5659cbfd5df2879d17f9ba0b66477fec Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 17 May 2011 13:36:18 +0530 Subject: ath9k: Drag the driver to the year 2011 The Times They Are a-Changin'. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 6195639..5b49cd0 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * Copyright (c) 2009 Gabor Juhos * Copyright (c) 2009 Imre Kaloz * diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 5a1f4f5..bfb6481 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 0cd6783..dbab5b9 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h index 36f7d06..234617c 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 4361704..4800dfe 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h index 69a94c7..6d2e2f3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index cb611b2..015d974 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index f44c84a..f344cc2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index 6203eed..7573257 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 7a332f1..077e8a6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index a57e963..2fe0a34 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 47780ef..453af6d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index f915a3d..e8ac70d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index f276cb9..f48051c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index c7ad056..6a6125c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index afb0b5e..ab21a49 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #ifndef AR9003_EEPROM_H #define AR9003_EEPROM_H diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index a55eddb..392bf0f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index be6adec..10d71f7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 45cc7e8..c504493 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 356d2fd7..e4d6a87 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 25f3c2f..eee23ec 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index c7505b4..443090d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2010 Atheros Communications, Inc. + * Copyright (c) 2010-2011 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index fbdde29..611ea6c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 03b37d7..b070f40 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index c7f4679..2f65994 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 23f15a7..41ce0b1 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Atheros Communications Inc. + * Copyright (c) 2009-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index a9efca8..234f776 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Atheros Communications Inc. + * Copyright (c) 2009-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 558b228..a1250c5 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 4420780..1bef41d 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 74535e6..fa6bd2d 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Atheros Communications Inc. + * Copyright (c) 2009-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 5124f14..77ec288 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Atheros Communications Inc. + * Copyright (c) 2009-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 7afe332..c21269c 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 5488a32..8ce6ad8 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 8c18bed..e61404d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 3e31613..de99c0d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 6f714dd..5b1e894 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index b87db47..7856f0d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index c031854..17f0a68 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 0349b3a..bc713fc 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 2e3a33a..260f1f3 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 0d6ff79..794f630 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index e09b20f..5bc0220 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 0ded2c6..aa6a731 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index af57fe5..db2352e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 8657d26..61e6d39 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index bee100e..7b77968 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 0ecc242..2d81c70 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 5c76352..4d84295 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index 91a5305..e1ffbb6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 8b8f044..2f3e072 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b75b5dc..72543ce 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7af2773..57435ce 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index b172d15..45c585a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index bd6d2b9..c2091f1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index b60c130..8e848c4 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 45303bdb..8635cd2 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index e83128c..f3cb54a 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 9441bf8..8b38030 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index b877d96..133502b 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2004-2009 Atheros Communications, Inc. + * Copyright (c) 2004-2011 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 5d984b8..c3d8502 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2004 Sam Leffler, Errno Consulting * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 4f52e04..07e35e5 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 456f3ec..c18ee99 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index f9b1eb4..35422fc 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 6095eeb..fde6da6 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 41469d7..fa821b9 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above -- cgit v0.10.2 From ac56703e0e790509963ee42cddebe706fbd3b74c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 17 May 2011 10:34:12 +0200 Subject: ath9k: fix ad-hoc nexttbtt calculation rounding up the delta between last-beacon-tsf and tsf to intval is wrong and can lead to misconfigured timers which breaks beacon transmission. Fix this by adding intval and subtracting the offset of the tsf within the current slot. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 2f65994..61b501a 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -654,7 +654,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, delta = (tsf - sc->beacon.bc_tstamp); else delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp)); - nexttbtt = tsf + roundup(delta, intval); + nexttbtt = tsf + intval - (delta % intval); } ath_dbg(common, ATH_DBG_BEACON, -- cgit v0.10.2 From 620d785ba9066d5436857ec8e7c104c7b1c467e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 17 May 2011 14:00:00 +0200 Subject: b43: add helpers for block R/W ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index fd69d6a..02eca18 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -897,6 +897,18 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) ssb_write32(dev->sdev, offset, value); } +static inline void b43_block_read(struct b43_wldev *dev, void *buffer, + size_t count, u16 offset, u8 reg_width) +{ + ssb_block_read(dev->sdev, buffer, count, offset, reg_width); +} + +static inline void b43_block_write(struct b43_wldev *dev, const void *buffer, + size_t count, u16 offset, u8 reg_width) +{ + ssb_block_write(dev->sdev, buffer, count, offset, reg_width); +} + static inline bool b43_using_pio_transfers(struct b43_wldev *dev) { return dev->__using_pio_transfers; diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index af0596d..72ab94d 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -339,7 +339,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI; b43_piotx_write16(q, B43_PIO_TXCTL, ctl); - ssb_block_write(dev->sdev, data, (data_len & ~1), + b43_block_write(dev, data, (data_len & ~1), q->mmio_base + B43_PIO_TXDATA, sizeof(u16)); if (data_len & 1) { @@ -351,7 +351,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, b43_piotx_write16(q, B43_PIO_TXCTL, ctl); tail[0] = data[data_len - 1]; tail[1] = 0; - ssb_block_write(dev->sdev, tail, 2, + b43_block_write(dev, tail, 2, q->mmio_base + B43_PIO_TXDATA, sizeof(u16)); } @@ -393,7 +393,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31; b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); - ssb_block_write(dev->sdev, data, (data_len & ~3), + b43_block_write(dev, data, (data_len & ~3), q->mmio_base + B43_PIO8_TXDATA, sizeof(u32)); if (data_len & 3) { @@ -421,7 +421,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, break; } b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); - ssb_block_write(dev->sdev, tail, 4, + b43_block_write(dev, tail, 4, q->mmio_base + B43_PIO8_TXDATA, sizeof(u32)); } @@ -657,11 +657,11 @@ data_ready: /* Get the preamble (RX header) */ if (q->rev >= 8) { - ssb_block_read(dev->sdev, rxhdr, sizeof(*rxhdr), + b43_block_read(dev, rxhdr, sizeof(*rxhdr), q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); } else { - ssb_block_read(dev->sdev, rxhdr, sizeof(*rxhdr), + b43_block_read(dev, rxhdr, sizeof(*rxhdr), q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); } @@ -697,7 +697,7 @@ data_ready: skb_reserve(skb, 2); skb_put(skb, len + padding); if (q->rev >= 8) { - ssb_block_read(dev->sdev, skb->data + padding, (len & ~3), + b43_block_read(dev, skb->data + padding, (len & ~3), q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); if (len & 3) { @@ -705,7 +705,7 @@ data_ready: BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4); /* Read the last few bytes. */ - ssb_block_read(dev->sdev, tail, 4, + b43_block_read(dev, tail, 4, q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); switch (len & 3) { @@ -724,7 +724,7 @@ data_ready: } } } else { - ssb_block_read(dev->sdev, skb->data + padding, (len & ~1), + b43_block_read(dev, skb->data + padding, (len & ~1), q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); if (len & 1) { @@ -732,7 +732,7 @@ data_ready: BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2); /* Read the last byte. */ - ssb_block_read(dev->sdev, tail, 2, + b43_block_read(dev, tail, 2, q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); skb->data[len + padding - 1] = tail[0]; -- cgit v0.10.2 From 0355a3452fe218b2bc61a7a571064ee86dd6bf4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 17 May 2011 14:00:01 +0200 Subject: b43: make b43_wireless_init less bus specific MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ea58e27..fcbf670 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4925,19 +4925,16 @@ static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl) ieee80211_free_hw(hw); } -static int b43_wireless_init(struct ssb_device *dev) +static struct b43_wl *b43_wireless_init(struct ssb_device *dev) { struct ssb_sprom *sprom = &dev->bus->sprom; struct ieee80211_hw *hw; struct b43_wl *wl; - int err = -ENOMEM; - - b43_sprom_fixup(dev->bus); hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops); if (!hw) { b43err(NULL, "Could not allocate ieee80211 device\n"); - goto out; + return ERR_PTR(-ENOMEM); } wl = hw_to_b43_wl(hw); @@ -4971,12 +4968,9 @@ static int b43_wireless_init(struct ssb_device *dev) INIT_WORK(&wl->tx_work, b43_tx_work); skb_queue_head_init(&wl->tx_queue); - ssb_set_devtypedata(dev, wl); b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", dev->bus->chip_id, dev->id.revision); - err = 0; -out: - return err; + return wl; } static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id) @@ -4989,11 +4983,14 @@ static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id) if (!wl) { /* Probing the first core. Must setup common struct b43_wl */ first = 1; - err = b43_wireless_init(dev); - if (err) + b43_sprom_fixup(dev->bus); + wl = b43_wireless_init(dev); + if (IS_ERR(wl)) { + err = PTR_ERR(wl); goto out; - wl = ssb_get_devtypedata(dev); - B43_WARN_ON(!wl); + } + ssb_set_devtypedata(dev, wl); + B43_WARN_ON(ssb_get_devtypedata(dev) != wl); } err = b43_one_core_attach(dev, wl); if (err) -- cgit v0.10.2 From 05100a29cb65b7473bc0c71282df3e31b460b728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 17 May 2011 14:00:02 +0200 Subject: b43: dma: cache translation (routing bits) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 02eca18..3c8200c 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -567,6 +567,8 @@ struct b43_dma { struct b43_dmaring *tx_ring_mcast; /* Multicast */ struct b43_dmaring *rx_ring; + + u32 translation; /* Routing bits */ }; struct b43_pio_txqueue; diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 10cfba3..47d44bc 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -80,7 +80,7 @@ static void op32_fill_descriptor(struct b43_dmaring *ring, addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK); addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addr |= ssb_dma_translation(ring->dev->sdev); + addr |= ring->dev->dma.translation; ctl = bufsize & B43_DMA32_DCTL_BYTECNT; if (slot == ring->nr_slots - 1) ctl |= B43_DMA32_DCTL_DTABLEEND; @@ -174,7 +174,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring, addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addrhi |= (ssb_dma_translation(ring->dev->sdev) << 1); + addrhi |= (ring->dev->dma.translation << 1); if (slot == ring->nr_slots - 1) ctl0 |= B43_DMA64_DCTL0_DTABLEEND; if (start) @@ -658,7 +658,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) int err = 0; u32 value; u32 addrext; - u32 trans = ssb_dma_translation(ring->dev->sdev); + u32 trans = ring->dev->dma.translation; if (ring->tx) { if (ring->type == B43_DMA_64BIT) { @@ -1055,6 +1055,7 @@ int b43_dma_init(struct b43_wldev *dev) err = b43_dma_set_mask(dev, dmamask); if (err) return err; + dma->translation = ssb_dma_translation(dev->sdev); err = -ENOMEM; /* setup TX DMA channels. */ -- cgit v0.10.2 From c4a2a08165dd5a58e24eb342902839dca78887b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 17 May 2011 18:57:27 +0200 Subject: b43: add helper for finding GPIO device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index fcbf670..7b3b3f7 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2556,10 +2556,20 @@ out: /* Initialize the GPIOs * http://bcm-specs.sipsolutions.net/GPIO */ -static int b43_gpio_init(struct b43_wldev *dev) +static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev) { struct ssb_bus *bus = dev->sdev->bus; - struct ssb_device *gpiodev, *pcidev = NULL; + +#ifdef CONFIG_SSB_DRIVER_PCICORE + return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev); +#else + return bus->chipco.dev; +#endif +} + +static int b43_gpio_init(struct b43_wldev *dev) +{ + struct ssb_device *gpiodev; u32 mask, set; b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) @@ -2591,15 +2601,11 @@ static int b43_gpio_init(struct b43_wldev *dev) if (dev->sdev->id.revision >= 2) mask |= 0x0010; /* FIXME: This is redundant. */ -#ifdef CONFIG_SSB_DRIVER_PCICORE - pcidev = bus->pcicore.dev; -#endif - gpiodev = bus->chipco.dev ? : pcidev; - if (!gpiodev) - return 0; - ssb_write32(gpiodev, B43_GPIO_CONTROL, - (ssb_read32(gpiodev, B43_GPIO_CONTROL) - & mask) | set); + gpiodev = b43_ssb_gpio_dev(dev); + if (gpiodev) + ssb_write32(gpiodev, B43_GPIO_CONTROL, + (ssb_read32(gpiodev, B43_GPIO_CONTROL) + & mask) | set); return 0; } @@ -2607,16 +2613,11 @@ static int b43_gpio_init(struct b43_wldev *dev) /* Turn off all GPIO stuff. Call this on module unload, for example. */ static void b43_gpio_cleanup(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->sdev->bus; - struct ssb_device *gpiodev, *pcidev = NULL; + struct ssb_device *gpiodev; -#ifdef CONFIG_SSB_DRIVER_PCICORE - pcidev = bus->pcicore.dev; -#endif - gpiodev = bus->chipco.dev ? : pcidev; - if (!gpiodev) - return; - ssb_write32(gpiodev, B43_GPIO_CONTROL, 0); + gpiodev = b43_ssb_gpio_dev(dev); + if (gpiodev) + ssb_write32(gpiodev, B43_GPIO_CONTROL, 0); } /* http://bcm-specs.sipsolutions.net/EnableMac */ -- cgit v0.10.2 From 1495298ddd496131b8226a837ab10bdd5acb3480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 17 May 2011 18:57:28 +0200 Subject: b43: separate ssb core reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7b3b3f7..1bc40eb 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1143,10 +1143,9 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) } } -void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) +static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, u32 flags) { u32 tmslow; - u32 macctl; flags |= B43_TMSLOW_PHYCLKEN; flags |= B43_TMSLOW_PHYRESET; @@ -1166,6 +1165,13 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */ msleep(1); +} + +void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) +{ + u32 macctl; + + b43_ssb_wireless_core_reset(dev, flags); /* Turn Analog ON, but only if we already know the PHY-type. * This protects against very early setup where we don't know the -- cgit v0.10.2 From 755173291a86c6e77414e1eaf22279fde88ccd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 17 May 2011 19:19:39 +0200 Subject: b43: read PHY info only when needed (for PHY-A) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We risk reading TMSHIGH register twice, but PHY-A are really rare and we do not support them at the moment. Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 1bc40eb..fff14ad 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2118,7 +2118,6 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) int err; /* Get microcode */ - tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); if ((rev >= 5) && (rev <= 10)) filename = "ucode5"; else if ((rev >= 11) && (rev <= 12)) @@ -2157,6 +2156,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) switch (dev->phy.type) { case B43_PHYTYPE_A: if ((rev >= 5) && (rev <= 10)) { + tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) filename = "a0g1initvals5"; else @@ -2201,6 +2201,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) switch (dev->phy.type) { case B43_PHYTYPE_A: if ((rev >= 5) && (rev <= 10)) { + tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) filename = "a0g1bsinitvals5"; else -- cgit v0.10.2 From ba4903f97a275ed0967b58ff882f8ab41bec24ad Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 17 May 2011 21:09:54 +0200 Subject: ath9k: implement .tx_last_beacon() Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index b070f40..f75068b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -397,6 +397,9 @@ struct ath_beacon { struct ath_descdma bdma; struct ath_txq *cabq; struct list_head bbuf; + + bool tx_processed; + bool tx_last; }; void ath_beacon_tasklet(unsigned long data); diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 61b501a..d4d8cec 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -18,6 +18,12 @@ #define FUDGE 2 +static void ath9k_reset_beacon_status(struct ath_softc *sc) +{ + sc->beacon.tx_processed = false; + sc->beacon.tx_last = false; +} + /* * This function will modify certain transmit queue properties depending on * the operating mode of the station (AP or AdHoc). Parameters are AIFS @@ -72,6 +78,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ieee80211_supported_band *sband; u8 rate = 0; + ath9k_reset_beacon_status(sc); + ds = bf->bf_desc; flags = ATH9K_TXDESC_NOACK; @@ -134,6 +142,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, struct ieee80211_tx_info *info; int cabq_depth; + ath9k_reset_beacon_status(sc); + avp = (void *)vif->drv_priv; cabq = sc->beacon.cabq; @@ -644,6 +654,8 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, struct ath_common *common = ath9k_hw_common(ah); u32 tsf, delta, intval, nexttbtt; + ath9k_reset_beacon_status(sc); + tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE); intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 8635cd2..bd18b1d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2324,6 +2324,45 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) return false; } +int ath9k_tx_last_beacon(struct ieee80211_hw *hw) +{ + struct ath_softc *sc = hw->priv; + struct ath_hw *ah = sc->sc_ah; + struct ieee80211_vif *vif; + struct ath_vif *avp; + struct ath_buf *bf; + struct ath_tx_status ts; + int status; + + vif = sc->beacon.bslot[0]; + if (!vif) + return 0; + + avp = (void *)vif->drv_priv; + if (!avp->is_bslot_active) + return 0; + + if (!sc->beacon.tx_processed) { + tasklet_disable(&sc->bcon_tasklet); + + bf = avp->av_bcbuf; + if (!bf || !bf->bf_mpdu) + goto skip; + + status = ath9k_hw_txprocdesc(ah, bf->bf_desc, &ts); + if (status == -EINPROGRESS) + goto skip; + + sc->beacon.tx_processed = true; + sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); + +skip: + tasklet_enable(&sc->bcon_tasklet); + } + + return sc->beacon.tx_last; +} + struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -2348,4 +2387,5 @@ struct ieee80211_ops ath9k_ops = { .set_coverage_class = ath9k_set_coverage_class, .flush = ath9k_flush, .tx_frames_pending = ath9k_tx_frames_pending, + .tx_last_beacon = ath9k_tx_last_beacon, }; -- cgit v0.10.2 From d676ff493d9dfb8b34892214665028a8c85e2056 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 17 May 2011 16:13:34 -0700 Subject: mac80211: Don't sleep when growing the mesh path After commit 1928ecab620907a0953f811316d05f367f3f4dba (mac80211: fix and simplify mesh locking) mesh table allocation is performed with the pathtbl_resize_lock taken. Under those conditions one should not sleep. This patch makes the allocations GFP_ATOMIC to prevent that. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 2bda0ac..51f6fe8 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -76,12 +76,12 @@ static struct mesh_table *mesh_table_alloc(int size_order) int i; struct mesh_table *newtbl; - newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL); + newtbl = kmalloc(sizeof(struct mesh_table), GFP_ATOMIC); if (!newtbl) return NULL; newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) * - (1 << size_order), GFP_KERNEL); + (1 << size_order), GFP_ATOMIC); if (!newtbl->hash_buckets) { kfree(newtbl); @@ -89,7 +89,7 @@ static struct mesh_table *mesh_table_alloc(int size_order) } newtbl->hashwlock = kmalloc(sizeof(spinlock_t) * - (1 << size_order), GFP_KERNEL); + (1 << size_order), GFP_ATOMIC); if (!newtbl->hashwlock) { kfree(newtbl->hash_buckets); kfree(newtbl); -- cgit v0.10.2 From a2cd43c52aa5c676b03d575177536e05ac672c75 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Wed, 18 May 2011 11:42:03 +0300 Subject: nl80211: remove some stack variables in trigger_scan and start_sched_scan Some stack variables (name *ssid and *channel) are only used to define the size of the memory block that needs to be allocated for the request structure in the nl80211_trigger_scan() and nl80211_start_sched_scan() functions. This is unnecessary because the sizes of the actual elements in the structure can be used instead. Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2222ce08..ec83f41 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3294,8 +3294,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; struct cfg80211_scan_request *request; - struct cfg80211_ssid *ssid; - struct ieee80211_channel *channel; struct nlattr *attr; struct wiphy *wiphy; int err, tmp, n_ssids = 0, n_channels, i; @@ -3342,8 +3340,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) return -EINVAL; request = kzalloc(sizeof(*request) - + sizeof(*ssid) * n_ssids - + sizeof(channel) * n_channels + + sizeof(*request->ssids) * n_ssids + + sizeof(*request->channels) * n_channels + ie_len, GFP_KERNEL); if (!request) return -ENOMEM; @@ -3449,8 +3447,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, struct cfg80211_sched_scan_request *request; struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; - struct cfg80211_ssid *ssid; - struct ieee80211_channel *channel; struct nlattr *attr; struct wiphy *wiphy; int err, tmp, n_ssids = 0, n_channels, i; @@ -3507,8 +3503,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, return -EINVAL; request = kzalloc(sizeof(*request) - + sizeof(*ssid) * n_ssids - + sizeof(channel) * n_channels + + sizeof(*request->ssids) * n_ssids + + sizeof(*request->channels) * n_channels + ie_len, GFP_KERNEL); if (!request) return -ENOMEM; -- cgit v0.10.2 From c6e38c06cb51bee42ff80a36a0f7c67b485c4541 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 18 May 2011 17:56:00 +0530 Subject: ath9k: use PS wakeup before REG_READ otherwise we will get deadbeef when the station is in idle state Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index c21269c..d55ffd7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -435,6 +435,7 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, conf->channel_type, channel_type_str(conf->channel_type)); + ath9k_ps_wakeup(sc); put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); len += snprintf(buf + len, sizeof(buf) - len, @@ -443,7 +444,6 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); len += snprintf(buf + len, sizeof(buf) - len, "addrmask: %pM\n", addr); - ath9k_ps_wakeup(sc); tmp = ath9k_hw_getrxfilter(sc->sc_ah); ath9k_ps_restore(sc); len += snprintf(buf + len, sizeof(buf) - len, -- cgit v0.10.2 From 19a76fa9593bad778dabeeec1f6c2df6effe9ca3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 22 May 2011 22:23:00 +0000 Subject: net: ping: cleanups ping_v4_unhash() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net/ipv4/ping.c: In function ‘ping_v4_unhash’: net/ipv4/ping.c:140:28: warning: variable ‘hslot’ set but not used Signed-off-by: Eric Dumazet CC: Vasiliy Kulikov Acked-by: Vasiliy Kulikov Signed-off-by: David S. Miller diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 1f3bb11..9aaa671 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -137,9 +137,6 @@ static void ping_v4_unhash(struct sock *sk) struct inet_sock *isk = inet_sk(sk); pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); if (sk_hashed(sk)) { - struct hlist_nulls_head *hslot; - - hslot = ping_hashslot(&ping_table, sock_net(sk), isk->inet_num); write_lock_bh(&ping_table.lock); hlist_nulls_del(&sk->sk_nulls_node); sock_put(sk); -- cgit v0.10.2 From 418f275ed5b03c48e0e6c3401466660dfe894f76 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 22 May 2011 22:41:48 +0000 Subject: snap: remove one synchronize_net() No need to wait for a rcu grace period after list insertion. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/802/psnap.c b/net/802/psnap.c index 21cde8f..db6baf7 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -147,7 +147,6 @@ struct datalink_proto *register_snap_client(const unsigned char *desc, out: spin_unlock_bh(&snap_lock); - synchronize_net(); return proto; } -- cgit v0.10.2 From a4910b744486254cfa61995954c118fb2283c4fd Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Mon, 23 May 2011 03:36:35 +0000 Subject: ehea: Fix multicast registration on semi-promiscuous mode Ehea will not register multicast groups in phyp if the physical interface is in promiscuous mode. But it should register if the logical port is in promiscuous mode, but the physical port is not. Ehea physical promiscuous mode is defined by ehea_port->promisc, while logical port is defined by IFF_PROMISC. So currently, if the user set the interface in promiscuous mode, IGMP will not be registred in PHYP, and PHYP will never pass the multicast packet to the logical port, which is bad So, this patch just fixes it, assuring that we register in phyp if the physical port is not on promiscuous mode. Signed-off-by: Breno Leitao Signed-off-by: David S. Miller diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 6a0a8fc..3fd5a24 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -2083,7 +2083,7 @@ static void ehea_set_multicast_list(struct net_device *dev) struct netdev_hw_addr *ha; int ret; - if (dev->flags & IFF_PROMISC) { + if (port->promisc) { ehea_promiscuous(dev, 1); return; } -- cgit v0.10.2 From 8efa885406359af300d46910642b50ca82c0fe47 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 23 May 2011 11:02:42 +0000 Subject: sch_sfq: avoid giving spurious NET_XMIT_CN signals While chasing a possible net_sched bug, I found that IP fragments have litle chance to pass a congestioned SFQ qdisc : - Say SFQ qdisc is full because one flow is non responsive. - ip_fragment() wants to send two fragments belonging to an idle flow. - sfq_enqueue() queues first packet, but see queue limit reached : - sfq_enqueue() drops one packet from 'big consumer', and returns NET_XMIT_CN. - ip_fragment() cancel remaining fragments. This patch restores fairness, making sure we return NET_XMIT_CN only if we dropped a packet from the same flow. Signed-off-by: Eric Dumazet CC: Patrick McHardy CC: Jarek Poplawski CC: Jamal Hadi Salim CC: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 7ef87f9..b1d00f8 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -361,7 +361,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct sfq_sched_data *q = qdisc_priv(sch); unsigned int hash; - sfq_index x; + sfq_index x, qlen; struct sfq_slot *slot; int uninitialized_var(ret); @@ -405,8 +405,12 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) if (++sch->q.qlen <= q->limit) return NET_XMIT_SUCCESS; + qlen = slot->qlen; sfq_drop(sch); - return NET_XMIT_CN; + /* Return Congestion Notification only if we dropped a packet + * from this flow. + */ + return (qlen != slot->qlen) ? NET_XMIT_CN : NET_XMIT_SUCCESS; } static struct sk_buff * -- cgit v0.10.2 From b3eec79b0776e5340a3db75b34953977c7e5086e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 May 2011 07:48:39 +0000 Subject: bug.h: Add WARN_RATELIMIT Add a generic mechanism to ratelimit WARN(foo, fmt, ...) messages using a hidden per call site static struct ratelimit_state. Also add an __WARN_RATELIMIT variant to be able to use a specific struct ratelimit_state. Signed-off-by: Joe Perches Signed-off-by: David S. Miller diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index e5a3f58..12b250c 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -165,6 +165,22 @@ extern void warn_slowpath_null(const char *file, const int line); #define WARN_ON_RATELIMIT(condition, state) \ WARN_ON((condition) && __ratelimit(state)) +#define __WARN_RATELIMIT(condition, state, format...) \ +({ \ + int rtn = 0; \ + if (unlikely(__ratelimit(state))) \ + rtn = WARN(condition, format); \ + rtn; \ +}) + +#define WARN_RATELIMIT(condition, format...) \ +({ \ + static DEFINE_RATELIMIT_STATE(_rs, \ + DEFAULT_RATELIMIT_INTERVAL, \ + DEFAULT_RATELIMIT_BURST); \ + __WARN_RATELIMIT(condition, &_rs, format); \ +}) + /* * WARN_ON_SMP() is for cases that the warning is either * meaningless for !SMP or may even cause failures. -- cgit v0.10.2 From 6c4a5cb219520c7bc937ee186ca53f03733bd09f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 21 May 2011 07:48:40 +0000 Subject: net: filter: Use WARN_RATELIMIT A mis-configured filter can spam the logs with lots of stack traces. Rate-limit the warnings and add printout of the bogus filter information. Original-patch-by: Ben Greear Signed-off-by: Joe Perches Signed-off-by: David S. Miller diff --git a/net/core/filter.c b/net/core/filter.c index 0eb8c44..0e3622f 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -350,7 +350,9 @@ load_b: continue; } default: - WARN_ON(1); + WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n", + fentry->code, fentry->jt, + fentry->jf, fentry->k); return 0; } } -- cgit v0.10.2 From 6ac3f6649223d916bbdf1e823926f8f3b34b5d99 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 24 May 2011 01:11:51 -0400 Subject: ipv6: Fix return of xfrm6_tunnel_rcv() Like ipv4, just return xfrm6_rcv_spi()'s return value directly. Signed-off-by: David S. Miller diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index a6770a0..4fe1db12 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -241,7 +241,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb) __be32 spi; spi = xfrm6_tunnel_spi_lookup(net, (const xfrm_address_t *)&iph->saddr); - return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi) > 0 ? : 0; + return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi); } static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, -- cgit v0.10.2 From 229de618ba6ff36e382b908b7637fe56c25ae9f1 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 23 May 2011 12:17:09 +0000 Subject: net/irda: convert bfin_sir to common Blackfin UART header No need to duplicate these defines now that the common Blackfin code has unified these for all UART devices. Signed-off-by: Mike Frysinger Cc: Samuel Ortiz Cc: David Miller Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c index f940dfa..9d4ce1a 100644 --- a/drivers/net/irda/bfin_sir.c +++ b/drivers/net/irda/bfin_sir.c @@ -67,27 +67,27 @@ static void bfin_sir_stop_tx(struct bfin_sir_port *port) disable_dma(port->tx_dma_channel); #endif - while (!(SIR_UART_GET_LSR(port) & THRE)) { + while (!(UART_GET_LSR(port) & THRE)) { cpu_relax(); continue; } - SIR_UART_STOP_TX(port); + UART_CLEAR_IER(port, ETBEI); } static void bfin_sir_enable_tx(struct bfin_sir_port *port) { - SIR_UART_ENABLE_TX(port); + UART_SET_IER(port, ETBEI); } static void bfin_sir_stop_rx(struct bfin_sir_port *port) { - SIR_UART_STOP_RX(port); + UART_CLEAR_IER(port, ERBFI); } static void bfin_sir_enable_rx(struct bfin_sir_port *port) { - SIR_UART_ENABLE_RX(port); + UART_SET_IER(port, ERBFI); } static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) @@ -116,7 +116,7 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) do { udelay(utime); - lsr = SIR_UART_GET_LSR(port); + lsr = UART_GET_LSR(port); } while (!(lsr & TEMT) && count--); /* The useconds for 1 bits to transmit */ @@ -125,27 +125,27 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) /* Clear UCEN bit to reset the UART state machine * and control registers */ - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); val &= ~UCEN; - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); /* Set DLAB in LCR to Access THR RBR IER */ - SIR_UART_SET_DLAB(port); + UART_SET_DLAB(port); SSYNC(); - SIR_UART_PUT_DLL(port, quot & 0xFF); - SIR_UART_PUT_DLH(port, (quot >> 8) & 0xFF); + UART_PUT_DLL(port, quot & 0xFF); + UART_PUT_DLH(port, (quot >> 8) & 0xFF); SSYNC(); /* Clear DLAB in LCR */ - SIR_UART_CLEAR_DLAB(port); + UART_CLEAR_DLAB(port); SSYNC(); - SIR_UART_PUT_LCR(port, lcr); + UART_PUT_LCR(port, lcr); - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); val |= UCEN; - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); ret = 0; break; @@ -154,12 +154,12 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) break; } - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); /* If not add the 'RPOLC', we can't catch the receive interrupt. * It's related with the HW layout and the IR transiver. */ val |= IREN | RPOLC; - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); return ret; } @@ -168,7 +168,7 @@ static int bfin_sir_is_receiving(struct net_device *dev) struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_port *port = self->sir_port; - if (!(SIR_UART_GET_IER(port) & ERBFI)) + if (!(UART_GET_IER(port) & ERBFI)) return 0; return self->rx_buff.state != OUTSIDE_FRAME; } @@ -182,7 +182,7 @@ static void bfin_sir_tx_chars(struct net_device *dev) if (self->tx_buff.len != 0) { chr = *(self->tx_buff.data); - SIR_UART_PUT_CHAR(port, chr); + UART_PUT_CHAR(port, chr); self->tx_buff.data++; self->tx_buff.len--; } else { @@ -206,8 +206,8 @@ static void bfin_sir_rx_chars(struct net_device *dev) struct bfin_sir_port *port = self->sir_port; unsigned char ch; - SIR_UART_CLEAR_LSR(port); - ch = SIR_UART_GET_CHAR(port); + UART_CLEAR_LSR(port); + ch = UART_GET_CHAR(port); async_unwrap_char(dev, &self->stats, &self->rx_buff, ch); dev->last_rx = jiffies; } @@ -219,7 +219,7 @@ static irqreturn_t bfin_sir_rx_int(int irq, void *dev_id) struct bfin_sir_port *port = self->sir_port; spin_lock(&self->lock); - while ((SIR_UART_GET_LSR(port) & DR)) + while ((UART_GET_LSR(port) & DR)) bfin_sir_rx_chars(dev); spin_unlock(&self->lock); @@ -233,7 +233,7 @@ static irqreturn_t bfin_sir_tx_int(int irq, void *dev_id) struct bfin_sir_port *port = self->sir_port; spin_lock(&self->lock); - if (SIR_UART_GET_LSR(port) & THRE) + if (UART_GET_LSR(port) & THRE) bfin_sir_tx_chars(dev); spin_unlock(&self->lock); @@ -312,7 +312,7 @@ static void bfin_sir_dma_rx_chars(struct net_device *dev) struct bfin_sir_port *port = self->sir_port; int i; - SIR_UART_CLEAR_LSR(port); + UART_CLEAR_LSR(port); for (i = port->rx_dma_buf.head; i < port->rx_dma_buf.tail; i++) async_unwrap_char(dev, &self->stats, &self->rx_buff, port->rx_dma_buf.buf[i]); @@ -430,11 +430,10 @@ static void bfin_sir_shutdown(struct bfin_sir_port *port, struct net_device *dev unsigned short val; bfin_sir_stop_rx(port); - SIR_UART_DISABLE_INTS(port); - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); val &= ~(UCEN | IREN | RPOLC); - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); #ifdef CONFIG_SIR_BFIN_DMA disable_dma(port->tx_dma_channel); @@ -518,12 +517,12 @@ static void bfin_sir_send_work(struct work_struct *work) * sending data. We also can set the speed, which will * reset all the UART. */ - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); val &= ~(IREN | RPOLC); - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); SSYNC(); val |= IREN | RPOLC; - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); SSYNC(); /* bfin_sir_set_speed(port, self->speed); */ diff --git a/drivers/net/irda/bfin_sir.h b/drivers/net/irda/bfin_sir.h index e3b285a..29cbde8 100644 --- a/drivers/net/irda/bfin_sir.h +++ b/drivers/net/irda/bfin_sir.h @@ -26,7 +26,6 @@ #include #include #include -#include #undef DRIVER_NAME #ifdef CONFIG_SIR_BFIN_DMA @@ -83,64 +82,10 @@ struct bfin_sir_self { #define DRIVER_NAME "bfin_sir" -#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR) -#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL) -#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH) -#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR) -#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL) - -#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v) -#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v) -#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v) -#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v) -#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v) - -#ifdef CONFIG_BF54x -#define SIR_UART_GET_LSR(port) bfin_read16((port)->membase + OFFSET_LSR) -#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER_SET) -#define SIR_UART_SET_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_SET), v) -#define SIR_UART_CLEAR_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_CLEAR), v) -#define SIR_UART_PUT_LSR(port, v) bfin_write16(((port)->membase + OFFSET_LSR), v) -#define SIR_UART_CLEAR_LSR(port) bfin_write16(((port)->membase + OFFSET_LSR), -1) - -#define SIR_UART_SET_DLAB(port) -#define SIR_UART_CLEAR_DLAB(port) - -#define SIR_UART_ENABLE_INTS(port, v) SIR_UART_SET_IER(port, v) -#define SIR_UART_DISABLE_INTS(port) SIR_UART_CLEAR_IER(port, 0xF) -#define SIR_UART_STOP_TX(port) do { SIR_UART_PUT_LSR(port, TFI); SIR_UART_CLEAR_IER(port, ETBEI); } while (0) -#define SIR_UART_ENABLE_TX(port) do { SIR_UART_SET_IER(port, ETBEI); } while (0) -#define SIR_UART_STOP_RX(port) do { SIR_UART_CLEAR_IER(port, ERBFI); } while (0) -#define SIR_UART_ENABLE_RX(port) do { SIR_UART_SET_IER(port, ERBFI); } while (0) -#else - -#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR) -#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER) -#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v) - -#define SIR_UART_SET_DLAB(port) do { SIR_UART_PUT_LCR(port, SIR_UART_GET_LCR(port) | DLAB); } while (0) -#define SIR_UART_CLEAR_DLAB(port) do { SIR_UART_PUT_LCR(port, SIR_UART_GET_LCR(port) & ~DLAB); } while (0) - -#define SIR_UART_ENABLE_INTS(port, v) SIR_UART_PUT_IER(port, v) -#define SIR_UART_DISABLE_INTS(port) SIR_UART_PUT_IER(port, 0) -#define SIR_UART_STOP_TX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) & ~ETBEI); } while (0) -#define SIR_UART_ENABLE_TX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) | ETBEI); } while (0) -#define SIR_UART_STOP_RX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) & ~ERBFI); } while (0) -#define SIR_UART_ENABLE_RX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) | ERBFI); } while (0) - -static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port) -{ - unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR); - port->lsr |= (lsr & (BI|FE|PE|OE)); - return lsr | port->lsr; -} - -static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port) -{ - port->lsr = 0; - bfin_read16(port->membase + OFFSET_LSR); -} -#endif +#define port_membase(port) (((struct bfin_sir_port *)(port))->membase) +#define get_lsr_cache(port) (((struct bfin_sir_port *)(port))->lsr) +#define put_lsr_cache(port, v) (((struct bfin_sir_port *)(port))->lsr = (v)) +#include static const unsigned short per[][4] = { /* rx pin tx pin NULL uart_number */ -- cgit v0.10.2 From 71338aa7d050c86d8765cd36e46be514fb0ebbce Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Mon, 23 May 2011 12:17:35 +0000 Subject: net: convert %p usage to %pK The %pK format specifier is designed to hide exposed kernel pointers, specifically via /proc interfaces. Exposing these pointers provides an easy target for kernel write vulnerabilities, since they reveal the locations of writable structures containing easily triggerable function pointers. The behavior of %pK depends on the kptr_restrict sysctl. If kptr_restrict is set to 0, no deviation from the standard %p behavior occurs. If kptr_restrict is set to 1, the default, if the current user (intended to be a reader via seq_printf(), etc.) does not have CAP_SYSLOG (currently in the LSM tree), kernel pointers using %pK are printed as 0's. If kptr_restrict is set to 2, kernel pointers using %pK are printed as 0's regardless of privileges. Replacing with 0's was chosen over the default "(null)", which cannot be parsed by userland %p, which expects "(nil)". The supporting code for kptr_restrict and %pK are currently in the -mm tree. This patch converts users of %p in net/ to %pK. Cases of printing pointers to the syslog are not covered, since this would eliminate useful information for postmortem debugging and the reading of the syslog is already optionally protected by the dmesg_restrict sysctl. Signed-off-by: Dan Rosenberg Cc: James Morris Cc: Eric Dumazet Cc: Thomas Graf Cc: Eugene Teo Cc: Kees Cook Cc: Ingo Molnar Cc: David S. Miller Cc: Peter Zijlstra Cc: Eric Paris Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/net/atm/proc.c b/net/atm/proc.c index f85da077..be3afde 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -191,7 +191,7 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc) { struct sock *sk = sk_atm(vcc); - seq_printf(seq, "%p ", vcc); + seq_printf(seq, "%pK ", vcc); if (!vcc->dev) seq_printf(seq, "Unassigned "); else @@ -218,7 +218,7 @@ static void svc_info(struct seq_file *seq, struct atm_vcc *vcc) { if (!vcc->dev) seq_printf(seq, sizeof(void *) == 4 ? - "N/A@%p%10s" : "N/A@%p%2s", vcc, ""); + "N/A@%pK%10s" : "N/A@%pK%2s", vcc, ""); else seq_printf(seq, "%3d %3d %5d ", vcc->dev->number, vcc->vpi, vcc->vci); diff --git a/net/can/bcm.c b/net/can/bcm.c index cced806..184a657 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -165,9 +165,9 @@ static int bcm_proc_show(struct seq_file *m, void *v) struct bcm_sock *bo = bcm_sk(sk); struct bcm_op *op; - seq_printf(m, ">>> socket %p", sk->sk_socket); - seq_printf(m, " / sk %p", sk); - seq_printf(m, " / bo %p", bo); + seq_printf(m, ">>> socket %pK", sk->sk_socket); + seq_printf(m, " / sk %pK", sk); + seq_printf(m, " / bo %pK", bo); seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs); seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex)); seq_printf(m, " <<<\n"); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 11e17804..c9893d4 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -979,7 +979,7 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) srcp = inet->inet_num; seq_printf(seq, "%4d: %08X:%04X %08X:%04X" - " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n", + " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", i, src, srcp, dest, destp, sp->sk_state, sk_wmem_alloc_get(sp), sk_rmem_alloc_get(sp), diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3c8d9b6..a7d6671 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2371,7 +2371,7 @@ static void get_openreq4(struct sock *sk, struct request_sock *req, int ttd = req->expires - jiffies; seq_printf(f, "%4d: %08X:%04X %08X:%04X" - " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p%n", + " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %pK%n", i, ireq->loc_addr, ntohs(inet_sk(sk)->inet_sport), @@ -2426,7 +2426,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0); seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " - "%08X %5d %8d %lu %d %p %lu %lu %u %u %d%n", + "%08X %5d %8d %lu %d %pK %lu %lu %u %u %d%n", i, src, srcp, dest, destp, sk->sk_state, tp->write_seq - tp->snd_una, rx_queue, @@ -2461,7 +2461,7 @@ static void get_timewait4_sock(struct inet_timewait_sock *tw, srcp = ntohs(tw->tw_sport); seq_printf(f, "%4d: %08X:%04X %08X:%04X" - " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p%n", + " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK%n", i, src, srcp, dest, destp, tw->tw_substate, 0, 0, 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0, atomic_read(&tw->tw_refcnt), tw, len); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 599374f..abca870 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2090,7 +2090,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, __u16 srcp = ntohs(inet->inet_sport); seq_printf(f, "%5d: %08X:%04X %08X:%04X" - " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d%n", + " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d%n", bucket, src, srcp, dest, destp, sp->sk_state, sk_wmem_alloc_get(sp), sk_rmem_alloc_get(sp), diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ae64984..cc7313b 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -1240,7 +1240,7 @@ static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) srcp = inet_sk(sp)->inet_num; seq_printf(seq, "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n", + "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", i, src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[2], src->s6_addr32[3], srcp, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 8683664..d1fd287 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -2036,7 +2036,7 @@ static void get_openreq6(struct seq_file *seq, seq_printf(seq, "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n", + "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK\n", i, src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[2], src->s6_addr32[3], @@ -2087,7 +2087,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) seq_printf(seq, "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %lu %lu %u %u %d\n", + "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %lu %lu %u %u %d\n", i, src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[2], src->s6_addr32[3], srcp, @@ -2129,7 +2129,7 @@ static void get_timewait6_sock(struct seq_file *seq, seq_printf(seq, "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n", + "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK\n", i, src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[2], src->s6_addr32[3], srcp, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index fc0c42a..41f8c9c 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1391,7 +1391,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket srcp = ntohs(inet->inet_sport); seq_printf(seq, "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n", + "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", bucket, src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[2], src->s6_addr32[3], srcp, diff --git a/net/key/af_key.c b/net/key/af_key.c index d62401c..8f92cf8 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3656,7 +3656,7 @@ static int pfkey_seq_show(struct seq_file *f, void *v) if (v == SEQ_START_TOKEN) seq_printf(f ,"sk RefCnt Rmem Wmem User Inode\n"); else - seq_printf(f ,"%p %-6d %-6u %-6u %-6u %-6lu\n", + seq_printf(f, "%pK %-6d %-6u %-6u %-6u %-6lu\n", s, atomic_read(&s->sk_refcnt), sk_rmem_alloc_get(s), diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 5fe4f3b..6ef64ad 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1985,7 +1985,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v) struct sock *s = v; struct netlink_sock *nlk = nlk_sk(s); - seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d %-8lu\n", + seq_printf(seq, "%pK %-3d %-6d %08x %-8d %-8d %pK %-8d %-8d %-8lu\n", s, s->sk_protocol, nlk->pid, diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 549527b..925f715 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2706,7 +2706,7 @@ static int packet_seq_show(struct seq_file *seq, void *v) const struct packet_sock *po = pkt_sk(s); seq_printf(seq, - "%p %-6d %-4d %04x %-5d %1d %-6u %-6u %-6lu\n", + "%pK %-6d %-4d %04x %-5d %1d %-6u %-6u %-6lu\n", s, atomic_read(&s->sk_refcnt), s->sk_type, diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 8c5bfce..ab07711 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -607,7 +607,7 @@ static int pn_sock_seq_show(struct seq_file *seq, void *v) struct pn_sock *pn = pn_sk(sk); seq_printf(seq, "%2d %04X:%04X:%02X %02X %08X:%08X %5d %lu " - "%d %p %d%n", + "%d %pK %d%n", sk->sk_protocol, pn->sobject, pn->dobject, pn->resource, sk->sk_state, sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk), diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 61aacfb..05a6ce2 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -212,7 +212,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) sctp_for_each_hentry(epb, node, &head->chain) { ep = sctp_ep(epb); sk = epb->sk; - seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, + seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, sctp_sk(sk)->type, sk->sk_state, hash, epb->bind_addr.port, sock_i_uid(sk), sock_i_ino(sk)); @@ -316,7 +316,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) assoc = sctp_assoc(epb); sk = epb->sk; seq_printf(seq, - "%8p %8p %-3d %-3d %-2d %-4d " + "%8pK %8pK %-3d %-3d %-2d %-4d " "%4d %8d %8d %7d %5lu %-5d %5d ", assoc, sk, sctp_sk(sk)->type, sk->sk_state, assoc->state, hash, diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index b1d75be..0722a25 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2254,7 +2254,7 @@ static int unix_seq_show(struct seq_file *seq, void *v) struct unix_sock *u = unix_sk(s); unix_state_lock(s); - seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu", + seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu", s, atomic_read(&s->sk_refcnt), 0, -- cgit v0.10.2 From be3fc413da9eb17cce0991f214ab019d16c88c41 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 23 May 2011 23:07:32 +0000 Subject: net: use synchronize_rcu_expedited() synchronize_rcu() is very slow in various situations (HZ=100, CONFIG_NO_HZ=y, CONFIG_PREEMPT=n) Extract from my (mostly idle) 8 core machine : synchronize_rcu() in 99985 us synchronize_rcu() in 79982 us synchronize_rcu() in 87612 us synchronize_rcu() in 79827 us synchronize_rcu() in 109860 us synchronize_rcu() in 98039 us synchronize_rcu() in 89841 us synchronize_rcu() in 79842 us synchronize_rcu() in 80151 us synchronize_rcu() in 119833 us synchronize_rcu() in 99858 us synchronize_rcu() in 73999 us synchronize_rcu() in 79855 us synchronize_rcu() in 79853 us When we hold RTNL mutex, we would like to spend some cpu cycles but not block too long other processes waiting for this mutex. We also want to setup/dismantle network features as fast as possible at boot/shutdown time. This patch makes synchronize_net() call the expedited version if RTNL is locked. synchronize_rcu_expedited() typical delay is about 20 us on my machine. synchronize_rcu_expedited() in 18 us synchronize_rcu_expedited() in 18 us synchronize_rcu_expedited() in 18 us synchronize_rcu_expedited() in 18 us synchronize_rcu_expedited() in 20 us synchronize_rcu_expedited() in 16 us synchronize_rcu_expedited() in 20 us synchronize_rcu_expedited() in 18 us synchronize_rcu_expedited() in 18 us Signed-off-by: Eric Dumazet CC: Paul E. McKenney CC: Ben Greear Reviewed-by: Paul E. McKenney Signed-off-by: David S. Miller diff --git a/net/core/dev.c b/net/core/dev.c index bcb05cb..ec11d75 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5954,7 +5954,10 @@ EXPORT_SYMBOL(free_netdev); void synchronize_net(void) { might_sleep(); - synchronize_rcu(); + if (rtnl_is_locked()) + synchronize_rcu_expedited(); + else + synchronize_rcu(); } EXPORT_SYMBOL(synchronize_net); -- cgit v0.10.2 From 24cf3af3fed5edcf90bc2a0ed181e6ce1513d2dc Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 23 May 2011 23:15:05 +0000 Subject: igmp: call ip_mc_clear_src() only when we have no users of ip_mc_list In igmp_group_dropped() we call ip_mc_clear_src(), which resets the number of source filters per mulitcast. However, igmp_group_dropped() is also called on NETDEV_DOWN, NETDEV_PRE_TYPE_CHANGE and NETDEV_UNREGISTER, which means that the group might get added back on NETDEV_UP, NETDEV_REGISTER and NETDEV_POST_TYPE_CHANGE respectively, leaving us with broken source filters. To fix that, we must clear the source filters only when there are no users in the ip_mc_list, i.e. in ip_mc_dec_group() and on device destroy. Acked-by: David L Stevens Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 672e476..f1d27f6 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1155,20 +1155,18 @@ static void igmp_group_dropped(struct ip_mc_list *im) if (!in_dev->dead) { if (IGMP_V1_SEEN(in_dev)) - goto done; + return; if (IGMP_V2_SEEN(in_dev)) { if (reporter) igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE); - goto done; + return; } /* IGMPv3 */ igmpv3_add_delrec(in_dev, im); igmp_ifc_event(in_dev); } -done: #endif - ip_mc_clear_src(im); } static void igmp_group_added(struct ip_mc_list *im) @@ -1305,6 +1303,7 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr) *ip = i->next_rcu; in_dev->mc_count--; igmp_group_dropped(i); + ip_mc_clear_src(i); if (!in_dev->dead) ip_rt_multicast_event(in_dev); @@ -1414,7 +1413,8 @@ void ip_mc_destroy_dev(struct in_device *in_dev) in_dev->mc_list = i->next_rcu; in_dev->mc_count--; - igmp_group_dropped(i); + /* We've dropped the groups in ip_mc_down already */ + ip_mc_clear_src(i); ip_ma_put(i); } } -- cgit v0.10.2 From eb722d7a2e11b0426a17acaa7336120acbc49406 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 24 May 2011 02:06:06 +0000 Subject: bnx2x: fix inverted condition Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index d5bd35b..2890443 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -2675,7 +2675,7 @@ alloc_mem_err: * Min size diferent for TPA and non-TPA queues */ if (ring_size < (fp->disable_tpa ? - MIN_RX_SIZE_TPA : MIN_RX_SIZE_NONTPA)) { + MIN_RX_SIZE_NONTPA : MIN_RX_SIZE_TPA)) { /* release memory allocated for this queue */ bnx2x_free_fp_mem_at(bp, index); return -ENOMEM; -- cgit v0.10.2 From 19694ac88d4a73c6f12159d9e53bd636319a69dc Mon Sep 17 00:00:00 2001 From: Alexey Orishko Date: Tue, 24 May 2011 05:26:13 +0000 Subject: CDC NCM: release interfaces fix in unbind() Changes: - claim slave/data interface during bind() and release interfaces in unbind() unconditionally - in case of error during bind(), release claimed data interface in the same function - remove obsolited "*_claimed" entries from driver context Signed-off-by: Alexey Orishko Signed-off-by: David S. Miller diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4ab557d..cdd3ae4 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -54,7 +54,7 @@ #include #include -#define DRIVER_VERSION "06-May-2011" +#define DRIVER_VERSION "24-May-2011" /* CDC NCM subclass 3.2.1 */ #define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10 @@ -134,8 +134,6 @@ struct cdc_ncm_ctx { u16 tx_ndp_modulus; u16 tx_seq; u16 connected; - u8 data_claimed; - u8 control_claimed; }; static void cdc_ncm_tx_timeout(unsigned long arg); @@ -460,17 +458,6 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx) del_timer_sync(&ctx->tx_timer); - if (ctx->data_claimed) { - usb_set_intfdata(ctx->data, NULL); - usb_driver_release_interface(driver_of(ctx->intf), ctx->data); - } - - if (ctx->control_claimed) { - usb_set_intfdata(ctx->control, NULL); - usb_driver_release_interface(driver_of(ctx->intf), - ctx->control); - } - if (ctx->tx_rem_skb != NULL) { dev_kfree_skb_any(ctx->tx_rem_skb); ctx->tx_rem_skb = NULL; @@ -495,7 +482,7 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (ctx == NULL) - goto error; + return -ENODEV; memset(ctx, 0, sizeof(*ctx)); @@ -568,46 +555,36 @@ advance: /* check if we got everything */ if ((ctx->control == NULL) || (ctx->data == NULL) || - (ctx->ether_desc == NULL)) + (ctx->ether_desc == NULL) || (ctx->control != intf)) goto error; /* claim interfaces, if any */ - if (ctx->data != intf) { - temp = usb_driver_claim_interface(driver, ctx->data, dev); - if (temp) - goto error; - ctx->data_claimed = 1; - } - - if (ctx->control != intf) { - temp = usb_driver_claim_interface(driver, ctx->control, dev); - if (temp) - goto error; - ctx->control_claimed = 1; - } + temp = usb_driver_claim_interface(driver, ctx->data, dev); + if (temp) + goto error; iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; /* reset data interface */ temp = usb_set_interface(dev->udev, iface_no, 0); if (temp) - goto error; + goto error2; /* initialize data interface */ if (cdc_ncm_setup(ctx)) - goto error; + goto error2; /* configure data interface */ temp = usb_set_interface(dev->udev, iface_no, 1); if (temp) - goto error; + goto error2; cdc_ncm_find_endpoints(ctx, ctx->data); cdc_ncm_find_endpoints(ctx, ctx->control); if ((ctx->in_ep == NULL) || (ctx->out_ep == NULL) || (ctx->status_ep == NULL)) - goto error; + goto error2; dev->net->ethtool_ops = &cdc_ncm_ethtool_ops; @@ -617,7 +594,7 @@ advance: temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress); if (temp) - goto error; + goto error2; dev_info(&dev->udev->dev, "MAC-Address: " "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", @@ -642,38 +619,38 @@ advance: ctx->tx_speed = ctx->rx_speed = 0; return 0; +error2: + usb_set_intfdata(ctx->control, NULL); + usb_set_intfdata(ctx->data, NULL); + usb_driver_release_interface(driver, ctx->data); error: cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]); dev->data[0] = 0; - dev_info(&dev->udev->dev, "Descriptor failure\n"); + dev_info(&dev->udev->dev, "bind() failure\n"); return -ENODEV; } static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf) { struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; - struct usb_driver *driver; + struct usb_driver *driver = driver_of(intf); if (ctx == NULL) return; /* no setup */ - driver = driver_of(intf); - - usb_set_intfdata(ctx->data, NULL); - usb_set_intfdata(ctx->control, NULL); - usb_set_intfdata(ctx->intf, NULL); - - /* release interfaces, if any */ - if (ctx->data_claimed) { + /* disconnect master --> disconnect slave */ + if (intf == ctx->control && ctx->data) { + usb_set_intfdata(ctx->data, NULL); usb_driver_release_interface(driver, ctx->data); - ctx->data_claimed = 0; - } + ctx->data = NULL; - if (ctx->control_claimed) { + } else if (intf == ctx->data && ctx->control) { + usb_set_intfdata(ctx->control, NULL); usb_driver_release_interface(driver, ctx->control); - ctx->control_claimed = 0; + ctx->control = NULL; } + usb_set_intfdata(ctx->intf, NULL); cdc_ncm_free(ctx); } -- cgit v0.10.2 From b30c516f875004f025f4d10147bde28c5e98466b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 24 May 2011 13:29:50 -0400 Subject: net: fix __dst_destroy_metrics_generic() dst_default_metrics is readonly, we dont want to kfree() it later. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/core/dst.c b/net/core/dst.c index 81a4fa1..9ccca03 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -315,7 +315,7 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old) { unsigned long prev, new; - new = (unsigned long) dst_default_metrics; + new = ((unsigned long) dst_default_metrics) | DST_METRICS_READ_ONLY; prev = cmpxchg(&dst->_metrics, old, new); if (prev == old) kfree(__DST_METRICS_PTR(old)); -- cgit v0.10.2 From 33eb9873a283a2076f2b5628813d5365ca420ea9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 24 May 2011 13:32:18 -0400 Subject: bridge: initialize fake_rtable metrics bridge netfilter code uses a fake_rtable, and we must init its _metric field or risk NULL dereference later. Ref: https://bugzilla.kernel.org/show_bug.cgi?id=35672 Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index e1f5ec7..3fa1231 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -117,6 +117,10 @@ static struct dst_ops fake_dst_ops = { * ipt_REJECT needs it. Future netfilter modules might * require us to fill additional fields. */ +static const u32 br_dst_default_metrics[RTAX_MAX] = { + [RTAX_MTU - 1] = 1500, +}; + void br_netfilter_rtable_init(struct net_bridge *br) { struct rtable *rt = &br->fake_rtable; @@ -124,7 +128,7 @@ void br_netfilter_rtable_init(struct net_bridge *br) atomic_set(&rt->dst.__refcnt, 1); rt->dst.dev = br->dev; rt->dst.path = &rt->dst; - dst_metric_set(&rt->dst, RTAX_MTU, 1500); + dst_init_metrics(&rt->dst, br_dst_default_metrics, true); rt->dst.flags = DST_NOXFRM; rt->dst.ops = &fake_dst_ops; } -- cgit v0.10.2 From 5d8bee676fc9fc9389302baa9ba47bc2ed885f64 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Mon, 23 May 2011 20:29:09 +0000 Subject: be2net: hash key for rss-config cmd not set A non-zero, non-descript value is needed as the hash key. The hash variable was left un-initialized; but sometimes it gets a zero value and hashing is not effective. The constant value used now (not of any significance) seems to work fine. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 2463b1c..81654ae 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1703,7 +1703,8 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size) { struct be_mcc_wrb *wrb; struct be_cmd_req_rss_config *req; - u32 myhash[10]; + u32 myhash[10] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF, + 0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF}; int status; if (mutex_lock_interruptible(&adapter->mbox_lock)) -- cgit v0.10.2 From 1f37070d3ff325827c6213e51b57f21fd5ac9d05 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 24 May 2011 13:50:52 -0400 Subject: dst: catch uninitialized metrics Catch cases where dst_metric_set() and other functions are called but _metrics is NULL. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/include/net/dst.h b/include/net/dst.h index 07a0402..7d15d23 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -111,6 +111,8 @@ static inline u32 *dst_metrics_write_ptr(struct dst_entry *dst) { unsigned long p = dst->_metrics; + BUG_ON(!p); + if (p & DST_METRICS_READ_ONLY) return dst->ops->cow_metrics(dst, p); return __DST_METRICS_PTR(p); -- cgit v0.10.2 From 54a430c0a4991951805df92efb8c42bdb1277ffd Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 20 May 2011 11:56:18 -0700 Subject: iwlagn: dbg_fixed_rate only used when CONFIG_MAC80211_DEBUGFS enabled Fix compiling error when CONFIG_MAC80211_DEBUGFS is not enabled drivers/net/wireless/iwlwifi/iwl-agn-rs.c:351: error: 'struct iwl_lq_sta' has no member named 'dbg_fixed_rate' drivers/net/wireless/iwlwifi/iwl-agn-rs.c:1076: error: 'struct iwl_lq_sta' has no member named 'dbg_fixed_rate' Reported-by: Randy Dunlap Signed-off-by: Wey-Yi Guy Acked-by: Randy Dunlap Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index fec0df0..592b0cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -335,7 +335,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, return tid; } -#if defined(CONFIG_MAC80211_DEBUGFS) || defined(CONFIG_IWLWIFI_DEVICE_SVTOOL) +#ifdef CONFIG_MAC80211_DEBUGFS static void rs_program_fix_rate(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta) { @@ -1072,7 +1072,7 @@ done: /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); -#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL +#ifdef CONFIG_MAC80211_DEBUGFS if (priv->dbg_fixed_rate != lq_sta->dbg_fixed_rate) rs_program_fix_rate(priv, lq_sta); #endif -- cgit v0.10.2 From 1ba0145884de7993c5d4f02d629eb18c17527e6e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 22 May 2011 17:16:20 -0700 Subject: wireless: fix cfg80211.h new kernel-doc warnings Fix new kernel-doc warnings in : Warning(linux-2.6.39-git5/include/net/cfg80211.h:560): No description found for parameter 'bss_param' Warning(linux-2.6.39-git5/include/net/cfg80211.h:1555): Enum value 'WIPHY_FLAG_SUPPORTS_SCHED_SCAN' not described in enum 'wiphy_flags' Signed-off-by: Randy Dunlap Signed-off-by: John W. Linville diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 727131b..0589f55 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -531,6 +531,7 @@ struct sta_bss_parameters { * @tx_retries: cumulative retry counts * @tx_failed: number of failed transmissions (retries exceeded, no ACK) * @rx_dropped_misc: Dropped for un-specified reason. + * @bss_param: current BSS parameters * @generation: generation number for nl80211 dumps. * This number should increase every time the list of stations * changes, i.e. when a station is added or removed, so that @@ -1537,7 +1538,7 @@ struct cfg80211_ops { * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH. - * @WIPHY_FLAG_SCHED_SCAN: The device supports scheduled scans. + * @WIPHY_FLAG_SUPPORTS_SCHED_SCAN: The device supports scheduled scans. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), -- cgit v0.10.2 From daf8cf608d57a0b9f22276036e420cc82cf6ab4f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 22 May 2011 17:22:45 -0700 Subject: wireless: fix fatal kernel-doc error + warning in mac80211.h Fix new kernel-doc Error and Warning in : Error(linux-2.6.39-git5/include/net/mac80211.h:550): cannot understand prototype: 'struct ieee80211_sched_scan_ies ' Warning(linux-2.6.39-git5/include/net/mac80211.h:2289): No description found for parameter 'sta' Signed-off-by: Randy Dunlap Signed-off-by: John W. Linville diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 62a1c22..03067fb 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -538,7 +538,7 @@ struct ieee80211_tx_info { }; /** - * ieee80211_sched_scan_ies - scheduled scan IEs + * struct ieee80211_sched_scan_ies - scheduled scan IEs * * This structure is used to pass the appropriate IEs to be used in scheduled * scans for all bands. It contains both the IEs passed from the userspace @@ -2278,6 +2278,7 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, /** * ieee80211_sta_set_tim - set the TIM bit for a sleeping station + * @sta: &struct ieee80211_sta pointer for the sleeping station * * If a driver buffers frames for a powersave station instead of passing * them back to mac80211 for retransmission, the station needs to be told -- cgit v0.10.2 From 6b3678354647a653e669746c05765f05d2b90239 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 24 May 2011 16:15:41 -0400 Subject: bug.h: Fix build with CONFIG_PRINTK disabled. Based upon an email by Joe Perches. Reported-by: Randy Dunlap Signed-off-by: David S. Miller Acked-by: Randy Dunlap diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 12b250c..9178484 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -162,6 +162,8 @@ extern void warn_slowpath_null(const char *file, const int line); unlikely(__ret_warn_once); \ }) +#ifdef CONFIG_PRINTK + #define WARN_ON_RATELIMIT(condition, state) \ WARN_ON((condition) && __ratelimit(state)) @@ -181,6 +183,25 @@ extern void warn_slowpath_null(const char *file, const int line); __WARN_RATELIMIT(condition, &_rs, format); \ }) +#else + +#define WARN_ON_RATELIMIT(condition, state) \ + WARN_ON(condition) + +#define __WARN_RATELIMIT(condition, state, format...) \ +({ \ + int rtn = WARN(condition, format); \ + rtn; \ +}) + +#define WARN_RATELIMIT(condition, format...) \ +({ \ + int rtn = WARN(condition, format); \ + rtn; \ +}) + +#endif + /* * WARN_ON_SMP() is for cases that the warning is either * meaningless for !SMP or may even cause failures. -- cgit v0.10.2 From 6dcbbe25dcc9bd2bdeb4f685f8fb874ffc10e6be Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 24 May 2011 08:31:08 +0000 Subject: net: move is_vlan_dev into public header file (v2) Migrate is_vlan_dev() to if_vlan.h so that core networkig can use it Signed-off-by: Neil Horman CC: davem@davemloft.net CC: bhutchings@solarflare.com Signed-off-by: David S. Miller diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 290bd8a..dc01681 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -110,6 +110,11 @@ static inline void vlan_group_set_device(struct vlan_group *vg, array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev; } +static inline int is_vlan_dev(struct net_device *dev) +{ + return dev->priv_flags & IFF_802_1Q_VLAN; +} + #define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT) #define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT) diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index c3408de..9da07e3 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -118,11 +118,6 @@ extern void vlan_netlink_fini(void); extern struct rtnl_link_ops vlan_link_ops; -static inline int is_vlan_dev(struct net_device *dev) -{ - return dev->priv_flags & IFF_802_1Q_VLAN; -} - extern int vlan_net_id; struct proc_dir_entry; -- cgit v0.10.2 From f11970e383acd6f505f492f1bc07fb1a4d884829 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 24 May 2011 08:31:09 +0000 Subject: net: make dev_disable_lro use physical device if passed a vlan dev (v2) If the device passed into dev_disable_lro is a vlan, then repoint the dev poniter so that we actually modify the underlying physical device. Signed-of-by: Neil Horman CC: davem@davemloft.net CC: bhutchings@solarflare.com Signed-off-by: David S. Miller diff --git a/net/core/dev.c b/net/core/dev.c index ec11d75..c7e305d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1308,6 +1308,13 @@ void dev_disable_lro(struct net_device *dev) { u32 flags; + /* + * If we're trying to disable lro on a vlan device + * use the underlying physical device instead + */ + if (is_vlan_dev(dev)) + dev = vlan_dev_real_dev(dev); + if (dev->ethtool_ops && dev->ethtool_ops->get_flags) flags = dev->ethtool_ops->get_flags(dev); else -- cgit v0.10.2 From 8b4472cc13136d04727e399c6fdadf58d2218b0a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 24 May 2011 21:48:02 +0000 Subject: sctp: fix memory leak of the ASCONF queue when free asoc If an ASCONF chunk is outstanding, then the following ASCONF chunk will be queued for later transmission. But when we free the asoc, we forget to free the ASCONF queue at the same time, this will cause memory leak. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 1a21c57..525f97c 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -64,6 +64,7 @@ /* Forward declarations for internal functions. */ static void sctp_assoc_bh_rcv(struct work_struct *work); static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc); +static void sctp_assoc_free_asconf_queue(struct sctp_association *asoc); /* Keep track of the new idr low so that we don't re-use association id * numbers too fast. It is protected by they idr spin lock is in the @@ -446,6 +447,9 @@ void sctp_association_free(struct sctp_association *asoc) /* Free any cached ASCONF_ACK chunk. */ sctp_assoc_free_asconf_acks(asoc); + /* Free the ASCONF queue. */ + sctp_assoc_free_asconf_queue(asoc); + /* Free any cached ASCONF chunk. */ if (asoc->addip_last_asconf) sctp_chunk_free(asoc->addip_last_asconf); @@ -1578,6 +1582,18 @@ retry: return error; } +/* Free the ASCONF queue */ +static void sctp_assoc_free_asconf_queue(struct sctp_association *asoc) +{ + struct sctp_chunk *asconf; + struct sctp_chunk *tmp; + + list_for_each_entry_safe(asconf, tmp, &asoc->addip_chunk_list, list) { + list_del_init(&asconf->list); + sctp_chunk_free(asconf); + } +} + /* Free asconf_ack cache */ static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc) { -- cgit v0.10.2 From 1ba37c518f8f83094209396c65a72732b2c1df3b Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 24 May 2011 21:56:02 +0000 Subject: xen: netfront: hold RTNL when updating features. Konrad reports: [ 0.930811] RTNL: assertion failed at /home/konrad/ssd/linux/net/core/dev.c (5258) [ 0.930821] Pid: 22, comm: xenwatch Not tainted 2.6.39-05193-gd762f43 #1 [ 0.930825] Call Trace: [ 0.930834] [] __netdev_update_features+0xae/0xe0 [ 0.930840] [] netdev_update_features+0x11/0x30 [ 0.930847] [] netback_changed+0x4e5/0x800 [xen_netfront] [ 0.930854] [] xenbus_otherend_changed+0xa8/0xb0 [ 0.930860] [] ? _raw_spin_unlock_irqrestore+0x19/0x20 [ 0.930866] [] backend_changed+0xe/0x10 [ 0.930871] [] xenwatch_thread+0xba/0x180 [ 0.930876] [] ? wake_up_bit+0x40/0x40 [ 0.930881] [] ? split+0xf0/0xf0 [ 0.930886] [] kthread+0x96/0xa0 [ 0.930891] [] kernel_thread_helper+0x4/0x10 [ 0.930896] [] ? int_ret_from_sys_call+0x7/0x1b [ 0.930901] [] ? retint_restore_args+0x5/0x6 [ 0.930906] [] ? gs_change+0x13/0x13 This update happens in xenbus watch callback context and hence does not already hold the rtnl. Take the lock as necessary. Signed-off-by: Ian Campbell Tested-by: Konrad Rzeszutek Wilk Signed-off-by: David S. Miller diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index db9a763..d29365a 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1581,7 +1581,9 @@ static int xennet_connect(struct net_device *dev) if (err) return err; + rtnl_lock(); netdev_update_features(dev); + rtnl_unlock(); spin_lock_bh(&np->rx_lock); spin_lock_irq(&np->tx_lock); -- cgit v0.10.2 From d10358de8d70aaeb965a974d56e9b72f6c6dbb3a Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 25 May 2011 01:07:22 +0000 Subject: via-velocity: don't annotate MAC registers as packed On ARM, memory accesses through packed pointers behave in unexpected ways in GCC releases 4.3 and higher; see https://lkml.org/lkml/2011/2/2/163 for discussion. In this particular case, 32-bit I/O registers are accessed bytewise, causing incorrect setting of the DMA address registers which in turn leads to an error interrupt storm that brings the system to a halt. Since the mac_regs structure does not need any packing anyway, this patch simply removes the attribute to fix the issue. Signed-off-by: Ulrich Hecht Signed-off-by: David S. Miller diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index d722753..0f1f05f 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -1096,7 +1096,7 @@ struct mac_regs { volatile __le16 PatternCRC[8]; /* 0xB0 */ volatile __le32 ByteMask[4][4]; /* 0xC0 */ -} __packed; +}; enum hw_mib { -- cgit v0.10.2 From 367bbf2aa1654c12ab5d6dbf4428b043b425be29 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Wed, 25 May 2011 02:12:23 +0000 Subject: isdn: netjet - blacklist Digium TDM400P [2nd try ... 1st attempt didn't make it to netdev mailing list] A quick google search reveals that people with this card are blacklisting it in the initramfs and in the module blacklist based on a statement that it is unsupported. Since the older Digium is also unsupported I'm pretty confident that this newer card is also not supported. lspci -xxx -vv shows 04:07.0 Communication controller: Tiger Jet Network Inc. Tiger3XX Modem/ISDN interface Subsystem: Device b100:0003 P. ----8<---- The Asterisk Voice Card, DIGIUM TDM400P is unsupported by the netjet driver. Blacklist it like the Digium X100P/X101P card. Signed-off-by: Prarit Bhargava Signed-off-by: David S. Miller diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index 54ae71a..db25b6b 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -1072,6 +1072,12 @@ nj_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } + if (pdev->subsystem_vendor == 0xb100 && + pdev->subsystem_device == 0x0003 ) { + pr_notice("Netjet: Digium TDM400P not handled yet\n"); + return -ENODEV; + } + card = kzalloc(sizeof(struct tiger_hw), GFP_ATOMIC); if (!card) { pr_info("No kmem for Netjet\n"); -- cgit v0.10.2 From 07bd8df5df4369487812bf85a237322ff3569b77 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 25 May 2011 04:40:11 +0000 Subject: sch_sfq: fix peek() implementation Since commit eeaeb068f139 (sch_sfq: allow big packets and be fair), sfq_peek() can return a different skb that would be normally dequeued by sfq_dequeue() [ if current slot->allot is negative ] Use generic qdisc_peek_dequeued() instead of custom implementation, to get consistent result. Signed-off-by: Eric Dumazet CC: Jarek Poplawski CC: Patrick McHardy CC: Jesper Dangaard Brouer Signed-off-by: David S. Miller diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index b1d00f8..b6ea6af 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -414,18 +414,6 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) } static struct sk_buff * -sfq_peek(struct Qdisc *sch) -{ - struct sfq_sched_data *q = qdisc_priv(sch); - - /* No active slots */ - if (q->tail == NULL) - return NULL; - - return q->slots[q->tail->next].skblist_next; -} - -static struct sk_buff * sfq_dequeue(struct Qdisc *sch) { struct sfq_sched_data *q = qdisc_priv(sch); @@ -706,7 +694,7 @@ static struct Qdisc_ops sfq_qdisc_ops __read_mostly = { .priv_size = sizeof(struct sfq_sched_data), .enqueue = sfq_enqueue, .dequeue = sfq_dequeue, - .peek = sfq_peek, + .peek = qdisc_peek_dequeued, .drop = sfq_drop, .init = sfq_init, .reset = sfq_reset, -- cgit v0.10.2 From a5971d43ef76f4b73c58e2d893de9db487388c87 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 25 May 2011 04:55:51 +0000 Subject: bnx2x: protect sequence increment with mutex Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index a97d9be..4b70311 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -2222,12 +2222,13 @@ static void bnx2x_pmf_update(struct bnx2x *bp) u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param) { int mb_idx = BP_FW_MB_IDX(bp); - u32 seq = ++bp->fw_seq; + u32 seq; u32 rc = 0; u32 cnt = 1; u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10; mutex_lock(&bp->fw_mb_mutex); + seq = ++bp->fw_seq; SHMEM_WR(bp, func_mb[mb_idx].drv_mb_param, param); SHMEM_WR(bp, func_mb[mb_idx].drv_mb_header, (command | seq)); -- cgit v0.10.2 From 1dcb14d9e874d12bab9ceeba776b742f1682b0a6 Mon Sep 17 00:00:00 2001 From: Meelis Roos Date: Wed, 25 May 2011 05:43:47 +0000 Subject: Add Fujitsu 1000base-SX PCI ID to tg3 This patch adds the PCI ID of Fujitsu 1000base-SX NIC to tg3 driver. Tested to detect the card, MAC and serdes, not tested with link at the moment since I have no fiber switch here. I did not add new constants to the pci_ids.h header file since these constants are used only here. Signed-off-by: Meelis Roos Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index db19332..f4b01c6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -292,6 +292,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100)}, {PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3)}, + {PCI_DEVICE(0x10cf, 0x11a2)}, /* Fujitsu 1000base-SX with BCM5703SKHB */ {} }; -- cgit v0.10.2 From 2907c35ff64708065e5a7fd54e8ded8263eb3074 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 25 May 2011 07:34:04 +0000 Subject: net: hold rtnl again in dump callbacks Commit e67f88dd12f6 (dont hold rtnl mutex during netlink dump callbacks) missed fact that rtnl_fill_ifinfo() must be called with rtnl held. Because of possible deadlocks between two mutexes (cb_mutex and rtnl), its not easy to solve this problem, so revert this part of the patch. It also forgot one rcu_read_unlock() in FIB dump_rules() Add one ASSERT_RTNL() in rtnl_fill_ifinfo() to remind us the rule. Signed-off-by: Eric Dumazet CC: Patrick McHardy CC: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 3911586..008dc70 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -602,6 +602,7 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, skip: idx++; } + rcu_read_unlock(); cb->args[1] = idx; rules_ops_put(ops); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d1644e3..2d56cb9 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -850,6 +850,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, struct nlattr *attr, *af_spec; struct rtnl_af_ops *af_ops; + ASSERT_RTNL(); nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); if (nlh == NULL) return -EMSGSIZE; @@ -1876,6 +1877,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) int min_len; int family; int type; + int err; type = nlh->nlmsg_type; if (type > RTM_MAX) @@ -1902,8 +1904,11 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (dumpit == NULL) return -EOPNOTSUPP; + __rtnl_unlock(); rtnl = net->rtnl; - return netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); + err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); + rtnl_lock(); + return err; } memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); @@ -1975,7 +1980,7 @@ static int __net_init rtnetlink_net_init(struct net *net) { struct sock *sk; sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, - rtnetlink_rcv, NULL, THIS_MODULE); + rtnetlink_rcv, &rtnl_mutex, THIS_MODULE); if (!sk) return -ENOMEM; net->rtnl = sk; -- cgit v0.10.2 From 9fe0617d9b6d21f700ee9e658e1c9fe3be2fb402 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 25 May 2011 08:13:01 +0000 Subject: bonding: prevent deadlock on slave store with alb mode (v3) This soft lockup was recently reported: [root@dell-per715-01 ~]# echo +bond5 > /sys/class/net/bonding_masters [root@dell-per715-01 ~]# echo +eth1 > /sys/class/net/bond5/bonding/slaves bonding: bond5: doing slave updates when interface is down. bonding bond5: master_dev is not up in bond_enslave [root@dell-per715-01 ~]# echo -eth1 > /sys/class/net/bond5/bonding/slaves bonding: bond5: doing slave updates when interface is down. BUG: soft lockup - CPU#12 stuck for 60s! [bash:6444] CPU 12: Modules linked in: bonding autofs4 hidp rfcomm l2cap bluetooth lockd sunrpc be2d Pid: 6444, comm: bash Not tainted 2.6.18-262.el5 #1 RIP: 0010:[] [] .text.lock.spinlock+0x26/00 RSP: 0018:ffff810113167da8 EFLAGS: 00000286 RAX: ffff810113167fd8 RBX: ffff810123a47800 RCX: 0000000000ff1025 RDX: 0000000000000000 RSI: ffff810123a47800 RDI: ffff81021b57f6f8 RBP: ffff81021b57f500 R08: 0000000000000000 R09: 000000000000000c R10: 00000000ffffffff R11: ffff81011d41c000 R12: ffff81021b57f000 R13: 0000000000000000 R14: 0000000000000282 R15: 0000000000000282 FS: 00002b3b41ef3f50(0000) GS:ffff810123b27940(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00002b3b456dd000 CR3: 000000031fc60000 CR4: 00000000000006e0 Call Trace: [] _spin_lock_bh+0x9/0x14 [] :bonding:tlb_clear_slave+0x22/0xa1 [] :bonding:bond_alb_deinit_slave+0xba/0xf0 [] :bonding:bond_release+0x1b4/0x450 [] __down_write_nested+0x12/0x92 [] :bonding:bonding_store_slaves+0x25c/0x2f7 [] sysfs_write_file+0xb9/0xe8 [] vfs_write+0xce/0x174 [] sys_write+0x45/0x6e [] tracesys+0xd5/0xe0 It occurs because we are able to change the slave configuarion of a bond while the bond interface is down. The bonding driver initializes some data structures only after its ndo_open routine is called. Among them is the initalization of the alb tx and rx hash locks. So if we add or remove a slave without first opening the bond master device, we run the risk of trying to lock/unlock a spinlock that has garbage for data in it, which results in our above softlock. Note that sometimes this works, because in many cases an unlocked spinlock has the raw_lock parameter initialized to zero (meaning that the kzalloc of the net_device private data is equivalent to calling spin_lock_init), but thats not true in all cases, and we aren't guaranteed that condition, so we need to pass the relevant spinlocks through the spin_lock_init function. Fix it by moving the spin_lock_init calls for the tx and rx hashtable locks to the ndo_init path, so they are ready for use by the bond_store_slaves path. Change notes: v2) Based on conversation with Jay and Nicolas it seems that the ability to enslave devices while the bond master is down should be safe to do. As such this is an outlier bug, and so instead we'll just initalize the errant spinlocks in the init path rather than the open path, solving the problem. We'll also remove the warnings about the bond being down during enslave operations, since it should be safe v3) Fix spelling error Signed-off-by: Neil Horman Reported-by: jtluka@redhat.com CC: Jay Vosburgh CC: Andy Gospodarek CC: nicolas.2p.debian@gmail.com CC: "David S. Miller" Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 8f2d2e7..2df9276 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -163,8 +163,6 @@ static int tlb_initialize(struct bonding *bond) struct tlb_client_info *new_hashtbl; int i; - spin_lock_init(&(bond_info->tx_hashtbl_lock)); - new_hashtbl = kzalloc(size, GFP_KERNEL); if (!new_hashtbl) { pr_err("%s: Error: Failed to allocate TLB hash table\n", @@ -747,8 +745,6 @@ static int rlb_initialize(struct bonding *bond) int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info); int i; - spin_lock_init(&(bond_info->rx_hashtbl_lock)); - new_hashtbl = kmalloc(size, GFP_KERNEL); if (!new_hashtbl) { pr_err("%s: Error: Failed to allocate RLB hash table\n", diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6dc4284..9ec4a50 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1542,12 +1542,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_dev->name, slave_dev->name); } - /* bond must be initialized by bond_open() before enslaving */ - if (!(bond_dev->flags & IFF_UP)) { - pr_warning("%s: master_dev is not up in bond_enslave\n", - bond_dev->name); - } - /* already enslaved */ if (slave_dev->flags & IFF_SLAVE) { pr_debug("Error, Device was already enslaved\n"); @@ -4834,9 +4828,19 @@ static int bond_init(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id); + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); pr_debug("Begin bond_init for %s\n", bond_dev->name); + /* + * Initialize locks that may be required during + * en/deslave operations. All of the bond_open work + * (of which this is part) should really be moved to + * a phase prior to dev_open + */ + spin_lock_init(&(bond_info->tx_hashtbl_lock)); + spin_lock_init(&(bond_info->rx_hashtbl_lock)); + bond->wq = create_singlethread_workqueue(bond_dev->name); if (!bond->wq) return -ENOMEM; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 4059bfc..bb1319f 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -227,12 +227,6 @@ static ssize_t bonding_store_slaves(struct device *d, struct net_device *dev; struct bonding *bond = to_bond(d); - /* Quick sanity check -- is the bond interface up? */ - if (!(bond->dev->flags & IFF_UP)) { - pr_warning("%s: doing slave updates when interface is down.\n", - bond->dev->name); - } - if (!rtnl_trylock()) return restart_syscall(); -- cgit v0.10.2 From 94265cf5f731c7df29fdfde262ca3e6d51e6828c Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Wed, 25 May 2011 08:38:58 +0000 Subject: bonding: documentation and code cleanup for resend_igmp Improves the documentation about how IGMP resend parameter works, fix two missing checks and coding style issues. Signed-off-by: Flavio Leitner Acked-by: Rick Jones Signed-off-by: David S. Miller diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index 1f45bd8..675612f 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -770,8 +770,17 @@ resend_igmp a failover event. One membership report is issued immediately after the failover, subsequent packets are sent in each 200ms interval. - The valid range is 0 - 255; the default value is 1. This option - was added for bonding version 3.7.0. + The valid range is 0 - 255; the default value is 1. A value of 0 + prevents the IGMP membership report from being issued in response + to the failover event. + + This option is useful for bonding modes balance-rr (0), active-backup + (1), balance-tlb (5) and balance-alb (6), in which a failover can + switch the IGMP traffic from one slave to another. Therefore a fresh + IGMP report must be issued to cause the switch to forward the incoming + IGMP traffic over the newly selected slave. + + This option was added for bonding version 3.7.0. 3. Configuring Bonding Devices ============================== diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 9ec4a50..6141667 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -852,7 +852,7 @@ static void bond_resend_igmp_join_requests(struct bonding *bond) static void bond_resend_igmp_join_requests_delayed(struct work_struct *work) { struct bonding *bond = container_of(work, struct bonding, - mcast_work.work); + mcast_work.work); bond_resend_igmp_join_requests(bond); } @@ -1172,10 +1172,12 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) } /* resend IGMP joins since active slave has changed or - * all were sent on curr_active_slave */ - if (((USES_PRIMARY(bond->params.mode) && new_active) || - bond->params.mode == BOND_MODE_ROUNDROBIN) && - netif_running(bond->dev)) { + * all were sent on curr_active_slave. + * resend only if bond is brought up with the affected + * bonding modes and the retransmission is enabled */ + if (netif_running(bond->dev) && (bond->params.resend_igmp > 0) && + ((USES_PRIMARY(bond->params.mode) && new_active) || + bond->params.mode == BOND_MODE_ROUNDROBIN)) { bond->igmp_retrans = bond->params.resend_igmp; queue_delayed_work(bond->wq, &bond->mcast_work, 0); } diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index bb1319f..88fcb25 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1533,8 +1533,8 @@ static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR, * Show and set the number of IGMP membership reports to send on link failure */ static ssize_t bonding_show_resend_igmp(struct device *d, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { struct bonding *bond = to_bond(d); @@ -1542,8 +1542,8 @@ static ssize_t bonding_show_resend_igmp(struct device *d, } static ssize_t bonding_store_resend_igmp(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { int new_value, ret = count; struct bonding *bond = to_bond(d); @@ -1555,7 +1555,7 @@ static ssize_t bonding_store_resend_igmp(struct device *d, goto out; } - if (new_value < 0) { + if (new_value < 0 || new_value > 255) { pr_err("%s: Invalid resend_igmp value %d not in range 0-255; rejected.\n", bond->dev->name, new_value); ret = -EINVAL; -- cgit v0.10.2