/* * Zydas retry rates table. Each line is listed in the same order as * in zd_rates[] and contains all the rate used when a packet is sent * starting with a given rates. Let's consider an example : * * "11 Mbits : 4, 3, 2, 1, 0" means : * - packet is sent using 4 different rates * - 1st rate is index 3 (ie 11 Mbits) * - 2nd rate is index 2 (ie 5.5 Mbits) * - 3rd rate is index 1 (ie 2 Mbits) * - 4th rate is index 0 (ie 1 Mbits)
*/
r = zd_chip_enable_int(chip); if (r) goto out;
r = zd_chip_init_hw(chip); if (r) goto disable_int;
ZD_ASSERT(!irqs_disabled());
r = zd_read_regdomain(chip, &default_regdomain); if (r) goto disable_int;
spin_lock_irq(&mac->lock);
mac->regdomain = mac->default_regdomain = default_regdomain;
spin_unlock_irq(&mac->lock);
/* We must inform the device that we are doing encryption/decryption in
* software at the moment. */
r = zd_set_encryption_type(chip, ENC_SNIFFER); if (r) goto disable_int;
r = zd_reg2alpha2(mac->regdomain, alpha2); if (r) goto disable_int;
r = regulatory_hint(hw->wiphy, alpha2);
disable_int:
zd_chip_disable_int(chip);
out: return r;
}
staticint set_mac_and_bssid(struct zd_mac *mac)
{ int r;
if (!mac->vif) return -1;
r = zd_write_mac_addr(&mac->chip, mac->vif->addr); if (r) return r;
/* Vendor driver after setting MAC either sets BSSID for AP or * filter for other modes.
*/ if (mac->type != NL80211_IFTYPE_AP) return set_rx_filter(mac); else return zd_write_bssid(&mac->chip, mac->vif->addr);
}
if (!usb->initialized) {
r = zd_usb_init_hw(usb); if (r) goto out;
}
r = zd_chip_enable_int(chip); if (r < 0) goto out;
r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G); if (r < 0) goto disable_int;
r = set_rx_filter(mac); if (r) goto disable_int;
r = set_mc_hash(mac); if (r) goto disable_int;
/* Wait after setting the multicast hash table and powering on * the radio otherwise interface bring up will fail. This matches * what the vendor driver did.
*/
msleep(10);
r = zd_chip_switch_radio_on(chip); if (r < 0) {
dev_err(zd_chip_dev(chip), "%s: failed to set radio on\n", __func__); goto disable_int;
}
r = zd_chip_enable_rxtx(chip); if (r < 0) goto disable_radio;
r = zd_chip_enable_hwint(chip); if (r < 0) goto disable_rxtx;
/* The order here deliberately is a little different from the open() * method, since we need to make sure there is no opportunity for RX * frames to be processed by mac80211 after we have stopped it.
*/
/** * zd_mac_tx_status - reports tx status of a packet if required * @hw: a &struct ieee80211_hw pointer * @skb: a sk-buffer * @ackssi: ACK signal strength * @tx_status: success and/or retry * * This information calls ieee80211_tx_status_irqsafe() if required by the * control information. It copies the control information into the status * information. * * If no status information has been requested, the skb is freed.
*/ staticvoid zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ackssi, struct tx_status *tx_status)
{ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); int i; int success = 1, retry = 1; int first_idx; conststruct tx_retry_rate *retries;
/** * zd_mac_tx_failed - callback for failed frames * @urb: pointer to the urb structure * * This function is called if a frame couldn't be successfully * transferred. The first frame from the tx queue, will be selected and * reported as error to the upper layers.
*/ void zd_mac_tx_failed(struct urb *urb)
{ struct ieee80211_hw * hw = zd_usb_to_hw(urb->context); struct zd_mac *mac = zd_hw_mac(hw); struct sk_buff_head *q = &mac->ack_wait_queue; struct sk_buff *skb; struct tx_status *tx_status = (struct tx_status *)urb->transfer_buffer; unsignedlong flags; int success = !tx_status->failure; int retry = tx_status->retry + success; int found = 0; int i, position = 0;
/* if the hardware reports a failure and we had a 802.11 ACK * pending, then we skip the first skb when searching for a
* matching frame */ if (tx_status->failure && mac->ack_pending &&
skb_queue_is_first(q, skb)) { continue;
}
tx_hdr = (struct ieee80211_hdr *)skb->data;
/* we skip all frames not matching the reported destination */ if (unlikely(!ether_addr_equal(tx_hdr->addr1, tx_status->mac))) continue;
/* we skip all frames not matching the reported final rate */
if (found) { for (i=1; i<=position; i++) {
skb = __skb_dequeue(q);
zd_mac_tx_status(hw, skb,
mac->ack_pending ? mac->ack_signal : 0,
i == position ? tx_status : NULL);
mac->ack_pending = 0;
}
}
spin_unlock_irqrestore(&q->lock, flags);
}
/** * zd_mac_tx_to_dev - callback for USB layer * @skb: a &sk_buff pointer * @error: error value, 0 if transmission successful * * Informs the MAC layer that the frame has successfully transferred to the * device. If an ACK is required and the transfer to the device has been * successful, the packets are put on the @ack_wait_queue with * the control set removed.
*/ void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
{ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hw *hw = info->rate_driver_data[0]; struct zd_mac *mac = zd_hw_mac(hw);
ieee80211_tx_info_clear_status(info);
skb_pull(skb, sizeof(struct zd_ctrlset)); if (unlikely(error ||
(info->flags & IEEE80211_TX_CTL_NO_ACK))) { /* * FIXME : do we need to fill in anything ?
*/
ieee80211_tx_status_irqsafe(hw, skb);
} else { struct sk_buff_head *q = &mac->ack_wait_queue;
skb_queue_tail(q, skb); while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) {
skb = skb_dequeue(q); if (!skb) break;
staticint zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
{ /* ZD_PURE_RATE() must be used to remove the modulation type flag of * the zd-rate values.
*/ staticconst u8 rate_divisor[] = {
[ZD_PURE_RATE(ZD_CCK_RATE_1M)] = 1,
[ZD_PURE_RATE(ZD_CCK_RATE_2M)] = 2, /* Bits must be doubled. */
[ZD_PURE_RATE(ZD_CCK_RATE_5_5M)] = 11,
[ZD_PURE_RATE(ZD_CCK_RATE_11M)] = 11,
[ZD_PURE_RATE(ZD_OFDM_RATE_6M)] = 6,
[ZD_PURE_RATE(ZD_OFDM_RATE_9M)] = 9,
[ZD_PURE_RATE(ZD_OFDM_RATE_12M)] = 12,
[ZD_PURE_RATE(ZD_OFDM_RATE_18M)] = 18,
[ZD_PURE_RATE(ZD_OFDM_RATE_24M)] = 24,
[ZD_PURE_RATE(ZD_OFDM_RATE_36M)] = 36,
[ZD_PURE_RATE(ZD_OFDM_RATE_48M)] = 48,
[ZD_PURE_RATE(ZD_OFDM_RATE_54M)] = 54,
};
u32 bits = (u32)tx_length * 8;
u32 divisor;
divisor = rate_divisor[ZD_PURE_RATE(zd_rate)]; if (divisor == 0) return -EINVAL;
switch (zd_rate) { case ZD_CCK_RATE_5_5M:
bits = (2*bits) + 10; /* round up to the next integer */ break; case ZD_CCK_RATE_11M: if (service) {
u32 t = bits % 11;
*service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION; if (0 < t && t <= 3) {
*service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION;
}
}
bits += 10; /* round up to the next integer */ break;
}
return bits/divisor;
}
staticvoid cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, struct ieee80211_hdr *header, struct ieee80211_tx_info *info)
{ /* * CONTROL TODO: * - if backoff needed, enable bit 0 * - if burst (backoff not needed) disable bit 0
*/
cs->control = 0;
/* First fragment */ if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
/* No ACK expected (multicast, etc.) */ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
cs->control |= ZD_CS_NO_ACK;
/* PS-POLL */ if (ieee80211_is_pspoll(header->frame_control))
cs->control |= ZD_CS_PS_POLL_FRAME;
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
cs->control |= ZD_CS_RTS;
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
cs->control |= ZD_CS_SELF_CTS;
r = zd_iowrite32a_locked(&mac->chip, ioreqs, num_cmds);
release_sema: /* * Try very hard to release device beacon semaphore, as otherwise * device/driver can be left in unusable state.
*/
end_jiffies = jiffies + HZ / 2; /*~500ms*/
ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE); while (ret < 0) { if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {
ret = -ETIMEDOUT; break;
}
msleep(20);
ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
}
if (ret < 0)
dev_err(zd_mac_dev(mac), "Could not release " "CR_BCN_FIFO_SEMAPHORE!\n"); if (r < 0 || ret < 0) { if (r >= 0)
r = ret;
/* We don't know if beacon was written successfully or not,
* so clear current. */
zd_mac_free_cur_beacon_locked(mac);
goto out;
}
/* Beacon has now been written successfully, update current. */
zd_mac_free_cur_beacon_locked(mac);
mac->beacon.cur_beacon = beacon;
beacon = NULL;
/* 802.11b/g 2.4G CCK 1Mb * 802.11a, not yet implemented, uses different values (see GPL vendor * driver)
*/
r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
CR_BCN_PLCP_CFG);
out:
kfree(ioreqs);
out_nofree:
kfree_skb(beacon);
mutex_unlock(&mac->chip.mutex);
/* * Firmware computes the duration itself (for all frames except PSPoll) * and needs the field set to 0 at input, otherwise firmware messes up * duration_id and sets bits 14 and 15 on.
*/ if (!ieee80211_is_pspoll(hdr->frame_control))
hdr->duration_id = 0;
txrate = ieee80211_get_tx_rate(mac->hw, info);
cs->modulation = txrate->hw_value; if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
cs->modulation = txrate->hw_value_short;
cs->tx_length = cpu_to_le16(frag_len);
cs_set_control(mac, cs, hdr, info);
packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
ZD_ASSERT(packet_length <= 0xffff); /* ZD1211B: Computing the length difference this way, gives us * flexibility to compute the packet length.
*/
cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
packet_length - frag_len : packet_length);
/* * CURRENT LENGTH: * - transmit frame length in microseconds * - seems to be derived from frame length * - see Cal_Us_Service() in zdinlinef.h * - if macp->bTxBurstEnable is enabled, then multiply by 4 * - bTxBurstEnable is never set in the vendor driver * * SERVICE: * - "for PLCP configuration" * - always 0 except in some situations at 802.11b 11M * - see line 53 of zdinlinef.h
*/
cs->service = 0;
r = zd_calc_tx_length_us(&cs->service, ZD_RATE(cs->modulation),
le16_to_cpu(cs->tx_length)); if (r < 0) return r;
cs->current_length = cpu_to_le16(r);
cs->next_frame_length = 0;
return 0;
}
/** * zd_op_tx - transmits a network frame to the device * * @hw: a &struct ieee80211_hw pointer * @control: the control structure * @skb: socket buffer * * This function transmit an IEEE 802.11 network frame to the device. The * control block of the skbuff will be initialized. If necessary the incoming * mac80211 queues will be stopped.
*/ staticvoid zd_op_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb)
{ struct zd_mac *mac = zd_hw_mac(hw); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); int r;
r = fill_ctrlset(mac, skb); if (r) goto fail;
info->rate_driver_data[0] = hw;
r = zd_usb_tx(&mac->chip.usb, skb); if (r) goto fail; return;
fail:
dev_kfree_skb(skb);
}
/** * filter_ack - filters incoming packets for acknowledgements * @hw: a &struct ieee80211_hw pointer * @rx_hdr: received header * @stats: the status for the received packet * * This functions looks for ACK packets and tries to match them with the * frames in the tx queue. If a match is found the frame will be dequeued and * the upper layers is informed about the successful transmission. If * mac80211 queues have been stopped and the number of frames still to be * transmitted is low the queues will be opened again. * * Returns 1 if the frame was an ACK, 0 if it was ignored.
*/ staticint filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, struct ieee80211_rx_status *stats)
{ struct zd_mac *mac = zd_hw_mac(hw); struct sk_buff *skb; struct sk_buff_head *q; unsignedlong flags; int found = 0; int i, position = 0;
if (!ieee80211_is_ack(rx_hdr->frame_control)) return 0;
/* Note about pass_failed_fcs and pass_ctrl access below: * mac locking intentionally omitted here, as this is the only unlocked * reader and the only writer is configure_filter. Plus, if there were * any races accessing these variables, it wouldn't really matter. * If mac80211 ever provides a way for us to access filter flags * from outside configure_filter, we could improve on this. Also, this * situation may change once we implement some kind of DMA-into-skb
* RX path. */
/* Caller has to ensure that length >= sizeof(struct rx_status). */
status = (struct rx_status *)
(buffer + (length - sizeof(struct rx_status))); if (status->frame_status & ZD_RX_ERROR) { if (mac->pass_failed_fcs &&
(status->frame_status & ZD_RX_CRC32_ERROR)) {
stats.flag |= RX_FLAG_FAILED_FCS_CRC;
bad_frame = 1;
} else { return -EINVAL;
}
}
/* todo: return index in the big switches in zd_rx_rate instead */ for (i = 0; i < mac->band.n_bitrates; i++) if (rate == mac->band.bitrates[i].hw_value)
stats.rate_idx = i;
/* Except for bad frames, filter each frame to see if it is an ACK, in * which case our internal TX tracking is updated. Normally we then * bail here as there's no need to pass ACKs on up to the stack, but * there is also the case where the stack has requested us to pass
* control frames on up (pass_ctrl) which we must consider. */ if (!bad_frame &&
filter_ack(hw, (struct ieee80211_hdr *)buffer, &stats)
&& !mac->pass_ctrl) return 0;
fc = get_unaligned((__le16*)buffer);
need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
skb = dev_alloc_skb(length + (need_padding ? 2 : 0)); if (skb == NULL) return -ENOMEM; if (need_padding) { /* Make sure the payload data is 4 byte aligned. */
skb_reserve(skb, 2);
}
/* FIXME : could we avoid this big memcpy ? */
skb_put_data(skb, buffer, length);
/* using NL80211_IFTYPE_UNSPECIFIED to indicate no mode selected */ if (mac->type != NL80211_IFTYPE_UNSPECIFIED) return -EOPNOTSUPP;
switch (vif->type) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP:
mac->type = vif->type; break; default: return -EOPNOTSUPP;
}
if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags)) return; if (!mac->vif || mac->vif->type != NL80211_IFTYPE_AP) return;
/* * Send out buffered broad- and multicast frames.
*/ while (!ieee80211_queue_stopped(mac->hw, 0)) {
skb = ieee80211_get_buffered_bc(mac->hw, mac->vif); if (!skb) break;
zd_op_tx(mac->hw, NULL, skb);
}
/* * Fetch next beacon so that tim_count is updated.
*/
beacon = ieee80211_beacon_get(mac->hw, mac->vif, 0); if (beacon)
zd_mac_config_beacon(mac->hw, beacon, true);
/* Only deal with supported flags */
changed_flags &= SUPPORTED_FIF_FLAGS;
*new_flags &= SUPPORTED_FIF_FLAGS;
/* * If multicast parameter (as returned by zd_op_prepare_multicast) * has changed, no bit in changed_flags is set. To handle this * situation, we do not return if changed_flags is 0. If we do so, * we will have some issue with IPv6 which uses multicast for link * layer address resolution.
*/ if (*new_flags & FIF_ALLMULTI)
zd_mc_add_all(&hash);
if (changed_flags & FIF_CONTROL) {
r = set_rx_filter(mac); if (r)
dev_err(zd_mac_dev(mac), "set_rx_filter error %d\n", r);
}
/* no handling required for FIF_OTHER_BSS as we don't currently
* do BSSID filtering */ /* FIXME: in future it would be nice to enable the probe response * filter (so that the driver doesn't see them) until * FIF_BCN_PRBRESP_PROMISC is set. however due to atomicity here, we'd * have to schedule work to enable prbresp reception, which might * happen too late. For now we'll just listen and forward them all the
* time. */
}
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.