static void rt2x00usb_free_entries(struct data_queue *queue) { struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; struct queue_entry_priv_usb *entry_priv; struct queue_entry_priv_usb_bcn *bcn_priv; unsigned int i; if (!queue->entries) return; for (i = 0; i < queue->limit; i++) { entry_priv = queue->entries[i].priv_data; usb_kill_urb(entry_priv->urb); usb_free_urb(entry_priv->urb); } /* * If this is not the beacon queue or * no guardian byte was required for the beacon, * then we are done. */ if (queue->qid != QID_BEACON || !rt2x00_has_cap_flag(rt2x00dev, REQUIRE_BEACON_GUARD)) return; for (i = 0; i < queue->limit; i++) { bcn_priv = queue->entries[i].priv_data; usb_kill_urb(bcn_priv->guardian_urb); usb_free_urb(bcn_priv->guardian_urb); } }
static int rt2x00usb_alloc_entries(struct data_queue *queue) { struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; struct queue_entry_priv_usb *entry_priv; struct queue_entry_priv_usb_bcn *bcn_priv; unsigned int i; for (i = 0; i < queue->limit; i++) { entry_priv = queue->entries[i].priv_data; entry_priv->urb = usb_alloc_urb(0, GFP_KERNEL); if (!entry_priv->urb) return -ENOMEM; } /* * If this is not the beacon queue or * no guardian byte was required for the beacon, * then we are done. */ if (queue->qid != QID_BEACON || !rt2x00_has_cap_flag(rt2x00dev, REQUIRE_BEACON_GUARD)) return 0; for (i = 0; i < queue->limit; i++) { bcn_priv = queue->entries[i].priv_data; bcn_priv->guardian_urb = usb_alloc_urb(0, GFP_KERNEL); if (!bcn_priv->guardian_urb) return -ENOMEM; } return 0; }
static void rt2x00usb_interrupt_txdone(struct urb *urb) { struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* * Check if the frame was correctly uploaded */ if (urb->status) set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); /* * Report the frame as DMA done */ rt2x00lib_dmadone(entry); if (rt2x00dev->ops->lib->tx_dma_done) rt2x00dev->ops->lib->tx_dma_done(entry); /* * Schedule the delayed work for reading the TX status * from the device. */ if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_TXSTATUS_FIFO) || !kfifo_is_empty(&rt2x00dev->txstatus_fifo)) queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); }
static bool rt2x00usb_flush_entry(struct queue_entry *entry, void *data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_usb *entry_priv = entry->priv_data; struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return false; usb_kill_urb(entry_priv->urb); /* * Kill guardian urb (if required by driver). */ if ((entry->queue->qid == QID_BEACON) && (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_BEACON_GUARD))) usb_kill_urb(bcn_priv->guardian_urb); return false; }
void rt2x00mac_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { struct rt2x00_dev *rt2x00dev = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); enum data_queue_qid qid = skb_get_queue_mapping(skb); struct data_queue *queue = NULL; /* * Mac80211 might be calling this function while we are trying * to remove the device or perhaps suspending it. * Note that we can only stop the TX queues inside the TX path * due to possible race conditions in mac80211. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) goto exit_free_skb; /* * Use the ATIM queue if appropriate and present. */ if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && rt2x00_has_cap_flag(rt2x00dev, REQUIRE_ATIM_QUEUE)) qid = QID_ATIM; queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); if (unlikely(!queue)) { rt2x00_err(rt2x00dev, "Attempt to send packet over invalid queue %d\n" "Please file bug report to %s\n", qid, DRV_PROJECT); goto exit_free_skb; } /* * If CTS/RTS is required. create and queue that frame first. * Make sure we have at least enough entries available to send * this CTS/RTS frame as well as the data frame. * Note that when the driver has set the set_rts_threshold() * callback function it doesn't need software generation of * either RTS or CTS-to-self frame and handles everything * inside the hardware. */ if (!rt2x00dev->ops->hw->set_rts_threshold && (tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS | IEEE80211_TX_RC_USE_CTS_PROTECT))) { if (rt2x00queue_available(queue) <= 1) goto exit_fail; if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) goto exit_fail; } if (unlikely(rt2x00queue_write_tx_frame(queue, skb, control->sta, false))) goto exit_fail; /* * Pausing queue has to be serialized with rt2x00lib_txdone(). Note * we should not use spin_lock_bh variant as bottom halve was already * disabled before ieee80211_xmit() call. */ spin_lock(&queue->tx_lock); if (rt2x00queue_threshold(queue)) rt2x00queue_pause_queue(queue); spin_unlock(&queue->tx_lock); return; exit_fail: spin_lock(&queue->tx_lock); rt2x00queue_pause_queue(queue); spin_unlock(&queue->tx_lock); exit_free_skb: ieee80211_free_txskb(hw, skb); }
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, unsigned int ieee80211_flags) { struct rt2x00lib_conf libconf; u16 hw_value; u16 autowake_timeout; u16 beacon_int; u16 beacon_diff; memset(&libconf, 0, sizeof(libconf)); libconf.conf = conf; if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { if (!conf_is_ht(conf)) set_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags); else clear_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags); if (conf_is_ht40(conf)) { set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); hw_value = rt2x00ht_center_channel(rt2x00dev, conf); } else { clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); hw_value = conf->chandef.chan->hw_value; } memcpy(&libconf.rf, &rt2x00dev->spec.channels[hw_value], sizeof(libconf.rf)); memcpy(&libconf.channel, &rt2x00dev->spec.channels_info[hw_value], sizeof(libconf.channel)); /* Used for VCO periodic calibration */ rt2x00dev->rf_channel = libconf.rf.channel; } if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_PS_AUTOWAKE) && (ieee80211_flags & IEEE80211_CONF_CHANGE_PS)) cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); /* * Start configuration. */ rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags); /* * Some configuration changes affect the link quality * which means we need to reset the link tuner. */ if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) rt2x00link_reset_tuner(rt2x00dev, false); if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && rt2x00_has_cap_flag(rt2x00dev, REQUIRE_PS_AUTOWAKE) && (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) && (conf->flags & IEEE80211_CONF_PS)) { beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon; beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int); if (beacon_diff > beacon_int) beacon_diff = 0; autowake_timeout = (conf->ps_dtim_period * beacon_int) - beacon_diff; queue_delayed_work(rt2x00dev->workqueue, &rt2x00dev->autowakeup_work, autowake_timeout - 15); } if (conf->flags & IEEE80211_CONF_PS) set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); else clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); rt2x00dev->curr_band = conf->chandef.chan->band; rt2x00dev->curr_freq = conf->chandef.chan->center_freq; rt2x00dev->tx_power = conf->power_level; rt2x00dev->short_retry = conf->short_frame_max_tx_count; rt2x00dev->long_retry = conf->long_frame_max_tx_count; }