|
@@ -54,7 +54,7 @@
|
|
|
#include "iwl-calib.h"
|
|
|
|
|
|
static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
|
|
|
- struct iwl4965_tx_queue *txq);
|
|
|
+ struct iwl_tx_queue *txq);
|
|
|
|
|
|
/******************************************************************************
|
|
|
*
|
|
@@ -145,6 +145,7 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
|
|
|
return escaped;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
|
|
|
* DMA services
|
|
|
*
|
|
@@ -206,173 +207,6 @@ static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge)
|
|
|
return index & (q->n_window - 1);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes
|
|
|
- */
|
|
|
-static int iwl4965_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q,
|
|
|
- int count, int slots_num, u32 id)
|
|
|
-{
|
|
|
- q->n_bd = count;
|
|
|
- q->n_window = slots_num;
|
|
|
- q->id = id;
|
|
|
-
|
|
|
- /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
|
|
|
- * and iwl_queue_dec_wrap are broken. */
|
|
|
- BUG_ON(!is_power_of_2(count));
|
|
|
-
|
|
|
- /* slots_num must be power-of-two size, otherwise
|
|
|
- * get_cmd_index is broken. */
|
|
|
- BUG_ON(!is_power_of_2(slots_num));
|
|
|
-
|
|
|
- q->low_mark = q->n_window / 4;
|
|
|
- if (q->low_mark < 4)
|
|
|
- q->low_mark = 4;
|
|
|
-
|
|
|
- q->high_mark = q->n_window / 8;
|
|
|
- if (q->high_mark < 2)
|
|
|
- q->high_mark = 2;
|
|
|
-
|
|
|
- q->write_ptr = q->read_ptr = 0;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
|
|
|
- */
|
|
|
-static int iwl4965_tx_queue_alloc(struct iwl_priv *priv,
|
|
|
- struct iwl4965_tx_queue *txq, u32 id)
|
|
|
-{
|
|
|
- struct pci_dev *dev = priv->pci_dev;
|
|
|
-
|
|
|
- /* Driver private data, only for Tx (not command) queues,
|
|
|
- * not shared with device. */
|
|
|
- if (id != IWL_CMD_QUEUE_NUM) {
|
|
|
- txq->txb = kmalloc(sizeof(txq->txb[0]) *
|
|
|
- TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
|
|
|
- if (!txq->txb) {
|
|
|
- IWL_ERROR("kmalloc for auxiliary BD "
|
|
|
- "structures failed\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
- } else
|
|
|
- txq->txb = NULL;
|
|
|
-
|
|
|
- /* Circular buffer of transmit frame descriptors (TFDs),
|
|
|
- * shared with device */
|
|
|
- txq->bd = pci_alloc_consistent(dev,
|
|
|
- sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
|
|
|
- &txq->q.dma_addr);
|
|
|
-
|
|
|
- if (!txq->bd) {
|
|
|
- IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
|
|
|
- sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
|
|
|
- goto error;
|
|
|
- }
|
|
|
- txq->q.id = id;
|
|
|
-
|
|
|
- return 0;
|
|
|
-
|
|
|
- error:
|
|
|
- if (txq->txb) {
|
|
|
- kfree(txq->txb);
|
|
|
- txq->txb = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- return -ENOMEM;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_tx_queue_init - Allocate and initialize one tx/cmd queue
|
|
|
- */
|
|
|
-int iwl4965_tx_queue_init(struct iwl_priv *priv,
|
|
|
- struct iwl4965_tx_queue *txq, int slots_num, u32 txq_id)
|
|
|
-{
|
|
|
- struct pci_dev *dev = priv->pci_dev;
|
|
|
- int len;
|
|
|
- int rc = 0;
|
|
|
-
|
|
|
- /*
|
|
|
- * Alloc buffer array for commands (Tx or other types of commands).
|
|
|
- * For the command queue (#4), 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.
|
|
|
- */
|
|
|
- len = sizeof(struct iwl_cmd) * slots_num;
|
|
|
- if (txq_id == IWL_CMD_QUEUE_NUM)
|
|
|
- len += IWL_MAX_SCAN_SIZE;
|
|
|
- txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
|
|
|
- if (!txq->cmd)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- /* Alloc driver data array and TFD circular buffer */
|
|
|
- rc = iwl4965_tx_queue_alloc(priv, txq, txq_id);
|
|
|
- if (rc) {
|
|
|
- pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
|
|
|
-
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
- txq->need_update = 0;
|
|
|
-
|
|
|
- /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
|
|
|
- * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
|
|
|
- BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
|
|
|
-
|
|
|
- /* Initialize queue's high/low-water marks, and head/tail indexes */
|
|
|
- iwl4965_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
|
|
|
-
|
|
|
- /* Tell device where to find queue */
|
|
|
- iwl4965_hw_tx_queue_init(priv, txq);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_tx_queue_free - Deallocate DMA queue.
|
|
|
- * @txq: Transmit queue to deallocate.
|
|
|
- *
|
|
|
- * Empty queue by removing and destroying all BD's.
|
|
|
- * Free all buffers.
|
|
|
- * 0-fill, but do not free "txq" descriptor structure.
|
|
|
- */
|
|
|
-void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
|
|
|
-{
|
|
|
- struct iwl4965_queue *q = &txq->q;
|
|
|
- struct pci_dev *dev = priv->pci_dev;
|
|
|
- int len;
|
|
|
-
|
|
|
- if (q->n_bd == 0)
|
|
|
- return;
|
|
|
-
|
|
|
- /* first, empty all BD's */
|
|
|
- for (; q->write_ptr != q->read_ptr;
|
|
|
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
|
|
|
- iwl4965_hw_txq_free_tfd(priv, txq);
|
|
|
-
|
|
|
- len = sizeof(struct iwl_cmd) * q->n_window;
|
|
|
- if (q->id == IWL_CMD_QUEUE_NUM)
|
|
|
- len += IWL_MAX_SCAN_SIZE;
|
|
|
-
|
|
|
- /* De-alloc array of command/tx buffers */
|
|
|
- pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
|
|
|
-
|
|
|
- /* De-alloc circular buffer of TFDs */
|
|
|
- if (txq->q.n_bd)
|
|
|
- pci_free_consistent(dev, sizeof(struct iwl4965_tfd_frame) *
|
|
|
- txq->q.n_bd, txq->bd, txq->q.dma_addr);
|
|
|
-
|
|
|
- /* De-alloc array of per-TFD driver data */
|
|
|
- if (txq->txb) {
|
|
|
- kfree(txq->txb);
|
|
|
- txq->txb = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- /* 0-fill queue descriptor structure */
|
|
|
- memset(txq, 0, sizeof(*txq));
|
|
|
-}
|
|
|
-
|
|
|
const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
|
|
|
|
|
/*************** STATION TABLE MANAGEMENT ****
|
|
@@ -433,7 +267,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
|
|
|
{
|
|
|
int i;
|
|
|
int index = IWL_INVALID_STATION;
|
|
|
- struct iwl4965_station_entry *station;
|
|
|
+ struct iwl_station_entry *station;
|
|
|
unsigned long flags_spin;
|
|
|
DECLARE_MAC_BUF(mac);
|
|
|
|
|
@@ -476,7 +310,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
|
|
|
priv->num_stations++;
|
|
|
|
|
|
/* Set up the REPLY_ADD_STA command to send to device */
|
|
|
- memset(&station->sta, 0, sizeof(struct iwl4965_addsta_cmd));
|
|
|
+ memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
|
|
|
memcpy(station->sta.sta.addr, addr, ETH_ALEN);
|
|
|
station->sta.mode = 0;
|
|
|
station->sta.sta.sta_id = index;
|
|
@@ -493,7 +327,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
|
|
|
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
|
|
|
|
|
/* Add station to device's station table */
|
|
|
- iwl4965_send_add_station(priv, &station->sta, flags);
|
|
|
+ iwl_send_add_sta(priv, &station->sta, flags);
|
|
|
return index;
|
|
|
|
|
|
}
|
|
@@ -513,9 +347,9 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
|
|
|
*/
|
|
|
int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
|
|
{
|
|
|
- struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
|
|
|
+ struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
|
|
|
struct iwl4965_queue *q = &txq->q;
|
|
|
- struct iwl4965_tfd_frame *tfd;
|
|
|
+ struct iwl_tfd_frame *tfd;
|
|
|
u32 *control_flags;
|
|
|
struct iwl_cmd *out_cmd;
|
|
|
u32 idx;
|
|
@@ -902,8 +736,8 @@ static int iwl4965_send_bt_config(struct iwl_priv *priv)
|
|
|
|
|
|
static int iwl4965_send_scan_abort(struct iwl_priv *priv)
|
|
|
{
|
|
|
- int rc = 0;
|
|
|
- struct iwl4965_rx_packet *res;
|
|
|
+ int ret = 0;
|
|
|
+ struct iwl_rx_packet *res;
|
|
|
struct iwl_host_cmd cmd = {
|
|
|
.id = REPLY_SCAN_ABORT_CMD,
|
|
|
.meta.flags = CMD_WANT_SKB,
|
|
@@ -917,13 +751,13 @@ static int iwl4965_send_scan_abort(struct iwl_priv *priv)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- rc = iwl_send_cmd_sync(priv, &cmd);
|
|
|
- if (rc) {
|
|
|
+ ret = iwl_send_cmd_sync(priv, &cmd);
|
|
|
+ if (ret) {
|
|
|
clear_bit(STATUS_SCAN_ABORTING, &priv->status);
|
|
|
- return rc;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
- res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
|
|
|
+ res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
|
|
|
if (res->u.status != CAN_ABORT_STATUS) {
|
|
|
/* The scan abort will return 1 for success or
|
|
|
* 2 for "failure". A failure condition can be
|
|
@@ -938,7 +772,7 @@ static int iwl4965_send_scan_abort(struct iwl_priv *priv)
|
|
|
|
|
|
dev_kfree_skb_any(cmd.meta.u.skb);
|
|
|
|
|
|
- return rc;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -963,51 +797,6 @@ static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_fla
|
|
|
return iwl_send_cmd(priv, &cmd);
|
|
|
}
|
|
|
|
|
|
-int iwl4965_send_add_station(struct iwl_priv *priv,
|
|
|
- struct iwl4965_addsta_cmd *sta, u8 flags)
|
|
|
-{
|
|
|
- struct iwl4965_rx_packet *res = NULL;
|
|
|
- int rc = 0;
|
|
|
- struct iwl_host_cmd cmd = {
|
|
|
- .id = REPLY_ADD_STA,
|
|
|
- .len = sizeof(struct iwl4965_addsta_cmd),
|
|
|
- .meta.flags = flags,
|
|
|
- .data = sta,
|
|
|
- };
|
|
|
-
|
|
|
- if (!(flags & CMD_ASYNC))
|
|
|
- cmd.meta.flags |= CMD_WANT_SKB;
|
|
|
-
|
|
|
- rc = iwl_send_cmd(priv, &cmd);
|
|
|
-
|
|
|
- if (rc || (flags & CMD_ASYNC))
|
|
|
- return rc;
|
|
|
-
|
|
|
- res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
|
|
|
- if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
|
|
|
- IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
|
|
|
- res->hdr.flags);
|
|
|
- rc = -EIO;
|
|
|
- }
|
|
|
-
|
|
|
- if (rc == 0) {
|
|
|
- switch (res->u.add_sta.status) {
|
|
|
- case ADD_STA_SUCCESS_MSK:
|
|
|
- IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
|
|
|
- break;
|
|
|
- default:
|
|
|
- rc = -EIO;
|
|
|
- IWL_WARNING("REPLY_ADD_STA failed\n");
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- priv->alloc_rxb_skb--;
|
|
|
- dev_kfree_skb_any(cmd.meta.u.skb);
|
|
|
-
|
|
|
- return rc;
|
|
|
-}
|
|
|
-
|
|
|
static void iwl4965_clear_free_frames(struct iwl_priv *priv)
|
|
|
{
|
|
|
struct list_head *element;
|
|
@@ -1783,7 +1572,7 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
|
|
|
struct sk_buff *skb_frag,
|
|
|
int sta_id)
|
|
|
{
|
|
|
- struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
|
|
|
+ struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
|
|
|
struct iwl_wep_key *wepkey;
|
|
|
int keyidx = 0;
|
|
|
|
|
@@ -1959,7 +1748,7 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv,
|
|
|
IWL_DEBUG_DROP("Station %s not in station map. "
|
|
|
"Defaulting to broadcast...\n",
|
|
|
print_mac(mac, hdr->addr1));
|
|
|
- iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
|
|
|
+ iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
|
|
|
return priv->hw_params.bcast_sta_id;
|
|
|
|
|
|
default:
|
|
@@ -1975,10 +1764,10 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
|
|
|
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
|
|
|
{
|
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
|
|
- struct iwl4965_tfd_frame *tfd;
|
|
|
+ struct iwl_tfd_frame *tfd;
|
|
|
u32 *control_flags;
|
|
|
int txq_id = ctl->queue;
|
|
|
- struct iwl4965_tx_queue *txq = NULL;
|
|
|
+ struct iwl_tx_queue *txq = NULL;
|
|
|
struct iwl4965_queue *q = NULL;
|
|
|
dma_addr_t phys_addr;
|
|
|
dma_addr_t txcmd_phys;
|
|
@@ -2175,10 +1964,10 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
|
|
|
txq->need_update = 0;
|
|
|
}
|
|
|
|
|
|
- iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
|
|
|
+ iwl_print_hex_dump(priv, IWL_DL_TX, out_cmd->cmd.payload,
|
|
|
sizeof(out_cmd->cmd.tx));
|
|
|
|
|
|
- iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
|
|
|
+ iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
|
|
|
ieee80211_get_hdrlen(fc));
|
|
|
|
|
|
/* Set up entry for this TFD in Tx byte-count array */
|
|
@@ -2441,7 +2230,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv,
|
|
|
u8 type)
|
|
|
{
|
|
|
struct iwl4965_spectrum_cmd spectrum;
|
|
|
- struct iwl4965_rx_packet *res;
|
|
|
+ struct iwl_rx_packet *res;
|
|
|
struct iwl_host_cmd cmd = {
|
|
|
.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
|
|
|
.data = (void *)&spectrum,
|
|
@@ -2486,7 +2275,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
|
|
|
+ res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
|
|
|
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
|
|
|
IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
|
|
|
rc = -EIO;
|
|
@@ -2542,7 +2331,7 @@ static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
|
|
|
*/
|
|
|
int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
|
|
|
{
|
|
|
- struct iwl4965_tx_queue *txq = &priv->txq[txq_id];
|
|
|
+ struct iwl_tx_queue *txq = &priv->txq[txq_id];
|
|
|
struct iwl4965_queue *q = &txq->q;
|
|
|
int nfreed = 0;
|
|
|
|
|
@@ -2559,7 +2348,7 @@ int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
|
|
|
if (txq_id != IWL_CMD_QUEUE_NUM) {
|
|
|
iwl4965_txstatus_to_ieee(priv,
|
|
|
&(txq->txb[txq->q.read_ptr]));
|
|
|
- iwl4965_hw_txq_free_tfd(priv, txq);
|
|
|
+ iwl_hw_txq_free_tfd(priv, txq);
|
|
|
} else if (nfreed > 1) {
|
|
|
IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
|
|
|
q->write_ptr, q->read_ptr);
|
|
@@ -2568,12 +2357,6 @@ int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
|
|
|
nfreed++;
|
|
|
}
|
|
|
|
|
|
-/* if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
|
|
|
- (txq_id != IWL_CMD_QUEUE_NUM) &&
|
|
|
- priv->mac80211_registered)
|
|
|
- ieee80211_wake_queue(priv->hw, txq_id); */
|
|
|
-
|
|
|
-
|
|
|
return nfreed;
|
|
|
}
|
|
|
|
|
@@ -2623,7 +2406,7 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
|
|
|
* iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
|
|
|
*/
|
|
|
static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
|
|
|
- struct iwl4965_ht_agg *agg,
|
|
|
+ struct iwl_ht_agg *agg,
|
|
|
struct iwl4965_tx_resp_agg *tx_resp,
|
|
|
u16 start_idx)
|
|
|
{
|
|
@@ -2742,13 +2525,13 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
|
|
|
* iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
|
|
|
*/
|
|
|
static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
|
|
int txq_id = SEQ_TO_QUEUE(sequence);
|
|
|
int index = SEQ_TO_INDEX(sequence);
|
|
|
- struct iwl4965_tx_queue *txq = &priv->txq[txq_id];
|
|
|
+ struct iwl_tx_queue *txq = &priv->txq[txq_id];
|
|
|
struct ieee80211_tx_status *tx_status;
|
|
|
struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
|
|
|
u32 status = le32_to_cpu(tx_resp->status);
|
|
@@ -2781,7 +2564,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|
|
|
|
|
if (txq->sched_retry) {
|
|
|
const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
|
|
|
- struct iwl4965_ht_agg *agg = NULL;
|
|
|
+ struct iwl_ht_agg *agg = NULL;
|
|
|
|
|
|
if (!qc)
|
|
|
return;
|
|
@@ -2797,7 +2580,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|
|
}
|
|
|
|
|
|
if (txq->q.read_ptr != (scd_ssn & 0xff)) {
|
|
|
- int freed;
|
|
|
+ int freed, ampdu_q;
|
|
|
index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
|
|
|
IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
|
|
|
"%d index %d\n", scd_ssn , index);
|
|
@@ -2806,9 +2589,15 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|
|
|
|
|
if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
|
|
|
txq_id >= 0 && priv->mac80211_registered &&
|
|
|
- agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
|
|
|
- ieee80211_wake_queue(priv->hw, txq_id);
|
|
|
-
|
|
|
+ agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
|
|
|
+ /* calculate mac80211 ampdu sw queue to wake */
|
|
|
+ ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID +
|
|
|
+ priv->hw->queues;
|
|
|
+ if (agg->state == IWL_AGG_OFF)
|
|
|
+ ieee80211_wake_queue(priv->hw, txq_id);
|
|
|
+ else
|
|
|
+ ieee80211_wake_queue(priv->hw, ampdu_q);
|
|
|
+ }
|
|
|
iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
|
|
|
}
|
|
|
} else {
|
|
@@ -2827,20 +2616,17 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|
|
tx_resp->failure_frame);
|
|
|
|
|
|
IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
|
|
|
+#ifdef CONFIG_IWL4965_HT
|
|
|
if (index != -1) {
|
|
|
int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
|
|
|
-#ifdef CONFIG_IWL4965_HT
|
|
|
if (tid != MAX_TID_COUNT)
|
|
|
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
|
|
|
if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
|
|
|
- (txq_id >= 0) &&
|
|
|
- priv->mac80211_registered)
|
|
|
+ (txq_id >= 0) && priv->mac80211_registered)
|
|
|
ieee80211_wake_queue(priv->hw, txq_id);
|
|
|
if (tid != MAX_TID_COUNT)
|
|
|
iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
|
|
|
-#endif
|
|
|
}
|
|
|
-#ifdef CONFIG_IWL4965_HT
|
|
|
}
|
|
|
#endif /* CONFIG_IWL4965_HT */
|
|
|
|
|
@@ -2850,9 +2636,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|
|
|
|
|
|
|
|
static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
struct iwl4965_alive_resp *palive;
|
|
|
struct delayed_work *pwork;
|
|
|
|
|
@@ -2886,18 +2672,18 @@ static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
|
|
|
}
|
|
|
|
|
|
static void iwl4965_rx_reply_add_sta(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
|
|
|
IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
static void iwl4965_rx_reply_error(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
|
|
|
IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
|
|
|
"seq 0x%04X ser 0x%08X\n",
|
|
@@ -2910,9 +2696,9 @@ static void iwl4965_rx_reply_error(struct iwl_priv *priv,
|
|
|
|
|
|
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
|
|
|
|
|
|
-static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
struct iwl4965_rxon_cmd *rxon = (void *)&priv->active_rxon;
|
|
|
struct iwl4965_csa_notification *csa = &(pkt->u.csa_notif);
|
|
|
IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
|
|
@@ -2922,15 +2708,15 @@ static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *
|
|
|
}
|
|
|
|
|
|
static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif);
|
|
|
|
|
|
if (!report->state) {
|
|
|
- IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO,
|
|
|
- "Spectrum Measure Notification: Start\n");
|
|
|
+ IWL_DEBUG(IWL_DL_11H,
|
|
|
+ "Spectrum Measure Notification: Start\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -2940,10 +2726,10 @@ static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
|
|
|
}
|
|
|
|
|
|
static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif);
|
|
|
IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
|
|
|
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
|
|
@@ -2951,13 +2737,13 @@ static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
|
|
|
}
|
|
|
|
|
|
static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
|
|
|
"notification for %s:\n",
|
|
|
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
|
|
|
- iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
|
|
|
+ iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
|
|
|
}
|
|
|
|
|
|
static void iwl4965_bg_beacon_update(struct work_struct *work)
|
|
@@ -2986,10 +2772,10 @@ static void iwl4965_bg_beacon_update(struct work_struct *work)
|
|
|
}
|
|
|
|
|
|
static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status);
|
|
|
u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
|
|
|
|
|
@@ -3009,10 +2795,10 @@ static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
|
|
|
|
|
|
/* Service response to REPLY_SCAN_CMD (0x80) */
|
|
|
static void iwl4965_rx_reply_scan(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
struct iwl4965_scanreq_notification *notif =
|
|
|
(struct iwl4965_scanreq_notification *)pkt->u.raw;
|
|
|
|
|
@@ -3022,9 +2808,9 @@ static void iwl4965_rx_reply_scan(struct iwl_priv *priv,
|
|
|
|
|
|
/* Service SCAN_START_NOTIFICATION (0x82) */
|
|
|
static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
struct iwl4965_scanstart_notification *notif =
|
|
|
(struct iwl4965_scanstart_notification *)pkt->u.raw;
|
|
|
priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
|
|
@@ -3039,9 +2825,9 @@ static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv,
|
|
|
|
|
|
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
|
|
|
static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
struct iwl4965_scanresults_notification *notif =
|
|
|
(struct iwl4965_scanresults_notification *)pkt->u.raw;
|
|
|
|
|
@@ -3064,9 +2850,9 @@ static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv,
|
|
|
|
|
|
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
|
|
|
static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
struct iwl4965_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
|
|
|
|
|
|
IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
|
|
@@ -3122,9 +2908,9 @@ reschedule:
|
|
|
/* Handle notification from uCode that card's power state is changing
|
|
|
* due to software, hardware, or critical temperature RFKILL */
|
|
|
static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
|
|
|
unsigned long status = priv->status;
|
|
|
|
|
@@ -3242,9 +3028,9 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
|
|
|
* if the callback returns 1
|
|
|
*/
|
|
|
static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
|
|
|
- struct iwl4965_rx_mem_buffer *rxb)
|
|
|
+ struct iwl_rx_mem_buffer *rxb)
|
|
|
{
|
|
|
- struct iwl4965_rx_packet *pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
|
|
|
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
|
|
int txq_id = SEQ_TO_QUEUE(sequence);
|
|
|
int index = SEQ_TO_INDEX(sequence);
|
|
@@ -3279,438 +3065,28 @@ static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/************************** RX-FUNCTIONS ****************************/
|
|
|
-/*
|
|
|
- * Rx theory of operation
|
|
|
- *
|
|
|
- * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
|
|
|
- * each of which point to Receive Buffers to be filled by 4965. These get
|
|
|
- * used not only for Rx frames, but for any command response or notification
|
|
|
- * from the 4965. The driver and 4965 manage the Rx buffers by means
|
|
|
- * of indexes into the circular buffer.
|
|
|
- *
|
|
|
- * Rx Queue Indexes
|
|
|
- * The host/firmware share two index registers for managing the Rx buffers.
|
|
|
- *
|
|
|
- * The READ index maps to the first position that the firmware may be writing
|
|
|
- * to -- the driver can read up to (but not including) this position and get
|
|
|
- * good data.
|
|
|
- * The READ index is managed by the firmware once the card is enabled.
|
|
|
- *
|
|
|
- * The WRITE index maps to the last position the driver has read from -- the
|
|
|
- * position preceding WRITE is the last slot the firmware can place a packet.
|
|
|
- *
|
|
|
- * The queue is empty (no good data) if WRITE = READ - 1, and is full if
|
|
|
- * WRITE = READ.
|
|
|
- *
|
|
|
- * During initialization, the host sets up the READ queue position to the first
|
|
|
- * INDEX position, and WRITE to the last (READ - 1 wrapped)
|
|
|
- *
|
|
|
- * When the firmware places a packet in a buffer, it will advance the READ index
|
|
|
- * and fire the RX interrupt. The driver can then query the READ index and
|
|
|
- * process as many packets as possible, moving the WRITE index forward as it
|
|
|
- * resets the Rx queue buffers with new memory.
|
|
|
- *
|
|
|
- * The management in the driver is as follows:
|
|
|
- * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
|
|
|
- * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
|
|
|
- * to replenish the iwl->rxq->rx_free.
|
|
|
- * + In iwl4965_rx_replenish (scheduled) if 'processed' != 'read' then the
|
|
|
- * iwl->rxq is replenished and the READ INDEX is updated (updating the
|
|
|
- * 'processed' and 'read' driver indexes as well)
|
|
|
- * + A received packet is processed and handed to the kernel network stack,
|
|
|
- * detached from the iwl->rxq. The driver 'processed' index is updated.
|
|
|
- * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
|
|
|
- * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
|
|
|
- * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there
|
|
|
- * were enough free buffers and RX_STALLED is set it is cleared.
|
|
|
- *
|
|
|
- *
|
|
|
- * Driver sequence:
|
|
|
- *
|
|
|
- * iwl4965_rx_queue_alloc() Allocates rx_free
|
|
|
- * iwl4965_rx_replenish() Replenishes rx_free list from rx_used, and calls
|
|
|
- * iwl4965_rx_queue_restock
|
|
|
- * iwl4965_rx_queue_restock() Moves available buffers from rx_free into Rx
|
|
|
- * queue, updates firmware pointers, and updates
|
|
|
- * the WRITE index. If insufficient rx_free buffers
|
|
|
- * are available, schedules iwl4965_rx_replenish
|
|
|
- *
|
|
|
- * -- enable interrupts --
|
|
|
- * ISR - iwl4965_rx() Detach iwl4965_rx_mem_buffers from pool up to the
|
|
|
- * READ INDEX, detaching the SKB from the pool.
|
|
|
- * Moves the packet buffer from queue to rx_used.
|
|
|
- * Calls iwl4965_rx_queue_restock to refill any empty
|
|
|
- * slots.
|
|
|
- * ...
|
|
|
- *
|
|
|
- */
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_rx_queue_space - Return number of free slots available in queue.
|
|
|
- */
|
|
|
-static int iwl4965_rx_queue_space(const struct iwl4965_rx_queue *q)
|
|
|
-{
|
|
|
- int s = q->read - q->write;
|
|
|
- if (s <= 0)
|
|
|
- s += RX_QUEUE_SIZE;
|
|
|
- /* keep some buffer to not confuse full and empty queue */
|
|
|
- s -= 2;
|
|
|
- if (s < 0)
|
|
|
- s = 0;
|
|
|
- return s;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_rx_queue_update_write_ptr - Update the write pointer for the RX queue
|
|
|
- */
|
|
|
-int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_queue *q)
|
|
|
-{
|
|
|
- u32 reg = 0;
|
|
|
- int rc = 0;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- spin_lock_irqsave(&q->lock, flags);
|
|
|
-
|
|
|
- if (q->need_update == 0)
|
|
|
- goto exit_unlock;
|
|
|
-
|
|
|
- /* If power-saving is in use, make sure device is awake */
|
|
|
- if (test_bit(STATUS_POWER_PMI, &priv->status)) {
|
|
|
- reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
|
|
|
-
|
|
|
- if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
|
|
|
- iwl_set_bit(priv, CSR_GP_CNTRL,
|
|
|
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
|
|
- goto exit_unlock;
|
|
|
- }
|
|
|
-
|
|
|
- rc = iwl_grab_nic_access(priv);
|
|
|
- if (rc)
|
|
|
- goto exit_unlock;
|
|
|
-
|
|
|
- /* Device expects a multiple of 8 */
|
|
|
- iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
|
|
|
- q->write & ~0x7);
|
|
|
- iwl_release_nic_access(priv);
|
|
|
-
|
|
|
- /* Else device is assumed to be awake */
|
|
|
- } else
|
|
|
- /* Device expects a multiple of 8 */
|
|
|
- iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
|
|
|
-
|
|
|
-
|
|
|
- q->need_update = 0;
|
|
|
-
|
|
|
- exit_unlock:
|
|
|
- spin_unlock_irqrestore(&q->lock, flags);
|
|
|
- return rc;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
|
|
|
- */
|
|
|
-static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl_priv *priv,
|
|
|
- dma_addr_t dma_addr)
|
|
|
-{
|
|
|
- return cpu_to_le32((u32)(dma_addr >> 8));
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_rx_queue_restock - refill RX queue from pre-allocated pool
|
|
|
- *
|
|
|
- * If there are slots in the RX queue that need to be restocked,
|
|
|
- * and we have free pre-allocated buffers, fill the ranks as much
|
|
|
- * as we can, pulling from rx_free.
|
|
|
- *
|
|
|
- * This moves the 'write' index forward to catch up with 'processed', and
|
|
|
- * also updates the memory address in the firmware to reference the new
|
|
|
- * target buffer.
|
|
|
- */
|
|
|
-static int iwl4965_rx_queue_restock(struct iwl_priv *priv)
|
|
|
-{
|
|
|
- struct iwl4965_rx_queue *rxq = &priv->rxq;
|
|
|
- struct list_head *element;
|
|
|
- struct iwl4965_rx_mem_buffer *rxb;
|
|
|
- unsigned long flags;
|
|
|
- int write, rc;
|
|
|
-
|
|
|
- spin_lock_irqsave(&rxq->lock, flags);
|
|
|
- write = rxq->write & ~0x7;
|
|
|
- while ((iwl4965_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
|
|
|
- /* Get next free Rx buffer, remove from free list */
|
|
|
- element = rxq->rx_free.next;
|
|
|
- rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list);
|
|
|
- list_del(element);
|
|
|
-
|
|
|
- /* Point to Rx buffer via next RBD in circular buffer */
|
|
|
- rxq->bd[rxq->write] = iwl4965_dma_addr2rbd_ptr(priv, rxb->dma_addr);
|
|
|
- rxq->queue[rxq->write] = rxb;
|
|
|
- rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
|
|
|
- rxq->free_count--;
|
|
|
- }
|
|
|
- spin_unlock_irqrestore(&rxq->lock, flags);
|
|
|
- /* If the pre-allocated buffer pool is dropping low, schedule to
|
|
|
- * refill it */
|
|
|
- if (rxq->free_count <= RX_LOW_WATERMARK)
|
|
|
- queue_work(priv->workqueue, &priv->rx_replenish);
|
|
|
-
|
|
|
-
|
|
|
- /* If we've added more space for the firmware to place data, tell it.
|
|
|
- * Increment device's write pointer in multiples of 8. */
|
|
|
- if ((write != (rxq->write & ~0x7))
|
|
|
- || (abs(rxq->write - rxq->read) > 7)) {
|
|
|
- spin_lock_irqsave(&rxq->lock, flags);
|
|
|
- rxq->need_update = 1;
|
|
|
- spin_unlock_irqrestore(&rxq->lock, flags);
|
|
|
- rc = iwl4965_rx_queue_update_write_ptr(priv, rxq);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_rx_replenish - Move all used packet from rx_used to rx_free
|
|
|
- *
|
|
|
- * When moving to rx_free an SKB is allocated for the slot.
|
|
|
- *
|
|
|
- * Also restock the Rx queue via iwl4965_rx_queue_restock.
|
|
|
- * This is called as a scheduled work item (except for during initialization)
|
|
|
- */
|
|
|
-static void iwl4965_rx_allocate(struct iwl_priv *priv)
|
|
|
-{
|
|
|
- struct iwl4965_rx_queue *rxq = &priv->rxq;
|
|
|
- struct list_head *element;
|
|
|
- struct iwl4965_rx_mem_buffer *rxb;
|
|
|
- unsigned long flags;
|
|
|
- spin_lock_irqsave(&rxq->lock, flags);
|
|
|
- while (!list_empty(&rxq->rx_used)) {
|
|
|
- element = rxq->rx_used.next;
|
|
|
- rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list);
|
|
|
-
|
|
|
- /* Alloc a new receive buffer */
|
|
|
- rxb->skb =
|
|
|
- alloc_skb(priv->hw_params.rx_buf_size,
|
|
|
- __GFP_NOWARN | GFP_ATOMIC);
|
|
|
- if (!rxb->skb) {
|
|
|
- if (net_ratelimit())
|
|
|
- printk(KERN_CRIT DRV_NAME
|
|
|
- ": Can not allocate SKB buffers\n");
|
|
|
- /* We don't reschedule replenish work here -- we will
|
|
|
- * call the restock method and if it still needs
|
|
|
- * more buffers it will schedule replenish */
|
|
|
- break;
|
|
|
- }
|
|
|
- priv->alloc_rxb_skb++;
|
|
|
- list_del(element);
|
|
|
-
|
|
|
- /* Get physical address of RB/SKB */
|
|
|
- rxb->dma_addr =
|
|
|
- pci_map_single(priv->pci_dev, rxb->skb->data,
|
|
|
- priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE);
|
|
|
- list_add_tail(&rxb->list, &rxq->rx_free);
|
|
|
- rxq->free_count++;
|
|
|
- }
|
|
|
- spin_unlock_irqrestore(&rxq->lock, flags);
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* this should be called while priv->lock is locked
|
|
|
*/
|
|
|
-static void __iwl4965_rx_replenish(void *data)
|
|
|
-{
|
|
|
- struct iwl_priv *priv = data;
|
|
|
-
|
|
|
- iwl4965_rx_allocate(priv);
|
|
|
- iwl4965_rx_queue_restock(priv);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-void iwl4965_rx_replenish(void *data)
|
|
|
-{
|
|
|
- struct iwl_priv *priv = data;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- iwl4965_rx_allocate(priv);
|
|
|
-
|
|
|
- spin_lock_irqsave(&priv->lock, flags);
|
|
|
- iwl4965_rx_queue_restock(priv);
|
|
|
- spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
-}
|
|
|
-
|
|
|
-/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
|
|
|
- * If an SKB has been detached, the POOL needs to have its SKB set to NULL
|
|
|
- * This free routine walks the list of POOL entries and if SKB is set to
|
|
|
- * non NULL it is unmapped and freed
|
|
|
- */
|
|
|
-static void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
|
|
|
-{
|
|
|
- int i;
|
|
|
- for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
|
|
|
- if (rxq->pool[i].skb != NULL) {
|
|
|
- pci_unmap_single(priv->pci_dev,
|
|
|
- rxq->pool[i].dma_addr,
|
|
|
- priv->hw_params.rx_buf_size,
|
|
|
- PCI_DMA_FROMDEVICE);
|
|
|
- dev_kfree_skb(rxq->pool[i].skb);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
|
|
|
- rxq->dma_addr);
|
|
|
- rxq->bd = NULL;
|
|
|
-}
|
|
|
-
|
|
|
-int iwl4965_rx_queue_alloc(struct iwl_priv *priv)
|
|
|
+static void __iwl_rx_replenish(struct iwl_priv *priv)
|
|
|
{
|
|
|
- struct iwl4965_rx_queue *rxq = &priv->rxq;
|
|
|
- struct pci_dev *dev = priv->pci_dev;
|
|
|
- int i;
|
|
|
-
|
|
|
- spin_lock_init(&rxq->lock);
|
|
|
- INIT_LIST_HEAD(&rxq->rx_free);
|
|
|
- INIT_LIST_HEAD(&rxq->rx_used);
|
|
|
-
|
|
|
- /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
|
|
|
- rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
|
|
|
- if (!rxq->bd)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- /* Fill the rx_used queue with _all_ of the Rx buffers */
|
|
|
- for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
|
|
|
- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
|
|
|
-
|
|
|
- /* Set us so that we have processed and used all buffers, but have
|
|
|
- * not restocked the Rx queue with fresh buffers */
|
|
|
- rxq->read = rxq->write = 0;
|
|
|
- rxq->free_count = 0;
|
|
|
- rxq->need_update = 0;
|
|
|
- return 0;
|
|
|
+ iwl_rx_allocate(priv);
|
|
|
+ iwl_rx_queue_restock(priv);
|
|
|
}
|
|
|
|
|
|
-void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
|
|
|
-{
|
|
|
- unsigned long flags;
|
|
|
- int i;
|
|
|
- spin_lock_irqsave(&rxq->lock, flags);
|
|
|
- INIT_LIST_HEAD(&rxq->rx_free);
|
|
|
- INIT_LIST_HEAD(&rxq->rx_used);
|
|
|
- /* Fill the rx_used queue with _all_ of the Rx buffers */
|
|
|
- for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
|
|
|
- /* In the reset function, these buffers may have been allocated
|
|
|
- * to an SKB, so we need to unmap and free potential storage */
|
|
|
- if (rxq->pool[i].skb != NULL) {
|
|
|
- pci_unmap_single(priv->pci_dev,
|
|
|
- rxq->pool[i].dma_addr,
|
|
|
- priv->hw_params.rx_buf_size,
|
|
|
- PCI_DMA_FROMDEVICE);
|
|
|
- priv->alloc_rxb_skb--;
|
|
|
- dev_kfree_skb(rxq->pool[i].skb);
|
|
|
- rxq->pool[i].skb = NULL;
|
|
|
- }
|
|
|
- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
|
|
|
- }
|
|
|
-
|
|
|
- /* Set us so that we have processed and used all buffers, but have
|
|
|
- * not restocked the Rx queue with fresh buffers */
|
|
|
- rxq->read = rxq->write = 0;
|
|
|
- rxq->free_count = 0;
|
|
|
- spin_unlock_irqrestore(&rxq->lock, flags);
|
|
|
-}
|
|
|
-
|
|
|
-/* Convert linear signal-to-noise ratio into dB */
|
|
|
-static u8 ratio2dB[100] = {
|
|
|
-/* 0 1 2 3 4 5 6 7 8 9 */
|
|
|
- 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
|
|
|
- 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
|
|
|
- 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
|
|
|
- 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
|
|
|
- 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
|
|
|
- 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
|
|
|
- 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
|
|
|
- 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
|
|
|
- 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
|
|
|
- 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */
|
|
|
-};
|
|
|
-
|
|
|
-/* Calculates a relative dB value from a ratio of linear
|
|
|
- * (i.e. not dB) signal levels.
|
|
|
- * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
|
|
|
-int iwl4965_calc_db_from_ratio(int sig_ratio)
|
|
|
-{
|
|
|
- /* 1000:1 or higher just report as 60 dB */
|
|
|
- if (sig_ratio >= 1000)
|
|
|
- return 60;
|
|
|
-
|
|
|
- /* 100:1 or higher, divide by 10 and use table,
|
|
|
- * add 20 dB to make up for divide by 10 */
|
|
|
- if (sig_ratio >= 100)
|
|
|
- return (20 + (int)ratio2dB[sig_ratio/10]);
|
|
|
-
|
|
|
- /* We shouldn't see this */
|
|
|
- if (sig_ratio < 1)
|
|
|
- return 0;
|
|
|
-
|
|
|
- /* Use table for ratios 1:1 - 99:1 */
|
|
|
- return (int)ratio2dB[sig_ratio];
|
|
|
-}
|
|
|
-
|
|
|
-#define PERFECT_RSSI (-20) /* dBm */
|
|
|
-#define WORST_RSSI (-95) /* dBm */
|
|
|
-#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
|
|
|
-
|
|
|
-/* Calculate an indication of rx signal quality (a percentage, not dBm!).
|
|
|
- * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
|
|
|
- * about formulas used below. */
|
|
|
-int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
|
|
|
-{
|
|
|
- int sig_qual;
|
|
|
- int degradation = PERFECT_RSSI - rssi_dbm;
|
|
|
-
|
|
|
- /* If we get a noise measurement, use signal-to-noise ratio (SNR)
|
|
|
- * as indicator; formula is (signal dbm - noise dbm).
|
|
|
- * SNR at or above 40 is a great signal (100%).
|
|
|
- * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
|
|
|
- * Weakest usable signal is usually 10 - 15 dB SNR. */
|
|
|
- if (noise_dbm) {
|
|
|
- if (rssi_dbm - noise_dbm >= 40)
|
|
|
- return 100;
|
|
|
- else if (rssi_dbm < noise_dbm)
|
|
|
- return 0;
|
|
|
- sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
|
|
|
-
|
|
|
- /* Else use just the signal level.
|
|
|
- * This formula is a least squares fit of data points collected and
|
|
|
- * compared with a reference system that had a percentage (%) display
|
|
|
- * for signal quality. */
|
|
|
- } else
|
|
|
- sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
|
|
|
- (15 * RSSI_RANGE + 62 * degradation)) /
|
|
|
- (RSSI_RANGE * RSSI_RANGE);
|
|
|
-
|
|
|
- if (sig_qual > 100)
|
|
|
- sig_qual = 100;
|
|
|
- else if (sig_qual < 1)
|
|
|
- sig_qual = 0;
|
|
|
-
|
|
|
- return sig_qual;
|
|
|
-}
|
|
|
|
|
|
/**
|
|
|
- * iwl4965_rx_handle - Main entry function for receiving responses from uCode
|
|
|
+ * iwl_rx_handle - Main entry function for receiving responses from uCode
|
|
|
*
|
|
|
* Uses the priv->rx_handlers callback function array to invoke
|
|
|
* the appropriate handlers, including command responses,
|
|
|
* frame-received notifications, and other notifications.
|
|
|
*/
|
|
|
-static void iwl4965_rx_handle(struct iwl_priv *priv)
|
|
|
+void iwl_rx_handle(struct iwl_priv *priv)
|
|
|
{
|
|
|
- struct iwl4965_rx_mem_buffer *rxb;
|
|
|
- struct iwl4965_rx_packet *pkt;
|
|
|
- struct iwl4965_rx_queue *rxq = &priv->rxq;
|
|
|
+ struct iwl_rx_mem_buffer *rxb;
|
|
|
+ struct iwl_rx_packet *pkt;
|
|
|
+ struct iwl_rx_queue *rxq = &priv->rxq;
|
|
|
u32 r, i;
|
|
|
int reclaim;
|
|
|
unsigned long flags;
|
|
@@ -3719,14 +3095,14 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
|
|
|
|
|
|
/* uCode's read index (stored in shared DRAM) indicates the last Rx
|
|
|
* buffer that the driver may process (last buffer filled by ucode). */
|
|
|
- r = iwl4965_hw_get_rx_read(priv);
|
|
|
+ r = priv->cfg->ops->lib->shared_mem_rx_idx(priv);
|
|
|
i = rxq->read;
|
|
|
|
|
|
/* Rx interrupt, but nothing sent from uCode */
|
|
|
if (i == r)
|
|
|
- IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
|
|
|
+ IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d\n", r, i);
|
|
|
|
|
|
- if (iwl4965_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
|
|
|
+ if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
|
|
|
fill_rx = 1;
|
|
|
|
|
|
while (i != r) {
|
|
@@ -3742,7 +3118,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
|
|
|
pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
|
|
|
priv->hw_params.rx_buf_size,
|
|
|
PCI_DMA_FROMDEVICE);
|
|
|
- pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
|
|
|
+ pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
|
|
|
|
|
/* Reclaim a command buffer only if this packet is a response
|
|
|
* to a (driver-originated) command.
|
|
@@ -3761,13 +3137,12 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
|
|
|
* handle those that need handling via function in
|
|
|
* rx_handlers table. See iwl4965_setup_rx_handlers() */
|
|
|
if (priv->rx_handlers[pkt->hdr.cmd]) {
|
|
|
- IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
|
|
|
- "r = %d, i = %d, %s, 0x%02x\n", r, i,
|
|
|
- get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
|
|
|
+ IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d, %s, 0x%02x\n", r,
|
|
|
+ i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
|
|
|
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
|
|
|
} else {
|
|
|
/* No handling needed */
|
|
|
- IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
|
|
|
+ IWL_DEBUG(IWL_DL_RX,
|
|
|
"r %d i %d No handler needed for %s, 0x%02x\n",
|
|
|
r, i, get_cmd_string(pkt->hdr.cmd),
|
|
|
pkt->hdr.cmd);
|
|
@@ -3805,7 +3180,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
|
|
|
count++;
|
|
|
if (count >= 8) {
|
|
|
priv->rxq.read = i;
|
|
|
- __iwl4965_rx_replenish(priv);
|
|
|
+ __iwl_rx_replenish(priv);
|
|
|
count = 0;
|
|
|
}
|
|
|
}
|
|
@@ -3813,14 +3188,91 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
|
|
|
|
|
|
/* Backtrack one entry */
|
|
|
priv->rxq.read = i;
|
|
|
- iwl4965_rx_queue_restock(priv);
|
|
|
+ iwl_rx_queue_restock(priv);
|
|
|
+}
|
|
|
+/* Convert linear signal-to-noise ratio into dB */
|
|
|
+static u8 ratio2dB[100] = {
|
|
|
+/* 0 1 2 3 4 5 6 7 8 9 */
|
|
|
+ 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
|
|
|
+ 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
|
|
|
+ 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
|
|
|
+ 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
|
|
|
+ 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
|
|
|
+ 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
|
|
|
+ 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
|
|
|
+ 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
|
|
|
+ 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
|
|
|
+ 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */
|
|
|
+};
|
|
|
+
|
|
|
+/* Calculates a relative dB value from a ratio of linear
|
|
|
+ * (i.e. not dB) signal levels.
|
|
|
+ * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
|
|
|
+int iwl4965_calc_db_from_ratio(int sig_ratio)
|
|
|
+{
|
|
|
+ /* 1000:1 or higher just report as 60 dB */
|
|
|
+ if (sig_ratio >= 1000)
|
|
|
+ return 60;
|
|
|
+
|
|
|
+ /* 100:1 or higher, divide by 10 and use table,
|
|
|
+ * add 20 dB to make up for divide by 10 */
|
|
|
+ if (sig_ratio >= 100)
|
|
|
+ return (20 + (int)ratio2dB[sig_ratio/10]);
|
|
|
+
|
|
|
+ /* We shouldn't see this */
|
|
|
+ if (sig_ratio < 1)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Use table for ratios 1:1 - 99:1 */
|
|
|
+ return (int)ratio2dB[sig_ratio];
|
|
|
+}
|
|
|
+
|
|
|
+#define PERFECT_RSSI (-20) /* dBm */
|
|
|
+#define WORST_RSSI (-95) /* dBm */
|
|
|
+#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
|
|
|
+
|
|
|
+/* Calculate an indication of rx signal quality (a percentage, not dBm!).
|
|
|
+ * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
|
|
|
+ * about formulas used below. */
|
|
|
+int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
|
|
|
+{
|
|
|
+ int sig_qual;
|
|
|
+ int degradation = PERFECT_RSSI - rssi_dbm;
|
|
|
+
|
|
|
+ /* If we get a noise measurement, use signal-to-noise ratio (SNR)
|
|
|
+ * as indicator; formula is (signal dbm - noise dbm).
|
|
|
+ * SNR at or above 40 is a great signal (100%).
|
|
|
+ * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
|
|
|
+ * Weakest usable signal is usually 10 - 15 dB SNR. */
|
|
|
+ if (noise_dbm) {
|
|
|
+ if (rssi_dbm - noise_dbm >= 40)
|
|
|
+ return 100;
|
|
|
+ else if (rssi_dbm < noise_dbm)
|
|
|
+ return 0;
|
|
|
+ sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
|
|
|
+
|
|
|
+ /* Else use just the signal level.
|
|
|
+ * This formula is a least squares fit of data points collected and
|
|
|
+ * compared with a reference system that had a percentage (%) display
|
|
|
+ * for signal quality. */
|
|
|
+ } else
|
|
|
+ sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
|
|
|
+ (15 * RSSI_RANGE + 62 * degradation)) /
|
|
|
+ (RSSI_RANGE * RSSI_RANGE);
|
|
|
+
|
|
|
+ if (sig_qual > 100)
|
|
|
+ sig_qual = 100;
|
|
|
+ else if (sig_qual < 1)
|
|
|
+ sig_qual = 0;
|
|
|
+
|
|
|
+ return sig_qual;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* iwl4965_tx_queue_update_write_ptr - Send new write index to hardware
|
|
|
*/
|
|
|
static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
|
|
|
- struct iwl4965_tx_queue *txq)
|
|
|
+ struct iwl_tx_queue *txq)
|
|
|
{
|
|
|
u32 reg = 0;
|
|
|
int rc = 0;
|
|
@@ -3863,12 +3315,13 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
-static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon)
|
|
|
+static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
|
|
|
{
|
|
|
+ struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
|
|
|
DECLARE_MAC_BUF(mac);
|
|
|
|
|
|
IWL_DEBUG_RADIO("RX CONFIG:\n");
|
|
|
- iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
|
|
|
+ iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
|
|
|
IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
|
|
|
IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
|
|
|
IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
|
|
@@ -4094,10 +3547,10 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
|
|
|
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
|
|
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- if (iwl_debug_level & IWL_DL_FW_ERRORS) {
|
|
|
+ if (priv->debug_level & IWL_DL_FW_ERRORS) {
|
|
|
iwl4965_dump_nic_error_log(priv);
|
|
|
iwl4965_dump_nic_event_log(priv);
|
|
|
- iwl4965_print_rx_config_cmd(&priv->staging_rxon);
|
|
|
+ iwl4965_print_rx_config_cmd(priv);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -4108,7 +3561,7 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
|
|
|
clear_bit(STATUS_READY, &priv->status);
|
|
|
|
|
|
if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
|
|
|
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
|
|
|
+ IWL_DEBUG(IWL_DL_FW_ERRORS,
|
|
|
"Restarting adapter due to uCode error.\n");
|
|
|
|
|
|
if (iwl_is_associated(priv)) {
|
|
@@ -4116,7 +3569,8 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
|
|
|
sizeof(priv->recovery_rxon));
|
|
|
priv->error_recovering = 1;
|
|
|
}
|
|
|
- queue_work(priv->workqueue, &priv->restart);
|
|
|
+ if (priv->cfg->mod_params->restart_fw)
|
|
|
+ queue_work(priv->workqueue, &priv->restart);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -4161,7 +3615,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
|
|
|
iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
|
|
|
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- if (iwl_debug_level & IWL_DL_ISR) {
|
|
|
+ if (priv->debug_level & IWL_DL_ISR) {
|
|
|
/* just for debug */
|
|
|
inta_mask = iwl_read32(priv, CSR_INT_MASK);
|
|
|
IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
|
|
@@ -4195,7 +3649,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- if (iwl_debug_level & (IWL_DL_ISR)) {
|
|
|
+ if (priv->debug_level & (IWL_DL_ISR)) {
|
|
|
/* NIC fires this, but we don't use it, redundant with WAKEUP */
|
|
|
if (inta & CSR_INT_BIT_SCD)
|
|
|
IWL_DEBUG_ISR("Scheduler finished to transmit "
|
|
@@ -4216,8 +3670,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
|
|
|
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
|
|
|
hw_rf_kill = 1;
|
|
|
|
|
|
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR,
|
|
|
- "RF_KILL bit toggled to %s.\n",
|
|
|
+ IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n",
|
|
|
hw_rf_kill ? "disable radio":"enable radio");
|
|
|
|
|
|
/* Queue restart only if RF_KILL switch was set to "kill"
|
|
@@ -4249,7 +3702,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
|
|
|
/* uCode wakes up after power-down sleep */
|
|
|
if (inta & CSR_INT_BIT_WAKEUP) {
|
|
|
IWL_DEBUG_ISR("Wakeup interrupt\n");
|
|
|
- iwl4965_rx_queue_update_write_ptr(priv, &priv->rxq);
|
|
|
+ iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
|
|
|
iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[0]);
|
|
|
iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[1]);
|
|
|
iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[2]);
|
|
@@ -4264,7 +3717,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
|
|
|
* Rx "responses" (frame-received notification), and other
|
|
|
* notifications from uCode come through here*/
|
|
|
if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
|
|
|
- iwl4965_rx_handle(priv);
|
|
|
+ iwl_rx_handle(priv);
|
|
|
handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
|
|
|
}
|
|
|
|
|
@@ -4288,7 +3741,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
|
|
|
iwl4965_enable_interrupts(priv);
|
|
|
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- if (iwl_debug_level & (IWL_DL_ISR)) {
|
|
|
+ if (priv->debug_level & (IWL_DL_ISR)) {
|
|
|
inta = iwl_read32(priv, CSR_INT);
|
|
|
inta_mask = iwl_read32(priv, CSR_INT_MASK);
|
|
|
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
|
|
@@ -4708,105 +4161,6 @@ static int iwl4965_read_ucode(struct iwl_priv *priv)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_set_ucode_ptrs - Set uCode address location
|
|
|
- *
|
|
|
- * Tell initialization uCode where to find runtime uCode.
|
|
|
- *
|
|
|
- * BSM registers initially contain pointers to initialization uCode.
|
|
|
- * We need to replace them to load runtime uCode inst and data,
|
|
|
- * and to save runtime data when powering down.
|
|
|
- */
|
|
|
-static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
|
|
|
-{
|
|
|
- dma_addr_t pinst;
|
|
|
- dma_addr_t pdata;
|
|
|
- int rc = 0;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- /* bits 35:4 for 4965 */
|
|
|
- pinst = priv->ucode_code.p_addr >> 4;
|
|
|
- pdata = priv->ucode_data_backup.p_addr >> 4;
|
|
|
-
|
|
|
- spin_lock_irqsave(&priv->lock, flags);
|
|
|
- rc = iwl_grab_nic_access(priv);
|
|
|
- if (rc) {
|
|
|
- spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
- return rc;
|
|
|
- }
|
|
|
-
|
|
|
- /* Tell bootstrap uCode where to find image to load */
|
|
|
- iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
|
|
|
- iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
|
|
|
- iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
|
|
|
- priv->ucode_data.len);
|
|
|
-
|
|
|
- /* Inst bytecount must be last to set up, bit 31 signals uCode
|
|
|
- * that all new ptr/size info is in place */
|
|
|
- iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
|
|
|
- priv->ucode_code.len | BSM_DRAM_INST_LOAD);
|
|
|
-
|
|
|
- iwl_release_nic_access(priv);
|
|
|
-
|
|
|
- spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
-
|
|
|
- IWL_DEBUG_INFO("Runtime uCode pointers are set.\n");
|
|
|
-
|
|
|
- return rc;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
|
|
|
- *
|
|
|
- * Called after REPLY_ALIVE notification received from "initialize" uCode.
|
|
|
- *
|
|
|
- * The 4965 "initialize" ALIVE reply contains calibration data for:
|
|
|
- * Voltage, temperature, and MIMO tx gain correction, now stored in priv
|
|
|
- * (3945 does not contain this data).
|
|
|
- *
|
|
|
- * Tell "initialize" uCode to go ahead and load the runtime uCode.
|
|
|
-*/
|
|
|
-static void iwl4965_init_alive_start(struct iwl_priv *priv)
|
|
|
-{
|
|
|
- /* Check alive response for "valid" sign from uCode */
|
|
|
- if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
|
|
|
- /* We had an error bringing up the hardware, so take it
|
|
|
- * all the way back down so we can try again */
|
|
|
- IWL_DEBUG_INFO("Initialize Alive failed.\n");
|
|
|
- goto restart;
|
|
|
- }
|
|
|
-
|
|
|
- /* Bootstrap uCode has loaded initialize uCode ... verify inst image.
|
|
|
- * This is a paranoid check, because we would not have gotten the
|
|
|
- * "initialize" alive if code weren't properly loaded. */
|
|
|
- if (iwl_verify_ucode(priv)) {
|
|
|
- /* Runtime instruction load was bad;
|
|
|
- * take it all the way back down so we can try again */
|
|
|
- IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
|
|
|
- goto restart;
|
|
|
- }
|
|
|
-
|
|
|
- /* Calculate temperature */
|
|
|
- priv->temperature = iwl4965_get_temperature(priv);
|
|
|
-
|
|
|
- /* Send pointers to protocol/runtime uCode image ... init code will
|
|
|
- * load and launch runtime uCode, which will send us another "Alive"
|
|
|
- * notification. */
|
|
|
- IWL_DEBUG_INFO("Initialization Alive received.\n");
|
|
|
- if (iwl4965_set_ucode_ptrs(priv)) {
|
|
|
- /* Runtime instruction load won't happen;
|
|
|
- * take it all the way back down so we can try again */
|
|
|
- IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n");
|
|
|
- goto restart;
|
|
|
- }
|
|
|
- return;
|
|
|
-
|
|
|
- restart:
|
|
|
- queue_work(priv->workqueue, &priv->restart);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* iwl4965_alive_start - called after REPLY_ALIVE notification received
|
|
|
* from protocol/runtime uCode (initialization uCode's
|
|
@@ -5056,7 +4410,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- ret = priv->cfg->ops->lib->hw_nic_init(priv);
|
|
|
+ ret = iwl_hw_nic_init(priv);
|
|
|
if (ret) {
|
|
|
IWL_ERROR("Unable to init nic\n");
|
|
|
return ret;
|
|
@@ -5132,7 +4486,7 @@ static void iwl4965_bg_init_alive_start(struct work_struct *data)
|
|
|
return;
|
|
|
|
|
|
mutex_lock(&priv->mutex);
|
|
|
- iwl4965_init_alive_start(priv);
|
|
|
+ priv->cfg->ops->lib->init_alive_start(priv);
|
|
|
mutex_unlock(&priv->mutex);
|
|
|
}
|
|
|
|
|
@@ -5161,7 +4515,7 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
|
|
|
mutex_lock(&priv->mutex);
|
|
|
|
|
|
if (!iwl_is_rfkill(priv)) {
|
|
|
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
|
|
|
+ IWL_DEBUG(IWL_DL_RF_KILL,
|
|
|
"HW and/or SW RF Kill no longer active, restarting "
|
|
|
"device\n");
|
|
|
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
|
|
@@ -5184,6 +4538,24 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
|
|
|
mutex_unlock(&priv->mutex);
|
|
|
}
|
|
|
|
|
|
+static void iwl4965_bg_set_monitor(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct iwl_priv *priv = container_of(work,
|
|
|
+ struct iwl_priv, set_monitor);
|
|
|
+
|
|
|
+ IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");
|
|
|
+
|
|
|
+ mutex_lock(&priv->mutex);
|
|
|
+
|
|
|
+ if (!iwl_is_ready(priv))
|
|
|
+ IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
|
|
|
+ else
|
|
|
+ if (iwl4965_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0)
|
|
|
+ IWL_ERROR("iwl4965_set_mode() failed\n");
|
|
|
+
|
|
|
+ mutex_unlock(&priv->mutex);
|
|
|
+}
|
|
|
+
|
|
|
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
|
|
|
|
|
|
static void iwl4965_bg_scan_check(struct work_struct *data)
|
|
@@ -5197,9 +4569,9 @@ static void iwl4965_bg_scan_check(struct work_struct *data)
|
|
|
mutex_lock(&priv->mutex);
|
|
|
if (test_bit(STATUS_SCANNING, &priv->status) ||
|
|
|
test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
|
|
|
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN,
|
|
|
- "Scan completion watchdog resetting adapter (%dms)\n",
|
|
|
- jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
|
|
|
+ IWL_DEBUG(IWL_DL_SCAN, "Scan completion watchdog resetting "
|
|
|
+ "adapter (%dms)\n",
|
|
|
+ jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
|
|
|
|
|
|
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
|
|
|
iwl4965_send_scan_abort(priv);
|
|
@@ -5453,7 +4825,7 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data)
|
|
|
return;
|
|
|
|
|
|
mutex_lock(&priv->mutex);
|
|
|
- iwl4965_rx_replenish(priv);
|
|
|
+ iwl_rx_replenish(priv);
|
|
|
mutex_unlock(&priv->mutex);
|
|
|
}
|
|
|
|
|
@@ -5501,7 +4873,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
|
|
|
|
|
|
#ifdef CONFIG_IWL4965_HT
|
|
|
if (priv->current_ht_config.is_ht)
|
|
|
- iwl4965_set_rxon_ht(priv, &priv->current_ht_config);
|
|
|
+ iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
|
|
#endif /* CONFIG_IWL4965_HT*/
|
|
|
iwl_set_rxon_chain(priv);
|
|
|
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
|
|
@@ -5600,7 +4972,7 @@ static void iwl4965_bg_scan_completed(struct work_struct *work)
|
|
|
struct iwl_priv *priv =
|
|
|
container_of(work, struct iwl_priv, scan_completed);
|
|
|
|
|
|
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
|
|
|
+ IWL_DEBUG(IWL_DL_SCAN, "SCAN complete scan\n");
|
|
|
|
|
|
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
|
|
return;
|
|
@@ -6073,7 +5445,22 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw,
|
|
|
* XXX: dummy
|
|
|
* see also iwl4965_connection_init_rx_config
|
|
|
*/
|
|
|
- *total_flags = 0;
|
|
|
+ struct iwl_priv *priv = hw->priv;
|
|
|
+ int new_flags = 0;
|
|
|
+ if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
|
|
|
+ if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
|
|
|
+ IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
|
|
|
+ IEEE80211_IF_TYPE_MNTR,
|
|
|
+ changed_flags, *total_flags);
|
|
|
+ /* queue work 'cuz mac80211 is holding a lock which
|
|
|
+ * prevents us from issuing (synchronous) f/w cmds */
|
|
|
+ queue_work(priv->workqueue, &priv->set_monitor);
|
|
|
+ new_flags &= FIF_PROMISC_IN_BSS |
|
|
|
+ FIF_OTHER_BSS |
|
|
|
+ FIF_ALLMULTI;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ *total_flags = new_flags;
|
|
|
}
|
|
|
|
|
|
static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
|
|
@@ -6261,7 +5648,7 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
|
|
|
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
|
|
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
|
|
|
|
|
- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
|
|
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
|
|
|
|
|
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
|
|
|
|
@@ -6395,7 +5782,7 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
|
|
|
{
|
|
|
struct iwl_priv *priv = hw->priv;
|
|
|
int i, avail;
|
|
|
- struct iwl4965_tx_queue *txq;
|
|
|
+ struct iwl_tx_queue *txq;
|
|
|
struct iwl4965_queue *q;
|
|
|
unsigned long flags;
|
|
|
|
|
@@ -6428,6 +5815,9 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
|
|
|
static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
|
|
|
struct ieee80211_low_level_stats *stats)
|
|
|
{
|
|
|
+ struct iwl_priv *priv = hw->priv;
|
|
|
+
|
|
|
+ priv = hw->priv;
|
|
|
IWL_DEBUG_MAC80211("enter\n");
|
|
|
IWL_DEBUG_MAC80211("leave\n");
|
|
|
|
|
@@ -6436,6 +5826,9 @@ static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
|
|
|
|
|
|
static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw)
|
|
|
{
|
|
|
+ struct iwl_priv *priv;
|
|
|
+
|
|
|
+ priv = hw->priv;
|
|
|
IWL_DEBUG_MAC80211("enter\n");
|
|
|
IWL_DEBUG_MAC80211("leave\n");
|
|
|
|
|
@@ -6569,13 +5962,18 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
|
|
|
* See the level definitions in iwl for details.
|
|
|
*/
|
|
|
|
|
|
-static ssize_t show_debug_level(struct device_driver *d, char *buf)
|
|
|
+static ssize_t show_debug_level(struct device *d,
|
|
|
+ struct device_attribute *attr, char *buf)
|
|
|
{
|
|
|
- return sprintf(buf, "0x%08X\n", iwl_debug_level);
|
|
|
+ struct iwl_priv *priv = d->driver_data;
|
|
|
+
|
|
|
+ return sprintf(buf, "0x%08X\n", priv->debug_level);
|
|
|
}
|
|
|
-static ssize_t store_debug_level(struct device_driver *d,
|
|
|
+static ssize_t store_debug_level(struct device *d,
|
|
|
+ struct device_attribute *attr,
|
|
|
const char *buf, size_t count)
|
|
|
{
|
|
|
+ struct iwl_priv *priv = d->driver_data;
|
|
|
char *p = (char *)buf;
|
|
|
u32 val;
|
|
|
|
|
@@ -6584,17 +5982,37 @@ static ssize_t store_debug_level(struct device_driver *d,
|
|
|
printk(KERN_INFO DRV_NAME
|
|
|
": %s is not in hex or decimal form.\n", buf);
|
|
|
else
|
|
|
- iwl_debug_level = val;
|
|
|
+ priv->debug_level = val;
|
|
|
|
|
|
return strnlen(buf, count);
|
|
|
}
|
|
|
|
|
|
-static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
|
|
- show_debug_level, store_debug_level);
|
|
|
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
|
|
+ show_debug_level, store_debug_level);
|
|
|
+
|
|
|
|
|
|
#endif /* CONFIG_IWLWIFI_DEBUG */
|
|
|
|
|
|
|
|
|
+static ssize_t show_version(struct device *d,
|
|
|
+ struct device_attribute *attr, char *buf)
|
|
|
+{
|
|
|
+ struct iwl_priv *priv = d->driver_data;
|
|
|
+ struct iwl4965_alive_resp *palive = &priv->card_alive;
|
|
|
+
|
|
|
+ if (palive->is_valid)
|
|
|
+ return sprintf(buf, "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
|
|
|
+ "fw type: 0x%01X 0x%01X\n",
|
|
|
+ palive->ucode_major, palive->ucode_minor,
|
|
|
+ palive->sw_rev[0], palive->sw_rev[1],
|
|
|
+ palive->ver_type, palive->ver_subtype);
|
|
|
+
|
|
|
+ else
|
|
|
+ return sprintf(buf, "fw not loaded\n");
|
|
|
+}
|
|
|
+
|
|
|
+static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL);
|
|
|
+
|
|
|
static ssize_t show_temperature(struct device *d,
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
{
|
|
@@ -6998,6 +6416,7 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
|
|
|
INIT_WORK(&priv->abort_scan, iwl4965_bg_abort_scan);
|
|
|
INIT_WORK(&priv->rf_kill, iwl4965_bg_rf_kill);
|
|
|
INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
|
|
|
+ INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
|
|
|
INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate);
|
|
|
INIT_DELAYED_WORK(&priv->init_alive_start, iwl4965_bg_init_alive_start);
|
|
|
INIT_DELAYED_WORK(&priv->alive_start, iwl4965_bg_alive_start);
|
|
@@ -7036,6 +6455,10 @@ static struct attribute *iwl4965_sysfs_entries[] = {
|
|
|
&dev_attr_status.attr,
|
|
|
&dev_attr_temperature.attr,
|
|
|
&dev_attr_tx_power.attr,
|
|
|
+#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
+ &dev_attr_debug_level.attr,
|
|
|
+#endif
|
|
|
+ &dev_attr_version.attr,
|
|
|
|
|
|
NULL
|
|
|
};
|
|
@@ -7085,7 +6508,9 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|
|
/* Disabling hardware scan means that mac80211 will perform scans
|
|
|
* "the hard way", rather than using device's scan. */
|
|
|
if (cfg->mod_params->disable_hw_scan) {
|
|
|
- IWL_DEBUG_INFO("Disabling hw_scan\n");
|
|
|
+ if (cfg->mod_params->debug & IWL_DL_INFO)
|
|
|
+ dev_printk(KERN_DEBUG, &(pdev->dev),
|
|
|
+ "Disabling hw_scan\n");
|
|
|
iwl4965_hw_ops.hw_scan = NULL;
|
|
|
}
|
|
|
|
|
@@ -7104,7 +6529,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|
|
priv->pci_dev = pdev;
|
|
|
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- iwl_debug_level = priv->cfg->mod_params->debug;
|
|
|
+ priv->debug_level = priv->cfg->mod_params->debug;
|
|
|
atomic_set(&priv->restrict_refcnt, 0);
|
|
|
#endif
|
|
|
|
|
@@ -7310,8 +6735,8 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
|
|
|
iwl4965_dealloc_ucode_pci(priv);
|
|
|
|
|
|
if (priv->rxq.bd)
|
|
|
- iwl4965_rx_queue_free(priv, &priv->rxq);
|
|
|
- iwl4965_hw_txq_ctx_free(priv);
|
|
|
+ iwl_rx_queue_free(priv, &priv->rxq);
|
|
|
+ iwl_hw_txq_ctx_free(priv);
|
|
|
|
|
|
iwlcore_clear_stations_table(priv);
|
|
|
iwl_eeprom_free(priv);
|
|
@@ -7420,18 +6845,11 @@ static int __init iwl4965_init(void)
|
|
|
IWL_ERROR("Unable to initialize PCI module\n");
|
|
|
goto error_register;
|
|
|
}
|
|
|
-#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
|
|
|
- if (ret) {
|
|
|
- IWL_ERROR("Unable to create driver sysfs file\n");
|
|
|
- goto error_debug;
|
|
|
- }
|
|
|
-#endif
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
+
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
-error_debug:
|
|
|
pci_unregister_driver(&iwl_driver);
|
|
|
#endif
|
|
|
error_register:
|
|
@@ -7441,9 +6859,6 @@ error_register:
|
|
|
|
|
|
static void __exit iwl4965_exit(void)
|
|
|
{
|
|
|
-#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
- driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
|
|
|
-#endif
|
|
|
pci_unregister_driver(&iwl_driver);
|
|
|
iwl4965_rate_control_unregister();
|
|
|
}
|