diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2400pci.c')
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.c | 85 | 
1 files changed, 56 insertions, 29 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index ad2c98af7e9..5063e01410e 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -586,9 +586,11 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,  static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev,  				     struct link_qual *qual, u8 vgc_level)  { -	rt2400pci_bbp_write(rt2x00dev, 13, vgc_level); -	qual->vgc_level = vgc_level; -	qual->vgc_level_reg = vgc_level; +	if (qual->vgc_level_reg != vgc_level) { +		rt2400pci_bbp_write(rt2x00dev, 13, vgc_level); +		qual->vgc_level = vgc_level; +		qual->vgc_level_reg = vgc_level; +	}  }  static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev, @@ -877,7 +879,8 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,  static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,  				 enum dev_state state)  { -	int mask = (state == STATE_RADIO_IRQ_OFF); +	int mask = (state == STATE_RADIO_IRQ_OFF) || +		   (state == STATE_RADIO_IRQ_OFF_ISR);  	u32 reg;  	/* @@ -978,7 +981,9 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,  		rt2400pci_toggle_rx(rt2x00dev, state);  		break;  	case STATE_RADIO_IRQ_ON: +	case STATE_RADIO_IRQ_ON_ISR:  	case STATE_RADIO_IRQ_OFF: +	case STATE_RADIO_IRQ_OFF_ISR:  		rt2400pci_toggle_irq(rt2x00dev, state);  		break;  	case STATE_DEEP_SLEEP: @@ -1076,9 +1081,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,  				   struct txentry_desc *txdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; -	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); -	u32 word;  	u32 reg;  	/* @@ -1091,9 +1093,15 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,  	rt2x00queue_map_txskb(rt2x00dev, entry->skb); -	rt2x00_desc_read(entry_priv->desc, 1, &word); -	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); -	rt2x00_desc_write(entry_priv->desc, 1, word); +	/* +	 * Write the TX descriptor for the beacon. +	 */ +	rt2400pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); + +	/* +	 * Dump beacon to userspace through debugfs. +	 */ +	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);  	/*  	 * Enable beaconing again. @@ -1230,23 +1238,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,  	}  } -static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) +static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance)  {  	struct rt2x00_dev *rt2x00dev = dev_instance; -	u32 reg; - -	/* -	 * Get the interrupt sources & saved to local variable. -	 * Write register value back to clear pending interrupts. -	 */ -	rt2x00pci_register_read(rt2x00dev, CSR7, ®); -	rt2x00pci_register_write(rt2x00dev, CSR7, reg); - -	if (!reg) -		return IRQ_NONE; - -	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) -		return IRQ_HANDLED; +	u32 reg = rt2x00dev->irqvalue[0];  	/*  	 * Handle interrupts, walk through all bits @@ -1284,9 +1279,40 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)  	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))  		rt2400pci_txdone(rt2x00dev, QID_AC_BK); +	/* Enable interrupts again. */ +	rt2x00dev->ops->lib->set_device_state(rt2x00dev, +					      STATE_RADIO_IRQ_ON_ISR);  	return IRQ_HANDLED;  } +static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) +{ +	struct rt2x00_dev *rt2x00dev = dev_instance; +	u32 reg; + +	/* +	 * Get the interrupt sources & saved to local variable. +	 * Write register value back to clear pending interrupts. +	 */ +	rt2x00pci_register_read(rt2x00dev, CSR7, ®); +	rt2x00pci_register_write(rt2x00dev, CSR7, reg); + +	if (!reg) +		return IRQ_NONE; + +	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		return IRQ_HANDLED; + +	/* Store irqvalues for use in the interrupt thread. */ +	rt2x00dev->irqvalue[0] = reg; + +	/* Disable interrupts, will be enabled again in the interrupt thread. */ +	rt2x00dev->ops->lib->set_device_state(rt2x00dev, +					      STATE_RADIO_IRQ_OFF_ISR); + +	return IRQ_WAKE_THREAD; +} +  /*   * Device probe functions.   */ @@ -1396,8 +1422,8 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	/*  	 * Check if the BBP tuning should be enabled.  	 */ -	if (!rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING)) -		__set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); +	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING)) +		__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);  	return 0;  } @@ -1563,7 +1589,8 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {  	.remove_interface	= rt2x00mac_remove_interface,  	.config			= rt2x00mac_config,  	.configure_filter	= rt2x00mac_configure_filter, -	.set_tim		= rt2x00mac_set_tim, +	.sw_scan_start		= rt2x00mac_sw_scan_start, +	.sw_scan_complete	= rt2x00mac_sw_scan_complete,  	.get_stats		= rt2x00mac_get_stats,  	.bss_info_changed	= rt2x00mac_bss_info_changed,  	.conf_tx		= rt2400pci_conf_tx, @@ -1574,6 +1601,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {  static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {  	.irq_handler		= rt2400pci_interrupt, +	.irq_handler_thread	= rt2400pci_interrupt_thread,  	.probe_hw		= rt2400pci_probe_hw,  	.initialize		= rt2x00pci_initialize,  	.uninitialize		= rt2x00pci_uninitialize, @@ -1585,7 +1613,6 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {  	.reset_tuner		= rt2400pci_reset_tuner,  	.link_tuner		= rt2400pci_link_tuner,  	.write_tx_desc		= rt2400pci_write_tx_desc, -	.write_tx_data		= rt2x00pci_write_tx_data,  	.write_beacon		= rt2400pci_write_beacon,  	.kick_tx_queue		= rt2400pci_kick_tx_queue,  	.kill_tx_queue		= rt2400pci_kill_tx_queue,  |