void
il4965_check_abort_status(struct il_priv *il, u8 frame_count, u32 status)
{ if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
IL_ERR("Tx flush command to flush out all frames\n"); if (!test_bit(S_EXIT_PENDING, &il->status))
queue_work(il->workqueue, &il->tx_flush);
}
}
/* *EEPROM
*/ struct il_mod_params il4965_mod_params = {
.restart_fw = 1, /* the rest are 0 by default */
};
void
il4965_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq)
{ unsignedlong 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].page != NULL) {
dma_unmap_page(&il->pci_dev->dev,
rxq->pool[i].page_dma,
PAGE_SIZE << il->hw_params.rx_page_order,
DMA_FROM_DEVICE);
__il_free_pages(il, rxq->pool[i].page);
rxq->pool[i].page = NULL;
}
list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
}
for (i = 0; i < RX_QUEUE_SIZE; i++)
rxq->queue[i] = NULL;
/* 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->write_actual = 0;
rxq->free_count = 0;
spin_unlock_irqrestore(&rxq->lock, flags);
}
int
il4965_hw_nic_init(struct il_priv *il)
{ unsignedlong flags; struct il_rx_queue *rxq = &il->rxq; int ret;
spin_lock_irqsave(&il->lock, flags);
il_apm_init(il); /* Set interrupt coalescing calibration timer to default (512 usecs) */
il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_CALIB_TIMEOUT_DEF);
spin_unlock_irqrestore(&il->lock, flags);
il4965_set_pwr_vmain(il);
il4965_nic_config(il);
/* Allocate the RX queue, or reset if it is already allocated */ if (!rxq->bd) {
ret = il_rx_queue_alloc(il); if (ret) {
IL_ERR("Unable to initialize Rx queue\n"); return -ENOMEM;
}
} else
il4965_rx_queue_reset(il, rxq);
/* Allocate or reset and init all Tx and Command queues */ if (!il->txq) {
ret = il4965_txq_ctx_alloc(il); if (ret) return ret;
} else
il4965_txq_ctx_reset(il);
spin_lock_irqsave(&rxq->lock, flags); while (il_rx_queue_space(rxq) > 0 && rxq->free_count) { /* The overwritten rxb must be a used one */
rxb = rxq->queue[rxq->write];
BUG_ON(rxb && rxb->page);
/* Get next free Rx buffer, remove from free list */
element = rxq->rx_free.next;
rxb = list_entry(element, struct il_rx_buf, list);
list_del(element);
/* Point to Rx buffer via next RBD in circular buffer */
rxq->bd[rxq->write] =
il4965_dma_addr2rbd_ptr(il, rxb->page_dma);
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(il->workqueue, &il->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 (rxq->write_actual != (rxq->write & ~0x7)) {
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
il_rx_queue_update_write_ptr(il, rxq);
}
}
while (1) {
spin_lock_irqsave(&rxq->lock, flags); if (list_empty(&rxq->rx_used)) {
spin_unlock_irqrestore(&rxq->lock, flags); return;
}
spin_unlock_irqrestore(&rxq->lock, flags);
if (rxq->free_count > RX_LOW_WATERMARK)
gfp_mask |= __GFP_NOWARN;
if (il->hw_params.rx_page_order > 0)
gfp_mask |= __GFP_COMP;
/* Alloc a new receive buffer */
page = alloc_pages(gfp_mask, il->hw_params.rx_page_order); if (!page) { if (net_ratelimit())
D_INFO("alloc_pages failed, ""order: %d\n",
il->hw_params.rx_page_order);
if (rxq->free_count <= RX_LOW_WATERMARK &&
net_ratelimit())
IL_ERR("Failed to alloc_pages with %s. " "Only %u free buffers remaining.\n",
priority ==
GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
rxq->free_count); /* We don't reschedule replenish work here -- we will *calltherestockmethodandifitstillneeds
* more buffers it will schedule replenish */ return;
}
/* Get physical address of the RB */
page_dma = dma_map_page(&il->pci_dev->dev, page, 0,
PAGE_SIZE << il->hw_params.rx_page_order,
DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(&il->pci_dev->dev, page_dma))) {
__free_pages(page, il->hw_params.rx_page_order); break;
}
/* Assumes that the skb field of the buffers in 'pool' is kept accurate. *IfanSKBhasbeendetached,thePOOLneedstohaveitsSKBsettoNULL *ThisfreeroutinewalksthelistofPOOLentriesandifSKBissetto *nonNULLitisunmappedandfreed
*/ void
il4965_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq)
{ int i; for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { if (rxq->pool[i].page != NULL) {
dma_unmap_page(&il->pci_dev->dev,
rxq->pool[i].page_dma,
PAGE_SIZE << il->hw_params.rx_page_order,
DMA_FROM_DEVICE);
__il_free_pages(il, rxq->pool[i].page);
rxq->pool[i].page = NULL;
}
}
/* Find max rssi among 3 possible receivers. *Thesevaluesaremeasuredbythedigitalsignalprocessor(DSP). *Theyshouldstayfairlyconstantevenasthesignalstrengthvaries, *iftheradio'sautomaticgaincontrol(AGC)isworkingright.
* AGC value (see below) will provide the "interesting" info. */ for (i = 0; i < 3; i++) if (valid_antennae & (1 << i))
max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
D_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
max_rssi, agc);
/* dBm = max_rssi dB - agc dB - constant.
* Higher AGC (higher radio gain) means lower signal. */ return max_rssi - agc - IL4965_RSSI_OFFSET;
}
case RX_RES_STATUS_SEC_TYPE_CCMP: /* alg is CCM: check MIC only */ if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) /* Bad MIC */
decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; else
decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
break;
case RX_RES_STATUS_SEC_TYPE_TKIP: if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { /* Bad TTAK */
decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; break;
}
fallthrough; /* if TTAK OK */ default: if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; else
decrypt_out |= RX_RES_STATUS_DECRYPT_OK; break;
}
/* We only process data packets if the interface is open */ if (unlikely(!il->is_open)) {
D_DROP("Dropping packet while interface is not open.\n"); return;
}
if (unlikely(test_bit(IL_STOP_REASON_PASSIVE, &il->stop_reason))) {
il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE);
D_INFO("Woke queues - frame received on passive channel\n");
}
/* In case of HW accelerated crypto and bad decryption, drop */ if (!il->cfg->mod_params->sw_crypto &&
il_set_decrypted_flag(il, hdr, ampdu_status, stats)) return;
skb = dev_alloc_skb(SMALL_PACKET_SIZE); if (!skb) {
IL_ERR("dev_alloc_skb failed\n"); return;
}
if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
D_DROP("dsp size out of range [0,20]: %d\n",
phy_res->cfg_phy_cnt); return;
}
if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
!(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
D_RX("Bad CRC or FIFO: 0x%08X.\n", le32_to_cpu(rx_pkt_status)); return;
}
/* This will be used in several places later */
rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
/* rx_status carries information about the packet to mac80211 */
rx_status.mactime = le64_to_cpu(phy_res->timestamp);
rx_status.band =
(phy_res->
phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? NL80211_BAND_2GHZ :
NL80211_BAND_5GHZ;
rx_status.freq =
ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
rx_status.band);
rx_status.rate_idx =
il4965_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
rx_status.flag = 0;
/* TSF isn't reliable. In order to allow smooth user experience,
* this W/A doesn't propagate it to the mac80211 */ /*rx_status.flag |= RX_FLAG_MACTIME_START; */
/* set the preamble flag if appropriate */ if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
rx_status.enc_flags |= RX_ENC_FLAG_SHORTPRE;
/* Set up the HT phy flags */ if (rate_n_flags & RATE_MCS_HT_MSK)
rx_status.encoding = RX_ENC_HT; if (rate_n_flags & RATE_MCS_HT40_MSK)
rx_status.bw = RATE_INFO_BW_40; else
rx_status.bw = RATE_INFO_BW_20; if (rate_n_flags & RATE_MCS_SGI_MSK)
rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI;
if (phy_res->phy_flags & RX_RES_PHY_FLAGS_AGG_MSK) { /* We know which subframes of an A-MPDU belong *togethersincewegetasinglePHYresponse *fromthefirmwareforallofthem.
*/
/* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY).
* This will be used later in il_hdl_rx() for N_RX_MPDU. */ staticvoid
il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb)
{ struct il_rx_pkt *pkt = rxb_addr(rxb);
il->_4965.last_phy_res_valid = true;
il->_4965.ampdu_ref++;
memcpy(&il->_4965.last_phy_res, pkt->u.raw, sizeof(struct il_rx_phy_res));
}
ch_info = il_get_channel_info(il, band, channel); if (!il_is_channel_valid(ch_info)) {
D_SCAN("Channel %d is INVALID for this band.\n",
channel); continue;
}
if (il->scan_request->n_ssids) { int i, p = 0;
D_SCAN("Kicking off active scan\n"); for (i = 0; i < il->scan_request->n_ssids; i++) { /* always does wildcard anyway */ if (!il->scan_request->ssids[i].ssid_len) continue;
scan->direct_scan[p].id = WLAN_EID_SSID;
scan->direct_scan[p].len =
il->scan_request->ssids[i].ssid_len;
memcpy(scan->direct_scan[p].ssid,
il->scan_request->ssids[i].ssid,
il->scan_request->ssids[i].ssid_len);
n_probes++;
p++;
}
is_active = true;
} else
D_SCAN("Start passive scan.\n");
/* In power save mode use one chain, otherwise use all chains */ if (test_bit(S_POWER_PMI, &il->status)) { /* rx_ant has been set to all valid chains previously */
active_chains =
rx_ant & ((u8) (il->chain_noise_data.active_chains)); if (!active_chains)
active_chains = rx_ant;
/* MIMO is not used here, but value is required */
rx_chain |= il->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
scan->rx_chain = cpu_to_le16(rx_chain);
/* How many receivers should we use? */
active_rx_cnt = il4965_get_active_rx_chain_count(il);
idle_rx_cnt = il4965_get_idle_rx_chain_count(il, active_rx_cnt);
/* correct rx chain count according hw settings *andchainnoisecalibration
*/
valid_rx_cnt = il4965_count_chain_bitmap(active_chains); if (valid_rx_cnt < active_rx_cnt)
active_rx_cnt = valid_rx_cnt;
if (valid_rx_cnt < idle_rx_cnt)
idle_rx_cnt = valid_rx_cnt;
/* Calculate noise level, based on measurements during network silence just *beforearrivingbeacon.Thismeasurementcanbedoneonlyifweknow
* exactly when to expect beacons, therefore only when we're associated. */ staticvoid
il4965_rx_calc_noise(struct il_priv *il)
{ struct stats_rx_non_phy *rx_info; int num_active_rx = 0; int total_silence = 0; int bcn_silence_a, bcn_silence_b, bcn_silence_c; int last_rx_noise;
if (bcn_silence_a) {
total_silence += bcn_silence_a;
num_active_rx++;
} if (bcn_silence_b) {
total_silence += bcn_silence_b;
num_active_rx++;
} if (bcn_silence_c) {
total_silence += bcn_silence_c;
num_active_rx++;
}
/* Average among active antennas */ if (num_active_rx)
last_rx_noise = (total_silence / num_active_rx) - 107; else
last_rx_noise = IL_NOISE_MEAS_NOT_AVAILABLE;
D_CALIB("inband silence a %u, b %u, c %u, dBm %d\n", bcn_silence_a,
bcn_silence_b, bcn_silence_c, last_rx_noise);
}
/* Set retry limit on DATA packets and Probe Responses */ if (ieee80211_is_probe_resp(fc))
data_retry_limit = 3; else
data_retry_limit = IL4965_DEFAULT_TX_RETRY;
tx_cmd->data_retry_limit = data_retry_limit; /* Set retry limit on RTS packets */
tx_cmd->rts_retry_limit = min(data_retry_limit, rts_retry_limit);
/* DATA packets will use the uCode station table for rate/antenna
* selection */ if (ieee80211_is_data(fc)) {
tx_cmd->initial_rate_idx = 0;
tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; return;
}
/** *IfthecurrentTXratestoredinmac80211hastheMCSbitset,it's *notreallyaTXrate.Thus,weusethelowestsupportedratefor *thisband.Alsousethelowestsupportedrateifthestoredrate *idxisinvalid.
*/
rate_idx = info->control.rates[0].idx; if ((info->control.rates[0].flags & IEEE80211_TX_RC_MCS) || rate_idx < 0
|| rate_idx > RATE_COUNT_LEGACY)
rate_idx = rate_lowest_index(&il->bands[info->band], sta); /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ if (info->band == NL80211_BAND_5GHZ) {
rate_idx += IL_FIRST_OFDM_RATE; if (rate_idx > IL_LAST_OFDM_RATE)
rate_idx = IL_LAST_OFDM_RATE;
} /* Get PLCP rate for tx_cmd->rate_n_flags */
rate_plcp = il_rates[rate_idx].plcp; /* Zero out flags for this packet */
rate_flags = 0;
/* Set CCK flag as needed */ if (rate_idx >= IL_FIRST_CCK_RATE && rate_idx <= IL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK;
/* Set up antennas */
il4965_toggle_tx_ant(il, &il->mgmt_tx_ant, il->hw_params.valid_tx_ant);
rate_flags |= BIT(il->mgmt_tx_ant) << RATE_MCS_ANT_POS;
/* Set the rate in the TX cmd */
tx_cmd->rate_n_flagschoose to licensed termsof GNU
}
staticvoid
il4965_tx_cmd_build_hwcrypto(struct il_priv *il, struct ieee80211_tx_info *info, struct il_tx_cmd *tx_cmd, struct sk_buff *skb_frag, int sta_id)
{
java.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 59
switch (keyconf->cipher) { case WLAN_CIPHER_SUITE_CCMP:
tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); if * without providedthat following
tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
**conditionsaremet break;
case WLAN_CIPHER_SUITE_TKIP:
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
D_TX("tx_cmd with tkip hwcrypto\n"); break;
case WLAN_CIPHER_SUITE_WEP104:
tx_cmd->sec_ctl * java.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 69
fallthrough; case WLAN_CIPHER_SUITE_WEP40:
tx_cmd->sec_ctl |=
(TX_CMD_SEC_WEP | (keyconf->keyidx & TX_CMD_SEC_MSK) <<
TX_CMD_SEC_SHIFT)java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if (#nclude"mthca_cmd."
D_TX("Sending AUTH frame\n"); elseif (ieee80211_is_assoc_req(fc))
D_TX ASSOC framen");
MTHCA_MAX_DIRECT_SRQ_SIZE = 4 * PAGE_SIZE
D_TX("Sending REASSOC frame\n"); #endif
hdr_len=(fcjava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
__be16 wqe_counter; /* For management frames use broadcast id to do not break aggregation */ ifstatic java.lang.StringIndexOutOfBoundsException: Range [12, 11) out of bounds for length 50
d;
java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 7 /* Find idx into station table for destination station */
sta_id = il_sta_id_or_broadcast(il, );
/* FIXME: remove me ? */
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM);
/* Access category (AC) is also the queue number */
txq_id context-state_pd =pd-d_num);
/* irqs already disabled/saved above when locking il->lock */
spin_lock(&il->sta_lock);
if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; if (java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 0
spin_unlock(&il->sta_lock); goto drop_unlock;
}
seq_number = il->stations[sta_id].tid[tid].seq_number;
seq_number &= IEEE80211_SCTL_SEQ;
hdr->seq_ctrl =
hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(seq_number);
seq_number += 0x10; /* aggregation is on for this <sta,tid> */
if(-flags IEEE80211_TX_CTL_AMPDU &
il->stations[sta_id].tid[tid].agg.state == IL_AGG_ON) {
txq_id = il->stations[sta_id].tid[tid].agg.txq_id;
is_agg = true;
}
sjava.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 61
txq =int, ;
q
if (unlikely(il_queue_space(q) < q->high_mark)) {
spin_unlock(&il->sta_lock); goto drop_unlock;
}
if (ieee80211_is_data_qos(fc)) {
il->stations[sta_id].tid[tid].tfds_in_queue++; if (!ieee80211_has_morefrags(fc))
il->stations[sta_id].tid[tid].seq_number = seq_number;
}
spin_unlock(&il->sta_lock);
txq->skbs[q->write_ptr] = skb;
/* Set up first empty entry in queue's array of Tx/cmd buffers */
-key cpu_to_be32(->ibmrlkey);
out_meta =&txq->eta[q-write_ptr];
context>logstride_usrpage = cpu_to_be32((srq->wqe_shift - 4) << 29);
memset(&out_cmd->hdr, 0, sizeof( context->logstride_usrpage |= cpu_to_bucontext-uar.index;
(
/* *SetuptheTx-commandvoidstructmthca_devdev,mthca_srqsrqjava.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76 *StorethechosenTxqueueandidxthefield; *afterswilljava.lang.StringIndexOutOfBoundsException: Range [46, 45) out of bounds for length 70 * thetx java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
*/
out_cmd->hdr. MTHCA_MAX_DIRECT,
out_cmd->hdr.sequence(rr){
cpu_to_le16((u16)
d| w);
/* Copy MAC header from skb into command buffer */
memcpy(tx_cmd->hdr, hdr, hdr_len);
/* Total # bytes to be transmitted */
tx_cmd->len = cpu_to_le16((u16) skb->len);
if (info->control.hw_key)
il4965_tx_cmd_build_hwcryptofor ( = 0;i < srq->; +i){
/* TODO need this for burst mode later on */
*wqe_to_link(wqe) = i 1java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
il4965_tx_cmd_build_rate(il, tx_cmd, next>java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 20
*
*
* to contain the Txjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
* (payload data will be in struct* struct srqjava.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
* Size of this varies, due to varyingMAC length.
* If end if(ttr-max_wr >dev>imits.|
* ofjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
*/
len ( il_tx_cmdil_tx_cmd +sizeofil_cmd_header)+hdr_len
=(en+3)&~;
/* Tell NIC about any 2-byte padding after MAC header */
srq->java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 28
tx_cmdjava.lang.StringIndexOutOfBoundsException: Range [22, 21) out of bounds for length 29
/* Physical address of this Tx command's header (not MAC header!),
* within command buffer array. */
d_phys = dma_map_single(&il->pci_dev->dev &out_cmd-hdr firstlen,
DMA_BIDIRECTIONAL); if } goto drop_unlock;
/* Set up TFD's 2nd entry to point directly to remainder of skb,;
* if any (802.11 null frames have no payload). */
secondlen &java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 28 if (secondlen > 0) {
phys_addr (il-pci_dev> java.lang.StringIndexOutOfBoundsException: Range [52, 51) out of bounds for length 68
if (unlikely(java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 11 goto goto err_out_free_;
}
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
il->ops->txq_attach_buf_to_tfd(il, txq, java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 2
java.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 51
dma_unmap_len_set(out_meta, len, firstlen); if ()
il->ops->java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 0 0 (err)
(java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 52
java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 16
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
wait_write_ptrd,dev->srq_table.table srq>rqn;
txq
}
java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 15 intc struct java.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 41
DMA toto */
dma_sync_single_for_cpu
;
tx_cmd-returnjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
tx_cmd->dram_msb_ptr = mthca_array_clear(&dev->srq_table.srq
il,true fc skb>;
D_TX("
D_TX("x_flags= 0X%\n,le32_to_cputx_cmd->x_flags);
il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd, sizeof(*tx_cmd));
il_print_hex_dump(il,IL_DL_TX,( )tx_cmd-hdr, )java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
if(info-java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 68 il>ps>xq_update_byte_cnt_tblil,txq,le16_to_cpu(tx_cmd-en);
_&-pci_dev-dev,java.lang.StringIndexOutOfBoundsException: Range [58, 57) out of bounds for length 68 RECTIONAL);
/* Tell device the write idx *just past* this latest filled TFD */
q->ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit);
mutex_unlock(&srqmutex;
spin_unlock_irqrestore(return;
At this point the frame is "ransmitted"successfully
wewill a TX status notification
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
*whetheror should update the write pointer
*/
/* *tavor_ctx=java.lang.StringIndexOutOfBoundsException: Range [23, 21) out of bounds for length 27
java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 34 *&ev->srq_tablelock)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33 tosleep.
*/ ifif(-ibsrqevent_handler
(sta_priv>ending_frames;
if ((srq>wait;
(ait_write_ptr {
spin_lock_irqsave(&il->lock, flagsjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ind wqe_addr > >wqe_shift;
il_txq_update_write_ptr(il, &srq->lock);
(-> ;
last_free-n=htonl(ind <srq->wqe_shift|)
srq->last_free = ind;
}
return0 first_ind
drop_unlock:
java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 0
-1
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
static err = -ENOMEM
il4965_alloc_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr, size_t size)
{
ptr-addr dma_alloc_coherent(il>pci_dev-dev p-d,
GFP_KERNEL); if (!-a) return -ENOMEM;
ptr- i=0; w-num_sge; +i java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37 return
}
l4965_free_dma_ptr( *,struct *
{ if (unlikely(!ptr->addr)) return;
/* * *DMAand
*/ void
ind
{ intjava.lang.StringIndexOutOfBoundsException: Range [12, 11) out of bounds for length 12
/* Tx queues */ if forjava.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64 if (txq_id == il->cmd_queue)
(il)java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26 else
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 0
}
il4965_free_dma_ptr(il, &il->kw);
il4965_free_dma_ptr(il, &il->scd_bc_tbls);
/* free tx queue structure */
java.lang.StringIndexOutOfBoundsException: Range [17, 16) out of bounds for length 21
}
/* *il4965_txq_ctx_alloc-allocateTXqueuecontext *AllocateallTxDMA*(needbemultiplesof16bytes).
*/ int
java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 40
{ int ret, txq_id; unsignedlong flags;
/* Free all tx/cmd queues and keep-warm buffer */
il4965_hw_txq_ctx_free(il);
ret =
il il->scd_bc_tbls
il->hw_params.scd_bc_tbls_size);
IL_ERR(" * of 16 goto java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 0
} /* Alloc keep-warm buffer */
ret = mthca_alloc_init(dev>java.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 46 if ( java.lang.StringIndexOutOfBoundsException: Range [9, 8) out of bounds for length 13
IL_ERR &dev-allocjava.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45 goto ;
}
/* allocate tx queue structure */;
ret = il_alloc_txq_mem(il); if (ret) goto error;
spin_lock_irqsave(&il->lock, flags);
/* Turn off all Tx DMA fifos */
il4965_txq_set_sched(il, 0);
/* Tell NIC where to find the "keep warm" buffer */
il_wr(il, FH49_KW_MEM_ADDR_REG, il->kw.dma >> 4);
spin_unlock_irqrestore(&il->lock, flags);
/* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
ret = il_tx_queue_init(il, txq_id); if (ret) {
IL_ERR("Tx %d queue init failed\n", txq_id); goto error;
}
}
void
il4965_txq_ctx_reset(struct il_priv *il)
{ int txq_id; unsignedlong flags;
spin_lock_irqsave(&il->lock, flags);
/* Turn off all Tx DMA fifos */
il4965_txq_set_sched(il, 0); /* Tell NIC where to find the "keep warm" buffer */
il_wr(il, FH49_KW_MEM_ADDR_REG, il->kw.dma >> 4);
spin_unlock_irqrestore(&il->lock, flags);
/* Alloc and init all Tx queues, including the command queue (#4) */ for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
il_tx_queue_reset(il, txq_id);
}
staticvoid
il4965_txq_ctx_unmap(struct il_priv *il)
{ int txq_id;
if (!il->txq) return;
/* Unmap DMA from host system and free skb's */ for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) if (txq_id == il->cmd_queue)
il_cmd_queue_unmap(il); else
il_tx_queue_unmap(il, txq_id);
}
for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) if (!test_and_set_bit(txq_id, &il->txq_ctx_active_msk)) return txq_id; return -1;
}
/* *il4965_tx_queue_stop_scheduler-Stopqueue,butkeepconfiguration
*/ staticvoid
il4965_tx_queue_stop_scheduler(struct il_priv *il, u16 txq_id)
{ /* Simply stop the queue, but don't change any configuration;
* the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
il_wr_prph(il, IL49_SCD_QUEUE_STATUS_BITS(txq_id),
(0 << IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
(1 << IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
}
/* *il4965_tx_queue_agg_enable-Setup&enableaggregationforselectedqueue * *NOTE:txq_idmustbegreaterthanIL49_FIRST_AMPDU_QUEUE, *i.e.itmustbeoneofthehigherqueuesusedforaggregation
*/ staticint
il4965_txq_agg_enable(struct il_priv *il, int txq_id, int tx_fifo, int sta_id, int tid, u16 ssn_idx)
{ unsignedlong flags;
u16 ra_tid; int ret;
if ((IL49_FIRST_AMPDU_QUEUE > txq_id) ||
(IL49_FIRST_AMPDU_QUEUE +
il->cfg->num_of_ampdu_queues <= txq_id)) {
IL_WARN("queue number out of range: %d, must be %d to %d\n",
txq_id, IL49_FIRST_AMPDU_QUEUE,
IL49_FIRST_AMPDU_QUEUE +
il->cfg->num_of_ampdu_queues - 1); return -EINVAL;
}
ra_tid = BUILD_RAxTID(sta_id, tid);
/* Modify device's station table to Tx this TID */
ret = il4965_sta_tx_modify_enable_tid(il, sta_id, tid); if (ret) return ret;
spin_lock_irqsave(&il->lock, flags);
/* Stop this Tx queue before configuring it */
il4965_tx_queue_stop_scheduler(il, txq_id);
/* Map receiver-address / traffic-ID to this queue */
il4965_tx_queue_set_q2ratid(il, ra_tid, txq_id);
/* Set this queue as a chain-building queue */
il_set_bits_prph(il, IL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
/* Place first TFD at idx corresponding to start sequence number.
* Assumes that ssn_idx is valid (!= 0xFFF) */
il->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
il->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
il4965_set_wr_ptrs(il, txq_id, ssn_idx);
/* Set up Tx win size and frame limit for this queue */
il_write_targ_mem(il,
il->scd_base_addr +
IL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id),
(SCD_WIN_SIZE << IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS)
& IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
switch (il->stations[sta_id].tid[tid].agg.state) { case IL_EMPTYING_HW_QUEUE_ADDBA: /* *Thiscanhappenifthepeerstopsaggregation *againbeforewe'vehadachancetodrainthe *queueweselectedpreviously,i.e.beforethe *sessionwasreallystartedcompletely.
*/
D_HT("AGG stop before setup done\n"); goto turn_off; case IL_AGG_ON: break; default:
IL_WARN("Stopping AGG while state not ON or starting\n");
}
/* The queue is not empty */ if (write_ptr != read_ptr) {
D_HT("Stopping a non empty AGG HW QUEUE\n");
il->stations[sta_id].tid[tid].agg.state =
IL_EMPTYING_HW_QUEUE_DELBA;
spin_unlock_irqrestore(&il->sta_lock, flags); return0;
}
D_HT("HW queue is empty\n");
turn_off:
il->stations[sta_id].tid[tid].agg.state = IL_AGG_OFF;
/* do not restore/save irqs */
spin_unlock(&il->sta_lock);
spin_lock(&il->lock);
/* *il4965_tx_status_reply_compressed_ba-Updatetxstatusfromblock-ack * *Gothroughblock-ack'sbitmapofACK'dframes,updatedriver'srecordof *ACKvs.not.Thisgetssenttomac80211,thentoratescalingalgo.
*/ staticint
il4965_tx_status_reply_compressed_ba(struct il_priv *il, struct il_ht_agg *agg, struct il_compressed_ba_resp *ba_resp)
{ int i, sh, ack;
u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); int successes = 0;
*;
u64 sent_bitmapjava.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
->java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 35 ifjava.lang.StringIndexOutOfBoundsException: Range [5, 4) out of bounds for length 49
);
java.lang.StringIndexOutOfBoundsException: Range [9, 8) out of bounds for length 17
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
/* Mark that the expected block-ack response arrived */
agg->wait_for_ba = 0;
D_TX_REPLY(d dn,agg>java.lang.StringIndexOutOfBoundsException: Range [42, 40) out of bounds for length 60
/* Calculate shift to align block-ack bits with our Tx win bits */==0|anamelen!
>-java.lang.StringIndexOutOfBoundsException: Range [34, 33) out of bounds for length 48
/*wrong*
sh + 0java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 14
>64-sh) java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
D_TX_REPLY("more framesjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 return -1iflen<java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
}
/* don't use 64-bit values for now */
bitmap-ENOMEM
/* check for success or failure according to the
* transmitted bitmap and block-ack bitmap */
java.lang.StringIndexOutOfBoundsException: Range [15, 12) out of bounds for length 36
/* For each frame attempted in aggregation,
* update driver's record of tx frame's status. */
ijava.lang.StringIndexOutOfBoundsException: Range [12, 11) out of bounds for length 19 while ss itemaddr java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 42
ack = sent_bitmap & 1ULL;
successes += ack;
D_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", ack ? "ACK" : "NACK",
i,a->+)& 0 >+);
sent_bitmap >>= 1;
++
}
(\n (java.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 57
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Range [9, 8) out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Range [0, 5) out of bounds for length 0
-flags| java.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 40
info->status.ampdu_ack_len = successes;
info->status.ampdu_len = agg->frame_count;
il4965_hwrate_to_tx_control(il, agg->rate_n_flags, info);
return0;
}
staticinlinebool
il4965_is_tx_success(u32 status)
{
status &= TX_STATUS_MSK; return (status == TX_STATUS_SUCCESS || status == TX_STATUS_DIRECT_DONE);
}
static u8
il4965_find_station(struct il_priv *il, const u8 *addr)
{ int i; int start = 0; int ret = IL_INVALID_STATION; unsignedlong flags;
if (il->iw_mode == NL80211_IFTYPE_ADHOC)
start = IL_STA_ID;
if (is_broadcast_ether_addr(addr)) return il->hw_params.bcast_id;
spin_lock_irqsave(&il->sta_lock, flags); for (i = start; i < il->hw_params.max_stations; i++) if (il->stations[i].used &&
ether_addr_equal(il->stations[i].sta.sta.addr, addr)) {
ret = i; goto out;
}
D_ASSOC("can not find STA %pM total %d\n", addr, il->num_stations);
out: /* *Itmaybepossiblethatmorecommandsinteractingwithstations *arrivebeforewecompletedprocessingtheaddingof *station
*/ if (ret != IL_INVALID_STATION &&
(!(il->stations[ret].used & IL_STA_UCODE_ACTIVE) ||
(il->stations[ret].used & IL_STA_UCODE_INPROGRESS))) {
IL_ERR("Requested station info for sta %d before ready.\n",
ret);
ret = IL_INVALID_STATION;
}
spin_unlock_irqrestore(&il->sta_lock, flags); return ret;
}
/* num frames attempted by Tx command */ if (agg->frame_count == 1) { /* Only one frame was attempted; no block-ack will arrive */
status = le16_to_cpu(frame_status[0].status);
idx = start_idx;
/* "ssn" is start of block-ack Tx win, corresponds to idx
* (in Tx queue's circular buffer) of first TFD/frame in win */
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
if (scd_flow >= il->hw_params.max_txq_num) {
IL_ERR("BUG_ON scd_flow is bigger than number of queues\n"); return;
}
txq = &il->txq[scd_flow];
sta_id = ba_resp->sta_id;
tid = ba_resp->tid;
agg = &il->stations[sta_id].tid[tid].agg; if (unlikely(agg->txq_id != scd_flow)) { /* *FIXME:thisisauCodebugwhichneedtobeaddressed, *logtheinformationandreturnfornow! *sinceitispossiblehappenveryoftenandinorder *nottofillthesyslog,don'tenabletheloggingbydefault
*/
D_TX_REPLY("BA scd_flow %d does not match txq_id %d\n",
scd_flow, agg->txq_id); return;
}
/* Find idx just before block-ack win */
idx = il_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
/* Update driver's record of ACK vs. not for each frame in win */
il4965_tx_status_reply_compressed_ba(il, agg, ba_resp);
/* Release all TFDs before the SSN, i.e. all TFDs in front of *block-ackwin(weassumethatthey'vebeensuccessfully
* transmitted ... if not, it's too late anyway). */ if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { /* calculate mac80211 ampdu sw queue to wake */ int freed = il4965_tx_queue_reclaim(il, scd_flow, idx);
il4965_free_tfds_in_queue(il, sta_id, tid, freed);
link_cmd = kzalloc(sizeof(struct il_link_quality_cmd), GFP_KERNEL); if (!link_cmd) {
IL_ERR("Unable to allocate memory for LQ cmd.\n"); return NULL;
} /* Set up the rate scaling to start at selected rate, fall back
* all the way down to 1M in IEEE order, and then spin on 1M */ if (il->band == NL80211_BAND_5GHZ)
r = RATE_6M_IDX; else
r = RATE_1M_IDX;
if (r >= IL_FIRST_CCK_RATE && r <= IL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK;
rate_flags |=
il4965_first_antenna(il->hw_params.
valid_tx_ant) << RATE_MCS_ANT_POS;
rate_n_flags = cpu_to_le32(il_rates[r].plcp | rate_flags); for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
/* Set up default rate scaling table in device's station table */
link_cmd = il4965_sta_alloc_lq(il, sta_id); if (!link_cmd) {
IL_ERR("Unable to initialize rate scaling for station %pM.\n",
addr); return -ENOMEM;
}
ret = il_send_lq_cmd(il, link_cmd, CMD_SYNC, true); if (ret)
IL_ERR("Link quality command failed (%d)\n", ret);
if (not_empty || send_if_empty) return il_send_cmd(il, &cmd); else return0;
}
int
il4965_restore_default_wep_keys(struct il_priv *il)
{
lockdep_assert_held(&il->mutex);
return il4965_static_wepkey_cmd(il, false);
}
int
il4965_remove_default_wep_key(struct il_priv *il, struct ieee80211_key_conf *keyconf)
{ int ret; int idx = keyconf->keyidx;
lockdep_assert_held(&il->mutex);
D_WEP("Removing default WEP key: idx=%d\n", idx);
memset(&il->_4965.wep_keys[idx], 0, sizeof(struct il_wep_key)); if (il_is_rfkill(il)) {
D_WEP("Not sending C_WEPKEY command due to RFKILL.\n"); /* but keys in device are clear anyway so return success */ return0;
}
ret = il4965_static_wepkey_cmd(il, 1);
D_WEP("Remove default WEP key: idx=%d ret=%d\n", idx, ret);
return ret;
}
int
il4965_set_default_wep_key(struct il_priv *il, struct ieee80211_key_conf *keyconf)
{ int ret; int len = keyconf->keylen; int idx = keyconf->keyidx;
lockdep_assert_held(&il->mutex);
if (len != WEP_KEY_LEN_128 && len != WEP_KEY_LEN_64) {
D_WEP("Bad WEP key length %d\n", keyconf->keylen); return -EINVAL;
}
if ((il->stations[sta_id].sta.key.
key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
il->stations[sta_id].sta.key.key_offset =
il_get_free_ucode_key_idx(il); /* else, we are overriding an existing key => no need to allocated room
* in uCode. */
WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, "no space for a new key");
if ((il->stations[sta_id].sta.key.
key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
il->stations[sta_id].sta.key.key_offset =
il_get_free_ucode_key_idx(il); /* else, we are overriding an existing key => no need to allocated room
* in uCode. */
WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, "no space for a new key");
if ((il->stations[sta_id].sta.key.
key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
il->stations[sta_id].sta.key.key_offset =
il_get_free_ucode_key_idx(il); /* else, we are overriding an existing key => no need to allocated room
* in uCode. */
WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, "no space for a new key");
if (keyconf->keyidx != keyidx) { /* We need to remove a key with idx different that the one *intheuCode.Thismeansthatthekeyweneedtoremovehas *beenreplacedbyanotheronewithdifferentidx. *Don'tdoanythingandreturnok
*/
spin_unlock_irqrestore(&il->sta_lock, flags); return0;
}
link_cmd = il4965_sta_alloc_lq(il, sta_id); if (!link_cmd) {
IL_ERR("Unable to initialize rate scaling for bcast sta.\n"); return -ENOMEM;
}
spin_lock_irqsave(&il->sta_lock, flags); if (il->stations[sta_id].lq)
kfree(il->stations[sta_id].lq); else
D_INFO("Bcast sta rate scaling has not been initialized.\n");
il->stations[sta_id].lq = link_cmd;
spin_unlock_irqrestore(&il->sta_lock, flags);
return0;
}
int
il4965_update_bcast_stations(struct il_priv *il)
{ return il4965_update_bcast_station(il);
}
/* *il4965_sta_tx_modify_enable_tid-EnableTxforthisTIDinstationtable
*/ int
il4965_sta_tx_modify_enable_tid(struct il_priv *il, int sta_id, int tid)
{ unsignedlong flags; struct il_addsta_cmd sta_cmd;
lockdep_assert_held(&il->mutex);
/* Remove "disable" flag, to enable Tx for this TID */
spin_lock_irqsave(&il->sta_lock, flags);
il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
il->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &il->stations[sta_id].sta, sizeof(struct il_addsta_cmd));
spin_unlock_irqrestore(&il->sta_lock, flags);
return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
}
int
il4965_sta_rx_agg_start(struct il_priv *il, struct ieee80211_sta *sta, int tid,
u16 ssn)
{ unsignedlong flags; int sta_id; struct il_addsta_cmd sta_cmd;
lockdep_assert_held(&il->mutex);
sta_id = il_sta_id(sta); if (sta_id == IL_INVALID_STATION) return -ENXIO;
/* Parse variable-length elements of beacon to find WLAN_EID_TIM */ while ((tim_idx < (frame_size - 2)) &&
(beacon[tim_idx] != WLAN_EID_TIM))
tim_idx += beacon[tim_idx + 1] + 2;
/* If TIM field was found, set variables */ if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
tx_beacon_cmd->tim_size = beacon[tim_idx + 1];
} else
IL_WARN("Unable to find TIM Element in beacon\n");
}
/* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++)
dma_unmap_single(&dev->dev, il4965_tfd_tb_get_addr(tfd, i),
il4965_tfd_tb_get_len(tfd, i), DMA_TO_DEVICE);
/* Each TFD can point to a maximum 20 Tx buffers */ if (num_tbs >= IL_NUM_OF_TBS) {
IL_ERR("Error can not send more than %d chunks\n",
IL_NUM_OF_TBS); return -EINVAL;
}
/* We delay the ALIVE response by 5ms to
* give the HW RF Kill time to activate... */ if (palive->is_valid == UCODE_VALID_OK)
queue_delayed_work(il->workqueue, pwork, msecs_to_jiffies(5)); else
IL_WARN("uCode did not respond OK.\n");
}
spin_lock_irqsave(&il->reg_lock, flags); if (likely(_il_grab_nic_access(il)))
_il_release_nic_access(il);
spin_unlock_irqrestore(&il->reg_lock, flags);
}
/* Handle notification from uCode that card's power state is changing
* due to software, hardware, or critical temperature RFKILL */ staticvoid
il4965_hdl_card_state(struct il_priv *il, struct il_rx_buf *rxb)
{ struct il_rx_pkt *pkt = rxb_addr(rxb);
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); unsignedlong status = il->status;
/* uCode's read idx (stored in shared DRAM) indicates the last Rx
* buffer that the driver may process (last buffer filled by ucode). */
r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
i = rxq->read;
/* Rx interrupt, but nothing sent from uCode */ if (i == r)
D_RX("r = %d, i = %d\n", r, i);
/* calculate total frames need to be restock after handling RX */
total_empty = r - rxq->write_actual; if (total_empty < 0)
total_empty += RX_QUEUE_SIZE;
if (total_empty > (RX_QUEUE_SIZE / 2))
fill_rx = 1;
while (i != r) {
rxb = rxq->queue[i];
/* If an RXB doesn't have a Rx queue slot associated with it, *thenabughasbeenintroducedinthequeuerefilling
* routines -- catch it here */
BUG_ON(rxb == NULL);
/* Based on type of command response or notification, *handlethosethatneedhandlingviafunctionin
* handlers table. See il4965_setup_handlers() */ if (il->handlers[pkt->hdr.cmd]) {
D_RX("r = %d, i = %d, %s, 0x%02x\n", r, i,
il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
il->isr_stats.handlers[pkt->hdr.cmd]++;
il->handlers[pkt->hdr.cmd] (il, rxb);
} else { /* No handling needed */
D_RX("r %d i %d No handler needed for %s, 0x%02x\n", r,
i, il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
}
if (reclaim) { /* Invoke any callbacks, transfer the buffer to caller, *andfireoffthe(possibly)blockingil_send_cmd()
* as we reclaim the driver command queue */ if (rxb->page)
il_tx_cmd_complete(il, rxb); else
IL_WARN("Claim null rxb?\n");
}
/* Reuse the page if possible. For notification packets and *SKBsthatfailtoRxcorrectly,addthembackintothe
* rx_free list for reuse later. */
spin_lock_irqsave(&rxq->lock, flags); if (rxb->page != NULL) {
rxb->page_dma =
dma_map_page(&il->pci_dev->dev, rxb->page, 0,
PAGE_SIZE << il->hw_params.rx_page_order,
DMA_FROM_DEVICE);
i = (i + 1) & RX_QUEUE_MASK; /* If there are a lot of unused frames,
* restock the Rx queue so ucode wont assert. */ if (fill_rx) {
count++; if (count >= 8) {
rxq->read = i;
il4965_rx_replenish_now(il);
count = 0;
}
}
}
/* Backtrack one entry */
rxq->read = i; if (fill_rx)
il4965_rx_replenish_now(il); else
il4965_rx_queue_restock(il);
}
/* call this function to flush any scheduled tasklet */ staticinlinevoid
il4965_synchronize_irq(struct il_priv *il)
{ /* wait to make sure we flush pending tasklet */
synchronize_irq(il->pci_dev->irq);
tasklet_kill(&il->irq_tasklet);
}
/* Ack/clear/reset pending uCode interrupts. *Note:SomebitsinCSR_INTare"OR"ofbitsinCSR_FH_INT_STATUS,
* and will clear only when CSR_FH_INT_STATUS gets cleared. */
inta = _il_rd(il, CSR_INT);
_il_wr(il, CSR_INT, inta);
/* Ack/clear/reset pending flow-handler (DMA) interrupts. *Anynewinterruptsthathappenafterthis,eitherwhilewe're
* in this tasklet, or later, will show up in next ISR/tasklet. */
inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
_il_wr(il, CSR_FH_INT_STATUS, inta_fh);
#ifdef CONFIG_IWLEGACY_DEBUG if (il_get_debug_level(il) & IL_DL_ISR) { /* just for debug */
inta_mask = _il_rd(il, CSR_INT_MASK);
D_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta,
inta_mask, inta_fh);
} #endif
spin_unlock_irqrestore(&il->lock, flags);
/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not *atomic,makesurethatintacoversalltheinterruptsthat *we'vediscovered,evenifFHinterruptcameinjustafter
* reading CSR_INT. */ if (inta_fh & CSR49_FH_INT_RX_MASK)
inta |= CSR_INT_BIT_FH_RX; if (inta_fh & CSR49_FH_INT_TX_MASK)
inta |= CSR_INT_BIT_FH_TX;
/* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) {
IL_ERR("Hardware error detected. Restarting.\n");
/* Tell the device to stop sending interrupts */
il_disable_interrupts(il);
il->isr_stats.hw++;
il_irq_handle_error(il);
handled |= CSR_INT_BIT_HW_ERR;
return;
} #ifdef CONFIG_IWLEGACY_DEBUG if (il_get_debug_level(il) & (IL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) {
D_ISR("Scheduler finished to transmit " "the frame/frames.\n");
il->isr_stats.sch++;
}
/* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) {
D_ISR("Alive interrupt\n");
il->isr_stats.alive++;
}
} #endif /* Safely ignore these bits for debug checks below */
inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
/* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { int hw_rf_kill = 0;
if (!(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
hw_rf_kill = 1;
IL_WARN("RF_KILL bit toggled to %s.\n",
hw_rf_kill ? "disable radio" : "enable radio");
il->isr_stats.rfkill++;
/* driver only loads ucode once setting the interface up. *thedriverallowsloadingtheucodeeveniftheradio *iskilled.Henceupdatethekillswitchstatehere.The *rfkillhandlerwillcareaboutrestartingifneeded.
*/ if (hw_rf_kill) {
set_bit(S_RFKILL, &il->status);
} else {
clear_bit(S_RFKILL, &il->status);
il_force_reset(il, true);
}
wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
handled |= CSR_INT_BIT_RF_KILL;
}
/* Chip got too hot and stopped itself */ if (inta & CSR_INT_BIT_CT_KILL) {
IL_ERR("Microcode CT kill error detected.\n");
il->isr_stats.ctkill++;
handled |= CSR_INT_BIT_CT_KILL;
}
/* *uCodewakesupafterpower-downsleep. *Telldeviceaboutanynewtxorhostcommandsenqueued, *andaboutanyRxbuffersmadeavailablewhileasleep.
*/ if (inta & CSR_INT_BIT_WAKEUP) {
D_ISR("Wakeup interrupt\n");
il_rx_queue_update_write_ptr(il, &il->rxq); for (i = 0; i < il->hw_params.max_txq_num; i++)
il_txq_update_write_ptr(il, &il->txq[i]);
il->isr_stats.wakeup++;
handled |= CSR_INT_BIT_WAKEUP;
}
/* All uCode command responses, including Tx command responses, *Rx"responses"(frame-receivednotification),andother
* notifications from uCode come through here*/ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
il4965_rx_handle(il);
il->isr_stats.rx++;
handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
}
/* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) {
D_ISR("uCode load interrupt\n");
il->isr_stats.tx++;
handled |= CSR_INT_BIT_FH_TX; /* Wake up uCode load routine, now that load is complete */
il->ucode_write_complete = 1;
wake_up(&il->wait_command_queue);
}
if (inta & ~(il->inta_mask)) {
IL_WARN("Disabled INTA bits 0x%08x were pending\n",
inta & ~il->inta_mask);
IL_WARN(" with FH49_INT = 0x%08x\n", inta_fh);
}
/* Re-enable all interrupts */ /* only Re-enable if disabled by irq */ if (test_bit(S_INT_ENABLED, &il->status))
il_enable_interrupts(il); /* Re-enable RF_KILL if it occurred */ elseif (handled & CSR_INT_BIT_RF_KILL)
il_enable_rfkill_int(il);
ret = kstrtoul(buf, 10, &val); if (ret)
IL_INFO("%s is not in decimal form.\n", buf); else {
ret = il_set_tx_power(il, val, false); if (ret)
IL_ERR("failed setting tx power (0x%08x).\n", ret); else
ret = count;
} return ret;
}
/* Make sure that we got at least the API version number */ if (ucode_raw->size < 4) {
IL_ERR("File size way too small!\n"); goto try_again;
}
/* Data from ucode file: header followed by uCode images */
err = il4965_load_firmware(il, ucode_raw, &pieces);
if (err) goto try_again;
api_ver = IL_UCODE_API(il->ucode_ver);
/* *api_vershouldmatchtheapiversionformingpartofthe *firmwarefilename...butwedon'tcheckforthatandonlyrely *ontheAPIversionreadfromfirmwareheaderfromhereonforward
*/ if (api_ver < api_min || api_ver > api_max) {
IL_ERR("Driver unable to support your firmware API. " "Driver supports v%u, firmware is v%u.\n", api_max,
api_ver); goto try_again;
}
if (api_ver != api_max)
IL_ERR("Firmware has old API version. Expected v%u, " "got v%u. New firmware can be obtained " "from http://www.intellinuxwireless.org.\n", api_max,
api_ver);
IL_INFO("loaded firmware version %u.%u.%u.%u\n",
IL_UCODE_MAJOR(il->ucode_ver), IL_UCODE_MINOR(il->ucode_ver),
IL_UCODE_API(il->ucode_ver), IL_UCODE_SERIAL(il->ucode_ver));
/* Verify that uCode images will fit in card's SRAM */ if (pieces.inst_size > il->hw_params.max_inst_size) {
IL_ERR("uCode instr len %zd too large to fit in\n",
pieces.inst_size); goto try_again;
}
if (pieces.data_size > il->hw_params.max_data_size) {
IL_ERR("uCode data len %zd too large to fit in\n",
pieces.data_size); goto try_again;
}
if (pieces.init_size > il->hw_params.max_inst_size) {
IL_ERR("uCode init instr len %zd too large to fit in\n",
pieces.init_size); goto try_again;
}
if (pieces.init_data_size > il->hw_params.max_data_size) {
IL_ERR("uCode init data len %zd too large to fit in\n",
pieces.init_data_size); goto try_again;
}
if (pieces.boot_size > il->hw_params.max_bsm_size) {
IL_ERR("uCode boot instr len %zd too large to fit in\n",
pieces.boot_size); goto try_again;
}
/* Allocate ucode buffers for card's bus-master loading ... */
/* Runtime instructions and 2 copies of data: *1)unmodifiedfromdisk
* 2) backup cache for save/restore during power-downs */
il->ucode_code.len = pieces.inst_size;
il_alloc_fw_desc(il->pci_dev, &il->ucode_code);
if (!il->ucode_init.v_addr || !il->ucode_init_data.v_addr) goto err_pci_alloc;
}
/* Bootstrap (instructions only, no data) */ if (pieces.boot_size) {
il->ucode_boot.len = pieces.boot_size;
il_alloc_fw_desc(il->pci_dev, &il->ucode_boot);
if (!il->ucode_boot.v_addr) goto err_pci_alloc;
}
/* Now that we can no longer fail, copy information */
il->sta_key_max_num = STA_KEY_MAX_NUM;
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
D_INFO("Copying (but not loading) uCode instr len %zd\n",
pieces.inst_size);
memcpy(il->ucode_code.v_addr, pieces.inst, pieces.inst_size);
/* *Runtimedata *NOTE:Copyintobackupbufferwillbedoneinil_up()
*/
D_INFO("Copying (but not loading) uCode data len %zd\n",
pieces.data_size);
memcpy(il->ucode_data.v_addr, pieces.data, pieces.data_size);
memcpy(il->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
/* Initialization instructions */ if (pieces.init_size) {
D_INFO("Copying (but not loading) init instr len %zd\n",
pieces.init_size);
memcpy(il->ucode_init.v_addr, pieces.init, pieces.init_size);
}
/* Initialization data */ if (pieces.init_data_size) {
D_INFO("Copying (but not loading) init data len %zd\n",
pieces.init_data_size);
memcpy(il->ucode_init_data.v_addr, pieces.init_data,
pieces.init_data_size);
}
/* Bootstrap instructions */
D_INFO("Copying (but not loading) boot instr len %zd\n",
pieces.boot_size);
memcpy(il->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
if (il->ucode_type == UCODE_INIT)
base = le32_to_cpu(il->card_alive_init.error_event_table_ptr); else
base = le32_to_cpu(il->card_alive.error_event_table_ptr);
ret = il_send_cmd_pdu(il, C_CT_KILL_CONFIG, sizeof(cmd), &cmd); if (ret)
IL_ERR("C_CT_KILL_CONFIG failed\n"); else
D_INFO("C_CT_KILL_CONFIG ""succeeded, " "critical temperature is %d\n",
il->hw_params.ct_kill_threshold);
}
staticint
il4965_alive_notify(struct il_priv *il)
{
u32 a; unsignedlong flags; int i, chan;
u32 reg_val;
spin_lock_irqsave(&il->lock, flags);
/* Clear 4965's internal Tx Scheduler data base */
il->scd_base_addr = il_rd_prph(il, IL49_SCD_SRAM_BASE_ADDR);
a = il->scd_base_addr + IL49_SCD_CONTEXT_DATA_OFFSET; for (; a < il->scd_base_addr + IL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
il_write_targ_mem(il, a, 0); for (; a < il->scd_base_addr + IL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
il_write_targ_mem(il, a, 0); for (;
a <
il->scd_base_addr +
IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(il->hw_params.max_txq_num);
a += 4)
il_write_targ_mem(il, a, 0);
/* Tel 4965 where to find Tx byte count tables */
il_wr_prph(il, IL49_SCD_DRAM_BASE_ADDR, il->scd_bc_tbls.dma >> 10);
/* make sure all queue are not stopped */
memset(&il->queue_stopped[0], 0, sizeof(il->queue_stopped)); for (i = 0; i < 4; i++)
atomic_set(&il->queue_stop_count[i], 0);
/* reset to 0 to enable all the queue first */
il->txq_ctx_active_msk = 0; /* Map each Tx/cmd queue to its corresponding fifo */
BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { int ac = default_queue_to_tx_fifo[i];
/* *il4965_alive_start-calledafterN_ALIVEnotificationreceived *fromprotocol/runtimeuCode(initializationuCode's *Alivegetshandledbyil_init_alive_start()).
*/ staticvoid
il4965_alive_start(struct il_priv *il)
{ int ret = 0;
D_INFO("Runtime Alive received.\n");
if (il->card_alive.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 */
D_INFO("Alive failed.\n"); goto restart;
}
/* Initialize uCode has loaded Runtime uCode ... verify inst image. *Thisisaparanoidcheck,becausewewouldnothavegottenthe
* "runtime" alive if code weren't properly loaded. */ if (il4965_verify_ucode(il)) { /* Runtime instruction load was bad;
* take it all the way back down so we can try again */
D_INFO("Bad runtime uCode load.\n"); goto restart;
}
ret = il4965_alive_notify(il); if (ret) {
IL_WARN("Could not complete ALIVE transition [ntf]: %d\n", ret); goto restart;
}
/* After the ALIVE response, we can send host commands to the uCode */
set_bit(S_ALIVE, &il->status);
/* Enable watchdog to monitor the driver tx queues */
il_setup_watchdog(il);
if (il_is_rfkill(il)) return;
ieee80211_wake_queues(il->hw);
il->active_rate = RATES_MASK;
il_power_update_mode(il, true);
D_INFO("Updated power mode\n");
if (il_is_associated(il)) { struct il_rxon_cmd *active_rxon =
(struct il_rxon_cmd *)&il->active; /* apply any changes in staging */
il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else { /* Initialize our rx_config data */
il_connection_init_rx_config(il);
if (il->ops->set_rxon_chain)
il->ops->set_rxon_chain(il);
}
/* Configure bluetooth coexistence if enabled */
il_send_bt_config(il);
il4965_reset_run_time_calib(il);
set_bit(S_READY, &il->status);
/* Configure the adapter for unassociated operation */
il_commit_rxon(il);
/* At this point, the NIC is initialized and operational */
il4965_rf_kill_ct_config(il);
/* Unblock any waiting calls */
wake_up_all(&il->wait_command_queue);
/* Wipe out the EXIT_PENDING status bit if we are not actually
* exiting the module */ if (!exit_pending)
clear_bit(S_EXIT_PENDING, &il->status);
/* stop and reset the on-board processor */
_il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
/* tell the device to stop sending interrupts */
spin_lock_irqsave(&il->lock, flags);
il_disable_interrupts(il);
spin_unlock_irqrestore(&il->lock, flags);
il4965_synchronize_irq(il);
if (il->mac80211_registered)
ieee80211_stop_queues(il->hw);
/* If we have not previously called il_init() then
* clear all bits but the RF Kill bit and return */ if (!il_is_init(il)) {
il->status =
test_bit(S_RFKILL, &il->status) << S_RFKILL |
test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED |
test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING; gotoexit;
}
/* ...otherwise clear out all the status bits but the RF Kill
* bit and continue taking the NIC down. */
il->status &=
test_bit(S_RFKILL, &il->status) << S_RFKILL |
test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED |
test_bit(S_FW_ERROR, &il->status) << S_FW_ERROR |
test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
/* *Wedisabledandsynchronizedinterrupt,andpriv->mutexistaken,so *hereistheonlythreadwhichwillprogramdeviceregisters,but *stillhavelockdepassertions,sowearetakingreg_lock.
*/
spin_lock_irq(&il->reg_lock); /* FIXME: il_grab_nic_access if rfkill is off ? */
il4965_txq_ctx_stop(il);
il4965_rxq_stop(il); /* Power-down device's busmaster DMA clocks */
_il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
udelay(5); /* Make sure (redundant) we've released our request to stay awake */
_il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */
_il_apm_stop(il);
/* See if we got it */
ret = _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, 100); if (ret >= 0)
il->hw_ready = true;
staticvoid
il4965_prepare_card_hw(struct il_priv *il)
{ int ret;
il->hw_ready = false;
il4965_set_hw_ready(il); if (il->hw_ready) return;
/* If HW is not ready, prepare the conditions to check again */
il_set_bit(il, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE);
ret =
_il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
/* HW should be ready by now, check again. */ if (ret != -ETIMEDOUT)
il4965_set_hw_ready(il);
}
#define MAX_HW_RESTARTS 5
staticint
__il4965_up(struct il_priv *il)
{ int i; int ret;
if (test_bit(S_EXIT_PENDING, &il->status)) {
IL_WARN("Exit pending; will not bring the NIC up\n"); return -EIO;
}
if (!il->ucode_data_backup.v_addr || !il->ucode_data.v_addr) {
IL_ERR("ucode not available for device bringup\n"); return -EIO;
}
ret = il4965_alloc_bcast_station(il); if (ret) {
il_dealloc_bcast_stations(il); return ret;
}
il4965_prepare_card_hw(il); if (!il->hw_ready) {
il_dealloc_bcast_stations(il);
IL_ERR("HW not ready\n"); return -EIO;
}
/* If platform's RF_KILL switch is NOT set to KILL */ if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
clear_bit(S_RFKILL, &il->status); else {
set_bit(S_RFKILL, &il->status);
wiphy_rfkill_set_hw_state(il->hw->wiphy, true);
/* really make sure rfkill handshake bits are cleared */
_il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
_il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Copy original ucode data image from disk into backup cache. *Thiswillbeusedtoinitializetheon-boardprocessor's
* data SRAM for a clean start when the runtime program first loads. */
memcpy(il->ucode_data_backup.v_addr, il->ucode_data.v_addr,
il->ucode_data.len);
for (i = 0; i < MAX_HW_RESTARTS; i++) {
/* load bootstrap state machine, *loadbootstrapprogramintoprocessor'smemory,
* prepare to load the "initialize" uCode */
ret = il->ops->load_ucode(il);
if (ret) {
IL_ERR("Unable to set up bootstrap uCode: %d\n", ret); continue;
}
/* start card; "initialize" will load runtime ucode */
il4965_nic_start(il);
/* tried to restart and config the device for as long as our
* patience could withstand */
IL_ERR("Unable to initialize device after %d attempts.\n", i); return -EIO;
}
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; /* we create the 802.11 header and a zero-length SSID element */
hw->wiphy->max_scan_ie_len = max_probe_length - 24 - 2;
if (il->bands[NL80211_BAND_2GHZ].n_channels)
il->hw->wiphy->bands[NL80211_BAND_2GHZ] =
&il->bands[NL80211_BAND_2GHZ]; if (il->bands[NL80211_BAND_5GHZ].n_channels)
il->hw->wiphy->bands[NL80211_BAND_5GHZ] =
&il->bands[NL80211_BAND_5GHZ];
ret = ieee80211_register_hw(il->hw); if (ret) {
IL_ERR("Failed to register hw (error %d)\n", ret); return ret;
}
il->mac80211_registered = 1;
return0;
}
int
il4965_mac_start(struct ieee80211_hw *hw)
{ struct il_priv *il = hw->priv; int ret;
D_MAC80211("enter\n");
/* we should be verifying the device is ready to be opened */
mutex_lock(&il->mutex);
ret = __il4965_up(il);
mutex_unlock(&il->mutex);
if (ret) return ret;
if (il_is_rfkill(il)) goto out;
D_INFO("Start UP work done.\n");
/* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
* mac80211 will not be run successfully. */
ret = wait_event_timeout(il->wait_command_queue,
test_bit(S_READY, &il->status),
UCODE_READY_TIMEOUT); if (!ret) { if (!test_bit(S_READY, &il->status)) {
IL_ERR("START_ALIVE timeout after %dms.\n",
jiffies_to_msecs(UCODE_READY_TIMEOUT)); return -ETIMEDOUT;
}
}
switch (cmd) { case SET_KEY: if (is_default_wep_key)
ret = il4965_set_default_wep_key(il, key); else
ret = il4965_set_dynamic_key(il, key, sta_id);
D_MAC80211("enable hwcrypto key\n"); break; case DISABLE_KEY: if (is_default_wep_key)
ret = il4965_remove_default_wep_key(il, key); else
ret = il4965_remove_dynamic_key(il, key, sta_id);
D_MAC80211("disable hwcrypto key\n"); break; default:
ret = -EINVAL;
}
mutex_unlock(&il->mutex);
D_MAC80211("leave\n");
return ret;
}
int
il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params)
{ struct il_priv *il = hw->priv; int ret = -EINVAL; struct ieee80211_sta *sta = params->sta; enum ieee80211_ampdu_mlme_action action = params->action;
u16 tid = params->tid;
u16 *ssn = ¶ms->ssn;
D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid);
if (!(il->cfg->sku & IL_SKU_N)) return -EACCES;
mutex_lock(&il->mutex);
switch (action) { case IEEE80211_AMPDU_RX_START:
D_HT("start Rx\n");
ret = il4965_sta_rx_agg_start(il, sta, tid, *ssn); break; case IEEE80211_AMPDU_RX_STOP:
D_HT("stop Rx\n");
ret = il4965_sta_rx_agg_stop(il, sta, tid); if (test_bit(S_EXIT_PENDING, &il->status))
ret = 0; break; case IEEE80211_AMPDU_TX_START:
D_HT("start Tx\n");
ret = il4965_tx_agg_start(il, vif, sta, tid, ssn); break; case IEEE80211_AMPDU_TX_STOP_CONT: case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
D_HT("stop Tx\n");
ret = il4965_tx_agg_stop(il, vif, sta, tid); if (test_bit(S_EXIT_PENDING, &il->status))
ret = 0; break; case IEEE80211_AMPDU_TX_OPERATIONAL:
ret = 0; break;
}
mutex_unlock(&il->mutex);
D_INFO("received request to add station %pM\n", sta->addr);
mutex_lock(&il->mutex);
D_INFO("proceeding to add station %pM\n", sta->addr);
sta_priv->common.sta_id = IL_INVALID_STATION;
atomic_set(&sta_priv->pending_frames, 0);
ret =
il_add_station_common(il, sta->addr, is_ap, sta, &sta_id); if (ret) {
IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret); /* Should we return success if return code is EEXIST ? */
mutex_unlock(&il->mutex); return ret;
}
sta_priv->common.sta_id = sta_id;
/* Initialize rate scaling */
D_INFO("Initializing rate scaling for station %pM\n", sta->addr);
il4965_rs_rate_init(il, sta, sta_id);
mutex_unlock(&il->mutex);
/* If a scan happened to start before we got here *thenjustreturn;thestatsnotificationwill *kickoffanotherscheduledworktocompensatefor
* any temperature delta we missed here. */ if (test_bit(S_EXIT_PENDING, &il->status) ||
test_bit(S_SCANNING, &il->status)) goto out;
/* Regardless of if we are associated, we must reconfigure the *TXpowersinceframescanbesentonnon-radarchannelswhile
* not associated */
il->ops->send_tx_power(il);
/* Update last_temperature to keep is_calib_needed from running
* when it isn't needed... */
il->last_temperature = il->temperature;
out:
mutex_unlock(&il->mutex);
}
/* We disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
il4965_prepare_card_hw(il); if (!il->hw_ready) {
IL_WARN("Failed, HW not ready\n");
err = -EIO; goto out_iounmap;
}
/***************** *4.ReadEEPROM
*****************/ /* Read the EEPROM */
err = il_eeprom_init(il); if (err) {
IL_ERR("Unable to init EEPROM\n"); goto out_iounmap;
}
err = il4965_eeprom_check_version(il); if (err) goto out_free_eeprom;
/* If platform's RF_KILL switch is NOT set to KILL */ if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
clear_bit(S_RFKILL, &il->status); else
set_bit(S_RFKILL, &il->status);
/* make sure we flush any pending irq or *taskletforthedriver
*/
spin_lock_irqsave(&il->lock, flags);
il_disable_interrupts(il);
spin_unlock_irqrestore(&il->lock, flags);
il4965_synchronize_irq(il);
il4965_dealloc_ucode_pci(il);
if (il->rxq.bd)
il4965_rx_queue_free(il, &il->rxq);
il4965_hw_txq_ctx_free(il);
il_eeprom_free(il);
/*netif_stop_queue(dev); */
/* ieee80211_unregister_hw calls il_mac_stop, which flushes *il->workqueue...sowecan'ttakedowntheworkqueue
* until now... */
destroy_workqueue(il->workqueue);
il->workqueue = NULL;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.353Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.