Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

This commit is contained in:
David S. Miller 2009-06-10 23:41:43 -07:00
commit 84503ddd65
69 changed files with 1278 additions and 1485 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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 */

View File

@ -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];

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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

View 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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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.

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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",

View File

@ -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;

View File

@ -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);

View File

@ -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__ */

View File

@ -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);

View File

@ -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(&reg_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 *)&reg_out, sizeof(u16));
if (err)
goto out;
reg_trans.tx_buf = &reg_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(&reg_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(&reg_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 *)&reg_out, sizeof(u16));
if (err)
goto out;
reg_trans.tx_buf = &reg_out;
reg_trans.len = sizeof(reg_out);
spi_message_add_tail(&reg_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);

View File

@ -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
};

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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),
};
/**

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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, &params) && 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);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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)