mirror of
https://github.com/torvalds/linux.git
synced 2024-11-02 02:01:29 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
84503ddd65
@ -153,7 +153,7 @@ config LIBERTAS_SDIO
|
||||
|
||||
config LIBERTAS_SPI
|
||||
tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
|
||||
depends on LIBERTAS && SPI && GENERIC_GPIO
|
||||
depends on LIBERTAS && SPI
|
||||
---help---
|
||||
A driver for Marvell Libertas 8686 SPI devices.
|
||||
|
||||
|
@ -109,6 +109,11 @@ struct ar9170_rxstream_mpdu_merge {
|
||||
bool has_plcp;
|
||||
};
|
||||
|
||||
#define AR9170_QUEUE_TIMEOUT 64
|
||||
#define AR9170_TX_TIMEOUT 8
|
||||
#define AR9170_JANITOR_DELAY 128
|
||||
#define AR9170_TX_INVALID_RATE 0xffffffff
|
||||
|
||||
struct ar9170 {
|
||||
struct ieee80211_hw *hw;
|
||||
struct mutex mutex;
|
||||
@ -117,10 +122,11 @@ struct ar9170 {
|
||||
|
||||
int (*open)(struct ar9170 *);
|
||||
void (*stop)(struct ar9170 *);
|
||||
int (*tx)(struct ar9170 *, struct sk_buff *, bool, unsigned int);
|
||||
int (*tx)(struct ar9170 *, struct sk_buff *);
|
||||
int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 ,
|
||||
void *, u32 , void *);
|
||||
void (*callback_cmd)(struct ar9170 *, u32 , void *);
|
||||
int (*flush)(struct ar9170 *);
|
||||
|
||||
/* interface mode settings */
|
||||
struct ieee80211_vif *vif;
|
||||
@ -177,10 +183,10 @@ struct ar9170 {
|
||||
struct ar9170_eeprom eeprom;
|
||||
struct ath_regulatory regulatory;
|
||||
|
||||
/* global tx status for unregistered Stations. */
|
||||
struct sk_buff_head global_tx_status;
|
||||
struct sk_buff_head global_tx_status_waste;
|
||||
struct delayed_work tx_status_janitor;
|
||||
/* tx queues - as seen by hw - */
|
||||
struct sk_buff_head tx_pending[__AR9170_NUM_TXQ];
|
||||
struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
|
||||
struct delayed_work tx_janitor;
|
||||
|
||||
/* rxstream mpdu merge */
|
||||
struct ar9170_rxstream_mpdu_merge rx_mpdu;
|
||||
@ -189,11 +195,19 @@ struct ar9170 {
|
||||
};
|
||||
|
||||
struct ar9170_sta_info {
|
||||
struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
|
||||
};
|
||||
|
||||
#define IS_STARTED(a) (a->state >= AR9170_STARTED)
|
||||
#define IS_ACCEPTING_CMD(a) (a->state >= AR9170_IDLE)
|
||||
#define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0)
|
||||
#define AR9170_TX_FLAG_NO_ACK BIT(1)
|
||||
#define AR9170_TX_FLAG_BLOCK_ACK BIT(2)
|
||||
|
||||
struct ar9170_tx_info {
|
||||
unsigned long timeout;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED)
|
||||
#define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE)
|
||||
|
||||
#define AR9170_FILTER_CHANGED_MODE BIT(0)
|
||||
#define AR9170_FILTER_CHANGED_MULTICAST BIT(1)
|
||||
@ -204,9 +218,9 @@ void *ar9170_alloc(size_t priv_size);
|
||||
int ar9170_register(struct ar9170 *ar, struct device *pdev);
|
||||
void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb);
|
||||
void ar9170_unregister(struct ar9170 *ar);
|
||||
void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
|
||||
bool update_statistics, u16 tx_status);
|
||||
void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb);
|
||||
void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
|
||||
int ar9170_nag_limiter(struct ar9170 *ar);
|
||||
|
||||
/* MAC */
|
||||
int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
|
@ -420,4 +420,7 @@ enum ar9170_txq {
|
||||
__AR9170_NUM_TXQ,
|
||||
};
|
||||
|
||||
#define AR9170_TXQ_DEPTH 32
|
||||
#define AR9170_TX_MAX_PENDING 128
|
||||
|
||||
#endif /* __AR9170_HW_H */
|
||||
|
@ -173,59 +173,122 @@ static struct ieee80211_supported_band ar9170_band_5GHz = {
|
||||
.ht_cap = AR9170_HT_CAP,
|
||||
};
|
||||
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
/*
|
||||
* In case some wants works with AR9170's crazy tx_status queueing techniques.
|
||||
* He might need this rather useful probing function.
|
||||
*
|
||||
* NOTE: caller must hold the queue's spinlock!
|
||||
*/
|
||||
static void ar9170_tx(struct ar9170 *ar);
|
||||
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ar9170_tx_control *txc = (void *) skb->data;
|
||||
struct ieee80211_hdr *hdr = (void *)txc->frame_data;
|
||||
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
|
||||
struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
|
||||
struct ieee80211_hdr *hdr = (void *) txc->frame_data;
|
||||
|
||||
printk(KERN_DEBUG "%s: => FRAME [skb:%p, queue:%d, DA:[%pM] "
|
||||
"mac_control:%04x, phy_control:%08x]\n",
|
||||
printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x "
|
||||
"mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
|
||||
wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
|
||||
ieee80211_get_DA(hdr), le16_to_cpu(txc->mac_control),
|
||||
le32_to_cpu(txc->phy_control));
|
||||
ieee80211_get_DA(hdr), arinfo->flags,
|
||||
le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
|
||||
jiffies_to_msecs(arinfo->timeout - jiffies));
|
||||
}
|
||||
|
||||
static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar,
|
||||
struct sk_buff_head *queue)
|
||||
static void __ar9170_dump_txqueue(struct ar9170 *ar,
|
||||
struct sk_buff_head *queue)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int i = 0;
|
||||
|
||||
printk(KERN_DEBUG "---[ cut here ]---\n");
|
||||
printk(KERN_DEBUG "%s: %d entries in tx_status queue.\n",
|
||||
printk(KERN_DEBUG "%s: %d entries in queue.\n",
|
||||
wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
|
||||
|
||||
skb_queue_walk(queue, skb) {
|
||||
struct ar9170_tx_control *txc = (void *) skb->data;
|
||||
struct ieee80211_hdr *hdr = (void *)txc->frame_data;
|
||||
|
||||
printk(KERN_DEBUG "index:%d => \n", i);
|
||||
printk(KERN_DEBUG "index:%d => \n", i++);
|
||||
ar9170_print_txheader(ar, skb);
|
||||
}
|
||||
if (i != skb_queue_len(queue))
|
||||
printk(KERN_DEBUG "WARNING: queue frame counter "
|
||||
"mismatch %d != %d\n", skb_queue_len(queue), i);
|
||||
printk(KERN_DEBUG "---[ end ]---\n");
|
||||
}
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
|
||||
void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
|
||||
bool valid_status, u16 tx_status)
|
||||
static void ar9170_dump_txqueue(struct ar9170 *ar,
|
||||
struct sk_buff_head *queue)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&queue->lock, flags);
|
||||
__ar9170_dump_txqueue(ar, queue);
|
||||
spin_unlock_irqrestore(&queue->lock, flags);
|
||||
}
|
||||
|
||||
static void __ar9170_dump_txstats(struct ar9170 *ar)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk(KERN_DEBUG "%s: QoS queue stats\n",
|
||||
wiphy_name(ar->hw->wiphy));
|
||||
|
||||
for (i = 0; i < __AR9170_NUM_TXQ; i++)
|
||||
printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d\n",
|
||||
wiphy_name(ar->hw->wiphy), i, ar->tx_stats[i].limit,
|
||||
ar->tx_stats[i].len, skb_queue_len(&ar->tx_status[i]));
|
||||
}
|
||||
|
||||
static void ar9170_dump_txstats(struct ar9170 *ar)
|
||||
{
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
unsigned int retries = 0, queue = skb_get_queue_mapping(skb);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ar->tx_stats_lock, flags);
|
||||
ar->tx_stats[queue].len--;
|
||||
if (ieee80211_queue_stopped(ar->hw, queue))
|
||||
ieee80211_wake_queue(ar->hw, queue);
|
||||
__ar9170_dump_txstats(ar);
|
||||
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
|
||||
}
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
|
||||
/* caller must guarantee exclusive access for _bin_ queue. */
|
||||
static void ar9170_recycle_expired(struct ar9170 *ar,
|
||||
struct sk_buff_head *queue,
|
||||
struct sk_buff_head *bin)
|
||||
{
|
||||
struct sk_buff *skb, *old = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&queue->lock, flags);
|
||||
while ((skb = skb_peek(queue))) {
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
struct ar9170_tx_info *arinfo;
|
||||
|
||||
txinfo = IEEE80211_SKB_CB(skb);
|
||||
arinfo = (void *) txinfo->rate_driver_data;
|
||||
|
||||
if (time_is_before_jiffies(arinfo->timeout)) {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => "
|
||||
"recycle \n", wiphy_name(ar->hw->wiphy),
|
||||
jiffies, arinfo->timeout);
|
||||
ar9170_print_txheader(ar, skb);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
__skb_unlink(skb, queue);
|
||||
__skb_queue_tail(bin, skb);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(old == skb)) {
|
||||
/* bail out - queue is shot. */
|
||||
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
old = skb;
|
||||
}
|
||||
spin_unlock_irqrestore(&queue->lock, flags);
|
||||
}
|
||||
|
||||
static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
|
||||
u16 tx_status)
|
||||
{
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
unsigned int retries = 0;
|
||||
|
||||
txinfo = IEEE80211_SKB_CB(skb);
|
||||
ieee80211_tx_info_clear_status(txinfo);
|
||||
@ -247,45 +310,61 @@ void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
|
||||
break;
|
||||
}
|
||||
|
||||
if (valid_status)
|
||||
txinfo->status.rates[0].count = retries + 1;
|
||||
|
||||
txinfo->status.rates[0].count = retries + 1;
|
||||
skb_pull(skb, sizeof(struct ar9170_tx_control));
|
||||
ieee80211_tx_status_irqsafe(ar->hw, skb);
|
||||
}
|
||||
|
||||
static struct sk_buff *ar9170_find_skb_in_queue(struct ar9170 *ar,
|
||||
const u8 *mac,
|
||||
const u32 queue,
|
||||
struct sk_buff_head *q)
|
||||
void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data;
|
||||
unsigned int queue = skb_get_queue_mapping(skb);
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb;
|
||||
|
||||
spin_lock_irqsave(&q->lock, flags);
|
||||
skb_queue_walk(q, skb) {
|
||||
struct ar9170_tx_control *txc = (void *) skb->data;
|
||||
struct ieee80211_hdr *hdr = (void *) txc->frame_data;
|
||||
u32 txc_queue = (le32_to_cpu(txc->phy_control) &
|
||||
AR9170_TX_PHY_QOS_MASK) >>
|
||||
AR9170_TX_PHY_QOS_SHIFT;
|
||||
spin_lock_irqsave(&ar->tx_stats_lock, flags);
|
||||
ar->tx_stats[queue].len--;
|
||||
|
||||
if ((queue != txc_queue) ||
|
||||
(compare_ether_addr(ieee80211_get_DA(hdr), mac)))
|
||||
continue;
|
||||
|
||||
__skb_unlink(skb, q);
|
||||
spin_unlock_irqrestore(&q->lock, flags);
|
||||
return skb;
|
||||
if (skb_queue_empty(&ar->tx_pending[queue])) {
|
||||
#ifdef AR9170_QUEUE_STOP_DEBUG
|
||||
printk(KERN_DEBUG "%s: wake queue %d\n",
|
||||
wiphy_name(ar->hw->wiphy), queue);
|
||||
__ar9170_dump_txstats(ar);
|
||||
#endif /* AR9170_QUEUE_STOP_DEBUG */
|
||||
ieee80211_wake_queue(ar->hw, queue);
|
||||
}
|
||||
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
|
||||
|
||||
if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) {
|
||||
dev_kfree_skb_any(skb);
|
||||
} else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) {
|
||||
arinfo->timeout = jiffies +
|
||||
msecs_to_jiffies(AR9170_TX_TIMEOUT);
|
||||
|
||||
skb_queue_tail(&ar->tx_status[queue], skb);
|
||||
} else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) {
|
||||
ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED);
|
||||
} else {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: unsupported frame flags!\n",
|
||||
wiphy_name(ar->hw->wiphy));
|
||||
ar9170_print_txheader(ar, skb);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
if (!ar->tx_stats[queue].len &&
|
||||
!skb_queue_empty(&ar->tx_pending[queue])) {
|
||||
ar9170_tx(ar);
|
||||
}
|
||||
spin_unlock_irqrestore(&q->lock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac,
|
||||
const u32 queue)
|
||||
static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar,
|
||||
const u8 *mac,
|
||||
struct sk_buff_head *queue,
|
||||
const u32 rate)
|
||||
{
|
||||
struct ieee80211_sta *sta;
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/*
|
||||
@ -296,78 +375,91 @@ static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac,
|
||||
* the firmware provided (-> destination MAC, and phy_control) -
|
||||
* and hope that we picked the right one...
|
||||
*/
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(ar->hw, mac);
|
||||
|
||||
if (likely(sta)) {
|
||||
struct ar9170_sta_info *sta_priv = (void *) sta->drv_priv;
|
||||
skb = skb_dequeue(&sta_priv->tx_status[queue]);
|
||||
rcu_read_unlock();
|
||||
if (likely(skb))
|
||||
return skb;
|
||||
} else
|
||||
rcu_read_unlock();
|
||||
spin_lock_irqsave(&queue->lock, flags);
|
||||
skb_queue_walk(queue, skb) {
|
||||
struct ar9170_tx_control *txc = (void *) skb->data;
|
||||
struct ieee80211_hdr *hdr = (void *) txc->frame_data;
|
||||
u32 r;
|
||||
|
||||
/* scan the waste queue for candidates */
|
||||
skb = ar9170_find_skb_in_queue(ar, mac, queue,
|
||||
&ar->global_tx_status_waste);
|
||||
if (!skb) {
|
||||
/* so it still _must_ be in the global list. */
|
||||
skb = ar9170_find_skb_in_queue(ar, mac, queue,
|
||||
&ar->global_tx_status);
|
||||
if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: skip frame => DA %pM != %pM\n",
|
||||
wiphy_name(ar->hw->wiphy), mac,
|
||||
ieee80211_get_DA(hdr));
|
||||
ar9170_print_txheader(ar, skb);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
continue;
|
||||
}
|
||||
|
||||
r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >>
|
||||
AR9170_TX_PHY_MCS_SHIFT;
|
||||
|
||||
if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: skip frame => rate %d != %d\n",
|
||||
wiphy_name(ar->hw->wiphy), rate, r);
|
||||
ar9170_print_txheader(ar, skb);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
continue;
|
||||
}
|
||||
|
||||
__skb_unlink(skb, queue);
|
||||
spin_unlock_irqrestore(&queue->lock, flags);
|
||||
return skb;
|
||||
}
|
||||
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
if (unlikely((!skb) && net_ratelimit())) {
|
||||
printk(KERN_ERR "%s: ESS:[%pM] does not have any "
|
||||
"outstanding frames in this queue (%d).\n",
|
||||
wiphy_name(ar->hw->wiphy), mac, queue);
|
||||
}
|
||||
printk(KERN_ERR "%s: ESS:[%pM] does not have any "
|
||||
"outstanding frames in queue.\n",
|
||||
wiphy_name(ar->hw->wiphy), mac);
|
||||
__ar9170_dump_txqueue(ar, queue);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
return skb;
|
||||
spin_unlock_irqrestore(&queue->lock, flags);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This worker tries to keep the global tx_status queue empty.
|
||||
* So we can guarantee that incoming tx_status reports for
|
||||
* unregistered stations are always synced with the actual
|
||||
* frame - which we think - belongs to.
|
||||
* This worker tries to keeps an maintain tx_status queues.
|
||||
* So we can guarantee that incoming tx_status reports are
|
||||
* actually for a pending frame.
|
||||
*/
|
||||
|
||||
static void ar9170_tx_status_janitor(struct work_struct *work)
|
||||
static void ar9170_tx_janitor(struct work_struct *work)
|
||||
{
|
||||
struct ar9170 *ar = container_of(work, struct ar9170,
|
||||
tx_status_janitor.work);
|
||||
struct sk_buff *skb;
|
||||
tx_janitor.work);
|
||||
struct sk_buff_head waste;
|
||||
unsigned int i;
|
||||
bool resched = false;
|
||||
|
||||
if (unlikely(!IS_STARTED(ar)))
|
||||
return ;
|
||||
|
||||
/* recycle the garbage back to mac80211... one by one. */
|
||||
while ((skb = skb_dequeue(&ar->global_tx_status_waste))) {
|
||||
skb_queue_head_init(&waste);
|
||||
|
||||
for (i = 0; i < __AR9170_NUM_TXQ; i++) {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: dispose queued frame =>\n",
|
||||
wiphy_name(ar->hw->wiphy));
|
||||
ar9170_print_txheader(ar, skb);
|
||||
printk(KERN_DEBUG "%s: garbage collector scans queue:%d\n",
|
||||
wiphy_name(ar->hw->wiphy), i);
|
||||
ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
|
||||
ar9170_dump_txqueue(ar, &ar->tx_status[i]);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
ar9170_handle_tx_status(ar, skb, false,
|
||||
AR9170_TX_STATUS_FAILED);
|
||||
|
||||
ar9170_recycle_expired(ar, &ar->tx_status[i], &waste);
|
||||
ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste);
|
||||
skb_queue_purge(&waste);
|
||||
|
||||
if (!skb_queue_empty(&ar->tx_status[i]) ||
|
||||
!skb_queue_empty(&ar->tx_pending[i]))
|
||||
resched = true;
|
||||
}
|
||||
|
||||
while ((skb = skb_dequeue(&ar->global_tx_status))) {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: moving frame into waste queue =>\n",
|
||||
wiphy_name(ar->hw->wiphy));
|
||||
|
||||
ar9170_print_txheader(ar, skb);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
skb_queue_tail(&ar->global_tx_status_waste, skb);
|
||||
}
|
||||
|
||||
/* recall the janitor in 100ms - if there's garbage in the can. */
|
||||
if (skb_queue_len(&ar->global_tx_status_waste) > 0)
|
||||
queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor,
|
||||
msecs_to_jiffies(100));
|
||||
if (resched)
|
||||
queue_delayed_work(ar->hw->workqueue,
|
||||
&ar->tx_janitor,
|
||||
msecs_to_jiffies(AR9170_JANITOR_DELAY));
|
||||
}
|
||||
|
||||
void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
|
||||
@ -394,15 +486,21 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
|
||||
*/
|
||||
|
||||
struct sk_buff *skb;
|
||||
u32 queue = (le32_to_cpu(cmd->tx_status.rate) &
|
||||
AR9170_TX_PHY_QOS_MASK) >> AR9170_TX_PHY_QOS_SHIFT;
|
||||
u32 phy = le32_to_cpu(cmd->tx_status.rate);
|
||||
u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >>
|
||||
AR9170_TX_PHY_QOS_SHIFT;
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: recv tx_status for %pM, p:%08x, q:%d\n",
|
||||
wiphy_name(ar->hw->wiphy), cmd->tx_status.dst, phy, q);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
|
||||
skb = ar9170_find_queued_skb(ar, cmd->tx_status.dst, queue);
|
||||
skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst,
|
||||
&ar->tx_status[q],
|
||||
AR9170_TX_INVALID_RATE);
|
||||
if (unlikely(!skb))
|
||||
return ;
|
||||
|
||||
ar9170_handle_tx_status(ar, skb, true,
|
||||
le16_to_cpu(cmd->tx_status.status));
|
||||
ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -442,6 +540,38 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
|
||||
/* retransmission issue / SIFS/EIFS collision ?! */
|
||||
break;
|
||||
|
||||
/* firmware debug */
|
||||
case 0xca:
|
||||
printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4);
|
||||
break;
|
||||
case 0xcb:
|
||||
len -= 4;
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n",
|
||||
*((char *)buf + 4));
|
||||
break;
|
||||
case 2:
|
||||
printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n",
|
||||
le16_to_cpup((__le16 *)((char *)buf + 4)));
|
||||
break;
|
||||
case 4:
|
||||
printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n",
|
||||
le32_to_cpup((__le32 *)((char *)buf + 4)));
|
||||
break;
|
||||
case 8:
|
||||
printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n",
|
||||
(unsigned long)le64_to_cpup(
|
||||
(__le64 *)((char *)buf + 4)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xcc:
|
||||
print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE,
|
||||
(char *)buf + 4, len - 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_INFO "received unhandled event %x\n", cmd->type);
|
||||
print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
|
||||
@ -455,7 +585,7 @@ static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar)
|
||||
ar->rx_mpdu.has_plcp = false;
|
||||
}
|
||||
|
||||
static int ar9170_nag_limiter(struct ar9170 *ar)
|
||||
int ar9170_nag_limiter(struct ar9170 *ar)
|
||||
{
|
||||
bool print_message;
|
||||
|
||||
@ -956,8 +1086,8 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
|
||||
|
||||
/* reinitialize queues statistics */
|
||||
memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
|
||||
for (i = 0; i < ARRAY_SIZE(ar->tx_stats); i++)
|
||||
ar->tx_stats[i].limit = 8;
|
||||
for (i = 0; i < __AR9170_NUM_TXQ; i++)
|
||||
ar->tx_stats[i].limit = AR9170_TXQ_DEPTH;
|
||||
|
||||
/* reset QoS defaults */
|
||||
AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/
|
||||
@ -1003,18 +1133,17 @@ out:
|
||||
static void ar9170_op_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
unsigned int i;
|
||||
|
||||
if (IS_STARTED(ar))
|
||||
ar->state = AR9170_IDLE;
|
||||
|
||||
flush_workqueue(ar->hw->workqueue);
|
||||
|
||||
cancel_delayed_work_sync(&ar->tx_status_janitor);
|
||||
cancel_delayed_work_sync(&ar->tx_janitor);
|
||||
cancel_work_sync(&ar->filter_config_work);
|
||||
cancel_work_sync(&ar->beacon_work);
|
||||
mutex_lock(&ar->mutex);
|
||||
skb_queue_purge(&ar->global_tx_status_waste);
|
||||
skb_queue_purge(&ar->global_tx_status);
|
||||
|
||||
if (IS_ACCEPTING_CMD(ar)) {
|
||||
ar9170_set_leds_state(ar, 0);
|
||||
@ -1024,51 +1153,32 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
|
||||
ar->stop(ar);
|
||||
}
|
||||
|
||||
for (i = 0; i < __AR9170_NUM_TXQ; i++) {
|
||||
skb_queue_purge(&ar->tx_pending[i]);
|
||||
skb_queue_purge(&ar->tx_status[i]);
|
||||
}
|
||||
mutex_unlock(&ar->mutex);
|
||||
}
|
||||
|
||||
int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ar9170_tx_control *txc;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ieee80211_rate *rate = NULL;
|
||||
struct ieee80211_tx_rate *txrate;
|
||||
struct ar9170_tx_info *arinfo;
|
||||
unsigned int queue = skb_get_queue_mapping(skb);
|
||||
unsigned long flags = 0;
|
||||
struct ar9170_sta_info *sta_info = NULL;
|
||||
u32 power, chains;
|
||||
u16 keytype = 0;
|
||||
u16 len, icv = 0;
|
||||
int err;
|
||||
bool tx_status;
|
||||
|
||||
if (unlikely(!IS_STARTED(ar)))
|
||||
goto err_free;
|
||||
BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
|
||||
|
||||
hdr = (void *)skb->data;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
len = skb->len;
|
||||
|
||||
spin_lock_irqsave(&ar->tx_stats_lock, flags);
|
||||
if (ar->tx_stats[queue].limit < ar->tx_stats[queue].len) {
|
||||
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
ar->tx_stats[queue].len++;
|
||||
ar->tx_stats[queue].count++;
|
||||
if (ar->tx_stats[queue].limit == ar->tx_stats[queue].len)
|
||||
ieee80211_stop_queue(hw, queue);
|
||||
|
||||
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
|
||||
|
||||
txc = (void *)skb_push(skb, sizeof(*txc));
|
||||
|
||||
tx_status = (((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) != 0) ||
|
||||
((info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) != 0));
|
||||
|
||||
if (info->control.hw_key) {
|
||||
icv = info->control.hw_key->icv_len;
|
||||
|
||||
@ -1084,7 +1194,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
goto err_dequeue;
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1101,16 +1211,65 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
|
||||
|
||||
txrate = &info->control.rates[0];
|
||||
|
||||
if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
|
||||
txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
|
||||
else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
|
||||
txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
|
||||
|
||||
arinfo = (void *)info->rate_driver_data;
|
||||
arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT);
|
||||
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
|
||||
(is_valid_ether_addr(ieee80211_get_DA(hdr)))) {
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||
if (unlikely(!info->control.sta))
|
||||
goto err_out;
|
||||
|
||||
txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
|
||||
arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE);
|
||||
/*
|
||||
* WARNING:
|
||||
* Putting the QoS queue bits into an unexplored territory is
|
||||
* certainly not elegant.
|
||||
*
|
||||
* In my defense: This idea provides a reasonable way to
|
||||
* smuggle valuable information to the tx_status callback.
|
||||
* Also, the idea behind this bit-abuse came straight from
|
||||
* the original driver code.
|
||||
*/
|
||||
|
||||
txc->phy_control |=
|
||||
cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT);
|
||||
arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK;
|
||||
} else {
|
||||
arinfo->flags = AR9170_TX_FLAG_NO_ACK;
|
||||
}
|
||||
|
||||
out:
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
skb_pull(skb, sizeof(*txc));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ar9170_tx_control *txc;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ieee80211_rate *rate = NULL;
|
||||
struct ieee80211_tx_rate *txrate;
|
||||
u32 power, chains;
|
||||
|
||||
txc = (void *) skb->data;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
txrate = &info->control.rates[0];
|
||||
|
||||
if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
|
||||
txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
|
||||
|
||||
@ -1130,9 +1289,12 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
u32 r = txrate->idx;
|
||||
u8 *txpower;
|
||||
|
||||
/* heavy clip control */
|
||||
txc->phy_control |= cpu_to_le32((r & 0x7) << 7);
|
||||
|
||||
r <<= AR9170_TX_PHY_MCS_SHIFT;
|
||||
if (WARN_ON(r & ~AR9170_TX_PHY_MCS_MASK))
|
||||
goto err_dequeue;
|
||||
BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK);
|
||||
|
||||
txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK);
|
||||
txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
|
||||
|
||||
@ -1194,53 +1356,154 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
chains = AR9170_TX_PHY_TXCHAIN_1;
|
||||
}
|
||||
txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT);
|
||||
}
|
||||
|
||||
if (tx_status) {
|
||||
txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE);
|
||||
/*
|
||||
* WARNING:
|
||||
* Putting the QoS queue bits into an unexplored territory is
|
||||
* certainly not elegant.
|
||||
*
|
||||
* In my defense: This idea provides a reasonable way to
|
||||
* smuggle valuable information to the tx_status callback.
|
||||
* Also, the idea behind this bit-abuse came straight from
|
||||
* the original driver code.
|
||||
*/
|
||||
static void ar9170_tx(struct ar9170 *ar)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ar9170_tx_info *arinfo;
|
||||
unsigned int i, frames, frames_failed, remaining_space;
|
||||
int err;
|
||||
bool schedule_garbagecollector = false;
|
||||
|
||||
txc->phy_control |=
|
||||
cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT);
|
||||
BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
|
||||
|
||||
if (info->control.sta) {
|
||||
sta_info = (void *) info->control.sta->drv_priv;
|
||||
skb_queue_tail(&sta_info->tx_status[queue], skb);
|
||||
} else {
|
||||
skb_queue_tail(&ar->global_tx_status, skb);
|
||||
if (unlikely(!IS_STARTED(ar)))
|
||||
return ;
|
||||
|
||||
queue_delayed_work(ar->hw->workqueue,
|
||||
&ar->tx_status_janitor,
|
||||
msecs_to_jiffies(100));
|
||||
remaining_space = AR9170_TX_MAX_PENDING;
|
||||
|
||||
for (i = 0; i < __AR9170_NUM_TXQ; i++) {
|
||||
spin_lock_irqsave(&ar->tx_stats_lock, flags);
|
||||
if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: queue %d full\n",
|
||||
wiphy_name(ar->hw->wiphy), i);
|
||||
|
||||
__ar9170_dump_txstats(ar);
|
||||
printk(KERN_DEBUG "stuck frames: ===> \n");
|
||||
ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
|
||||
ar9170_dump_txqueue(ar, &ar->tx_status[i]);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
ieee80211_stop_queue(ar->hw, i);
|
||||
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len,
|
||||
skb_queue_len(&ar->tx_pending[i]));
|
||||
|
||||
if (remaining_space < frames) {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: tx quota reached queue:%d, "
|
||||
"remaining slots:%d, needed:%d\n",
|
||||
wiphy_name(ar->hw->wiphy), i, remaining_space,
|
||||
frames);
|
||||
|
||||
ar9170_dump_txstats(ar);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
frames = remaining_space;
|
||||
}
|
||||
|
||||
ar->tx_stats[i].len += frames;
|
||||
ar->tx_stats[i].count += frames;
|
||||
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
|
||||
|
||||
if (!frames)
|
||||
continue;
|
||||
|
||||
frames_failed = 0;
|
||||
while (frames) {
|
||||
skb = skb_dequeue(&ar->tx_pending[i]);
|
||||
if (unlikely(!skb)) {
|
||||
frames_failed += frames;
|
||||
frames = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
arinfo = (void *) info->rate_driver_data;
|
||||
|
||||
/* TODO: cancel stuck frames */
|
||||
arinfo->timeout = jiffies +
|
||||
msecs_to_jiffies(AR9170_TX_TIMEOUT);
|
||||
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: send frame q:%d =>\n",
|
||||
wiphy_name(ar->hw->wiphy), i);
|
||||
ar9170_print_txheader(ar, skb);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
|
||||
err = ar->tx(ar, skb);
|
||||
if (unlikely(err)) {
|
||||
frames_failed++;
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
remaining_space--;
|
||||
schedule_garbagecollector = true;
|
||||
}
|
||||
|
||||
frames--;
|
||||
}
|
||||
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: ar9170_tx report for queue %d\n",
|
||||
wiphy_name(ar->hw->wiphy), i);
|
||||
|
||||
printk(KERN_DEBUG "%s: unprocessed pending frames left:\n",
|
||||
wiphy_name(ar->hw->wiphy));
|
||||
ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
|
||||
if (unlikely(frames_failed)) {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: frames failed =>\n",
|
||||
wiphy_name(ar->hw->wiphy), frames_failed);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
|
||||
spin_lock_irqsave(&ar->tx_stats_lock, flags);
|
||||
ar->tx_stats[i].len -= frames_failed;
|
||||
ar->tx_stats[i].count -= frames_failed;
|
||||
ieee80211_wake_queue(ar->hw, i);
|
||||
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
err = ar->tx(ar, skb, tx_status, 0);
|
||||
if (unlikely(tx_status && err)) {
|
||||
if (info->control.sta)
|
||||
skb_unlink(skb, &sta_info->tx_status[queue]);
|
||||
else
|
||||
skb_unlink(skb, &ar->global_tx_status);
|
||||
if (schedule_garbagecollector)
|
||||
queue_delayed_work(ar->hw->workqueue,
|
||||
&ar->tx_janitor,
|
||||
msecs_to_jiffies(AR9170_JANITOR_DELAY));
|
||||
}
|
||||
|
||||
int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
if (unlikely(!IS_STARTED(ar)))
|
||||
goto err_free;
|
||||
|
||||
if (unlikely(ar9170_tx_prepare(ar, skb)))
|
||||
goto err_free;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||
/* drop frame, we do not allow TX A-MPDU aggregation yet. */
|
||||
goto err_free;
|
||||
} else {
|
||||
unsigned int queue = skb_get_queue_mapping(skb);
|
||||
|
||||
ar9170_tx_prepare_phy(ar, skb);
|
||||
skb_queue_tail(&ar->tx_pending[queue], skb);
|
||||
}
|
||||
|
||||
ar9170_tx(ar);
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
err_dequeue:
|
||||
spin_lock_irqsave(&ar->tx_stats_lock, flags);
|
||||
ar->tx_stats[queue].len--;
|
||||
ar->tx_stats[queue].count--;
|
||||
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
|
||||
|
||||
err_free:
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
@ -1666,43 +1929,6 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
struct ar9170_sta_info *info = (void *) sta->drv_priv;
|
||||
struct sk_buff *skb;
|
||||
unsigned int i;
|
||||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_ADD:
|
||||
for (i = 0; i < ar->hw->queues; i++)
|
||||
skb_queue_head_init(&info->tx_status[i]);
|
||||
break;
|
||||
|
||||
case STA_NOTIFY_REMOVE:
|
||||
|
||||
/*
|
||||
* transfer all outstanding frames that need a tx_status
|
||||
* reports to the global tx_status queue
|
||||
*/
|
||||
|
||||
for (i = 0; i < ar->hw->queues; i++) {
|
||||
while ((skb = skb_dequeue(&info->tx_status[i]))) {
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: queueing frame in "
|
||||
"global tx_status queue =>\n",
|
||||
wiphy_name(ar->hw->wiphy));
|
||||
|
||||
ar9170_print_txheader(ar, skb);
|
||||
#endif /* AR9170_QUEUE_DEBUG */
|
||||
skb_queue_tail(&ar->global_tx_status, skb);
|
||||
}
|
||||
}
|
||||
queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor,
|
||||
msecs_to_jiffies(100));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int ar9170_get_stats(struct ieee80211_hw *hw,
|
||||
@ -1741,7 +1967,7 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
if ((param) && !(queue > ar->hw->queues)) {
|
||||
if ((param) && !(queue > __AR9170_NUM_TXQ)) {
|
||||
memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
|
||||
param, sizeof(*param));
|
||||
|
||||
@ -1817,12 +2043,14 @@ void *ar9170_alloc(size_t priv_size)
|
||||
mutex_init(&ar->mutex);
|
||||
spin_lock_init(&ar->cmdlock);
|
||||
spin_lock_init(&ar->tx_stats_lock);
|
||||
skb_queue_head_init(&ar->global_tx_status);
|
||||
skb_queue_head_init(&ar->global_tx_status_waste);
|
||||
for (i = 0; i < __AR9170_NUM_TXQ; i++) {
|
||||
skb_queue_head_init(&ar->tx_status[i]);
|
||||
skb_queue_head_init(&ar->tx_pending[i]);
|
||||
}
|
||||
ar9170_rx_reset_rx_mpdu(ar);
|
||||
INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
|
||||
INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
|
||||
INIT_DELAYED_WORK(&ar->tx_status_janitor, ar9170_tx_status_janitor);
|
||||
INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor);
|
||||
|
||||
/* all hw supports 2.4 GHz, so set channel to 1 by default */
|
||||
ar->channel = &ar9170_2ghz_chantable[0];
|
||||
|
@ -96,7 +96,49 @@ static struct usb_device_id ar9170_usb_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, ar9170_usb_ids);
|
||||
|
||||
static void ar9170_usb_tx_urb_complete_free(struct urb *urb)
|
||||
static void ar9170_usb_submit_urb(struct ar9170_usb *aru)
|
||||
{
|
||||
struct urb *urb;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
if (unlikely(!IS_STARTED(&aru->common)))
|
||||
return ;
|
||||
|
||||
spin_lock_irqsave(&aru->tx_urb_lock, flags);
|
||||
if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) {
|
||||
spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
|
||||
return ;
|
||||
}
|
||||
aru->tx_submitted_urbs++;
|
||||
|
||||
urb = usb_get_from_anchor(&aru->tx_pending);
|
||||
if (!urb) {
|
||||
aru->tx_submitted_urbs--;
|
||||
spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
|
||||
|
||||
return ;
|
||||
}
|
||||
spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
|
||||
|
||||
aru->tx_pending_urbs--;
|
||||
usb_anchor_urb(urb, &aru->tx_submitted);
|
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (unlikely(err)) {
|
||||
if (ar9170_nag_limiter(&aru->common))
|
||||
dev_err(&aru->udev->dev, "submit_urb failed (%d).\n",
|
||||
err);
|
||||
|
||||
usb_unanchor_urb(urb);
|
||||
aru->tx_submitted_urbs--;
|
||||
ar9170_tx_callback(&aru->common, urb->context);
|
||||
}
|
||||
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
|
||||
static void ar9170_usb_tx_urb_complete_frame(struct urb *urb)
|
||||
{
|
||||
struct sk_buff *skb = urb->context;
|
||||
struct ar9170_usb *aru = (struct ar9170_usb *)
|
||||
@ -107,8 +149,11 @@ static void ar9170_usb_tx_urb_complete_free(struct urb *urb)
|
||||
return ;
|
||||
}
|
||||
|
||||
ar9170_handle_tx_status(&aru->common, skb, false,
|
||||
AR9170_TX_STATUS_COMPLETE);
|
||||
aru->tx_submitted_urbs--;
|
||||
|
||||
ar9170_tx_callback(&aru->common, skb);
|
||||
|
||||
ar9170_usb_submit_urb(aru);
|
||||
}
|
||||
|
||||
static void ar9170_usb_tx_urb_complete(struct urb *urb)
|
||||
@ -290,21 +335,47 @@ err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru)
|
||||
static int ar9170_usb_flush(struct ar9170 *ar)
|
||||
{
|
||||
int ret;
|
||||
struct ar9170_usb *aru = (void *) ar;
|
||||
struct urb *urb;
|
||||
int ret, err = 0;
|
||||
|
||||
aru->common.state = AR9170_UNKNOWN_STATE;
|
||||
if (IS_STARTED(ar))
|
||||
aru->common.state = AR9170_IDLE;
|
||||
|
||||
usb_unlink_anchored_urbs(&aru->tx_submitted);
|
||||
usb_wait_anchor_empty_timeout(&aru->tx_pending,
|
||||
msecs_to_jiffies(800));
|
||||
while ((urb = usb_get_from_anchor(&aru->tx_pending))) {
|
||||
ar9170_tx_callback(&aru->common, (void *) urb->context);
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
|
||||
/* give the LED OFF command and the deauth frame a chance to air. */
|
||||
/* lets wait a while until the tx - queues are dried out */
|
||||
ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted,
|
||||
msecs_to_jiffies(100));
|
||||
if (ret == 0)
|
||||
dev_err(&aru->udev->dev, "kill pending tx urbs.\n");
|
||||
usb_poison_anchored_urbs(&aru->tx_submitted);
|
||||
err = -ETIMEDOUT;
|
||||
|
||||
usb_kill_anchored_urbs(&aru->tx_submitted);
|
||||
|
||||
if (IS_ACCEPTING_CMD(ar))
|
||||
aru->common.state = AR9170_STARTED;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru)
|
||||
{
|
||||
int err;
|
||||
|
||||
aru->common.state = AR9170_UNKNOWN_STATE;
|
||||
|
||||
err = ar9170_usb_flush(&aru->common);
|
||||
if (err)
|
||||
dev_err(&aru->udev->dev, "stuck tx urbs!\n");
|
||||
|
||||
usb_poison_anchored_urbs(&aru->tx_submitted);
|
||||
usb_poison_anchored_urbs(&aru->rx_submitted);
|
||||
}
|
||||
|
||||
@ -388,12 +459,10 @@ err_free:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb,
|
||||
bool txstatus_needed, unsigned int extra_len)
|
||||
static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ar9170_usb *aru = (struct ar9170_usb *) ar;
|
||||
struct urb *urb;
|
||||
int err;
|
||||
|
||||
if (unlikely(!IS_STARTED(ar))) {
|
||||
/* Seriously, what were you drink... err... thinking!? */
|
||||
@ -406,18 +475,17 @@ static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb,
|
||||
|
||||
usb_fill_bulk_urb(urb, aru->udev,
|
||||
usb_sndbulkpipe(aru->udev, AR9170_EP_TX),
|
||||
skb->data, skb->len + extra_len, (txstatus_needed ?
|
||||
ar9170_usb_tx_urb_complete :
|
||||
ar9170_usb_tx_urb_complete_free), skb);
|
||||
skb->data, skb->len,
|
||||
ar9170_usb_tx_urb_complete_frame, skb);
|
||||
urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
|
||||
usb_anchor_urb(urb, &aru->tx_submitted);
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (unlikely(err))
|
||||
usb_unanchor_urb(urb);
|
||||
usb_anchor_urb(urb, &aru->tx_pending);
|
||||
aru->tx_pending_urbs++;
|
||||
|
||||
usb_free_urb(urb);
|
||||
return err;
|
||||
|
||||
ar9170_usb_submit_urb(aru);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer)
|
||||
@ -617,10 +685,8 @@ static void ar9170_usb_stop(struct ar9170 *ar)
|
||||
if (IS_ACCEPTING_CMD(ar))
|
||||
aru->common.state = AR9170_STOPPED;
|
||||
|
||||
/* lets wait a while until the tx - queues are dried out */
|
||||
ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted,
|
||||
msecs_to_jiffies(1000));
|
||||
if (ret == 0)
|
||||
ret = ar9170_usb_flush(ar);
|
||||
if (ret)
|
||||
dev_err(&aru->udev->dev, "kill pending tx urbs.\n");
|
||||
|
||||
usb_poison_anchored_urbs(&aru->tx_submitted);
|
||||
@ -716,10 +782,16 @@ static int ar9170_usb_probe(struct usb_interface *intf,
|
||||
SET_IEEE80211_DEV(ar->hw, &udev->dev);
|
||||
|
||||
init_usb_anchor(&aru->rx_submitted);
|
||||
init_usb_anchor(&aru->tx_pending);
|
||||
init_usb_anchor(&aru->tx_submitted);
|
||||
init_completion(&aru->cmd_wait);
|
||||
spin_lock_init(&aru->tx_urb_lock);
|
||||
|
||||
aru->tx_pending_urbs = 0;
|
||||
aru->tx_submitted_urbs = 0;
|
||||
|
||||
aru->common.stop = ar9170_usb_stop;
|
||||
aru->common.flush = ar9170_usb_flush;
|
||||
aru->common.open = ar9170_usb_open;
|
||||
aru->common.tx = ar9170_usb_tx;
|
||||
aru->common.exec_cmd = ar9170_usb_exec_cmd;
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "ar9170.h"
|
||||
|
||||
#define AR9170_NUM_RX_URBS 16
|
||||
#define AR9170_NUM_TX_URBS 8
|
||||
|
||||
struct firmware;
|
||||
|
||||
@ -60,11 +61,15 @@ struct ar9170_usb {
|
||||
struct usb_interface *intf;
|
||||
|
||||
struct usb_anchor rx_submitted;
|
||||
struct usb_anchor tx_pending;
|
||||
struct usb_anchor tx_submitted;
|
||||
|
||||
bool req_one_stage_fw;
|
||||
|
||||
spinlock_t cmdlock;
|
||||
spinlock_t tx_urb_lock;
|
||||
unsigned int tx_submitted_urbs;
|
||||
unsigned int tx_pending_urbs;
|
||||
|
||||
struct completion cmd_wait;
|
||||
int readlen;
|
||||
u8 *readbuf;
|
||||
|
@ -11,5 +11,6 @@ ath5k-y += reset.o
|
||||
ath5k-y += attach.o
|
||||
ath5k-y += base.o
|
||||
ath5k-y += led.o
|
||||
ath5k-y += rfkill.o
|
||||
ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
|
||||
obj-$(CONFIG_ATH5K) += ath5k.o
|
||||
|
@ -1256,6 +1256,10 @@ extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
|
||||
extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
|
||||
extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
|
||||
|
||||
/* rfkill Functions */
|
||||
extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
|
||||
extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
|
||||
|
||||
/* Misc functions */
|
||||
int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
|
||||
|
@ -2360,6 +2360,8 @@ ath5k_init(struct ath5k_softc *sc)
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
ath5k_rfkill_hw_start(ah);
|
||||
|
||||
/*
|
||||
* Reset the key cache since some parts do not reset the
|
||||
* contents on initial power up or resume from suspend.
|
||||
@ -2468,6 +2470,8 @@ ath5k_stop_hw(struct ath5k_softc *sc)
|
||||
tasklet_kill(&sc->restq);
|
||||
tasklet_kill(&sc->beacontq);
|
||||
|
||||
ath5k_rfkill_hw_stop(sc->ah);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2526,6 +2530,9 @@ ath5k_intr(int irq, void *dev_id)
|
||||
*/
|
||||
ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
|
||||
}
|
||||
if (status & AR5K_INT_GPIO)
|
||||
tasklet_schedule(&sc->rf_kill.toggleq);
|
||||
|
||||
}
|
||||
} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/rfkill.h>
|
||||
|
||||
#include "ath5k.h"
|
||||
#include "debug.h"
|
||||
@ -91,6 +92,15 @@ struct ath5k_led
|
||||
struct led_classdev led_dev; /* led classdev */
|
||||
};
|
||||
|
||||
/* Rfkill */
|
||||
struct ath5k_rfkill {
|
||||
/* GPIO PIN for rfkill */
|
||||
u16 gpio;
|
||||
/* polarity of rfkill GPIO PIN */
|
||||
bool polarity;
|
||||
/* RFKILL toggle tasklet */
|
||||
struct tasklet_struct toggleq;
|
||||
};
|
||||
|
||||
#if CHAN_DEBUG
|
||||
#define ATH_CHAN_MAX (26+26+26+200+200)
|
||||
@ -167,6 +177,8 @@ struct ath5k_softc {
|
||||
struct tasklet_struct txtq; /* tx intr tasklet */
|
||||
struct ath5k_led tx_led; /* tx led */
|
||||
|
||||
struct ath5k_rfkill rf_kill;
|
||||
|
||||
spinlock_t block; /* protects beacon */
|
||||
struct tasklet_struct beacontq; /* beacon intr tasklet */
|
||||
struct ath5k_buf *bbuf; /* beacon buffer */
|
||||
|
@ -1304,23 +1304,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
||||
if (ah->ah_version != AR5K_AR5210)
|
||||
ath5k_hw_set_imr(ah, ah->ah_imr);
|
||||
|
||||
/*
|
||||
* Setup RFKill interrupt if rfkill flag is set on eeprom.
|
||||
* TODO: Use gpio pin and polarity infos from eeprom
|
||||
* TODO: Handle this in ath5k_intr because it'll result
|
||||
* a nasty interrupt storm.
|
||||
*/
|
||||
#if 0
|
||||
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
|
||||
ath5k_hw_set_gpio_input(ah, 0);
|
||||
ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
|
||||
if (ah->ah_gpio[0] == 0)
|
||||
ath5k_hw_set_gpio_intr(ah, 0, 1);
|
||||
else
|
||||
ath5k_hw_set_gpio_intr(ah, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Enable 32KHz clock function for AR5212+ chips
|
||||
* Set clocks to 32KHz operation and use an
|
||||
* external 32KHz crystal when sleeping if one
|
||||
|
121
drivers/net/wireless/ath/ath5k/rfkill.c
Normal file
121
drivers/net/wireless/ath/ath5k/rfkill.c
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* RFKILL support for ath5k
|
||||
*
|
||||
* Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include "base.h"
|
||||
|
||||
|
||||
static inline void ath5k_rfkill_disable(struct ath5k_softc *sc)
|
||||
{
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
|
||||
sc->rf_kill.gpio, sc->rf_kill.polarity);
|
||||
ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
|
||||
ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity);
|
||||
}
|
||||
|
||||
|
||||
static inline void ath5k_rfkill_enable(struct ath5k_softc *sc)
|
||||
{
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
|
||||
sc->rf_kill.gpio, sc->rf_kill.polarity);
|
||||
ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
|
||||
ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity);
|
||||
}
|
||||
|
||||
static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable)
|
||||
{
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
u32 curval;
|
||||
|
||||
ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio);
|
||||
curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio);
|
||||
ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ?
|
||||
!!curval : !curval);
|
||||
}
|
||||
|
||||
static bool
|
||||
ath5k_is_rfkill_set(struct ath5k_softc *sc)
|
||||
{
|
||||
/* configuring GPIO for input for some reason disables rfkill */
|
||||
/*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/
|
||||
return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) ==
|
||||
sc->rf_kill.polarity;
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_tasklet_rfkill_toggle(unsigned long data)
|
||||
{
|
||||
struct ath5k_softc *sc = (void *)data;
|
||||
bool blocked;
|
||||
|
||||
blocked = ath5k_is_rfkill_set(sc);
|
||||
wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ath5k_rfkill_hw_start(struct ath5k_hw *ah)
|
||||
{
|
||||
struct ath5k_softc *sc = ah->ah_sc;
|
||||
|
||||
/* read rfkill GPIO configuration from EEPROM header */
|
||||
sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
|
||||
sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
|
||||
|
||||
tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
|
||||
(unsigned long)sc);
|
||||
|
||||
ath5k_rfkill_disable(sc);
|
||||
|
||||
/* enable interrupt for rfkill switch */
|
||||
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
|
||||
ath5k_rfkill_set_intr(sc, true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ath5k_rfkill_hw_stop(struct ath5k_hw *ah)
|
||||
{
|
||||
struct ath5k_softc *sc = ah->ah_sc;
|
||||
|
||||
/* disable interrupt for rfkill switch */
|
||||
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
|
||||
ath5k_rfkill_set_intr(sc, false);
|
||||
|
||||
tasklet_kill(&sc->rf_kill.toggleq);
|
||||
|
||||
/* enable RFKILL when stopping HW so Wifi LED is turned off */
|
||||
ath5k_rfkill_enable(sc);
|
||||
}
|
||||
|
@ -711,6 +711,7 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||
return 0;
|
||||
|
||||
if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
|
||||
txtid->state &= ~AGGR_ADDBA_PROGRESS;
|
||||
txtid->addba_exchangeattempts = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -98,13 +98,6 @@ config B43_LEDS
|
||||
depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43)
|
||||
default y
|
||||
|
||||
# This config option automatically enables b43 RFKILL support,
|
||||
# if it's possible.
|
||||
config B43_RFKILL
|
||||
bool
|
||||
depends on B43 && (RFKILL = y || RFKILL = B43)
|
||||
default y
|
||||
|
||||
# This config option automatically enables b43 HW-RNG support,
|
||||
# if the HW-RNG core is enabled.
|
||||
config B43_HWRNG
|
||||
|
@ -13,7 +13,7 @@ b43-y += lo.o
|
||||
b43-y += wa.o
|
||||
b43-y += dma.o
|
||||
b43-$(CONFIG_B43_PIO) += pio.o
|
||||
b43-$(CONFIG_B43_RFKILL) += rfkill.o
|
||||
b43-y += rfkill.o
|
||||
b43-$(CONFIG_B43_LEDS) += leds.o
|
||||
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
|
||||
b43-$(CONFIG_B43_DEBUG) += debugfs.o
|
||||
|
@ -163,6 +163,7 @@ enum {
|
||||
#define B43_SHM_SH_WLCOREREV 0x0016 /* 802.11 core revision */
|
||||
#define B43_SHM_SH_PCTLWDPOS 0x0008
|
||||
#define B43_SHM_SH_RXPADOFF 0x0034 /* RX Padding data offset (PIO only) */
|
||||
#define B43_SHM_SH_FWCAPA 0x0042 /* Firmware capabilities (Opensource firmware only) */
|
||||
#define B43_SHM_SH_PHYVER 0x0050 /* PHY version */
|
||||
#define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */
|
||||
#define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */
|
||||
@ -297,6 +298,10 @@ enum {
|
||||
#define B43_HF_MLADVW 0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */
|
||||
#define B43_HF_PR45960W 0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */
|
||||
|
||||
/* Firmware capabilities field in SHM (Opensource firmware only) */
|
||||
#define B43_FWCAPA_HWCRYPTO 0x0001
|
||||
#define B43_FWCAPA_QOS 0x0002
|
||||
|
||||
/* MacFilter offsets. */
|
||||
#define B43_MACFILTER_SELF 0x0000
|
||||
#define B43_MACFILTER_BSSID 0x0003
|
||||
@ -596,6 +601,13 @@ struct b43_wl {
|
||||
/* Pointer to the ieee80211 hardware data structure */
|
||||
struct ieee80211_hw *hw;
|
||||
|
||||
/* The number of queues that were registered with the mac80211 subsystem
|
||||
* initially. This is a backup copy of hw->queues in case hw->queues has
|
||||
* to be dynamically lowered at runtime (Firmware does not support QoS).
|
||||
* hw->queues has to be restored to the original value before unregistering
|
||||
* from the mac80211 subsystem. */
|
||||
u16 mac80211_initially_registered_queues;
|
||||
|
||||
struct mutex mutex;
|
||||
spinlock_t irq_lock;
|
||||
/* R/W lock for data transmission.
|
||||
@ -631,9 +643,6 @@ struct b43_wl {
|
||||
char rng_name[30 + 1];
|
||||
#endif /* CONFIG_B43_HWRNG */
|
||||
|
||||
/* The RF-kill button */
|
||||
struct b43_rfkill rfkill;
|
||||
|
||||
/* List of all wireless devices on this chip */
|
||||
struct list_head devlist;
|
||||
u8 nr_devs;
|
||||
@ -752,6 +761,8 @@ struct b43_wldev {
|
||||
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
|
||||
bool radio_hw_enable; /* saved state of radio hardware enabled state */
|
||||
bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */
|
||||
bool qos_enabled; /* TRUE, if QoS is used. */
|
||||
bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
|
||||
|
||||
/* PHY/Radio device. */
|
||||
struct b43_phy phy;
|
||||
|
@ -1285,7 +1285,7 @@ static struct b43_dmaring *select_ring_by_priority(struct b43_wldev *dev,
|
||||
{
|
||||
struct b43_dmaring *ring;
|
||||
|
||||
if (b43_modparam_qos) {
|
||||
if (dev->qos_enabled) {
|
||||
/* 0 = highest priority */
|
||||
switch (queue_prio) {
|
||||
default:
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "b43.h"
|
||||
#include "leds.h"
|
||||
#include "rfkill.h"
|
||||
|
||||
|
||||
static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
|
||||
@ -164,10 +165,10 @@ static void b43_map_led(struct b43_wldev *dev,
|
||||
snprintf(name, sizeof(name),
|
||||
"b43-%s::radio", wiphy_name(hw->wiphy));
|
||||
b43_register_led(dev, &dev->led_radio, name,
|
||||
b43_rfkill_led_name(dev),
|
||||
ieee80211_get_radio_led_name(hw),
|
||||
led_index, activelow);
|
||||
/* Sync the RF-kill LED state with the switch state. */
|
||||
if (dev->radio_hw_enable)
|
||||
/* Sync the RF-kill LED state with radio and switch states. */
|
||||
if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev))
|
||||
b43_led_turn_on(dev, led_index, activelow);
|
||||
break;
|
||||
case B43_LED_WEIRD:
|
||||
|
@ -80,8 +80,8 @@ static int modparam_nohwcrypt;
|
||||
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
|
||||
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
||||
|
||||
int b43_modparam_qos = 1;
|
||||
module_param_named(qos, b43_modparam_qos, int, 0444);
|
||||
static int modparam_qos = 1;
|
||||
module_param_named(qos, modparam_qos, int, 0444);
|
||||
MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
|
||||
|
||||
static int modparam_btcoex = 1;
|
||||
@ -538,6 +538,13 @@ void b43_hf_write(struct b43_wldev *dev, u64 value)
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
|
||||
}
|
||||
|
||||
/* Read the firmware capabilities bitmask (Opensource firmware only) */
|
||||
static u16 b43_fwcapa_read(struct b43_wldev *dev)
|
||||
{
|
||||
B43_WARN_ON(!dev->fw.opensource);
|
||||
return b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_FWCAPA);
|
||||
}
|
||||
|
||||
void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
|
||||
{
|
||||
u32 low, high;
|
||||
@ -2307,12 +2314,34 @@ static int b43_upload_microcode(struct b43_wldev *dev)
|
||||
dev->fw.patch = fwpatch;
|
||||
dev->fw.opensource = (fwdate == 0xFFFF);
|
||||
|
||||
/* Default to use-all-queues. */
|
||||
dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues;
|
||||
dev->qos_enabled = !!modparam_qos;
|
||||
/* Default to firmware/hardware crypto acceleration. */
|
||||
dev->hwcrypto_enabled = 1;
|
||||
|
||||
if (dev->fw.opensource) {
|
||||
u16 fwcapa;
|
||||
|
||||
/* Patchlevel info is encoded in the "time" field. */
|
||||
dev->fw.patch = fwtime;
|
||||
b43info(dev->wl, "Loading OpenSource firmware version %u.%u%s\n",
|
||||
dev->fw.rev, dev->fw.patch,
|
||||
dev->fw.pcm_request_failed ? " (Hardware crypto not supported)" : "");
|
||||
b43info(dev->wl, "Loading OpenSource firmware version %u.%u\n",
|
||||
dev->fw.rev, dev->fw.patch);
|
||||
|
||||
fwcapa = b43_fwcapa_read(dev);
|
||||
if (!(fwcapa & B43_FWCAPA_HWCRYPTO) || dev->fw.pcm_request_failed) {
|
||||
b43info(dev->wl, "Hardware crypto acceleration not supported by firmware\n");
|
||||
/* Disable hardware crypto and fall back to software crypto. */
|
||||
dev->hwcrypto_enabled = 0;
|
||||
}
|
||||
if (!(fwcapa & B43_FWCAPA_QOS)) {
|
||||
b43info(dev->wl, "QoS not supported by firmware\n");
|
||||
/* Disable QoS. Tweak hw->queues to 1. It will be restored before
|
||||
* ieee80211_unregister to make sure the networking core can
|
||||
* properly free possible resources. */
|
||||
dev->wl->hw->queues = 1;
|
||||
dev->qos_enabled = 0;
|
||||
}
|
||||
} else {
|
||||
b43info(dev->wl, "Loading firmware version %u.%u "
|
||||
"(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
|
||||
@ -3627,7 +3656,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
|
||||
goto out_unlock;
|
||||
|
||||
if (dev->fw.pcm_request_failed) {
|
||||
if (dev->fw.pcm_request_failed || !dev->hwcrypto_enabled) {
|
||||
/* We don't have firmware for the crypto engine.
|
||||
* Must use software-crypto. */
|
||||
err = -EOPNOTSUPP;
|
||||
@ -4298,7 +4327,6 @@ static int b43_op_start(struct ieee80211_hw *hw)
|
||||
struct b43_wldev *dev = wl->current_dev;
|
||||
int did_init = 0;
|
||||
int err = 0;
|
||||
bool do_rfkill_exit = 0;
|
||||
|
||||
/* Kill all old instance specific information to make sure
|
||||
* the card won't use it in the short timeframe between start
|
||||
@ -4312,18 +4340,12 @@ static int b43_op_start(struct ieee80211_hw *hw)
|
||||
wl->beacon1_uploaded = 0;
|
||||
wl->beacon_templates_virgin = 1;
|
||||
|
||||
/* First register RFkill.
|
||||
* LEDs that are registered later depend on it. */
|
||||
b43_rfkill_init(dev);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (b43_status(dev) < B43_STAT_INITIALIZED) {
|
||||
err = b43_wireless_core_init(dev);
|
||||
if (err) {
|
||||
do_rfkill_exit = 1;
|
||||
if (err)
|
||||
goto out_mutex_unlock;
|
||||
}
|
||||
did_init = 1;
|
||||
}
|
||||
|
||||
@ -4332,17 +4354,16 @@ static int b43_op_start(struct ieee80211_hw *hw)
|
||||
if (err) {
|
||||
if (did_init)
|
||||
b43_wireless_core_exit(dev);
|
||||
do_rfkill_exit = 1;
|
||||
goto out_mutex_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: only do if device doesn't support rfkill irq */
|
||||
wiphy_rfkill_start_polling(hw->wiphy);
|
||||
|
||||
out_mutex_unlock:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
if (do_rfkill_exit)
|
||||
b43_rfkill_exit(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -4351,7 +4372,6 @@ static void b43_op_stop(struct ieee80211_hw *hw)
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev = wl->current_dev;
|
||||
|
||||
b43_rfkill_exit(dev);
|
||||
cancel_work_sync(&(wl->beacon_update_trigger));
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
@ -4433,6 +4453,7 @@ static const struct ieee80211_ops b43_hw_ops = {
|
||||
.sta_notify = b43_op_sta_notify,
|
||||
.sw_scan_start = b43_op_sw_scan_start_notifier,
|
||||
.sw_scan_complete = b43_op_sw_scan_complete_notifier,
|
||||
.rfkill_poll = b43_rfkill_poll,
|
||||
};
|
||||
|
||||
/* Hard-reset the chip. Do not call this directly.
|
||||
@ -4735,6 +4756,7 @@ static int b43_wireless_init(struct ssb_device *dev)
|
||||
b43err(NULL, "Could not allocate ieee80211 device\n");
|
||||
goto out;
|
||||
}
|
||||
wl = hw_to_b43_wl(hw);
|
||||
|
||||
/* fill hw info */
|
||||
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
|
||||
@ -4748,7 +4770,8 @@ static int b43_wireless_init(struct ssb_device *dev)
|
||||
BIT(NL80211_IFTYPE_WDS) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
||||
hw->queues = b43_modparam_qos ? 4 : 1;
|
||||
hw->queues = modparam_qos ? 4 : 1;
|
||||
wl->mac80211_initially_registered_queues = hw->queues;
|
||||
hw->max_rates = 2;
|
||||
SET_IEEE80211_DEV(hw, dev->dev);
|
||||
if (is_valid_ether_addr(sprom->et1mac))
|
||||
@ -4756,9 +4779,7 @@ static int b43_wireless_init(struct ssb_device *dev)
|
||||
else
|
||||
SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
|
||||
|
||||
/* Get and initialize struct b43_wl */
|
||||
wl = hw_to_b43_wl(hw);
|
||||
memset(wl, 0, sizeof(*wl));
|
||||
/* Initialize struct b43_wl */
|
||||
wl->hw = hw;
|
||||
spin_lock_init(&wl->irq_lock);
|
||||
rwlock_init(&wl->tx_lock);
|
||||
@ -4824,8 +4845,13 @@ static void b43_remove(struct ssb_device *dev)
|
||||
cancel_work_sync(&wldev->restart_work);
|
||||
|
||||
B43_WARN_ON(!wl);
|
||||
if (wl->current_dev == wldev)
|
||||
if (wl->current_dev == wldev) {
|
||||
/* Restore the queues count before unregistering, because firmware detect
|
||||
* might have modified it. Restoring is important, so the networking
|
||||
* stack can properly free resources. */
|
||||
wl->hw->queues = wl->mac80211_initially_registered_queues;
|
||||
ieee80211_unregister_hw(wl->hw);
|
||||
}
|
||||
|
||||
b43_one_core_detach(dev);
|
||||
|
||||
@ -4920,7 +4946,7 @@ static struct ssb_driver b43_ssb_driver = {
|
||||
static void b43_print_driverinfo(void)
|
||||
{
|
||||
const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
|
||||
*feat_leds = "", *feat_rfkill = "";
|
||||
*feat_leds = "";
|
||||
|
||||
#ifdef CONFIG_B43_PCI_AUTOSELECT
|
||||
feat_pci = "P";
|
||||
@ -4933,15 +4959,12 @@ static void b43_print_driverinfo(void)
|
||||
#endif
|
||||
#ifdef CONFIG_B43_LEDS
|
||||
feat_leds = "L";
|
||||
#endif
|
||||
#ifdef CONFIG_B43_RFKILL
|
||||
feat_rfkill = "R";
|
||||
#endif
|
||||
printk(KERN_INFO "Broadcom 43xx driver loaded "
|
||||
"[ Features: %s%s%s%s%s, Firmware-ID: "
|
||||
"[ Features: %s%s%s%s, Firmware-ID: "
|
||||
B43_SUPPORTED_FIRMWARE_ID " ]\n",
|
||||
feat_pci, feat_pcmcia, feat_nphy,
|
||||
feat_leds, feat_rfkill);
|
||||
feat_leds);
|
||||
}
|
||||
|
||||
static int __init b43_init(void)
|
||||
|
@ -39,7 +39,6 @@
|
||||
#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
|
||||
|
||||
|
||||
extern int b43_modparam_qos;
|
||||
extern int b43_modparam_verbose;
|
||||
|
||||
/* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef LINUX_B43_PHY_COMMON_H_
|
||||
#define LINUX_B43_PHY_COMMON_H_
|
||||
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct b43_wldev;
|
||||
|
||||
|
@ -313,7 +313,7 @@ static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev,
|
||||
{
|
||||
struct b43_pio_txqueue *q;
|
||||
|
||||
if (b43_modparam_qos) {
|
||||
if (dev->qos_enabled) {
|
||||
/* 0 = highest priority */
|
||||
switch (queue_prio) {
|
||||
default:
|
||||
|
@ -22,15 +22,11 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "rfkill.h"
|
||||
#include "b43.h"
|
||||
#include "phy_common.h"
|
||||
|
||||
#include <linux/kmod.h>
|
||||
|
||||
|
||||
/* Returns TRUE, if the radio is enabled in hardware. */
|
||||
static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
|
||||
bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
|
||||
{
|
||||
if (dev->phy.rev >= 3) {
|
||||
if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
|
||||
@ -45,110 +41,39 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
|
||||
}
|
||||
|
||||
/* The poll callback for the hardware button. */
|
||||
static void b43_rfkill_poll(struct rfkill *rfkill, void *data)
|
||||
void b43_rfkill_poll(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct b43_wldev *dev = data;
|
||||
struct b43_wl *wl = dev->wl;
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev = wl->current_dev;
|
||||
struct ssb_bus *bus = dev->dev->bus;
|
||||
bool enabled;
|
||||
bool brought_up = false;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
|
||||
mutex_unlock(&wl->mutex);
|
||||
return;
|
||||
if (ssb_bus_powerup(bus, 0)) {
|
||||
mutex_unlock(&wl->mutex);
|
||||
return;
|
||||
}
|
||||
ssb_device_enable(dev->dev, 0);
|
||||
brought_up = true;
|
||||
}
|
||||
|
||||
enabled = b43_is_hw_radio_enabled(dev);
|
||||
|
||||
if (unlikely(enabled != dev->radio_hw_enable)) {
|
||||
dev->radio_hw_enable = enabled;
|
||||
b43info(wl, "Radio hardware status changed to %s\n",
|
||||
enabled ? "ENABLED" : "DISABLED");
|
||||
enabled = !rfkill_set_hw_state(rfkill, !enabled);
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
|
||||
if (enabled != dev->phy.radio_on)
|
||||
b43_software_rfkill(dev, !enabled);
|
||||
}
|
||||
|
||||
if (brought_up) {
|
||||
ssb_device_disable(dev->dev, 0);
|
||||
ssb_bus_may_powerdown(bus);
|
||||
}
|
||||
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
/* Called when the RFKILL toggled in software. */
|
||||
static int b43_rfkill_soft_set(void *data, bool blocked)
|
||||
{
|
||||
struct b43_wldev *dev = data;
|
||||
struct b43_wl *wl = dev->wl;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (WARN_ON(!wl->rfkill.registered))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (b43_status(dev) < B43_STAT_INITIALIZED)
|
||||
goto out_unlock;
|
||||
|
||||
if (!dev->radio_hw_enable)
|
||||
goto out_unlock;
|
||||
|
||||
if (!blocked != dev->phy.radio_on)
|
||||
b43_software_rfkill(dev, blocked);
|
||||
err = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&wl->mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
const char *b43_rfkill_led_name(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_rfkill *rfk = &(dev->wl->rfkill);
|
||||
|
||||
if (!rfk->registered)
|
||||
return NULL;
|
||||
return rfkill_get_led_trigger_name(rfk->rfkill);
|
||||
}
|
||||
|
||||
static const struct rfkill_ops b43_rfkill_ops = {
|
||||
.set_block = b43_rfkill_soft_set,
|
||||
.poll = b43_rfkill_poll,
|
||||
};
|
||||
|
||||
void b43_rfkill_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_wl *wl = dev->wl;
|
||||
struct b43_rfkill *rfk = &(wl->rfkill);
|
||||
int err;
|
||||
|
||||
rfk->registered = 0;
|
||||
|
||||
snprintf(rfk->name, sizeof(rfk->name),
|
||||
"b43-%s", wiphy_name(wl->hw->wiphy));
|
||||
|
||||
rfk->rfkill = rfkill_alloc(rfk->name,
|
||||
dev->dev->dev,
|
||||
RFKILL_TYPE_WLAN,
|
||||
&b43_rfkill_ops, dev);
|
||||
if (!rfk->rfkill)
|
||||
goto out_error;
|
||||
|
||||
err = rfkill_register(rfk->rfkill);
|
||||
if (err)
|
||||
goto err_free;
|
||||
|
||||
rfk->registered = 1;
|
||||
|
||||
return;
|
||||
err_free:
|
||||
rfkill_destroy(rfk->rfkill);
|
||||
out_error:
|
||||
rfk->registered = 0;
|
||||
b43warn(wl, "RF-kill button init failed\n");
|
||||
}
|
||||
|
||||
void b43_rfkill_exit(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_rfkill *rfk = &(dev->wl->rfkill);
|
||||
|
||||
if (!rfk->registered)
|
||||
return;
|
||||
rfk->registered = 0;
|
||||
|
||||
rfkill_unregister(rfk->rfkill);
|
||||
rfkill_destroy(rfk->rfkill);
|
||||
rfk->rfkill = NULL;
|
||||
}
|
||||
|
@ -1,49 +1,11 @@
|
||||
#ifndef B43_RFKILL_H_
|
||||
#define B43_RFKILL_H_
|
||||
|
||||
struct ieee80211_hw;
|
||||
struct b43_wldev;
|
||||
|
||||
void b43_rfkill_poll(struct ieee80211_hw *hw);
|
||||
|
||||
#ifdef CONFIG_B43_RFKILL
|
||||
|
||||
#include <linux/rfkill.h>
|
||||
|
||||
|
||||
struct b43_rfkill {
|
||||
/* The RFKILL subsystem data structure */
|
||||
struct rfkill *rfkill;
|
||||
/* Did initialization succeed? Used for freeing. */
|
||||
bool registered;
|
||||
/* The unique name of this rfkill switch */
|
||||
char name[sizeof("b43-phy4294967295")];
|
||||
};
|
||||
|
||||
/* The init function returns void, because we are not interested
|
||||
* in failing the b43 init process when rfkill init failed. */
|
||||
void b43_rfkill_init(struct b43_wldev *dev);
|
||||
void b43_rfkill_exit(struct b43_wldev *dev);
|
||||
|
||||
const char *b43_rfkill_led_name(struct b43_wldev *dev);
|
||||
|
||||
|
||||
#else /* CONFIG_B43_RFKILL */
|
||||
/* No RFKILL support. */
|
||||
|
||||
struct b43_rfkill {
|
||||
/* empty */
|
||||
};
|
||||
|
||||
static inline void b43_rfkill_init(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline void b43_rfkill_exit(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline char * b43_rfkill_led_name(struct b43_wldev *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_B43_RFKILL */
|
||||
bool b43_is_hw_radio_enabled(struct b43_wldev *dev);
|
||||
|
||||
#endif /* B43_RFKILL_H_ */
|
||||
|
@ -118,7 +118,6 @@ u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
|
||||
void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
|
||||
const u16 octets, const u8 bitrate)
|
||||
{
|
||||
__le32 *data = &(plcp->data);
|
||||
__u8 *raw = plcp->raw;
|
||||
|
||||
if (b43_is_ofdm_rate(bitrate)) {
|
||||
@ -127,7 +126,7 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
|
||||
d = b43_plcp_get_ratecode_ofdm(bitrate);
|
||||
B43_WARN_ON(octets & 0xF000);
|
||||
d |= (octets << 5);
|
||||
*data = cpu_to_le32(d);
|
||||
plcp->data = cpu_to_le32(d);
|
||||
} else {
|
||||
u32 plen;
|
||||
|
||||
@ -141,7 +140,7 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
|
||||
raw[1] = 0x04;
|
||||
} else
|
||||
raw[1] = 0x04;
|
||||
*data |= cpu_to_le32(plen << 16);
|
||||
plcp->data |= cpu_to_le32(plen << 16);
|
||||
raw[0] = b43_plcp_get_ratecode_cck(bitrate);
|
||||
}
|
||||
}
|
||||
|
@ -42,14 +42,6 @@ config B43LEGACY_LEDS
|
||||
depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY)
|
||||
default y
|
||||
|
||||
# RFKILL support
|
||||
# This config option automatically enables b43legacy RFKILL support,
|
||||
# if it's possible.
|
||||
config B43LEGACY_RFKILL
|
||||
bool
|
||||
depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY)
|
||||
default y
|
||||
|
||||
# This config option automatically enables b43 HW-RNG support,
|
||||
# if the HW-RNG core is enabled.
|
||||
config B43LEGACY_HWRNG
|
||||
|
@ -6,7 +6,7 @@ b43legacy-y += radio.o
|
||||
b43legacy-y += sysfs.o
|
||||
b43legacy-y += xmit.o
|
||||
# b43 RFKILL button support
|
||||
b43legacy-$(CONFIG_B43LEGACY_RFKILL) += rfkill.o
|
||||
b43legacy-y += rfkill.o
|
||||
# b43legacy LED support
|
||||
b43legacy-$(CONFIG_B43LEGACY_LEDS) += leds.o
|
||||
# b43legacy debugging
|
||||
|
@ -602,9 +602,6 @@ struct b43legacy_wl {
|
||||
char rng_name[30 + 1];
|
||||
#endif
|
||||
|
||||
/* The RF-kill button */
|
||||
struct b43legacy_rfkill rfkill;
|
||||
|
||||
/* List of all wireless devices on this chip */
|
||||
struct list_head devlist;
|
||||
u8 nr_devs;
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "b43legacy.h"
|
||||
#include "leds.h"
|
||||
#include "rfkill.h"
|
||||
|
||||
|
||||
static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
|
||||
@ -164,10 +165,10 @@ static void b43legacy_map_led(struct b43legacy_wldev *dev,
|
||||
snprintf(name, sizeof(name),
|
||||
"b43legacy-%s::radio", wiphy_name(hw->wiphy));
|
||||
b43legacy_register_led(dev, &dev->led_radio, name,
|
||||
b43legacy_rfkill_led_name(dev),
|
||||
ieee80211_get_radio_led_name(hw),
|
||||
led_index, activelow);
|
||||
/* Sync the RF-kill LED state with the switch state. */
|
||||
if (dev->radio_hw_enable)
|
||||
/* Sync the RF-kill LED state with radio and switch states. */
|
||||
if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev))
|
||||
b43legacy_led_turn_on(dev, led_index, activelow);
|
||||
break;
|
||||
case B43legacy_LED_WEIRD:
|
||||
|
@ -3431,11 +3431,6 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
|
||||
struct b43legacy_wldev *dev = wl->current_dev;
|
||||
int did_init = 0;
|
||||
int err = 0;
|
||||
bool do_rfkill_exit = 0;
|
||||
|
||||
/* First register RFkill.
|
||||
* LEDs that are registered later depend on it. */
|
||||
b43legacy_rfkill_init(dev);
|
||||
|
||||
/* Kill all old instance specific information to make sure
|
||||
* the card won't use it in the short timeframe between start
|
||||
@ -3451,10 +3446,8 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
|
||||
|
||||
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
|
||||
err = b43legacy_wireless_core_init(dev);
|
||||
if (err) {
|
||||
do_rfkill_exit = 1;
|
||||
if (err)
|
||||
goto out_mutex_unlock;
|
||||
}
|
||||
did_init = 1;
|
||||
}
|
||||
|
||||
@ -3463,17 +3456,15 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
|
||||
if (err) {
|
||||
if (did_init)
|
||||
b43legacy_wireless_core_exit(dev);
|
||||
do_rfkill_exit = 1;
|
||||
goto out_mutex_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
wiphy_rfkill_start_polling(hw->wiphy);
|
||||
|
||||
out_mutex_unlock:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
if (do_rfkill_exit)
|
||||
b43legacy_rfkill_exit(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -3482,7 +3473,6 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw)
|
||||
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
|
||||
struct b43legacy_wldev *dev = wl->current_dev;
|
||||
|
||||
b43legacy_rfkill_exit(dev);
|
||||
cancel_work_sync(&(wl->beacon_update_trigger));
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
@ -3518,6 +3508,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
|
||||
.start = b43legacy_op_start,
|
||||
.stop = b43legacy_op_stop,
|
||||
.set_tim = b43legacy_op_beacon_set_tim,
|
||||
.rfkill_poll = b43legacy_rfkill_poll,
|
||||
};
|
||||
|
||||
/* Hard-reset the chip. Do not call this directly.
|
||||
|
@ -22,15 +22,12 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "rfkill.h"
|
||||
#include "radio.h"
|
||||
#include "b43legacy.h"
|
||||
|
||||
#include <linux/kmod.h>
|
||||
|
||||
|
||||
/* Returns TRUE, if the radio is enabled in hardware. */
|
||||
static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
|
||||
bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
|
||||
{
|
||||
if (dev->phy.rev >= 3) {
|
||||
if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
|
||||
@ -45,23 +42,31 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
|
||||
}
|
||||
|
||||
/* The poll callback for the hardware button. */
|
||||
static void b43legacy_rfkill_poll(struct rfkill *rfkill, void *data)
|
||||
void b43legacy_rfkill_poll(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct b43legacy_wldev *dev = data;
|
||||
struct b43legacy_wl *wl = dev->wl;
|
||||
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
|
||||
struct b43legacy_wldev *dev = wl->current_dev;
|
||||
struct ssb_bus *bus = dev->dev->bus;
|
||||
bool enabled;
|
||||
bool brought_up = false;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) {
|
||||
mutex_unlock(&wl->mutex);
|
||||
return;
|
||||
if (ssb_bus_powerup(bus, 0)) {
|
||||
mutex_unlock(&wl->mutex);
|
||||
return;
|
||||
}
|
||||
ssb_device_enable(dev->dev, 0);
|
||||
brought_up = true;
|
||||
}
|
||||
|
||||
enabled = b43legacy_is_hw_radio_enabled(dev);
|
||||
|
||||
if (unlikely(enabled != dev->radio_hw_enable)) {
|
||||
dev->radio_hw_enable = enabled;
|
||||
b43legacyinfo(wl, "Radio hardware status changed to %s\n",
|
||||
enabled ? "ENABLED" : "DISABLED");
|
||||
enabled = !rfkill_set_hw_state(rfkill, !enabled);
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
|
||||
if (enabled != dev->phy.radio_on) {
|
||||
if (enabled)
|
||||
b43legacy_radio_turn_on(dev);
|
||||
@ -69,95 +74,11 @@ static void b43legacy_rfkill_poll(struct rfkill *rfkill, void *data)
|
||||
b43legacy_radio_turn_off(dev, 0);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
/* Called when the RFKILL toggled in software.
|
||||
* This is called without locking. */
|
||||
static int b43legacy_rfkill_soft_set(void *data, bool blocked)
|
||||
{
|
||||
struct b43legacy_wldev *dev = data;
|
||||
struct b43legacy_wl *wl = dev->wl;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!wl->rfkill.registered)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
|
||||
goto out_unlock;
|
||||
|
||||
if (!dev->radio_hw_enable)
|
||||
goto out_unlock;
|
||||
|
||||
if (!blocked != dev->phy.radio_on) {
|
||||
if (!blocked)
|
||||
b43legacy_radio_turn_on(dev);
|
||||
else
|
||||
b43legacy_radio_turn_off(dev, 0);
|
||||
if (brought_up) {
|
||||
ssb_device_disable(dev->dev, 0);
|
||||
ssb_bus_may_powerdown(bus);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&wl->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
|
||||
{
|
||||
struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
|
||||
|
||||
if (!rfk->registered)
|
||||
return NULL;
|
||||
return rfkill_get_led_trigger_name(rfk->rfkill);
|
||||
}
|
||||
|
||||
static const struct rfkill_ops b43legacy_rfkill_ops = {
|
||||
.set_block = b43legacy_rfkill_soft_set,
|
||||
.poll = b43legacy_rfkill_poll,
|
||||
};
|
||||
|
||||
void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
|
||||
{
|
||||
struct b43legacy_wl *wl = dev->wl;
|
||||
struct b43legacy_rfkill *rfk = &(wl->rfkill);
|
||||
int err;
|
||||
|
||||
rfk->registered = 0;
|
||||
|
||||
snprintf(rfk->name, sizeof(rfk->name),
|
||||
"b43legacy-%s", wiphy_name(wl->hw->wiphy));
|
||||
rfk->rfkill = rfkill_alloc(rfk->name,
|
||||
dev->dev->dev,
|
||||
RFKILL_TYPE_WLAN,
|
||||
&b43legacy_rfkill_ops, dev);
|
||||
if (!rfk->rfkill)
|
||||
goto out_error;
|
||||
|
||||
err = rfkill_register(rfk->rfkill);
|
||||
if (err)
|
||||
goto err_free;
|
||||
|
||||
rfk->registered = 1;
|
||||
|
||||
return;
|
||||
err_free:
|
||||
rfkill_destroy(rfk->rfkill);
|
||||
out_error:
|
||||
rfk->registered = 0;
|
||||
b43legacywarn(wl, "RF-kill button init failed\n");
|
||||
}
|
||||
|
||||
void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
|
||||
{
|
||||
struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
|
||||
|
||||
if (!rfk->registered)
|
||||
return;
|
||||
rfk->registered = 0;
|
||||
|
||||
rfkill_unregister(rfk->rfkill);
|
||||
rfkill_destroy(rfk->rfkill);
|
||||
rfk->rfkill = NULL;
|
||||
}
|
||||
|
||||
|
@ -1,55 +1,11 @@
|
||||
#ifndef B43legacy_RFKILL_H_
|
||||
#define B43legacy_RFKILL_H_
|
||||
|
||||
struct ieee80211_hw;
|
||||
struct b43legacy_wldev;
|
||||
|
||||
#ifdef CONFIG_B43LEGACY_RFKILL
|
||||
void b43legacy_rfkill_poll(struct ieee80211_hw *hw);
|
||||
|
||||
#include <linux/rfkill.h>
|
||||
|
||||
|
||||
|
||||
struct b43legacy_rfkill {
|
||||
/* The RFKILL subsystem data structure */
|
||||
struct rfkill *rfkill;
|
||||
/* Did initialization succeed? Used for freeing. */
|
||||
bool registered;
|
||||
/* The unique name of this rfkill switch */
|
||||
char name[sizeof("b43legacy-phy4294967295")];
|
||||
};
|
||||
|
||||
/* The init function returns void, because we are not interested
|
||||
* in failing the b43 init process when rfkill init failed. */
|
||||
void b43legacy_rfkill_init(struct b43legacy_wldev *dev);
|
||||
void b43legacy_rfkill_exit(struct b43legacy_wldev *dev);
|
||||
|
||||
const char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
|
||||
|
||||
|
||||
#else /* CONFIG_B43LEGACY_RFKILL */
|
||||
/* No RFKILL support. */
|
||||
|
||||
struct b43legacy_rfkill {
|
||||
/* empty */
|
||||
};
|
||||
|
||||
static inline void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline void b43legacy_rfkill_free(struct b43legacy_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_B43LEGACY_RFKILL */
|
||||
bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev);
|
||||
|
||||
#endif /* B43legacy_RFKILL_H_ */
|
||||
|
@ -10,10 +10,6 @@ config IWLWIFI_LEDS
|
||||
bool "Enable LED support in iwlagn and iwl3945 drivers"
|
||||
depends on IWLWIFI
|
||||
|
||||
config IWLWIFI_RFKILL
|
||||
def_bool y
|
||||
depends on IWLWIFI && RFKILL
|
||||
|
||||
config IWLWIFI_SPECTRUM_MEASUREMENT
|
||||
bool "Enable Spectrum Measurement in iwlagn driver"
|
||||
depends on IWLWIFI
|
||||
|
@ -4,7 +4,6 @@ iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o
|
||||
iwlcore-objs += iwl-scan.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
|
||||
|
||||
obj-$(CONFIG_IWLAGN) += iwlagn.o
|
||||
|
@ -36,10 +36,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
|
||||
/*used for rfkill*/
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
/* Hardware specific file defines the PCI IDs table for that hardware module */
|
||||
extern struct pci_device_id iwl3945_hw_card_ids[];
|
||||
|
||||
@ -155,7 +151,6 @@ struct iwl3945_frame {
|
||||
#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
|
||||
#define STATUS_INT_ENABLED 2
|
||||
#define STATUS_RF_KILL_HW 3
|
||||
#define STATUS_RF_KILL_SW 4
|
||||
#define STATUS_INIT 5
|
||||
#define STATUS_ALIVE 6
|
||||
#define STATUS_READY 7
|
||||
|
@ -737,19 +737,13 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
|
||||
|
||||
if (flags & SW_CARD_DISABLED)
|
||||
set_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
else
|
||||
clear_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
|
||||
if (!(flags & RXON_CARD_DISABLED))
|
||||
iwl_scan_cancel(priv);
|
||||
|
||||
if ((test_bit(STATUS_RF_KILL_HW, &status) !=
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
|
||||
(test_bit(STATUS_RF_KILL_SW, &status) !=
|
||||
test_bit(STATUS_RF_KILL_SW, &priv->status)))
|
||||
queue_work(priv->workqueue, &priv->rf_kill);
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status)))
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
else
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
}
|
||||
@ -1045,7 +1039,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
else
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
queue_work(priv->workqueue, &priv->rf_kill);
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
|
||||
}
|
||||
|
||||
handled |= CSR_INT_BIT_RF_KILL;
|
||||
@ -1218,7 +1212,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
else
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
queue_work(priv->workqueue, &priv->rf_kill);
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
|
||||
}
|
||||
|
||||
handled |= CSR_INT_BIT_RF_KILL;
|
||||
@ -1726,12 +1720,10 @@ static void __iwl_down(struct iwl_priv *priv)
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
|
||||
/* If we have not previously called iwl_init() then
|
||||
* clear all bits but the RF Kill bits and return */
|
||||
* clear all bits but the RF Kill bit and return */
|
||||
if (!iwl_is_init(priv)) {
|
||||
priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
|
||||
STATUS_RF_KILL_HW |
|
||||
test_bit(STATUS_RF_KILL_SW, &priv->status) <<
|
||||
STATUS_RF_KILL_SW |
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
||||
STATUS_GEO_CONFIGURED |
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
|
||||
@ -1740,11 +1732,9 @@ static void __iwl_down(struct iwl_priv *priv)
|
||||
}
|
||||
|
||||
/* ...otherwise clear out all the status bits but the RF Kill
|
||||
* bits and continue taking the NIC down. */
|
||||
* bit and continue taking the NIC down. */
|
||||
priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
|
||||
STATUS_RF_KILL_HW |
|
||||
test_bit(STATUS_RF_KILL_SW, &priv->status) <<
|
||||
STATUS_RF_KILL_SW |
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
||||
STATUS_GEO_CONFIGURED |
|
||||
test_bit(STATUS_FW_ERROR, &priv->status) <<
|
||||
@ -1866,9 +1856,10 @@ static int __iwl_up(struct iwl_priv *priv)
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
|
||||
|
||||
iwl_enable_interrupts(priv);
|
||||
IWL_WARN(priv, "Radio disabled by %s RF Kill switch\n",
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
|
||||
IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2001,7 +1992,6 @@ static void iwl_bg_up(struct work_struct *data)
|
||||
mutex_lock(&priv->mutex);
|
||||
__iwl_up(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
iwl_rfkill_set_hw_state(priv);
|
||||
}
|
||||
|
||||
static void iwl_bg_restart(struct work_struct *data)
|
||||
@ -2179,8 +2169,6 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
iwl_rfkill_set_hw_state(priv);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -2775,7 +2763,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
||||
INIT_WORK(&priv->up, iwl_bg_up);
|
||||
INIT_WORK(&priv->restart, iwl_bg_restart);
|
||||
INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
|
||||
INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
|
||||
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
|
||||
INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
|
||||
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
|
||||
@ -3046,12 +3033,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
else
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
|
||||
err = iwl_rfkill_init(priv);
|
||||
if (err)
|
||||
IWL_ERR(priv, "Unable to initialize RFKILL system. "
|
||||
"Ignoring error: %d\n", err);
|
||||
else
|
||||
iwl_rfkill_set_hw_state(priv);
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
|
||||
iwl_power_initialize(priv);
|
||||
return 0;
|
||||
@ -3115,7 +3098,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
iwl_synchronize_irq(priv);
|
||||
|
||||
iwl_rfkill_unregister(priv);
|
||||
iwl_dealloc_ucode_pci(priv);
|
||||
|
||||
if (priv->rxq.bd)
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-rfkill.h"
|
||||
#include "iwl-power.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-helpers.h"
|
||||
@ -2211,126 +2210,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_card_state);
|
||||
|
||||
void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (test_bit(STATUS_RF_KILL_SW, &priv->status))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO OFF\n");
|
||||
|
||||
iwl_scan_cancel(priv);
|
||||
/* FIXME: This is a workaround for AP */
|
||||
if (priv->iw_mode != NL80211_IFTYPE_AP) {
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_SW_BIT_RFKILL);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
/* call the host command only if no hw rf-kill set */
|
||||
if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
|
||||
iwl_is_ready(priv))
|
||||
iwl_send_card_state(priv,
|
||||
CARD_STATE_CMD_DISABLE, 0);
|
||||
set_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
/* make sure mac80211 stop sending Tx frame */
|
||||
if (priv->mac80211_registered)
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio);
|
||||
|
||||
int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!test_bit(STATUS_RF_KILL_SW, &priv->status))
|
||||
return 0;
|
||||
|
||||
IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO ON\n");
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
||||
|
||||
/* If the driver is up it will receive CARD_STATE_NOTIFICATION
|
||||
* notification where it will clear SW rfkill status.
|
||||
* Setting it here would break the handler. Only if the
|
||||
* interface is down we can set here since we don't
|
||||
* receive any further notification.
|
||||
*/
|
||||
if (!priv->is_open)
|
||||
clear_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/* wake up ucode */
|
||||
msleep(10);
|
||||
|
||||
iwl_read32(priv, CSR_UCODE_DRV_GP1);
|
||||
spin_lock_irqsave(&priv->reg_lock, flags);
|
||||
if (!iwl_grab_nic_access(priv))
|
||||
iwl_release_nic_access(priv);
|
||||
spin_unlock_irqrestore(&priv->reg_lock, flags);
|
||||
|
||||
if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
|
||||
IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
|
||||
"disabled by HW switch\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* when driver is up while rfkill is on, it wont receive
|
||||
* any CARD_STATE_NOTIFICATION notifications so we have to
|
||||
* restart it in here
|
||||
*/
|
||||
if (priv->is_open && !test_bit(STATUS_ALIVE, &priv->status)) {
|
||||
clear_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
if (!iwl_is_rfkill(priv))
|
||||
queue_work(priv->workqueue, &priv->up);
|
||||
}
|
||||
|
||||
/* If the driver is already loaded, it will receive
|
||||
* CARD_STATE_NOTIFICATION notifications and the handler will
|
||||
* call restart to reload the driver.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);
|
||||
|
||||
void iwl_bg_rf_kill(struct work_struct *work)
|
||||
{
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
|
||||
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (!iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_RF_KILL(priv,
|
||||
"HW and/or SW RF Kill no longer active, restarting "
|
||||
"device\n");
|
||||
if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
|
||||
priv->is_open)
|
||||
queue_work(priv->workqueue, &priv->restart);
|
||||
} else {
|
||||
/* make sure mac80211 stop sending Tx frame */
|
||||
if (priv->mac80211_registered)
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
|
||||
if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
|
||||
IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
|
||||
"disabled by SW switch\n");
|
||||
else
|
||||
IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
|
||||
"Kill switch must be turned off for "
|
||||
"wireless networking to work.\n");
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
iwl_rfkill_set_hw_state(priv);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_bg_rf_kill);
|
||||
|
||||
void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
@ -2849,23 +2728,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
|
||||
if (conf->radio_enabled &&
|
||||
iwl_radio_kill_sw_enable_radio(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - "
|
||||
"waiting for uCode\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!conf->radio_enabled)
|
||||
iwl_radio_kill_sw_disable_radio(priv);
|
||||
}
|
||||
|
||||
if (!conf->radio_enabled) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
|
||||
goto out;
|
||||
|
@ -348,14 +348,6 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id);
|
||||
****************************************************/
|
||||
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
|
||||
|
||||
/*****************************************************
|
||||
* RF -Kill - here and not in iwl-rfkill.h to be available when
|
||||
* RF-kill subsystem is not compiled.
|
||||
****************************************************/
|
||||
void iwl_bg_rf_kill(struct work_struct *work);
|
||||
void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv);
|
||||
int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv);
|
||||
|
||||
/*******************************************************************************
|
||||
* Rate
|
||||
******************************************************************************/
|
||||
@ -498,7 +490,6 @@ void iwlcore_free_geos(struct iwl_priv *priv);
|
||||
#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
|
||||
#define STATUS_INT_ENABLED 2
|
||||
#define STATUS_RF_KILL_HW 3
|
||||
#define STATUS_RF_KILL_SW 4
|
||||
#define STATUS_INIT 5
|
||||
#define STATUS_ALIVE 6
|
||||
#define STATUS_READY 7
|
||||
@ -533,11 +524,6 @@ static inline int iwl_is_init(struct iwl_priv *priv)
|
||||
return test_bit(STATUS_INIT, &priv->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_rfkill_sw(struct iwl_priv *priv)
|
||||
{
|
||||
return test_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
|
||||
{
|
||||
return test_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
@ -545,7 +531,7 @@ static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
|
||||
|
||||
static inline int iwl_is_rfkill(struct iwl_priv *priv)
|
||||
{
|
||||
return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv);
|
||||
return iwl_is_rfkill_hw(priv);
|
||||
}
|
||||
|
||||
static inline int iwl_is_ready_rf(struct iwl_priv *priv)
|
||||
|
@ -449,8 +449,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
|
||||
test_bit(STATUS_INT_ENABLED, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_SW:\t %d\n",
|
||||
test_bit(STATUS_RF_KILL_SW, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
|
||||
test_bit(STATUS_INIT, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-fh.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-rfkill.h"
|
||||
#include "iwl-4965-hw.h"
|
||||
#include "iwl-3945-hw.h"
|
||||
#include "iwl-3945-led.h"
|
||||
@ -936,9 +935,6 @@ struct iwl_priv {
|
||||
* 4965's initialize alive response contains some calibration data. */
|
||||
struct iwl_init_alive_resp card_alive_init;
|
||||
struct iwl_alive_resp card_alive;
|
||||
#if defined(CONFIG_IWLWIFI_RFKILL)
|
||||
struct rfkill *rfkill;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
unsigned long last_blink_time;
|
||||
@ -1072,7 +1068,6 @@ struct iwl_priv {
|
||||
struct work_struct calibrated_work;
|
||||
struct work_struct scan_completed;
|
||||
struct work_struct rx_replenish;
|
||||
struct work_struct rf_kill;
|
||||
struct work_struct abort_scan;
|
||||
struct work_struct update_link_led;
|
||||
struct work_struct auth_work;
|
||||
|
@ -1,131 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*****************************************************************************/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
|
||||
/* software rf-kill from user */
|
||||
static int iwl_rfkill_soft_rf_kill(void *data, bool blocked)
|
||||
{
|
||||
struct iwl_priv *priv = data;
|
||||
|
||||
if (!priv->rfkill)
|
||||
return -EINVAL;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return 0;
|
||||
|
||||
IWL_DEBUG_RF_KILL(priv, "received soft RFKILL: block=%d\n", blocked);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (iwl_is_rfkill_hw(priv))
|
||||
goto out_unlock;
|
||||
|
||||
if (!blocked)
|
||||
iwl_radio_kill_sw_enable_radio(priv);
|
||||
else
|
||||
iwl_radio_kill_sw_disable_radio(priv);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&priv->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rfkill_ops iwl_rfkill_ops = {
|
||||
.set_block = iwl_rfkill_soft_rf_kill,
|
||||
};
|
||||
|
||||
int iwl_rfkill_init(struct iwl_priv *priv)
|
||||
{
|
||||
struct device *device = wiphy_dev(priv->hw->wiphy);
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(device == NULL);
|
||||
|
||||
IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n");
|
||||
priv->rfkill = rfkill_alloc(priv->cfg->name,
|
||||
device,
|
||||
RFKILL_TYPE_WLAN,
|
||||
&iwl_rfkill_ops, priv);
|
||||
if (!priv->rfkill) {
|
||||
IWL_ERR(priv, "Unable to allocate RFKILL device.\n");
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = rfkill_register(priv->rfkill);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret);
|
||||
goto free_rfkill;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
|
||||
return 0;
|
||||
|
||||
free_rfkill:
|
||||
rfkill_destroy(priv->rfkill);
|
||||
priv->rfkill = NULL;
|
||||
|
||||
error:
|
||||
IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rfkill_init);
|
||||
|
||||
void iwl_rfkill_unregister(struct iwl_priv *priv)
|
||||
{
|
||||
|
||||
if (priv->rfkill) {
|
||||
rfkill_unregister(priv->rfkill);
|
||||
rfkill_destroy(priv->rfkill);
|
||||
}
|
||||
|
||||
priv->rfkill = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rfkill_unregister);
|
||||
|
||||
/* set RFKILL to the right state. */
|
||||
void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
|
||||
{
|
||||
if (!priv->rfkill)
|
||||
return;
|
||||
|
||||
if (rfkill_set_hw_state(priv->rfkill,
|
||||
!!iwl_is_rfkill_hw(priv)))
|
||||
iwl_radio_kill_sw_disable_radio(priv);
|
||||
else
|
||||
iwl_radio_kill_sw_enable_radio(priv);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
|
@ -1,48 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*****************************************************************************/
|
||||
#ifndef __iwl_rf_kill_h__
|
||||
#define __iwl_rf_kill_h__
|
||||
|
||||
struct iwl_priv;
|
||||
|
||||
#include <linux/rfkill.h>
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_RFKILL
|
||||
|
||||
void iwl_rfkill_set_hw_state(struct iwl_priv *priv);
|
||||
void iwl_rfkill_unregister(struct iwl_priv *priv);
|
||||
int iwl_rfkill_init(struct iwl_priv *priv);
|
||||
#else
|
||||
static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {}
|
||||
static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {}
|
||||
static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* __iwl_rf_kill_h__ */
|
@ -1009,18 +1009,12 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
|
||||
|
||||
if (flags & SW_CARD_DISABLED)
|
||||
set_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
else
|
||||
clear_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
|
||||
iwl_scan_cancel(priv);
|
||||
|
||||
if ((test_bit(STATUS_RF_KILL_HW, &status) !=
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
|
||||
(test_bit(STATUS_RF_KILL_SW, &status) !=
|
||||
test_bit(STATUS_RF_KILL_SW, &priv->status)))
|
||||
queue_work(priv->workqueue, &priv->rf_kill);
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status)))
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
else
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
}
|
||||
@ -2586,8 +2580,6 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
||||
if (!iwl_is_init(priv)) {
|
||||
priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
|
||||
STATUS_RF_KILL_HW |
|
||||
test_bit(STATUS_RF_KILL_SW, &priv->status) <<
|
||||
STATUS_RF_KILL_SW |
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
||||
STATUS_GEO_CONFIGURED |
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
|
||||
@ -2596,11 +2588,9 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
||||
}
|
||||
|
||||
/* ...otherwise clear out all the status bits but the RF Kill
|
||||
* bits and continue taking the NIC down. */
|
||||
* bit and continue taking the NIC down. */
|
||||
priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
|
||||
STATUS_RF_KILL_HW |
|
||||
test_bit(STATUS_RF_KILL_SW, &priv->status) <<
|
||||
STATUS_RF_KILL_SW |
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
||||
STATUS_GEO_CONFIGURED |
|
||||
test_bit(STATUS_FW_ERROR, &priv->status) <<
|
||||
@ -2657,12 +2647,6 @@ static int __iwl3945_up(struct iwl_priv *priv)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
|
||||
IWL_WARN(priv, "Radio disabled by SW RF kill (module "
|
||||
"parameter)\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
|
||||
IWL_ERR(priv, "ucode not available for device bring up\n");
|
||||
return -EIO;
|
||||
@ -2779,15 +2763,14 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
|
||||
{
|
||||
struct iwl_priv *priv =
|
||||
container_of(data, struct iwl_priv, rfkill_poll.work);
|
||||
unsigned long status = priv->status;
|
||||
|
||||
if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
else
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
|
||||
if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status))
|
||||
queue_work(priv->workqueue, &priv->rf_kill);
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
|
||||
queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
|
||||
round_jiffies_relative(2 * HZ));
|
||||
@ -3019,7 +3002,6 @@ static void iwl3945_bg_up(struct work_struct *data)
|
||||
mutex_lock(&priv->mutex);
|
||||
__iwl3945_up(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
iwl_rfkill_set_hw_state(priv);
|
||||
}
|
||||
|
||||
static void iwl3945_bg_restart(struct work_struct *data)
|
||||
@ -3182,8 +3164,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
iwl_rfkill_set_hw_state(priv);
|
||||
|
||||
if (ret)
|
||||
goto out_release_irq;
|
||||
|
||||
@ -3836,7 +3816,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
|
||||
INIT_WORK(&priv->up, iwl3945_bg_up);
|
||||
INIT_WORK(&priv->restart, iwl3945_bg_restart);
|
||||
INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
|
||||
INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
|
||||
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
|
||||
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
|
||||
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
|
||||
@ -4203,13 +4182,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
if (err)
|
||||
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
|
||||
|
||||
err = iwl_rfkill_init(priv);
|
||||
if (err)
|
||||
IWL_ERR(priv, "Unable to initialize RFKILL system. "
|
||||
"Ignoring error: %d\n", err);
|
||||
else
|
||||
iwl_rfkill_set_hw_state(priv);
|
||||
|
||||
/* Start monitoring the killswitch */
|
||||
queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
|
||||
2 * HZ);
|
||||
@ -4275,7 +4247,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
|
||||
|
||||
iwl_rfkill_unregister(priv);
|
||||
cancel_delayed_work_sync(&priv->rfkill_poll);
|
||||
|
||||
iwl3945_dealloc_ucode_pci(priv);
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/list.h>
|
||||
@ -51,13 +50,6 @@ struct if_spi_card {
|
||||
u16 card_id;
|
||||
u8 card_rev;
|
||||
|
||||
/* Pin number for our GPIO chip-select. */
|
||||
/* TODO: Once the generic SPI layer has some additional features, we
|
||||
* should take this out and use the normal chip select here.
|
||||
* We need support for chip select delays, and not dropping chipselect
|
||||
* after each word. */
|
||||
int gpio_cs;
|
||||
|
||||
/* The last time that we initiated an SPU operation */
|
||||
unsigned long prev_xfer_time;
|
||||
|
||||
@ -130,12 +122,10 @@ static void spu_transaction_init(struct if_spi_card *card)
|
||||
* If not, we have to busy-wait to be on the safe side. */
|
||||
ndelay(400);
|
||||
}
|
||||
gpio_set_value(card->gpio_cs, 0); /* assert CS */
|
||||
}
|
||||
|
||||
static void spu_transaction_finish(struct if_spi_card *card)
|
||||
{
|
||||
gpio_set_value(card->gpio_cs, 1); /* drop CS */
|
||||
card->prev_xfer_time = jiffies;
|
||||
}
|
||||
|
||||
@ -145,6 +135,13 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
|
||||
{
|
||||
int err = 0;
|
||||
u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK);
|
||||
struct spi_message m;
|
||||
struct spi_transfer reg_trans;
|
||||
struct spi_transfer data_trans;
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(®_trans, 0, sizeof(reg_trans));
|
||||
memset(&data_trans, 0, sizeof(data_trans));
|
||||
|
||||
/* You must give an even number of bytes to the SPU, even if it
|
||||
* doesn't care about the last one. */
|
||||
@ -153,13 +150,16 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
|
||||
spu_transaction_init(card);
|
||||
|
||||
/* write SPU register index */
|
||||
err = spi_write(card->spi, (u8 *)®_out, sizeof(u16));
|
||||
if (err)
|
||||
goto out;
|
||||
reg_trans.tx_buf = ®_out;
|
||||
reg_trans.len = sizeof(reg_out);
|
||||
|
||||
err = spi_write(card->spi, buf, len);
|
||||
data_trans.tx_buf = buf;
|
||||
data_trans.len = len;
|
||||
|
||||
out:
|
||||
spi_message_add_tail(®_trans, &m);
|
||||
spi_message_add_tail(&data_trans, &m);
|
||||
|
||||
err = spi_sync(card->spi, &m);
|
||||
spu_transaction_finish(card);
|
||||
return err;
|
||||
}
|
||||
@ -186,10 +186,13 @@ static inline int spu_reg_is_port_reg(u16 reg)
|
||||
|
||||
static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
|
||||
{
|
||||
unsigned int i, delay;
|
||||
unsigned int delay;
|
||||
int err = 0;
|
||||
u16 zero = 0;
|
||||
u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK);
|
||||
struct spi_message m;
|
||||
struct spi_transfer reg_trans;
|
||||
struct spi_transfer dummy_trans;
|
||||
struct spi_transfer data_trans;
|
||||
|
||||
/* You must take an even number of bytes from the SPU, even if you
|
||||
* don't care about the last one. */
|
||||
@ -197,29 +200,34 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
|
||||
|
||||
spu_transaction_init(card);
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(®_trans, 0, sizeof(reg_trans));
|
||||
memset(&dummy_trans, 0, sizeof(dummy_trans));
|
||||
memset(&data_trans, 0, sizeof(data_trans));
|
||||
|
||||
/* write SPU register index */
|
||||
err = spi_write(card->spi, (u8 *)®_out, sizeof(u16));
|
||||
if (err)
|
||||
goto out;
|
||||
reg_trans.tx_buf = ®_out;
|
||||
reg_trans.len = sizeof(reg_out);
|
||||
spi_message_add_tail(®_trans, &m);
|
||||
|
||||
delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay :
|
||||
card->spu_reg_delay;
|
||||
if (card->use_dummy_writes) {
|
||||
/* Clock in dummy cycles while the SPU fills the FIFO */
|
||||
for (i = 0; i < delay / 16; ++i) {
|
||||
err = spi_write(card->spi, (u8 *)&zero, sizeof(u16));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
dummy_trans.len = delay / 8;
|
||||
spi_message_add_tail(&dummy_trans, &m);
|
||||
} else {
|
||||
/* Busy-wait while the SPU fills the FIFO */
|
||||
ndelay(100 + (delay * 10));
|
||||
reg_trans.delay_usecs =
|
||||
DIV_ROUND_UP((100 + (delay * 10)), 1000);
|
||||
}
|
||||
|
||||
/* read in data */
|
||||
err = spi_read(card->spi, buf, len);
|
||||
data_trans.rx_buf = buf;
|
||||
data_trans.len = len;
|
||||
spi_message_add_tail(&data_trans, &m);
|
||||
|
||||
out:
|
||||
err = spi_sync(card->spi, &m);
|
||||
spu_transaction_finish(card);
|
||||
return err;
|
||||
}
|
||||
@ -1049,7 +1057,6 @@ static int __devinit if_spi_probe(struct spi_device *spi)
|
||||
spi_set_drvdata(spi, card);
|
||||
card->pdata = pdata;
|
||||
card->spi = spi;
|
||||
card->gpio_cs = pdata->gpio_cs;
|
||||
card->prev_xfer_time = jiffies;
|
||||
|
||||
sema_init(&card->spi_ready, 0);
|
||||
@ -1058,26 +1065,18 @@ static int __devinit if_spi_probe(struct spi_device *spi)
|
||||
INIT_LIST_HEAD(&card->data_packet_list);
|
||||
spin_lock_init(&card->buffer_lock);
|
||||
|
||||
/* set up GPIO CS line. TODO: use regular CS line */
|
||||
err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select");
|
||||
if (err)
|
||||
goto free_card;
|
||||
err = gpio_direction_output(card->gpio_cs, 1);
|
||||
if (err)
|
||||
goto free_gpio;
|
||||
|
||||
/* Initialize the SPI Interface Unit */
|
||||
err = spu_init(card, pdata->use_dummy_writes);
|
||||
if (err)
|
||||
goto free_gpio;
|
||||
goto free_card;
|
||||
err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
|
||||
if (err)
|
||||
goto free_gpio;
|
||||
goto free_card;
|
||||
|
||||
/* Firmware load */
|
||||
err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
|
||||
if (err)
|
||||
goto free_gpio;
|
||||
goto free_card;
|
||||
if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
|
||||
lbs_deb_spi("Firmware is already loaded for "
|
||||
"Marvell WLAN 802.11 adapter\n");
|
||||
@ -1085,7 +1084,7 @@ static int __devinit if_spi_probe(struct spi_device *spi)
|
||||
err = if_spi_calculate_fw_names(card->card_id,
|
||||
card->helper_fw_name, card->main_fw_name);
|
||||
if (err)
|
||||
goto free_gpio;
|
||||
goto free_card;
|
||||
|
||||
lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
|
||||
"(chip_id = 0x%04x, chip_rev = 0x%02x) "
|
||||
@ -1096,23 +1095,23 @@ static int __devinit if_spi_probe(struct spi_device *spi)
|
||||
spi->max_speed_hz);
|
||||
err = if_spi_prog_helper_firmware(card);
|
||||
if (err)
|
||||
goto free_gpio;
|
||||
goto free_card;
|
||||
err = if_spi_prog_main_firmware(card);
|
||||
if (err)
|
||||
goto free_gpio;
|
||||
goto free_card;
|
||||
lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
|
||||
}
|
||||
|
||||
err = spu_set_interrupt_mode(card, 0, 1);
|
||||
if (err)
|
||||
goto free_gpio;
|
||||
goto free_card;
|
||||
|
||||
/* Register our card with libertas.
|
||||
* This will call alloc_etherdev */
|
||||
priv = lbs_add_card(card, &spi->dev);
|
||||
if (!priv) {
|
||||
err = -ENOMEM;
|
||||
goto free_gpio;
|
||||
goto free_card;
|
||||
}
|
||||
card->priv = priv;
|
||||
priv->card = card;
|
||||
@ -1157,8 +1156,6 @@ terminate_thread:
|
||||
if_spi_terminate_spi_thread(card);
|
||||
remove_card:
|
||||
lbs_remove_card(priv); /* will call free_netdev */
|
||||
free_gpio:
|
||||
gpio_free(card->gpio_cs);
|
||||
free_card:
|
||||
free_if_spi_card(card);
|
||||
out:
|
||||
@ -1179,7 +1176,6 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)
|
||||
free_irq(spi->irq, card);
|
||||
if_spi_terminate_spi_thread(card);
|
||||
lbs_remove_card(priv); /* will call free_netdev */
|
||||
gpio_free(card->gpio_cs);
|
||||
if (card->pdata->teardown)
|
||||
card->pdata->teardown(spi);
|
||||
free_if_spi_card(card);
|
||||
|
@ -157,55 +157,55 @@ MODULE_PARM_DESC(workaround_interval,
|
||||
#define NDIS_802_11_LENGTH_RATES_EX 16
|
||||
|
||||
enum ndis_80211_net_type {
|
||||
ndis_80211_type_freq_hop,
|
||||
ndis_80211_type_direct_seq,
|
||||
ndis_80211_type_ofdm_a,
|
||||
ndis_80211_type_ofdm_g
|
||||
NDIS_80211_TYPE_FREQ_HOP,
|
||||
NDIS_80211_TYPE_DIRECT_SEQ,
|
||||
NDIS_80211_TYPE_OFDM_A,
|
||||
NDIS_80211_TYPE_OFDM_G
|
||||
};
|
||||
|
||||
enum ndis_80211_net_infra {
|
||||
ndis_80211_infra_adhoc,
|
||||
ndis_80211_infra_infra,
|
||||
ndis_80211_infra_auto_unknown
|
||||
NDIS_80211_INFRA_ADHOC,
|
||||
NDIS_80211_INFRA_INFRA,
|
||||
NDIS_80211_INFRA_AUTO_UNKNOWN
|
||||
};
|
||||
|
||||
enum ndis_80211_auth_mode {
|
||||
ndis_80211_auth_open,
|
||||
ndis_80211_auth_shared,
|
||||
ndis_80211_auth_auto_switch,
|
||||
ndis_80211_auth_wpa,
|
||||
ndis_80211_auth_wpa_psk,
|
||||
ndis_80211_auth_wpa_none,
|
||||
ndis_80211_auth_wpa2,
|
||||
ndis_80211_auth_wpa2_psk
|
||||
NDIS_80211_AUTH_OPEN,
|
||||
NDIS_80211_AUTH_SHARED,
|
||||
NDIS_80211_AUTH_AUTO_SWITCH,
|
||||
NDIS_80211_AUTH_WPA,
|
||||
NDIS_80211_AUTH_WPA_PSK,
|
||||
NDIS_80211_AUTH_WPA_NONE,
|
||||
NDIS_80211_AUTH_WPA2,
|
||||
NDIS_80211_AUTH_WPA2_PSK
|
||||
};
|
||||
|
||||
enum ndis_80211_encr_status {
|
||||
ndis_80211_encr_wep_enabled,
|
||||
ndis_80211_encr_disabled,
|
||||
ndis_80211_encr_wep_key_absent,
|
||||
ndis_80211_encr_not_supported,
|
||||
ndis_80211_encr_tkip_enabled,
|
||||
ndis_80211_encr_tkip_key_absent,
|
||||
ndis_80211_encr_ccmp_enabled,
|
||||
ndis_80211_encr_ccmp_key_absent
|
||||
NDIS_80211_ENCR_WEP_ENABLED,
|
||||
NDIS_80211_ENCR_DISABLED,
|
||||
NDIS_80211_ENCR_WEP_KEY_ABSENT,
|
||||
NDIS_80211_ENCR_NOT_SUPPORTED,
|
||||
NDIS_80211_ENCR_TKIP_ENABLED,
|
||||
NDIS_80211_ENCR_TKIP_KEY_ABSENT,
|
||||
NDIS_80211_ENCR_CCMP_ENABLED,
|
||||
NDIS_80211_ENCR_CCMP_KEY_ABSENT
|
||||
};
|
||||
|
||||
enum ndis_80211_priv_filter {
|
||||
ndis_80211_priv_accept_all,
|
||||
ndis_80211_priv_8021x_wep
|
||||
NDIS_80211_PRIV_ACCEPT_ALL,
|
||||
NDIS_80211_PRIV_8021X_WEP
|
||||
};
|
||||
|
||||
enum ndis_80211_addkey_bits {
|
||||
ndis_80211_addkey_8021x_auth = cpu_to_le32(1 << 28),
|
||||
ndis_80211_addkey_set_init_recv_seq = cpu_to_le32(1 << 29),
|
||||
ndis_80211_addkey_pairwise_key = cpu_to_le32(1 << 30),
|
||||
ndis_80211_addkey_transmit_key = cpu_to_le32(1 << 31),
|
||||
NDIS_80211_ADDKEY_8021X_AUTH = cpu_to_le32(1 << 28),
|
||||
NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ = cpu_to_le32(1 << 29),
|
||||
NDIS_80211_ADDKEY_PAIRWISE_KEY = cpu_to_le32(1 << 30),
|
||||
NDIS_80211_ADDKEY_TRANSMIT_KEY = cpu_to_le32(1 << 31)
|
||||
};
|
||||
|
||||
enum ndis_80211_addwep_bits {
|
||||
ndis_80211_addwep_perclient_key = cpu_to_le32(1 << 30),
|
||||
ndis_80211_addwep_transmit_key = cpu_to_le32(1 << 31),
|
||||
NDIS_80211_ADDWEP_PERCLIENT_KEY = cpu_to_le32(1 << 30),
|
||||
NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31)
|
||||
};
|
||||
|
||||
struct ndis_80211_ssid {
|
||||
@ -361,7 +361,7 @@ static const struct ieee80211_rate rndis_rates[] = {
|
||||
};
|
||||
|
||||
/* RNDIS device private data */
|
||||
struct rndis_wext_private {
|
||||
struct rndis_wlan_private {
|
||||
struct usbnet *usbdev;
|
||||
|
||||
struct wireless_dev wdev;
|
||||
@ -441,13 +441,13 @@ static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff };
|
||||
|
||||
|
||||
static struct rndis_wext_private *get_rndis_wext_priv(struct usbnet *dev)
|
||||
static struct rndis_wlan_private *get_rndis_wlan_priv(struct usbnet *dev)
|
||||
{
|
||||
return (struct rndis_wext_private *)dev->driver_priv;
|
||||
return (struct rndis_wlan_private *)dev->driver_priv;
|
||||
}
|
||||
|
||||
|
||||
static u32 get_bcm4320_power(struct rndis_wext_private *priv)
|
||||
static u32 get_bcm4320_power(struct rndis_wlan_private *priv)
|
||||
{
|
||||
return BCM4320_DEFAULT_TXPOWER *
|
||||
bcm4320_power_output[priv->param_power_output] / 100;
|
||||
@ -480,7 +480,7 @@ static int rndis_error_status(__le32 rndis_status)
|
||||
|
||||
static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev);
|
||||
union {
|
||||
void *buf;
|
||||
struct rndis_msg_hdr *header;
|
||||
@ -526,7 +526,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
|
||||
|
||||
static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev);
|
||||
union {
|
||||
void *buf;
|
||||
struct rndis_msg_hdr *header;
|
||||
@ -747,7 +747,7 @@ static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
|
||||
|
||||
static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int ret;
|
||||
|
||||
ret = rndis_set_oid(usbdev, OID_802_11_SSID, ssid, sizeof(*ssid));
|
||||
@ -794,7 +794,7 @@ static int is_associated(struct usbnet *usbdev)
|
||||
|
||||
static int disassociate(struct usbnet *usbdev, int reset_ssid)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct ndis_80211_ssid ssid;
|
||||
int i, ret = 0;
|
||||
|
||||
@ -826,7 +826,7 @@ static int disassociate(struct usbnet *usbdev, int reset_ssid)
|
||||
|
||||
static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
__le32 tmp;
|
||||
int auth_mode, ret;
|
||||
|
||||
@ -835,23 +835,23 @@ static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
|
||||
|
||||
if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
|
||||
if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
|
||||
auth_mode = ndis_80211_auth_wpa2;
|
||||
auth_mode = NDIS_80211_AUTH_WPA2;
|
||||
else
|
||||
auth_mode = ndis_80211_auth_wpa2_psk;
|
||||
auth_mode = NDIS_80211_AUTH_WPA2_PSK;
|
||||
} else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
|
||||
if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
|
||||
auth_mode = ndis_80211_auth_wpa;
|
||||
auth_mode = NDIS_80211_AUTH_WPA;
|
||||
else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK)
|
||||
auth_mode = ndis_80211_auth_wpa_psk;
|
||||
auth_mode = NDIS_80211_AUTH_WPA_PSK;
|
||||
else
|
||||
auth_mode = ndis_80211_auth_wpa_none;
|
||||
auth_mode = NDIS_80211_AUTH_WPA_NONE;
|
||||
} else if (authalg & IW_AUTH_ALG_SHARED_KEY) {
|
||||
if (authalg & IW_AUTH_ALG_OPEN_SYSTEM)
|
||||
auth_mode = ndis_80211_auth_auto_switch;
|
||||
auth_mode = NDIS_80211_AUTH_AUTO_SWITCH;
|
||||
else
|
||||
auth_mode = ndis_80211_auth_shared;
|
||||
auth_mode = NDIS_80211_AUTH_SHARED;
|
||||
} else
|
||||
auth_mode = ndis_80211_auth_open;
|
||||
auth_mode = NDIS_80211_AUTH_OPEN;
|
||||
|
||||
tmp = cpu_to_le32(auth_mode);
|
||||
ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp,
|
||||
@ -869,16 +869,16 @@ static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
|
||||
|
||||
static int set_priv_filter(struct usbnet *usbdev)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
__le32 tmp;
|
||||
|
||||
devdbg(usbdev, "set_priv_filter: wpa_version=0x%x", priv->wpa_version);
|
||||
|
||||
if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
|
||||
priv->wpa_version & IW_AUTH_WPA_VERSION_WPA)
|
||||
tmp = cpu_to_le32(ndis_80211_priv_8021x_wep);
|
||||
tmp = cpu_to_le32(NDIS_80211_PRIV_8021X_WEP);
|
||||
else
|
||||
tmp = cpu_to_le32(ndis_80211_priv_accept_all);
|
||||
tmp = cpu_to_le32(NDIS_80211_PRIV_ACCEPT_ALL);
|
||||
|
||||
return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp,
|
||||
sizeof(tmp));
|
||||
@ -887,7 +887,7 @@ static int set_priv_filter(struct usbnet *usbdev)
|
||||
|
||||
static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
__le32 tmp;
|
||||
int encr_mode, ret;
|
||||
|
||||
@ -896,18 +896,18 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
|
||||
groupwise);
|
||||
|
||||
if (pairwise & IW_AUTH_CIPHER_CCMP)
|
||||
encr_mode = ndis_80211_encr_ccmp_enabled;
|
||||
encr_mode = NDIS_80211_ENCR_CCMP_ENABLED;
|
||||
else if (pairwise & IW_AUTH_CIPHER_TKIP)
|
||||
encr_mode = ndis_80211_encr_tkip_enabled;
|
||||
encr_mode = NDIS_80211_ENCR_TKIP_ENABLED;
|
||||
else if (pairwise &
|
||||
(IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
|
||||
encr_mode = ndis_80211_encr_wep_enabled;
|
||||
encr_mode = NDIS_80211_ENCR_WEP_ENABLED;
|
||||
else if (groupwise & IW_AUTH_CIPHER_CCMP)
|
||||
encr_mode = ndis_80211_encr_ccmp_enabled;
|
||||
encr_mode = NDIS_80211_ENCR_CCMP_ENABLED;
|
||||
else if (groupwise & IW_AUTH_CIPHER_TKIP)
|
||||
encr_mode = ndis_80211_encr_tkip_enabled;
|
||||
encr_mode = NDIS_80211_ENCR_TKIP_ENABLED;
|
||||
else
|
||||
encr_mode = ndis_80211_encr_disabled;
|
||||
encr_mode = NDIS_80211_ENCR_DISABLED;
|
||||
|
||||
tmp = cpu_to_le32(encr_mode);
|
||||
ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp,
|
||||
@ -925,7 +925,7 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
|
||||
|
||||
static int set_assoc_params(struct usbnet *usbdev)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
|
||||
set_auth_mode(usbdev, priv->wpa_version, priv->wpa_authalg);
|
||||
set_priv_filter(usbdev);
|
||||
@ -937,7 +937,7 @@ static int set_assoc_params(struct usbnet *usbdev)
|
||||
|
||||
static int set_infra_mode(struct usbnet *usbdev, int mode)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
__le32 tmp;
|
||||
int ret, i;
|
||||
|
||||
@ -970,12 +970,12 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
|
||||
|
||||
static void set_default_iw_params(struct usbnet *usbdev)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
|
||||
priv->wpa_keymgmt = 0;
|
||||
priv->wpa_version = 0;
|
||||
|
||||
set_infra_mode(usbdev, ndis_80211_infra_infra);
|
||||
set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA);
|
||||
set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
|
||||
IW_AUTH_ALG_OPEN_SYSTEM);
|
||||
set_priv_filter(usbdev);
|
||||
@ -996,7 +996,7 @@ static int deauthenticate(struct usbnet *usbdev)
|
||||
/* index must be 0 - N, as per NDIS */
|
||||
static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct ndis_80211_wep_key ndis_key;
|
||||
int ret;
|
||||
|
||||
@ -1011,7 +1011,7 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
|
||||
memcpy(&ndis_key.material, key, key_len);
|
||||
|
||||
if (index == priv->encr_tx_key_index) {
|
||||
ndis_key.index |= ndis_80211_addwep_transmit_key;
|
||||
ndis_key.index |= NDIS_80211_ADDWEP_TRANSMIT_KEY;
|
||||
ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
|
||||
IW_AUTH_CIPHER_NONE);
|
||||
if (ret)
|
||||
@ -1039,7 +1039,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
int index, const struct sockaddr *addr,
|
||||
const u8 *rx_seq, int alg, int flags)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct ndis_80211_key ndis_key;
|
||||
int ret;
|
||||
|
||||
@ -1047,15 +1047,15 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
return -EINVAL;
|
||||
if (key_len > sizeof(ndis_key.material) || key_len < 0)
|
||||
return -EINVAL;
|
||||
if ((flags & ndis_80211_addkey_set_init_recv_seq) && !rx_seq)
|
||||
if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq)
|
||||
return -EINVAL;
|
||||
if ((flags & ndis_80211_addkey_pairwise_key) && !addr)
|
||||
if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !addr)
|
||||
return -EINVAL;
|
||||
|
||||
devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index,
|
||||
!!(flags & ndis_80211_addkey_transmit_key),
|
||||
!!(flags & ndis_80211_addkey_pairwise_key),
|
||||
!!(flags & ndis_80211_addkey_set_init_recv_seq));
|
||||
!!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY),
|
||||
!!(flags & NDIS_80211_ADDKEY_PAIRWISE_KEY),
|
||||
!!(flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ));
|
||||
|
||||
memset(&ndis_key, 0, sizeof(ndis_key));
|
||||
|
||||
@ -1073,15 +1073,15 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
} else
|
||||
memcpy(ndis_key.material, key, key_len);
|
||||
|
||||
if (flags & ndis_80211_addkey_set_init_recv_seq)
|
||||
if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ)
|
||||
memcpy(ndis_key.rsc, rx_seq, 6);
|
||||
|
||||
if (flags & ndis_80211_addkey_pairwise_key) {
|
||||
if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) {
|
||||
/* pairwise key */
|
||||
memcpy(ndis_key.bssid, addr->sa_data, ETH_ALEN);
|
||||
} else {
|
||||
/* group key */
|
||||
if (priv->infra_mode == ndis_80211_infra_adhoc)
|
||||
if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
|
||||
memset(ndis_key.bssid, 0xff, ETH_ALEN);
|
||||
else
|
||||
get_bssid(usbdev, ndis_key.bssid);
|
||||
@ -1096,7 +1096,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
priv->encr_key_len[index] = key_len;
|
||||
priv->encr_key_wpa[index] = 1;
|
||||
|
||||
if (flags & ndis_80211_addkey_transmit_key)
|
||||
if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY)
|
||||
priv->encr_tx_key_index = index;
|
||||
|
||||
return 0;
|
||||
@ -1106,7 +1106,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
|
||||
/* remove_key is for both wep and wpa */
|
||||
static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct ndis_80211_remove_key remove_key;
|
||||
__le32 keyindex;
|
||||
int ret;
|
||||
@ -1128,7 +1128,7 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
|
||||
/* pairwise key */
|
||||
if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
|
||||
remove_key.index |=
|
||||
ndis_80211_addkey_pairwise_key;
|
||||
NDIS_80211_ADDKEY_PAIRWISE_KEY;
|
||||
memcpy(remove_key.bssid, bssid,
|
||||
sizeof(remove_key.bssid));
|
||||
} else
|
||||
@ -1161,7 +1161,7 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
|
||||
|
||||
static void set_multicast_list(struct usbnet *usbdev)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct dev_mc_list *mclist;
|
||||
__le32 filter;
|
||||
int ret, i, size;
|
||||
@ -1238,10 +1238,10 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex,
|
||||
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
mode = ndis_80211_infra_adhoc;
|
||||
mode = NDIS_80211_INFRA_ADHOC;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
mode = ndis_80211_infra_infra;
|
||||
mode = NDIS_80211_INFRA_INFRA;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -1256,7 +1256,7 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_scan_request *request)
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int ret;
|
||||
__le32 tmp;
|
||||
|
||||
@ -1286,7 +1286,7 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
|
||||
static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
|
||||
struct ndis_80211_bssid_ex *bssid)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct ieee80211_channel *channel;
|
||||
s32 signal;
|
||||
u64 timestamp;
|
||||
@ -1371,8 +1371,8 @@ out:
|
||||
|
||||
static void rndis_get_scan_results(struct work_struct *work)
|
||||
{
|
||||
struct rndis_wext_private *priv =
|
||||
container_of(work, struct rndis_wext_private, scan_work.work);
|
||||
struct rndis_wlan_private *priv =
|
||||
container_of(work, struct rndis_wlan_private, scan_work.work);
|
||||
struct usbnet *usbdev = priv->usbdev;
|
||||
int ret;
|
||||
|
||||
@ -1497,7 +1497,7 @@ static int rndis_iw_set_auth(struct net_device *dev,
|
||||
{
|
||||
struct iw_param *p = &wrqu->param;
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int ret = -ENOTSUPP;
|
||||
|
||||
switch (p->flags & IW_AUTH_INDEX) {
|
||||
@ -1578,7 +1578,7 @@ static int rndis_iw_get_auth(struct net_device *dev,
|
||||
{
|
||||
struct iw_param *p = &wrqu->param;
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
|
||||
switch (p->flags & IW_AUTH_INDEX) {
|
||||
case IW_AUTH_WPA_VERSION:
|
||||
@ -1609,7 +1609,7 @@ static int rndis_iw_set_encode(struct net_device *dev,
|
||||
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int ret, index, key_len;
|
||||
u8 *key;
|
||||
|
||||
@ -1672,7 +1672,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
|
||||
{
|
||||
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int keyidx, flags;
|
||||
|
||||
keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
|
||||
@ -1698,11 +1698,11 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
|
||||
|
||||
flags = 0;
|
||||
if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
|
||||
flags |= ndis_80211_addkey_set_init_recv_seq;
|
||||
flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ;
|
||||
if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
|
||||
flags |= ndis_80211_addkey_pairwise_key;
|
||||
flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY;
|
||||
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
|
||||
flags |= ndis_80211_addkey_transmit_key;
|
||||
flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;
|
||||
|
||||
return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, &ext->addr,
|
||||
ext->rx_seq, ext->alg, flags);
|
||||
@ -1713,7 +1713,7 @@ static int rndis_iw_set_genie(struct net_device *dev,
|
||||
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int ret = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -1747,7 +1747,7 @@ static int rndis_iw_get_genie(struct net_device *dev,
|
||||
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
|
||||
devdbg(usbdev, "SIOCGIWGENIE");
|
||||
|
||||
@ -1886,7 +1886,7 @@ static int rndis_iw_get_txpower(struct net_device *dev,
|
||||
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
__le32 tx_power;
|
||||
|
||||
if (priv->radio_on) {
|
||||
@ -1912,7 +1912,7 @@ static int rndis_iw_set_txpower(struct net_device *dev,
|
||||
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
__le32 tx_power = 0;
|
||||
|
||||
if (!wrqu->txpower.disabled) {
|
||||
@ -1969,7 +1969,7 @@ static int rndis_iw_set_mlme(struct net_device *dev,
|
||||
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct iw_mlme *mlme = (struct iw_mlme *)extra;
|
||||
unsigned char bssid[ETH_ALEN];
|
||||
|
||||
@ -1994,7 +1994,7 @@ static int rndis_iw_set_mlme(struct net_device *dev,
|
||||
static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->stats_lock, flags);
|
||||
@ -2037,28 +2037,28 @@ static const iw_handler rndis_iw_handler[] =
|
||||
IW_IOCTL(SIOCSIWMLME) = rndis_iw_set_mlme,
|
||||
};
|
||||
|
||||
static const iw_handler rndis_wext_private_handler[] = {
|
||||
static const iw_handler rndis_wlan_private_handler[] = {
|
||||
};
|
||||
|
||||
static const struct iw_priv_args rndis_wext_private_args[] = {
|
||||
static const struct iw_priv_args rndis_wlan_private_args[] = {
|
||||
};
|
||||
|
||||
|
||||
static const struct iw_handler_def rndis_iw_handlers = {
|
||||
.num_standard = ARRAY_SIZE(rndis_iw_handler),
|
||||
.num_private = ARRAY_SIZE(rndis_wext_private_handler),
|
||||
.num_private_args = ARRAY_SIZE(rndis_wext_private_args),
|
||||
.num_private = ARRAY_SIZE(rndis_wlan_private_handler),
|
||||
.num_private_args = ARRAY_SIZE(rndis_wlan_private_args),
|
||||
.standard = (iw_handler *)rndis_iw_handler,
|
||||
.private = (iw_handler *)rndis_wext_private_handler,
|
||||
.private_args = (struct iw_priv_args *)rndis_wext_private_args,
|
||||
.private = (iw_handler *)rndis_wlan_private_handler,
|
||||
.private_args = (struct iw_priv_args *)rndis_wlan_private_args,
|
||||
.get_wireless_stats = rndis_get_wireless_stats,
|
||||
};
|
||||
|
||||
|
||||
static void rndis_wext_worker(struct work_struct *work)
|
||||
static void rndis_wlan_worker(struct work_struct *work)
|
||||
{
|
||||
struct rndis_wext_private *priv =
|
||||
container_of(work, struct rndis_wext_private, work);
|
||||
struct rndis_wlan_private *priv =
|
||||
container_of(work, struct rndis_wlan_private, work);
|
||||
struct usbnet *usbdev = priv->usbdev;
|
||||
union iwreq_data evt;
|
||||
unsigned char bssid[ETH_ALEN];
|
||||
@ -2119,10 +2119,10 @@ get_bssid:
|
||||
set_multicast_list(usbdev);
|
||||
}
|
||||
|
||||
static void rndis_wext_set_multicast_list(struct net_device *dev)
|
||||
static void rndis_wlan_set_multicast_list(struct net_device *dev)
|
||||
{
|
||||
struct usbnet *usbdev = netdev_priv(dev);
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
|
||||
if (test_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending))
|
||||
return;
|
||||
@ -2131,9 +2131,9 @@ static void rndis_wext_set_multicast_list(struct net_device *dev)
|
||||
queue_work(priv->workqueue, &priv->work);
|
||||
}
|
||||
|
||||
static void rndis_wext_link_change(struct usbnet *usbdev, int state)
|
||||
static void rndis_wlan_link_change(struct usbnet *usbdev, int state)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
|
||||
/* queue work to avoid recursive calls into rndis_command */
|
||||
set_bit(state ? WORK_LINK_UP : WORK_LINK_DOWN, &priv->work_pending);
|
||||
@ -2141,14 +2141,14 @@ static void rndis_wext_link_change(struct usbnet *usbdev, int state)
|
||||
}
|
||||
|
||||
|
||||
static int rndis_wext_get_caps(struct usbnet *usbdev)
|
||||
static int rndis_wlan_get_caps(struct usbnet *usbdev)
|
||||
{
|
||||
struct {
|
||||
__le32 num_items;
|
||||
__le32 items[8];
|
||||
} networks_supported;
|
||||
int len, retval, i, n;
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
|
||||
/* determine supported modes */
|
||||
len = sizeof(networks_supported);
|
||||
@ -2160,14 +2160,14 @@ static int rndis_wext_get_caps(struct usbnet *usbdev)
|
||||
n = 8;
|
||||
for (i = 0; i < n; i++) {
|
||||
switch (le32_to_cpu(networks_supported.items[i])) {
|
||||
case ndis_80211_type_freq_hop:
|
||||
case ndis_80211_type_direct_seq:
|
||||
case NDIS_80211_TYPE_FREQ_HOP:
|
||||
case NDIS_80211_TYPE_DIRECT_SEQ:
|
||||
priv->caps |= CAP_MODE_80211B;
|
||||
break;
|
||||
case ndis_80211_type_ofdm_a:
|
||||
case NDIS_80211_TYPE_OFDM_A:
|
||||
priv->caps |= CAP_MODE_80211A;
|
||||
break;
|
||||
case ndis_80211_type_ofdm_g:
|
||||
case NDIS_80211_TYPE_OFDM_G:
|
||||
priv->caps |= CAP_MODE_80211G;
|
||||
break;
|
||||
}
|
||||
@ -2181,8 +2181,8 @@ static int rndis_wext_get_caps(struct usbnet *usbdev)
|
||||
#define STATS_UPDATE_JIFFIES (HZ)
|
||||
static void rndis_update_wireless_stats(struct work_struct *work)
|
||||
{
|
||||
struct rndis_wext_private *priv =
|
||||
container_of(work, struct rndis_wext_private, stats_work.work);
|
||||
struct rndis_wlan_private *priv =
|
||||
container_of(work, struct rndis_wlan_private, stats_work.work);
|
||||
struct usbnet *usbdev = priv->usbdev;
|
||||
struct iw_statistics iwstats;
|
||||
__le32 rssi, tmp;
|
||||
@ -2297,7 +2297,7 @@ static int bcm4320a_early_init(struct usbnet *usbdev)
|
||||
|
||||
static int bcm4320b_early_init(struct usbnet *usbdev)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
char buf[8];
|
||||
|
||||
/* Early initialization settings, setting these won't have effect
|
||||
@ -2363,21 +2363,21 @@ static int bcm4320b_early_init(struct usbnet *usbdev)
|
||||
}
|
||||
|
||||
/* same as rndis_netdev_ops but with local multicast handler */
|
||||
static const struct net_device_ops rndis_wext_netdev_ops = {
|
||||
static const struct net_device_ops rndis_wlan_netdev_ops = {
|
||||
.ndo_open = usbnet_open,
|
||||
.ndo_stop = usbnet_stop,
|
||||
.ndo_start_xmit = usbnet_start_xmit,
|
||||
.ndo_tx_timeout = usbnet_tx_timeout,
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_set_multicast_list = rndis_wext_set_multicast_list,
|
||||
.ndo_set_multicast_list = rndis_wlan_set_multicast_list,
|
||||
};
|
||||
|
||||
|
||||
static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
{
|
||||
struct wiphy *wiphy;
|
||||
struct rndis_wext_private *priv;
|
||||
struct rndis_wlan_private *priv;
|
||||
int retval, len;
|
||||
__le32 tmp;
|
||||
|
||||
@ -2385,7 +2385,7 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
* NOTE: We only support a single virtual interface, so wiphy
|
||||
* and wireless_dev are somewhat synonymous for this device.
|
||||
*/
|
||||
wiphy = wiphy_new(&rndis_config_ops, sizeof(struct rndis_wext_private));
|
||||
wiphy = wiphy_new(&rndis_config_ops, sizeof(struct rndis_wlan_private));
|
||||
if (!wiphy)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -2395,7 +2395,7 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
priv->wdev.iftype = NL80211_IFTYPE_STATION;
|
||||
|
||||
/* These have to be initialized before calling generic_rndis_bind().
|
||||
* Otherwise we'll be in big trouble in rndis_wext_early_init().
|
||||
* Otherwise we'll be in big trouble in rndis_wlan_early_init().
|
||||
*/
|
||||
usbdev->driver_priv = priv;
|
||||
usbdev->net->wireless_handlers = &rndis_iw_handlers;
|
||||
@ -2406,7 +2406,7 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
|
||||
/* because rndis_command() sleeps we need to use workqueue */
|
||||
priv->workqueue = create_singlethread_workqueue("rndis_wlan");
|
||||
INIT_WORK(&priv->work, rndis_wext_worker);
|
||||
INIT_WORK(&priv->work, rndis_wlan_worker);
|
||||
INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
|
||||
INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results);
|
||||
|
||||
@ -2420,9 +2420,9 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
* picks up rssi to closest station instead of to access point).
|
||||
*
|
||||
* rndis_host wants to avoid all OID as much as possible
|
||||
* so do promisc/multicast handling in rndis_wext.
|
||||
* so do promisc/multicast handling in rndis_wlan.
|
||||
*/
|
||||
usbdev->net->netdev_ops = &rndis_wext_netdev_ops;
|
||||
usbdev->net->netdev_ops = &rndis_wlan_netdev_ops;
|
||||
|
||||
tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST;
|
||||
retval = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &tmp,
|
||||
@ -2455,7 +2455,7 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
wiphy->max_scan_ssids = 1;
|
||||
|
||||
/* TODO: fill-out band information based on priv->caps */
|
||||
rndis_wext_get_caps(usbdev);
|
||||
rndis_wlan_get_caps(usbdev);
|
||||
|
||||
memcpy(priv->channels, rndis_channels, sizeof(rndis_channels));
|
||||
memcpy(priv->rates, rndis_rates, sizeof(rndis_rates));
|
||||
@ -2497,9 +2497,9 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
static void rndis_wext_unbind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
{
|
||||
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
|
||||
/* turn radio off */
|
||||
disassociate(usbdev, 0);
|
||||
@ -2520,7 +2520,7 @@ static void rndis_wext_unbind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
}
|
||||
|
||||
|
||||
static int rndis_wext_reset(struct usbnet *usbdev)
|
||||
static int rndis_wlan_reset(struct usbnet *usbdev)
|
||||
{
|
||||
return deauthenticate(usbdev);
|
||||
}
|
||||
@ -2529,40 +2529,40 @@ static int rndis_wext_reset(struct usbnet *usbdev)
|
||||
static const struct driver_info bcm4320b_info = {
|
||||
.description = "Wireless RNDIS device, BCM4320b based",
|
||||
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
|
||||
.bind = rndis_wext_bind,
|
||||
.unbind = rndis_wext_unbind,
|
||||
.bind = rndis_wlan_bind,
|
||||
.unbind = rndis_wlan_unbind,
|
||||
.status = rndis_status,
|
||||
.rx_fixup = rndis_rx_fixup,
|
||||
.tx_fixup = rndis_tx_fixup,
|
||||
.reset = rndis_wext_reset,
|
||||
.reset = rndis_wlan_reset,
|
||||
.early_init = bcm4320b_early_init,
|
||||
.link_change = rndis_wext_link_change,
|
||||
.link_change = rndis_wlan_link_change,
|
||||
};
|
||||
|
||||
static const struct driver_info bcm4320a_info = {
|
||||
.description = "Wireless RNDIS device, BCM4320a based",
|
||||
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
|
||||
.bind = rndis_wext_bind,
|
||||
.unbind = rndis_wext_unbind,
|
||||
.bind = rndis_wlan_bind,
|
||||
.unbind = rndis_wlan_unbind,
|
||||
.status = rndis_status,
|
||||
.rx_fixup = rndis_rx_fixup,
|
||||
.tx_fixup = rndis_tx_fixup,
|
||||
.reset = rndis_wext_reset,
|
||||
.reset = rndis_wlan_reset,
|
||||
.early_init = bcm4320a_early_init,
|
||||
.link_change = rndis_wext_link_change,
|
||||
.link_change = rndis_wlan_link_change,
|
||||
};
|
||||
|
||||
static const struct driver_info rndis_wext_info = {
|
||||
static const struct driver_info rndis_wlan_info = {
|
||||
.description = "Wireless RNDIS device",
|
||||
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
|
||||
.bind = rndis_wext_bind,
|
||||
.unbind = rndis_wext_unbind,
|
||||
.bind = rndis_wlan_bind,
|
||||
.unbind = rndis_wlan_unbind,
|
||||
.status = rndis_status,
|
||||
.rx_fixup = rndis_rx_fixup,
|
||||
.tx_fixup = rndis_tx_fixup,
|
||||
.reset = rndis_wext_reset,
|
||||
.reset = rndis_wlan_reset,
|
||||
.early_init = bcm4320a_early_init,
|
||||
.link_change = rndis_wext_link_change,
|
||||
.link_change = rndis_wlan_link_change,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -2672,11 +2672,11 @@ static const struct usb_device_id products [] = {
|
||||
{
|
||||
/* RNDIS is MSFT's un-official variant of CDC ACM */
|
||||
USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
|
||||
.driver_info = (unsigned long) &rndis_wext_info,
|
||||
.driver_info = (unsigned long) &rndis_wlan_info,
|
||||
}, {
|
||||
/* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */
|
||||
USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1),
|
||||
.driver_info = (unsigned long) &rndis_wext_info,
|
||||
.driver_info = (unsigned long) &rndis_wlan_info,
|
||||
},
|
||||
{ }, // END
|
||||
};
|
||||
|
@ -988,7 +988,6 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
|
||||
char *name, u32 cap)
|
||||
{
|
||||
int err;
|
||||
u32 state;
|
||||
struct rfkill *rfkill_dev;
|
||||
|
||||
rfkill_dev = rfkill_alloc(name, dev, type,
|
||||
@ -996,8 +995,6 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
|
||||
(void *)(unsigned long)cap);
|
||||
if (!rfkill_dev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
get_u32(&state, cap);
|
||||
rfkill_set_sw_state(rfkill_dev, !state);
|
||||
|
||||
err = rfkill_register(rfkill_dev);
|
||||
if (err) {
|
||||
|
@ -675,8 +675,8 @@ static int eeepc_hotk_add(struct acpi_device *device)
|
||||
if (!ehotk->eeepc_wlan_rfkill)
|
||||
goto wlan_fail;
|
||||
|
||||
rfkill_set_global_sw_state(RFKILL_TYPE_WLAN,
|
||||
get_acpi(CM_ASL_WLAN) != 1);
|
||||
rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill,
|
||||
get_acpi(CM_ASL_WLAN) != 1);
|
||||
result = rfkill_register(ehotk->eeepc_wlan_rfkill);
|
||||
if (result)
|
||||
goto wlan_fail;
|
||||
@ -693,8 +693,8 @@ static int eeepc_hotk_add(struct acpi_device *device)
|
||||
if (!ehotk->eeepc_bluetooth_rfkill)
|
||||
goto bluetooth_fail;
|
||||
|
||||
rfkill_set_global_sw_state(RFKILL_TYPE_BLUETOOTH,
|
||||
get_acpi(CM_ASL_BLUETOOTH) != 1);
|
||||
rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill,
|
||||
get_acpi(CM_ASL_BLUETOOTH) != 1);
|
||||
result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
|
||||
if (result)
|
||||
goto bluetooth_fail;
|
||||
|
@ -422,7 +422,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
|
||||
RFKILL_TYPE_WLAN,
|
||||
&hp_wmi_rfkill_ops,
|
||||
(void *) 0);
|
||||
rfkill_set_sw_state(wifi_rfkill, hp_wmi_wifi_state());
|
||||
err = rfkill_register(wifi_rfkill);
|
||||
if (err)
|
||||
goto register_wifi_error;
|
||||
@ -433,8 +432,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
|
||||
RFKILL_TYPE_BLUETOOTH,
|
||||
&hp_wmi_rfkill_ops,
|
||||
(void *) 1);
|
||||
rfkill_set_sw_state(bluetooth_rfkill,
|
||||
hp_wmi_bluetooth_state());
|
||||
err = rfkill_register(bluetooth_rfkill);
|
||||
if (err)
|
||||
goto register_bluetooth_error;
|
||||
@ -445,7 +442,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
|
||||
RFKILL_TYPE_WWAN,
|
||||
&hp_wmi_rfkill_ops,
|
||||
(void *) 2);
|
||||
rfkill_set_sw_state(wwan_rfkill, hp_wmi_wwan_state());
|
||||
err = rfkill_register(wwan_rfkill);
|
||||
if (err)
|
||||
goto register_wwan_err;
|
||||
|
@ -1114,7 +1114,6 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
|
||||
return err;
|
||||
}
|
||||
sony_rfkill_devices[nc_type] = rfk;
|
||||
sony_nc_rfkill_set((void *)nc_type, false);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1135,8 +1134,7 @@ static void sony_nc_rfkill_update()
|
||||
|
||||
if (hwblock) {
|
||||
if (rfkill_set_hw_state(sony_rfkill_devices[i], true))
|
||||
sony_nc_rfkill_set(sony_rfkill_devices[i],
|
||||
true);
|
||||
sony_nc_rfkill_set((void *)i, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1168,21 +1168,6 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
|
||||
|
||||
BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
|
||||
|
||||
initial_sw_status = (tp_rfkops->get_status)();
|
||||
if (initial_sw_status < 0) {
|
||||
printk(TPACPI_ERR
|
||||
"failed to read initial state for %s, error %d; "
|
||||
"will turn radio off\n", name, initial_sw_status);
|
||||
} else {
|
||||
initial_sw_state = (initial_sw_status == TPACPI_RFK_RADIO_OFF);
|
||||
if (set_default) {
|
||||
/* try to set the initial state as the default for the
|
||||
* rfkill type, since we ask the firmware to preserve
|
||||
* it across S5 in NVRAM */
|
||||
rfkill_set_global_sw_state(rfktype, initial_sw_state);
|
||||
}
|
||||
}
|
||||
|
||||
atp_rfk = kzalloc(sizeof(struct tpacpi_rfk), GFP_KERNEL);
|
||||
if (atp_rfk)
|
||||
atp_rfk->rfkill = rfkill_alloc(name,
|
||||
@ -1200,8 +1185,20 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
|
||||
atp_rfk->id = id;
|
||||
atp_rfk->ops = tp_rfkops;
|
||||
|
||||
rfkill_set_states(atp_rfk->rfkill, initial_sw_state,
|
||||
tpacpi_rfk_check_hwblock_state());
|
||||
initial_sw_status = (tp_rfkops->get_status)();
|
||||
if (initial_sw_status < 0) {
|
||||
printk(TPACPI_ERR
|
||||
"failed to read initial state for %s, error %d\n",
|
||||
name, initial_sw_status);
|
||||
} else {
|
||||
initial_sw_state = (initial_sw_status == TPACPI_RFK_RADIO_OFF);
|
||||
if (set_default) {
|
||||
/* try to keep the initial state, since we ask the
|
||||
* firmware to preserve it across S5 in NVRAM */
|
||||
rfkill_set_sw_state(atp_rfk->rfkill, initial_sw_state);
|
||||
}
|
||||
}
|
||||
rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state());
|
||||
|
||||
res = rfkill_register(atp_rfk->rfkill);
|
||||
if (res < 0) {
|
||||
|
@ -157,8 +157,14 @@ struct rfkill * __must_check rfkill_alloc(const char *name,
|
||||
* @rfkill: rfkill structure to be registered
|
||||
*
|
||||
* This function should be called by the transmitter driver to register
|
||||
* the rfkill structure needs to be registered. Before calling this function
|
||||
* the driver needs to be ready to service method calls from rfkill.
|
||||
* the rfkill structure. Before calling this function the driver needs
|
||||
* to be ready to service method calls from rfkill.
|
||||
*
|
||||
* If the software blocked state is not set before registration,
|
||||
* set_block will be called to initialize it to a default value.
|
||||
*
|
||||
* If the hardware blocked state is not set before registration,
|
||||
* it is assumed to be unblocked.
|
||||
*/
|
||||
int __must_check rfkill_register(struct rfkill *rfkill);
|
||||
|
||||
@ -206,7 +212,7 @@ void rfkill_destroy(struct rfkill *rfkill);
|
||||
*
|
||||
* rfkill drivers that get events when the hard-blocked state changes
|
||||
* use this function to notify the rfkill core (and through that also
|
||||
* userspace) of the current state -- they should also use this after
|
||||
* userspace) of the current state. They should also use this after
|
||||
* resume if the state could have changed.
|
||||
*
|
||||
* You need not (but may) call this function if poll_state is assigned.
|
||||
@ -228,8 +234,9 @@ bool __must_check rfkill_set_hw_state(struct rfkill *rfkill, bool blocked);
|
||||
* rfkill drivers that get events when the soft-blocked state changes
|
||||
* (yes, some platforms directly act on input but allow changing again)
|
||||
* use this function to notify the rfkill core (and through that also
|
||||
* userspace) of the current state -- they should also use this after
|
||||
* resume if the state could have changed.
|
||||
* userspace) of the current state. It is not necessary to notify on
|
||||
* resume; since hibernation can always change the soft-blocked state,
|
||||
* the rfkill core will unconditionally restore the previous state.
|
||||
*
|
||||
* This function can be called in any context, even from within rfkill
|
||||
* callbacks.
|
||||
@ -250,19 +257,6 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked);
|
||||
*/
|
||||
void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw);
|
||||
|
||||
/**
|
||||
* rfkill_set_global_sw_state - set global sw block default
|
||||
* @type: rfkill type to set default for
|
||||
* @blocked: default to set
|
||||
*
|
||||
* This function sets the global default -- use at boot if your platform has
|
||||
* an rfkill switch. If not early enough this call may be ignored.
|
||||
*
|
||||
* XXX: instead of ignoring -- how about just updating all currently
|
||||
* registered drivers?
|
||||
*/
|
||||
void rfkill_set_global_sw_state(const enum rfkill_type type, bool blocked);
|
||||
|
||||
/**
|
||||
* rfkill_blocked - query rfkill block
|
||||
*
|
||||
@ -317,11 +311,6 @@ static inline void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void rfkill_set_global_sw_state(const enum rfkill_type type,
|
||||
bool blocked)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool rfkill_blocked(struct rfkill *rfkill)
|
||||
{
|
||||
return false;
|
||||
|
@ -304,9 +304,6 @@ typedef unsigned char *sk_buff_data_t;
|
||||
* @tc_verd: traffic control verdict
|
||||
* @ndisc_nodetype: router type (from link layer)
|
||||
* @do_not_encrypt: set to prevent encryption of this frame
|
||||
* @requeue: set to indicate that the wireless core should attempt
|
||||
* a software retry on this frame if we failed to
|
||||
* receive an ACK for it
|
||||
* @dma_cookie: a cookie to one of several possible DMA operations
|
||||
* done by skb DMA functions
|
||||
* @secmark: security marking
|
||||
@ -380,7 +377,6 @@ struct sk_buff {
|
||||
#endif
|
||||
#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
|
||||
__u8 do_not_encrypt:1;
|
||||
__u8 requeue:1;
|
||||
#endif
|
||||
/* 0/13/14 bit hole */
|
||||
|
||||
|
@ -22,9 +22,6 @@ struct libertas_spi_platform_data {
|
||||
* speed, you may want to use 0 here. */
|
||||
u16 use_dummy_writes;
|
||||
|
||||
/* GPIO number to use as chip select */
|
||||
u16 gpio_cs;
|
||||
|
||||
/* Board specific setup/teardown */
|
||||
int (*setup)(struct spi_device *spi);
|
||||
int (*teardown)(struct spi_device *spi);
|
||||
|
@ -239,6 +239,8 @@ struct ieee80211_bss_conf {
|
||||
* @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211,
|
||||
* used to indicate that a pending frame requires TX processing before
|
||||
* it can be sent out.
|
||||
* @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211,
|
||||
* used to indicate that a frame was already retried due to PS
|
||||
*/
|
||||
enum mac80211_tx_control_flags {
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
|
||||
@ -256,6 +258,7 @@ enum mac80211_tx_control_flags {
|
||||
IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12),
|
||||
IEEE80211_TX_INTFL_RCALGO = BIT(13),
|
||||
IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14),
|
||||
IEEE80211_TX_INTFL_RETRIED = BIT(15),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -552,7 +552,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
||||
new->vlan_tci = old->vlan_tci;
|
||||
#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
|
||||
new->do_not_encrypt = old->do_not_encrypt;
|
||||
new->requeue = old->requeue;
|
||||
#endif
|
||||
|
||||
skb_copy_secmark(new, old);
|
||||
|
@ -132,6 +132,9 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
|
||||
|
||||
state = &sta->ampdu_mlme.tid_state_tx[tid];
|
||||
|
||||
if (*state == HT_AGG_STATE_OPERATIONAL)
|
||||
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
||||
|
||||
*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
|
||||
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
|
||||
|
||||
@ -337,6 +340,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
||||
sta->ampdu_mlme.tid_tx[tid]->dialog_token,
|
||||
sta->ampdu_mlme.tid_tx[tid]->ssn,
|
||||
0x40, 5000);
|
||||
sta->ampdu_mlme.addba_req_num[tid]++;
|
||||
/* activate the timer for the recipient's addBA response */
|
||||
sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
|
||||
jiffies + ADDBA_RESP_INTERVAL;
|
||||
@ -606,7 +610,6 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
|
||||
|
||||
*state = HT_AGG_STATE_IDLE;
|
||||
/* from now on packets are no longer put onto sta->pending */
|
||||
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
||||
kfree(sta->ampdu_mlme.tid_tx[tid]);
|
||||
sta->ampdu_mlme.tid_tx[tid] = NULL;
|
||||
|
||||
@ -689,7 +692,6 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
|
||||
|
||||
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
||||
} else {
|
||||
sta->ampdu_mlme.addba_req_num[tid]++;
|
||||
___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
|
||||
}
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
@ -1122,8 +1122,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
|
||||
p.txop = params->txop;
|
||||
if (drv_conf_tx(local, params->queue, &p)) {
|
||||
printk(KERN_DEBUG "%s: failed to set TX queue "
|
||||
"parameters for queue %d\n", local->mdev->name,
|
||||
params->queue);
|
||||
"parameters for queue %d\n",
|
||||
wiphy_name(local->hw.wiphy), params->queue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -589,6 +589,7 @@ enum queue_stop_reason {
|
||||
IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
|
||||
IEEE80211_QUEUE_STOP_REASON_PENDING,
|
||||
IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
|
||||
};
|
||||
|
||||
struct ieee80211_master_priv {
|
||||
@ -1121,6 +1122,10 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
enum queue_stop_reason reason);
|
||||
void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
enum queue_stop_reason reason);
|
||||
void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
struct sk_buff *skb);
|
||||
int ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs);
|
||||
|
||||
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
|
||||
u16 transaction, u16 auth_alg,
|
||||
|
@ -369,60 +369,12 @@ static void ieee80211_tasklet_handler(unsigned long data)
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
|
||||
* make a prepared TX frame (one that has been given to hw) to look like brand
|
||||
* new IEEE 802.11 frame that is ready to go through TX processing again.
|
||||
*/
|
||||
static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
|
||||
struct ieee80211_key *key,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
unsigned int hdrlen, iv_len, mic_len;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (!key)
|
||||
goto no_key;
|
||||
|
||||
switch (key->conf.alg) {
|
||||
case ALG_WEP:
|
||||
iv_len = WEP_IV_LEN;
|
||||
mic_len = WEP_ICV_LEN;
|
||||
break;
|
||||
case ALG_TKIP:
|
||||
iv_len = TKIP_IV_LEN;
|
||||
mic_len = TKIP_ICV_LEN;
|
||||
break;
|
||||
case ALG_CCMP:
|
||||
iv_len = CCMP_HDR_LEN;
|
||||
mic_len = CCMP_MIC_LEN;
|
||||
break;
|
||||
default:
|
||||
goto no_key;
|
||||
}
|
||||
|
||||
if (skb->len >= hdrlen + mic_len &&
|
||||
!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
|
||||
skb_trim(skb, skb->len - mic_len);
|
||||
if (skb->len >= hdrlen + iv_len) {
|
||||
memmove(skb->data + iv_len, skb->data, hdrlen);
|
||||
hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len);
|
||||
}
|
||||
|
||||
no_key:
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
|
||||
memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data,
|
||||
hdrlen - IEEE80211_QOS_CTL_LEN);
|
||||
skb_pull(skb, IEEE80211_QOS_CTL_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
sta->tx_filtered_count++;
|
||||
|
||||
/*
|
||||
@ -464,16 +416,15 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
*/
|
||||
if (test_sta_flags(sta, WLAN_STA_PS) &&
|
||||
skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
|
||||
ieee80211_remove_tx_extra(local, sta->key, skb);
|
||||
skb_queue_tail(&sta->tx_filtered, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) {
|
||||
if (!test_sta_flags(sta, WLAN_STA_PS) &&
|
||||
!(info->flags & IEEE80211_TX_INTFL_RETRIED)) {
|
||||
/* Software retry the packet once */
|
||||
skb->requeue = 1;
|
||||
ieee80211_remove_tx_extra(local, sta->key, skb);
|
||||
dev_queue_xmit(skb);
|
||||
info->flags |= IEEE80211_TX_INTFL_RETRIED;
|
||||
ieee80211_add_pending_skb(local, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -621,9 +621,6 @@ static void ieee80211_change_ps(struct ieee80211_local *local)
|
||||
struct ieee80211_conf *conf = &local->hw.conf;
|
||||
|
||||
if (local->ps_sdata) {
|
||||
if (!(local->ps_sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED))
|
||||
return;
|
||||
|
||||
ieee80211_enable_ps(local, local->ps_sdata);
|
||||
} else if (conf->flags & IEEE80211_CONF_PS) {
|
||||
conf->flags &= ~IEEE80211_CONF_PS;
|
||||
@ -653,7 +650,9 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 1 && found->u.mgd.powersave) {
|
||||
if (count == 1 && found->u.mgd.powersave &&
|
||||
(found->u.mgd.flags & IEEE80211_STA_ASSOCIATED) &&
|
||||
!(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) {
|
||||
s32 beaconint_us;
|
||||
|
||||
if (latency < 0)
|
||||
@ -793,13 +792,13 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
||||
printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
|
||||
"cWmin=%d cWmax=%d txop=%d\n",
|
||||
local->mdev->name, queue, aci, acm, params.aifs, params.cw_min,
|
||||
params.cw_max, params.txop);
|
||||
wiphy_name(local->hw.wiphy), queue, aci, acm,
|
||||
params.aifs, params.cw_min, params.cw_max, params.txop);
|
||||
#endif
|
||||
if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx)
|
||||
printk(KERN_DEBUG "%s: failed to set TX queue "
|
||||
"parameters for queue %d\n", local->mdev->name,
|
||||
queue);
|
||||
"parameters for queue %d\n",
|
||||
wiphy_name(local->hw.wiphy), queue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1322,6 +1321,11 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
|
||||
#endif
|
||||
|
||||
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
|
||||
|
||||
mutex_lock(&sdata->local->iflist_mtx);
|
||||
ieee80211_recalc_ps(sdata->local, -1);
|
||||
mutex_unlock(&sdata->local->iflist_mtx);
|
||||
|
||||
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
|
||||
ifmgd->ssid_len, NULL, 0);
|
||||
|
||||
@ -1342,6 +1346,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
unsigned long last_rx;
|
||||
bool disassoc = false;
|
||||
|
||||
/* TODO: start monitoring current AP signal quality and number of
|
||||
@ -1358,17 +1363,21 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
|
||||
printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
|
||||
sdata->dev->name, ifmgd->bssid);
|
||||
disassoc = true;
|
||||
goto unlock;
|
||||
rcu_read_unlock();
|
||||
goto out;
|
||||
}
|
||||
|
||||
last_rx = sta->last_rx;
|
||||
rcu_read_unlock();
|
||||
|
||||
if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) &&
|
||||
time_after(jiffies, sta->last_rx + IEEE80211_PROBE_WAIT)) {
|
||||
time_after(jiffies, last_rx + IEEE80211_PROBE_WAIT)) {
|
||||
printk(KERN_DEBUG "%s: no probe response from AP %pM "
|
||||
"- disassociating\n",
|
||||
sdata->dev->name, ifmgd->bssid);
|
||||
disassoc = true;
|
||||
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
|
||||
goto unlock;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1387,26 +1396,29 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
|
||||
}
|
||||
#endif
|
||||
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
ieee80211_recalc_ps(local, -1);
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
|
||||
ifmgd->ssid_len, NULL, 0);
|
||||
mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
|
||||
goto unlock;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) {
|
||||
if (time_after(jiffies, last_rx + IEEE80211_PROBE_IDLE_TIME)) {
|
||||
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
ieee80211_recalc_ps(local, -1);
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
|
||||
ifmgd->ssid_len, NULL, 0);
|
||||
}
|
||||
|
||||
out:
|
||||
if (!disassoc)
|
||||
mod_timer(&ifmgd->timer,
|
||||
jiffies + IEEE80211_MONITORING_INTERVAL);
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
if (disassoc)
|
||||
else
|
||||
ieee80211_set_disassoc(sdata, true, true,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
}
|
||||
@ -1889,8 +1901,12 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_authenticate(sdata);
|
||||
}
|
||||
|
||||
if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
|
||||
if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
|
||||
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
|
||||
mutex_lock(&sdata->local->iflist_mtx);
|
||||
ieee80211_recalc_ps(sdata->local, -1);
|
||||
mutex_unlock(&sdata->local->iflist_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1948,6 +1964,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
#endif
|
||||
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
ieee80211_recalc_ps(local, -1);
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
|
||||
ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
|
||||
|
@ -215,7 +215,7 @@ minstrel_get_next_sample(struct minstrel_sta_info *mi)
|
||||
unsigned int sample_ndx;
|
||||
sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column);
|
||||
mi->sample_idx++;
|
||||
if (mi->sample_idx > (mi->n_rates - 2)) {
|
||||
if ((int) mi->sample_idx > (mi->n_rates - 2)) {
|
||||
mi->sample_idx = 0;
|
||||
mi->sample_column++;
|
||||
if (mi->sample_column >= SAMPLE_COLUMNS)
|
||||
|
@ -797,8 +797,7 @@ static int ap_sta_ps_end(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff *skb;
|
||||
int sent = 0;
|
||||
int sent, buffered;
|
||||
|
||||
atomic_dec(&sdata->bss->num_sta_ps);
|
||||
|
||||
@ -814,22 +813,16 @@ static int ap_sta_ps_end(struct sta_info *sta)
|
||||
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
||||
|
||||
/* Send all buffered frames to the station */
|
||||
while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
|
||||
sent++;
|
||||
skb->requeue = 1;
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
|
||||
local->total_ps_buffered--;
|
||||
sent++;
|
||||
sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered);
|
||||
buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf);
|
||||
sent += buffered;
|
||||
local->total_ps_buffered -= buffered;
|
||||
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
||||
printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame "
|
||||
"since STA not sleeping anymore\n", sdata->dev->name,
|
||||
sta->sta.addr, sta->sta.aid);
|
||||
printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
|
||||
"since STA not sleeping anymore\n", sdata->dev->name,
|
||||
sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
|
||||
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
||||
skb->requeue = 1;
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
@ -1335,7 +1328,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
||||
* mac80211. That also explains the __skb_push()
|
||||
* below.
|
||||
*/
|
||||
align = (unsigned long)skb->data & 3;
|
||||
align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3;
|
||||
if (align) {
|
||||
if (WARN_ON(skb_headroom(skb) < 3)) {
|
||||
dev_kfree_skb(skb);
|
||||
|
@ -400,6 +400,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
sta_info_set_tim_bit(sta);
|
||||
|
||||
info->control.jiffies = jiffies;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
skb_queue_tail(&sta->ps_tx_buf, tx->skb);
|
||||
return TX_QUEUED;
|
||||
}
|
||||
@ -420,7 +421,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
* frame filtering and keeps a station blacklist on its own
|
||||
* (e.g: p54), so that frames can be delivered unimpeded.
|
||||
*
|
||||
* Note: It should be save to disable the filter now.
|
||||
* Note: It should be safe to disable the filter now.
|
||||
* As, it is really unlikely that we still have any pending
|
||||
* frame for this station in the hw's buffers/fifos left,
|
||||
* that is not rejected with a unsuccessful tx_status yet.
|
||||
@ -907,9 +908,8 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
|
||||
* deal with packet injection down monitor interface
|
||||
* with Radiotap Header -- only called for monitor mode interface
|
||||
*/
|
||||
static ieee80211_tx_result
|
||||
__ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb)
|
||||
static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
/*
|
||||
* this is the moment to interpret and discard the radiotap header that
|
||||
@ -960,7 +960,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
* on transmission
|
||||
*/
|
||||
if (skb->len < (iterator.max_length + FCS_LEN))
|
||||
return TX_DROP;
|
||||
return false;
|
||||
|
||||
skb_trim(skb, skb->len - FCS_LEN);
|
||||
}
|
||||
@ -982,7 +982,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
}
|
||||
|
||||
if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
|
||||
return TX_DROP;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* remove the radiotap header
|
||||
@ -991,7 +991,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
*/
|
||||
skb_pull(skb, iterator.max_length);
|
||||
|
||||
return TX_CONTINUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1025,7 +1025,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
/* process and remove the injection radiotap header */
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
|
||||
if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP)
|
||||
if (!__ieee80211_parse_tx_radiotap(tx, skb))
|
||||
return TX_DROP;
|
||||
|
||||
/*
|
||||
@ -1415,7 +1415,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
|
||||
if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
|
||||
local->hw.conf.dynamic_ps_timeout > 0) {
|
||||
local->hw.conf.dynamic_ps_timeout > 0 &&
|
||||
!local->sw_scanning && !local->hw_scanning && local->ps_sdata) {
|
||||
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_PS);
|
||||
|
@ -341,6 +341,52 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_stop_queue);
|
||||
|
||||
void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
unsigned long flags;
|
||||
int queue = skb_get_queue_mapping(skb);
|
||||
|
||||
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
__ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
__ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_PENDING);
|
||||
skb_queue_tail(&local->pending[queue], skb);
|
||||
__ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
}
|
||||
|
||||
int ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs)
|
||||
{
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
int queue, ret = 0, i;
|
||||
|
||||
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
for (i = 0; i < hw->queues; i++)
|
||||
__ieee80211_stop_queue(hw, i,
|
||||
IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
|
||||
while ((skb = skb_dequeue(skbs))) {
|
||||
ret++;
|
||||
queue = skb_get_queue_mapping(skb);
|
||||
skb_queue_tail(&local->pending[queue], skb);
|
||||
}
|
||||
|
||||
for (i = 0; i < hw->queues; i++) {
|
||||
if (ret)
|
||||
__ieee80211_stop_queue(hw, i,
|
||||
IEEE80211_QUEUE_STOP_REASON_PENDING);
|
||||
__ieee80211_wake_queue(hw, i,
|
||||
IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
}
|
||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb)
|
||||
* Now we know the 1d priority, fill in the QoS header if
|
||||
* there is one (and we haven't done this before).
|
||||
*/
|
||||
if (!skb->requeue && ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
u8 *p = ieee80211_get_qos_ctl(hdr);
|
||||
u8 ack_policy = 0;
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
|
@ -18,7 +18,7 @@ config RFKILL_LEDS
|
||||
default y
|
||||
|
||||
config RFKILL_INPUT
|
||||
bool "RF switch input support"
|
||||
bool "RF switch input support" if EMBEDDED
|
||||
depends on RFKILL
|
||||
depends on INPUT = y || RFKILL = INPUT
|
||||
default y if !EMBEDDED
|
||||
|
@ -57,6 +57,7 @@ struct rfkill {
|
||||
|
||||
bool registered;
|
||||
bool suspended;
|
||||
bool persistent;
|
||||
|
||||
const struct rfkill_ops *ops;
|
||||
void *data;
|
||||
@ -116,11 +117,9 @@ MODULE_PARM_DESC(default_state,
|
||||
"Default initial state for all radio types, 0 = radio off");
|
||||
|
||||
static struct {
|
||||
bool cur, def;
|
||||
bool cur, sav;
|
||||
} rfkill_global_states[NUM_RFKILL_TYPES];
|
||||
|
||||
static unsigned long rfkill_states_default_locked;
|
||||
|
||||
static bool rfkill_epo_lock_active;
|
||||
|
||||
|
||||
@ -392,7 +391,7 @@ void rfkill_epo(void)
|
||||
rfkill_set_block(rfkill, true);
|
||||
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++) {
|
||||
rfkill_global_states[i].def = rfkill_global_states[i].cur;
|
||||
rfkill_global_states[i].sav = rfkill_global_states[i].cur;
|
||||
rfkill_global_states[i].cur = true;
|
||||
}
|
||||
|
||||
@ -417,7 +416,7 @@ void rfkill_restore_states(void)
|
||||
|
||||
rfkill_epo_lock_active = false;
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++)
|
||||
__rfkill_switch_all(i, rfkill_global_states[i].def);
|
||||
__rfkill_switch_all(i, rfkill_global_states[i].sav);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
}
|
||||
|
||||
@ -464,29 +463,6 @@ bool rfkill_get_global_sw_state(const enum rfkill_type type)
|
||||
}
|
||||
#endif
|
||||
|
||||
void rfkill_set_global_sw_state(const enum rfkill_type type, bool blocked)
|
||||
{
|
||||
BUG_ON(type == RFKILL_TYPE_ALL);
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
|
||||
/* don't allow unblock when epo */
|
||||
if (rfkill_epo_lock_active && !blocked)
|
||||
goto out;
|
||||
|
||||
/* too late */
|
||||
if (rfkill_states_default_locked & BIT(type))
|
||||
goto out;
|
||||
|
||||
rfkill_states_default_locked |= BIT(type);
|
||||
|
||||
rfkill_global_states[type].cur = blocked;
|
||||
rfkill_global_states[type].def = blocked;
|
||||
out:
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_set_global_sw_state);
|
||||
|
||||
|
||||
bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
|
||||
{
|
||||
@ -532,13 +508,14 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked)
|
||||
blocked = blocked || hwblock;
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
if (!rfkill->registered)
|
||||
return blocked;
|
||||
if (!rfkill->registered) {
|
||||
rfkill->persistent = true;
|
||||
} else {
|
||||
if (prev != blocked && !hwblock)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
if (prev != blocked && !hwblock)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
}
|
||||
|
||||
return blocked;
|
||||
}
|
||||
@ -563,13 +540,14 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
|
||||
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
if (!rfkill->registered)
|
||||
return;
|
||||
if (!rfkill->registered) {
|
||||
rfkill->persistent = true;
|
||||
} else {
|
||||
if (swprev != sw || hwprev != hw)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
if (swprev != sw || hwprev != hw)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_set_states);
|
||||
|
||||
@ -750,15 +728,11 @@ static int rfkill_resume(struct device *dev)
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
bool cur;
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
cur = rfkill_global_states[rfkill->type].cur;
|
||||
cur = !!(rfkill->state & RFKILL_BLOCK_SW);
|
||||
rfkill_set_block(rfkill, cur);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
rfkill->suspended = false;
|
||||
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
rfkill_resume_polling(rfkill);
|
||||
|
||||
return 0;
|
||||
@ -888,15 +862,6 @@ int __must_check rfkill_register(struct rfkill *rfkill)
|
||||
dev_set_name(dev, "rfkill%lu", rfkill_no);
|
||||
rfkill_no++;
|
||||
|
||||
if (!(rfkill_states_default_locked & BIT(rfkill->type))) {
|
||||
/* first of its kind */
|
||||
BUILD_BUG_ON(NUM_RFKILL_TYPES >
|
||||
sizeof(rfkill_states_default_locked) * 8);
|
||||
rfkill_states_default_locked |= BIT(rfkill->type);
|
||||
rfkill_global_states[rfkill->type].cur =
|
||||
rfkill_global_states[rfkill->type].def;
|
||||
}
|
||||
|
||||
list_add_tail(&rfkill->node, &rfkill_list);
|
||||
|
||||
error = device_add(dev);
|
||||
@ -916,7 +881,17 @@ int __must_check rfkill_register(struct rfkill *rfkill)
|
||||
if (rfkill->ops->poll)
|
||||
schedule_delayed_work(&rfkill->poll_work,
|
||||
round_jiffies_relative(POLL_INTERVAL));
|
||||
schedule_work(&rfkill->sync_work);
|
||||
|
||||
if (!rfkill->persistent || rfkill_epo_lock_active) {
|
||||
schedule_work(&rfkill->sync_work);
|
||||
} else {
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
bool soft_blocked = !!(rfkill->state & RFKILL_BLOCK_SW);
|
||||
|
||||
if (!atomic_read(&rfkill_input_disabled))
|
||||
__rfkill_switch_all(rfkill->type, soft_blocked);
|
||||
#endif
|
||||
}
|
||||
|
||||
rfkill_send_events(rfkill, RFKILL_OP_ADD);
|
||||
|
||||
@ -1134,7 +1109,8 @@ static int rfkill_fop_release(struct inode *inode, struct file *file)
|
||||
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
if (data->input_handler)
|
||||
atomic_dec(&rfkill_input_disabled);
|
||||
if (atomic_dec_return(&rfkill_input_disabled) == 0)
|
||||
printk(KERN_DEBUG "rfkill: input handler enabled\n");
|
||||
#endif
|
||||
|
||||
kfree(data);
|
||||
@ -1157,7 +1133,8 @@ static long rfkill_fop_ioctl(struct file *file, unsigned int cmd,
|
||||
mutex_lock(&data->mtx);
|
||||
|
||||
if (!data->input_handler) {
|
||||
atomic_inc(&rfkill_input_disabled);
|
||||
if (atomic_inc_return(&rfkill_input_disabled) == 1)
|
||||
printk(KERN_DEBUG "rfkill: input handler disabled\n");
|
||||
data->input_handler = true;
|
||||
}
|
||||
|
||||
@ -1191,7 +1168,7 @@ static int __init rfkill_init(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++)
|
||||
rfkill_global_states[i].def = !rfkill_default_state;
|
||||
rfkill_global_states[i].cur = !rfkill_default_state;
|
||||
|
||||
error = class_register(&rfkill_class);
|
||||
if (error)
|
||||
|
@ -395,21 +395,23 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
/* check and set up bitrates */
|
||||
ieee80211_set_bitrate_flags(wiphy);
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
/* set up regulatory info */
|
||||
wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
|
||||
|
||||
res = device_add(&drv->wiphy.dev);
|
||||
if (res)
|
||||
goto out_unlock;
|
||||
return res;
|
||||
|
||||
res = rfkill_register(drv->rfkill);
|
||||
if (res)
|
||||
goto out_rm_dev;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
/* set up regulatory info */
|
||||
wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
|
||||
|
||||
list_add(&drv->list, &cfg80211_drv_list);
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
/* add to debugfs */
|
||||
drv->wiphy.debugfsdir =
|
||||
debugfs_create_dir(wiphy_name(&drv->wiphy),
|
||||
@ -430,13 +432,10 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
|
||||
cfg80211_debugfs_drv_add(drv);
|
||||
|
||||
res = 0;
|
||||
goto out_unlock;
|
||||
return 0;
|
||||
|
||||
out_rm_dev:
|
||||
device_del(&drv->wiphy.dev);
|
||||
out_unlock:
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_register);
|
||||
|
@ -2129,7 +2129,12 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
|
||||
* driver wanted to the wiphy to deal with conflicts
|
||||
*/
|
||||
|
||||
BUG_ON(request_wiphy->regd);
|
||||
/*
|
||||
* Userspace could have sent two replies with only
|
||||
* one kernel request.
|
||||
*/
|
||||
if (request_wiphy->regd)
|
||||
return -EALREADY;
|
||||
|
||||
r = reg_copy_regd(&request_wiphy->regd, rd);
|
||||
if (r)
|
||||
|
Loading…
Reference in New Issue
Block a user