diff options
Diffstat (limited to 'drivers/net/wireless/b43')
| -rw-r--r-- | drivers/net/wireless/b43/dma.c | 65 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/pcmcia.c | 4 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 11 | 
3 files changed, 63 insertions, 17 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 38bc5a7997f..122146943bf 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,  	const struct b43_dma_ops *ops;  	struct b43_dmaring *ring;  	struct b43_dmadesc_meta *meta; +	static const struct b43_txstatus fake; /* filled with 0 */ +	const struct b43_txstatus *txstat;  	int slot, firstused;  	bool frame_succeed; +	int skip; +	static u8 err_out1, err_out2;  	ring = parse_cookie(dev, status->cookie, &slot);  	if (unlikely(!ring)) @@ -1501,13 +1505,36 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,  	firstused = ring->current_slot - ring->used_slots + 1;  	if (firstused < 0)  		firstused = ring->nr_slots + firstused; + +	skip = 0;  	if (unlikely(slot != firstused)) {  		/* This possibly is a firmware bug and will result in -		 * malfunction, memory leaks and/or stall of DMA functionality. */ -		b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. " -		       "Expected %d, but got %d\n", -		       ring->index, firstused, slot); -		return; +		 * malfunction, memory leaks and/or stall of DMA functionality. +		 */ +		if (slot == next_slot(ring, next_slot(ring, firstused))) { +			/* If a single header/data pair was missed, skip over +			 * the first two slots in an attempt to recover. +			 */ +			slot = firstused; +			skip = 2; +			if (!err_out1) { +				/* Report the error once. */ +				b43dbg(dev->wl, +				       "Skip on DMA ring %d slot %d.\n", +				       ring->index, slot); +				err_out1 = 1; +			} +		} else { +			/* More than a single header/data pair were missed. +			 * Report this error once. +			 */ +			if (!err_out2) +				b43dbg(dev->wl, +				       "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n", +				       ring->index, firstused, slot); +			err_out2 = 1; +			return; +		}  	}  	ops = ring->ops; @@ -1522,11 +1549,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,  			       slot, firstused, ring->index);  			break;  		} +  		if (meta->skb) {  			struct b43_private_tx_info *priv_info = -				b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); +			     b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); -			unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); +			unmap_descbuffer(ring, meta->dmaaddr, +					 meta->skb->len, 1);  			kfree(priv_info->bouncebuffer);  			priv_info->bouncebuffer = NULL;  		} else { @@ -1538,8 +1567,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,  			struct ieee80211_tx_info *info;  			if (unlikely(!meta->skb)) { -				/* This is a scatter-gather fragment of a frame, so -				 * the skb pointer must not be NULL. */ +				/* This is a scatter-gather fragment of a frame, +				 * so the skb pointer must not be NULL. +				 */  				b43dbg(dev->wl, "TX status unexpected NULL skb "  				       "at slot %d (first=%d) on ring %d\n",  				       slot, firstused, ring->index); @@ -1550,9 +1580,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,  			/*  			 * Call back to inform the ieee80211 subsystem about -			 * the status of the transmission. +			 * the status of the transmission. When skipping over +			 * a missed TX status report, use a status structure +			 * filled with zeros to indicate that the frame was not +			 * sent (frame_count 0) and not acknowledged  			 */ -			frame_succeed = b43_fill_txstatus_report(dev, info, status); +			if (unlikely(skip)) +				txstat = &fake; +			else +				txstat = status; + +			frame_succeed = b43_fill_txstatus_report(dev, info, +								 txstat);  #ifdef CONFIG_B43_DEBUG  			if (frame_succeed)  				ring->nr_succeed_tx_packets++; @@ -1580,12 +1619,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,  		/* Everything unmapped and free'd. So it's not used anymore. */  		ring->used_slots--; -		if (meta->is_last_fragment) { +		if (meta->is_last_fragment && !skip) {  			/* This is the last scatter-gather  			 * fragment of the frame. We are done. */  			break;  		}  		slot = next_slot(ring, slot); +		if (skip > 0) +			--skip;  	}  	if (ring->stopped) {  		B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME); diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index f2ea2ceec8a..55f2bd7f8f7 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -130,6 +130,10 @@ static struct pcmcia_driver b43_pcmcia_driver = {  	.resume		= b43_pcmcia_resume,  }; +/* + * These are not module init/exit functions! + * The module_pcmcia_driver() helper cannot be used here. + */  int b43_pcmcia_init(void)  {  	return pcmcia_register_driver(&b43_pcmcia_driver); diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 3c35382ee6c..b70f220bc4b 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1564,7 +1564,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)  	u16 clip_off[2] = { 0xFFFF, 0xFFFF };  	u8 vcm_final = 0; -	s8 offset[4]; +	s32 offset[4];  	s32 results[8][4] = { };  	s32 results_min[4] = { };  	s32 poll_results[4] = { }; @@ -1615,7 +1615,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)  		}  		for (i = 0; i < 4; i += 2) {  			s32 curr; -			s32 mind = 40; +			s32 mind = 0x100000;  			s32 minpoll = 249;  			u8 minvcm = 0;  			if (2 * core != i) @@ -1732,7 +1732,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)  	u8 regs_save_radio[2];  	u16 regs_save_phy[2]; -	s8 offset[4]; +	s32 offset[4];  	u8 core;  	u8 rail; @@ -1799,7 +1799,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)  	}  	for (i = 0; i < 4; i++) { -		s32 mind = 40; +		s32 mind = 0x100000;  		u8 minvcm = 0;  		s32 minpoll = 249;  		s32 curr; @@ -5165,7 +5165,8 @@ static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)  #endif  #ifdef CONFIG_B43_SSB  	case B43_BUS_SSB: -		/* FIXME */ +		ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco, +					    avoid);  		break;  #endif  	}  |