diff options
Diffstat (limited to 'drivers/net/wireless/broadcom')
27 files changed, 236 insertions, 129 deletions
| diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index 74be3c809225..4c7980f84591 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c @@ -485,7 +485,6 @@ static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val)  		val = swab32(val);  	b43_write32(dev, B43_MMIO_RAM_CONTROL, offset); -	mmiowb();  	b43_write32(dev, B43_MMIO_RAM_DATA, val);  } @@ -656,9 +655,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)  	/* The hardware guarantees us an atomic write, if we  	 * write the low register first. */  	b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, low); -	mmiowb();  	b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, high); -	mmiowb();  }  void b43_tsf_write(struct b43_wldev *dev, u64 tsf) @@ -1822,11 +1819,9 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)  		if (b43_bus_host_is_sdio(dev->dev)) {  			/* wl->mutex is enough. */  			b43_do_beacon_update_trigger_work(dev); -			mmiowb();  		} else {  			spin_lock_irq(&wl->hardirq_lock);  			b43_do_beacon_update_trigger_work(dev); -			mmiowb();  			spin_unlock_irq(&wl->hardirq_lock);  		}  	} @@ -2078,7 +2073,6 @@ static irqreturn_t b43_interrupt_thread_handler(int irq, void *dev_id)  	mutex_lock(&dev->wl->mutex);  	b43_do_interrupt_thread(dev); -	mmiowb();  	mutex_unlock(&dev->wl->mutex);  	return IRQ_HANDLED; @@ -2143,7 +2137,6 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)  	spin_lock(&dev->wl->hardirq_lock);  	ret = b43_do_interrupt(dev); -	mmiowb();  	spin_unlock(&dev->wl->hardirq_lock);  	return ret; diff --git a/drivers/net/wireless/broadcom/b43/phy_lp.c b/drivers/net/wireless/broadcom/b43/phy_lp.c index 46408a560814..6b7f0238723f 100644 --- a/drivers/net/wireless/broadcom/b43/phy_lp.c +++ b/drivers/net/wireless/broadcom/b43/phy_lp.c @@ -1826,16 +1826,10 @@ static void lpphy_stop_tx_tone(struct b43_wldev *dev)  } -static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains, -			   int mode, bool useindex, u8 index) -{ -	//TODO -} -  static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)  {  	struct b43_phy_lp *lpphy = dev->phy.lp; -	struct lpphy_tx_gains gains, oldgains; +	struct lpphy_tx_gains oldgains;  	int old_txpctl, old_afe_ovr, old_rf, old_bbmult;  	lpphy_read_tx_pctl_mode_from_hardware(dev); @@ -1848,11 +1842,6 @@ static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)  	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); -	if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0) -		lpphy_papd_cal(dev, gains, 0, 1, 30); -	else -		lpphy_papd_cal(dev, gains, 0, 1, 65); -  	if (old_afe_ovr)  		lpphy_set_tx_gains(dev, oldgains);  	lpphy_set_bb_mult(dev, old_bbmult); diff --git a/drivers/net/wireless/broadcom/b43/sysfs.c b/drivers/net/wireless/broadcom/b43/sysfs.c index 3190493bd07f..93d03b673670 100644 --- a/drivers/net/wireless/broadcom/b43/sysfs.c +++ b/drivers/net/wireless/broadcom/b43/sysfs.c @@ -129,7 +129,6 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,  	} else  		err = -ENOSYS; -	mmiowb();  	mutex_unlock(&wldev->wl->mutex);  	return err ? err : count; diff --git a/drivers/net/wireless/broadcom/b43legacy/ilt.c b/drivers/net/wireless/broadcom/b43legacy/ilt.c index ee5682e54204..6d15fb4d30c6 100644 --- a/drivers/net/wireless/broadcom/b43legacy/ilt.c +++ b/drivers/net/wireless/broadcom/b43legacy/ilt.c @@ -315,14 +315,12 @@ const u16 b43legacy_ilt_sigmasqr2[B43legacy_ILT_SIGMASQR_SIZE] = {  void b43legacy_ilt_write(struct b43legacy_wldev *dev, u16 offset, u16 val)  {  	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset); -	mmiowb();  	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA1, val);  }  void b43legacy_ilt_write32(struct b43legacy_wldev *dev, u16 offset, u32 val)  {  	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset); -	mmiowb();  	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA2,  			    (val & 0xFFFF0000) >> 16);  	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA1, diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c index 55f411925960..c777efc6dc13 100644 --- a/drivers/net/wireless/broadcom/b43legacy/main.c +++ b/drivers/net/wireless/broadcom/b43legacy/main.c @@ -264,7 +264,6 @@ static void b43legacy_ram_write(struct b43legacy_wldev *dev, u16 offset,  		val = swab32(val);  	b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset); -	mmiowb();  	b43legacy_write32(dev, B43legacy_MMIO_RAM_DATA, val);  } @@ -341,14 +340,11 @@ void b43legacy_shm_write32(struct b43legacy_wldev *dev,  		if (offset & 0x0003) {  			/* Unaligned access */  			b43legacy_shm_control_word(dev, routing, offset >> 2); -			mmiowb();  			b43legacy_write16(dev,  					  B43legacy_MMIO_SHM_DATA_UNALIGNED,  					  (value >> 16) & 0xffff); -			mmiowb();  			b43legacy_shm_control_word(dev, routing,  						   (offset >> 2) + 1); -			mmiowb();  			b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA,  					  value & 0xffff);  			return; @@ -356,7 +352,6 @@ void b43legacy_shm_write32(struct b43legacy_wldev *dev,  		offset >>= 2;  	}  	b43legacy_shm_control_word(dev, routing, offset); -	mmiowb();  	b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, value);  } @@ -368,7 +363,6 @@ void b43legacy_shm_write16(struct b43legacy_wldev *dev, u16 routing, u16 offset,  		if (offset & 0x0003) {  			/* Unaligned access */  			b43legacy_shm_control_word(dev, routing, offset >> 2); -			mmiowb();  			b43legacy_write16(dev,  					  B43legacy_MMIO_SHM_DATA_UNALIGNED,  					  value); @@ -377,7 +371,6 @@ void b43legacy_shm_write16(struct b43legacy_wldev *dev, u16 routing, u16 offset,  		offset >>= 2;  	}  	b43legacy_shm_control_word(dev, routing, offset); -	mmiowb();  	b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA, value);  } @@ -471,7 +464,6 @@ static void b43legacy_time_lock(struct b43legacy_wldev *dev)  	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);  	status |= B43legacy_MACCTL_TBTTHOLD;  	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); -	mmiowb();  }  static void b43legacy_time_unlock(struct b43legacy_wldev *dev) @@ -494,10 +486,8 @@ static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf)  		u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;  		b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW, 0); -		mmiowb();  		b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_HIGH,  				    hi); -		mmiowb();  		b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW,  				    lo);  	} else { @@ -507,13 +497,9 @@ static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf)  		u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;  		b43legacy_write16(dev, B43legacy_MMIO_TSF_0, 0); -		mmiowb();  		b43legacy_write16(dev, B43legacy_MMIO_TSF_3, v3); -		mmiowb();  		b43legacy_write16(dev, B43legacy_MMIO_TSF_2, v2); -		mmiowb();  		b43legacy_write16(dev, B43legacy_MMIO_TSF_1, v1); -		mmiowb();  		b43legacy_write16(dev, B43legacy_MMIO_TSF_0, v0);  	}  } @@ -1250,7 +1236,6 @@ static void b43legacy_beacon_update_trigger_work(struct work_struct *work)  		/* The handler might have updated the IRQ mask. */  		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,  				  dev->irq_mask); -		mmiowb();  		spin_unlock_irq(&wl->irq_lock);  	}  	mutex_unlock(&wl->mutex); @@ -1346,7 +1331,6 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)  			       dma_reason[2], dma_reason[3],  			       dma_reason[4], dma_reason[5]);  			b43legacy_controller_restart(dev, "DMA error"); -			mmiowb();  			spin_unlock_irqrestore(&dev->wl->irq_lock, flags);  			return;  		} @@ -1396,7 +1380,6 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)  		handle_irq_transmit_status(dev);  	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); -	mmiowb();  	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);  } @@ -1488,7 +1471,6 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)  	dev->irq_reason = reason;  	tasklet_schedule(&dev->isr_tasklet);  out: -	mmiowb();  	spin_unlock(&dev->wl->irq_lock);  	return ret; @@ -2781,7 +2763,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,  	spin_lock_irqsave(&wl->irq_lock, flags);  	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); -	mmiowb();  	spin_unlock_irqrestore(&wl->irq_lock, flags);  out_unlock_mutex:  	mutex_unlock(&wl->mutex); @@ -2900,7 +2881,6 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,  	spin_lock_irqsave(&wl->irq_lock, flags);  	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);  	/* XXX: why? */ -	mmiowb();  	spin_unlock_irqrestore(&wl->irq_lock, flags);   out_unlock_mutex:  	mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/broadcom/b43legacy/phy.c b/drivers/net/wireless/broadcom/b43legacy/phy.c index 995c7d0c212a..f949766d27ca 100644 --- a/drivers/net/wireless/broadcom/b43legacy/phy.c +++ b/drivers/net/wireless/broadcom/b43legacy/phy.c @@ -134,7 +134,6 @@ u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset)  void b43legacy_phy_write(struct b43legacy_wldev *dev, u16 offset, u16 val)  {  	b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset); -	mmiowb();  	b43legacy_write16(dev, B43legacy_MMIO_PHY_DATA, val);  } diff --git a/drivers/net/wireless/broadcom/b43legacy/pio.h b/drivers/net/wireless/broadcom/b43legacy/pio.h index 1cd1b9ca5e9c..08cd02282beb 100644 --- a/drivers/net/wireless/broadcom/b43legacy/pio.h +++ b/drivers/net/wireless/broadcom/b43legacy/pio.h @@ -92,7 +92,6 @@ void b43legacy_pio_write(struct b43legacy_pioqueue *queue,  		       u16 offset, u16 value)  {  	b43legacy_write16(queue->dev, queue->mmio_base + offset, value); -	mmiowb();  } diff --git a/drivers/net/wireless/broadcom/b43legacy/radio.c b/drivers/net/wireless/broadcom/b43legacy/radio.c index eab1c9387846..c6db444ea07e 100644 --- a/drivers/net/wireless/broadcom/b43legacy/radio.c +++ b/drivers/net/wireless/broadcom/b43legacy/radio.c @@ -95,7 +95,6 @@ void b43legacy_radio_lock(struct b43legacy_wldev *dev)  	B43legacy_WARN_ON(status & B43legacy_MACCTL_RADIOLOCK);  	status |= B43legacy_MACCTL_RADIOLOCK;  	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); -	mmiowb();  	udelay(10);  } @@ -108,7 +107,6 @@ void b43legacy_radio_unlock(struct b43legacy_wldev *dev)  	B43legacy_WARN_ON(!(status & B43legacy_MACCTL_RADIOLOCK));  	status &= ~B43legacy_MACCTL_RADIOLOCK;  	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); -	mmiowb();  }  u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset) @@ -141,7 +139,6 @@ u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset)  void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val)  {  	b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset); -	mmiowb();  	b43legacy_write16(dev, B43legacy_MMIO_RADIO_DATA_LOW, val);  } @@ -333,7 +330,6 @@ u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev)  void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val)  {  	b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset); -	mmiowb();  	b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_DATA, (u16)val);  } diff --git a/drivers/net/wireless/broadcom/b43legacy/sysfs.c b/drivers/net/wireless/broadcom/b43legacy/sysfs.c index 2a1da15c913b..2db83eec7a11 100644 --- a/drivers/net/wireless/broadcom/b43legacy/sysfs.c +++ b/drivers/net/wireless/broadcom/b43legacy/sysfs.c @@ -143,7 +143,6 @@ static ssize_t b43legacy_attr_interfmode_store(struct device *dev,  	if (err)  		b43legacyerr(wldev->wl, "Interference Mitigation not "  		       "supported by device\n"); -	mmiowb();  	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);  	mutex_unlock(&wldev->wl->mutex); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 73d3c1a0a7c9..98b168736df0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -490,11 +490,18 @@ fail:  	return -ENOMEM;  } -void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) +void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) +{ +	struct brcmf_bcdc *bcdc = drvr->proto->pd; + +	brcmf_fws_detach_pre_delif(bcdc->fws); +} + +void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr)  {  	struct brcmf_bcdc *bcdc = drvr->proto->pd;  	drvr->proto->pd = NULL; -	brcmf_fws_detach(bcdc->fws); +	brcmf_fws_detach_post_delif(bcdc->fws);  	kfree(bcdc);  } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h index 3b0e9eff21b5..4bc52240ccea 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h @@ -18,14 +18,16 @@  #ifdef CONFIG_BRCMFMAC_PROTO_BCDC  int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr); -void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr); +void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr); +void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr);  void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state);  void brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp,  				 bool success);  struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr);  #else  static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; } -static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {} +static void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) {}; +static inline void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr) {}  #endif  #endif /* BRCMFMAC_BCDC_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index ec129864cc9c..60aede5abb4d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -628,15 +628,13 @@ int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)  	err = brcmf_sdiod_set_backplane_window(sdiodev, addr);  	if (err) -		return err; +		goto out;  	addr &= SBSDIO_SB_OFT_ADDR_MASK;  	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; -	if (!err) -		err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr, -					       mypkt); - +	err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr, mypkt); +out:  	brcmu_pkt_buf_free_skb(mypkt);  	return err; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 3d441c5c745c..2fe167eae22c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -91,6 +91,7 @@ struct brcmf_bus_ops {  	int (*get_fwname)(struct device *dev, const char *ext,  			  unsigned char *fw_name);  	void (*debugfs_create)(struct device *dev); +	int (*reset)(struct device *dev);  }; @@ -245,6 +246,15 @@ void brcmf_bus_debugfs_create(struct brcmf_bus *bus)  	return bus->ops->debugfs_create(bus->dev);  } +static inline +int brcmf_bus_reset(struct brcmf_bus *bus) +{ +	if (!bus->ops->reset) +		return -EOPNOTSUPP; + +	return bus->ops->reset(bus->dev); +} +  /*   * interface functions from common layer   */ @@ -262,6 +272,8 @@ void brcmf_detach(struct device *dev);  void brcmf_dev_reset(struct device *dev);  /* Request from bus module to initiate a coredump */  void brcmf_dev_coredump(struct device *dev); +/* Indication that firmware has halted or crashed */ +void brcmf_fw_crashed(struct device *dev);  /* Configure the "global" bus state used by upper layers */  void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index e92f6351bd22..8ee8af4e7ec4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -5464,6 +5464,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,  		conn_info->req_ie =  		    kmemdup(cfg->extra_buf, conn_info->req_ie_len,  			    GFP_KERNEL); +		if (!conn_info->req_ie) +			conn_info->req_ie_len = 0;  	} else {  		conn_info->req_ie_len = 0;  		conn_info->req_ie = NULL; @@ -5480,6 +5482,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,  		conn_info->resp_ie =  		    kmemdup(cfg->extra_buf, conn_info->resp_ie_len,  			    GFP_KERNEL); +		if (!conn_info->resp_ie) +			conn_info->resp_ie_len = 0;  	} else {  		conn_info->resp_ie_len = 0;  		conn_info->resp_ie = NULL; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 4fbe8791f674..7d6a08779693 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -841,17 +841,17 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx,  			 bool rtnl_locked)  {  	struct brcmf_if *ifp; +	int ifidx;  	ifp = drvr->iflist[bsscfgidx]; -	drvr->iflist[bsscfgidx] = NULL;  	if (!ifp) {  		bphy_err(drvr, "Null interface, bsscfgidx=%d\n", bsscfgidx);  		return;  	}  	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx,  		  ifp->ifidx); -	if (drvr->if2bss[ifp->ifidx] == bsscfgidx) -		drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID; +	ifidx = ifp->ifidx; +  	if (ifp->ndev) {  		if (bsscfgidx == 0) {  			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { @@ -879,6 +879,10 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx,  		brcmf_p2p_ifp_removed(ifp, rtnl_locked);  		kfree(ifp);  	} + +	drvr->iflist[bsscfgidx] = NULL; +	if (drvr->if2bss[ifidx] == bsscfgidx) +		drvr->if2bss[ifidx] = BRCMF_BSSIDX_INVALID;  }  void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked) @@ -1084,6 +1088,14 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data)  	return 0;  } +static void brcmf_core_bus_reset(struct work_struct *work) +{ +	struct brcmf_pub *drvr = container_of(work, struct brcmf_pub, +					      bus_reset); + +	brcmf_bus_reset(drvr->bus_if); +} +  static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)  {  	int ret = -1; @@ -1155,6 +1167,8 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)  #endif  #endif /* CONFIG_INET */ +	INIT_WORK(&drvr->bus_reset, brcmf_core_bus_reset); +  	/* populate debugfs */  	brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);  	brcmf_feat_debugfs_create(drvr); @@ -1273,6 +1287,18 @@ void brcmf_dev_coredump(struct device *dev)  		brcmf_dbg(TRACE, "failed to create coredump\n");  } +void brcmf_fw_crashed(struct device *dev) +{ +	struct brcmf_bus *bus_if = dev_get_drvdata(dev); +	struct brcmf_pub *drvr = bus_if->drvr; + +	bphy_err(drvr, "Firmware has halted or crashed\n"); + +	brcmf_dev_coredump(dev); + +	schedule_work(&drvr->bus_reset); +} +  void brcmf_detach(struct device *dev)  {  	s32 i; @@ -1299,6 +1325,8 @@ void brcmf_detach(struct device *dev)  	brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); +	brcmf_proto_detach_pre_delif(drvr); +  	/* make sure primary interface removed last */  	for (i = BRCMF_MAX_IFS-1; i > -1; i--)  		brcmf_remove_interface(drvr->iflist[i], false); @@ -1308,7 +1336,7 @@ void brcmf_detach(struct device *dev)  	brcmf_bus_stop(drvr->bus_if); -	brcmf_proto_detach(drvr); +	brcmf_proto_detach_post_delif(drvr);  	bus_if->drvr = NULL;  	wiphy_free(drvr->wiphy); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index d8085ce579f4..9f09aa31eeda 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -143,6 +143,8 @@ struct brcmf_pub {  	struct notifier_block inet6addr_notifier;  	struct brcmf_mp_device *settings; +	struct work_struct bus_reset; +  	u8 clmver[BRCMF_DCMD_SMLEN];  }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c index 7535cb0d4ac0..9f1417e00073 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c @@ -31,6 +31,10 @@ struct brcmf_dmi_data {  /* NOTE: Please keep all entries sorted alphabetically */ +static const struct brcmf_dmi_data acepc_t8_data = { +	BRCM_CC_4345_CHIP_ID, 6, "acepc-t8" +}; +  static const struct brcmf_dmi_data gpd_win_pocket_data = {  	BRCM_CC_4356_CHIP_ID, 2, "gpd-win-pocket"  }; @@ -49,6 +53,28 @@ static const struct brcmf_dmi_data pov_tab_p1006w_data = {  static const struct dmi_system_id dmi_platform_data[] = {  	{ +		/* ACEPC T8 Cherry Trail Z8350 mini PC */ +		.matches = { +			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), +			DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), +			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "T8"), +			/* also match on somewhat unique bios-version */ +			DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"), +		}, +		.driver_data = (void *)&acepc_t8_data, +	}, +	{ +		/* ACEPC T11 Cherry Trail Z8350 mini PC, same wifi as the T8 */ +		.matches = { +			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), +			DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), +			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "T11"), +			/* also match on somewhat unique bios-version */ +			DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"), +		}, +		.driver_data = (void *)&acepc_t8_data, +	}, +	{  		/* Match for the GPDwin which unfortunately uses somewhat  		 * generic dmi strings, which is why we test for 4 strings.  		 * Comparing against 23 other byt/cht boards, board_vendor diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 8209a42dea72..6a333dd80b2d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -711,7 +711,6 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev,  	size_t mp_path_len;  	u32 i, j;  	char end = '\0'; -	size_t reqsz;  	for (i = 0; i < table_size; i++) {  		if (mapping_table[i].chipid == chip && @@ -726,8 +725,7 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev,  		return NULL;  	} -	reqsz = sizeof(*fwreq) + n_fwnames * sizeof(struct brcmf_fw_item); -	fwreq = kzalloc(reqsz, GFP_KERNEL); +	fwreq = kzalloc(struct_size(fwreq, items, n_fwnames), GFP_KERNEL);  	if (!fwreq)  		return NULL; @@ -743,6 +741,7 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev,  	for (j = 0; j < n_fwnames; j++) {  		fwreq->items[j].path = fwnames[j].path; +		fwnames[j].path[0] = '\0';  		/* check if firmware path is provided by module parameter */  		if (brcmf_mp_global.firmware_path[0] != '\0') {  			strlcpy(fwnames[j].path, mp_path, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index abeb305492e0..c22c49ae552e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -580,24 +580,6 @@ static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg)  	return ifidx == *(int *)arg;  } -static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q, -				int ifidx) -{ -	bool (*matchfn)(struct sk_buff *, void *) = NULL; -	struct sk_buff *skb; -	int prec; - -	if (ifidx != -1) -		matchfn = brcmf_fws_ifidx_match; -	for (prec = 0; prec < q->num_prec; prec++) { -		skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); -		while (skb) { -			brcmu_pkt_buf_free_skb(skb); -			skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); -		} -	} -} -  static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger)  {  	int i; @@ -669,6 +651,28 @@ static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,  	return 0;  } +static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q, +				int ifidx) +{ +	bool (*matchfn)(struct sk_buff *, void *) = NULL; +	struct sk_buff *skb; +	int prec; +	u32 hslot; + +	if (ifidx != -1) +		matchfn = brcmf_fws_ifidx_match; +	for (prec = 0; prec < q->num_prec; prec++) { +		skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); +		while (skb) { +			hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); +			brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, +						true); +			brcmu_pkt_buf_free_skb(skb); +			skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); +		} +	} +} +  static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,  					    u32 slot_id)  { @@ -2200,6 +2204,8 @@ void brcmf_fws_del_interface(struct brcmf_if *ifp)  	brcmf_fws_lock(fws);  	ifp->fws_desc = NULL;  	brcmf_dbg(TRACE, "deleting %s\n", entry->name); +	brcmf_fws_macdesc_cleanup(fws, &fws->desc.iface[ifp->ifidx], +				  ifp->ifidx);  	brcmf_fws_macdesc_deinit(entry);  	brcmf_fws_cleanup(fws, ifp->ifidx);  	brcmf_fws_unlock(fws); @@ -2437,17 +2443,25 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr)  	return fws;  fail: -	brcmf_fws_detach(fws); +	brcmf_fws_detach_pre_delif(fws); +	brcmf_fws_detach_post_delif(fws);  	return ERR_PTR(rc);  } -void brcmf_fws_detach(struct brcmf_fws_info *fws) +void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws)  {  	if (!fws)  		return; - -	if (fws->fws_wq) +	if (fws->fws_wq) {  		destroy_workqueue(fws->fws_wq); +		fws->fws_wq = NULL; +	} +} + +void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws) +{ +	if (!fws) +		return;  	/* cleanup */  	brcmf_fws_lock(fws); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h index 4e6835766d5d..749c06dcdc17 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h @@ -19,7 +19,8 @@  #define FWSIGNAL_H_  struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr); -void brcmf_fws_detach(struct brcmf_fws_info *fws); +void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws); +void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws);  void brcmf_fws_debugfs_create(struct brcmf_pub *drvr);  bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws);  bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index d3780eae7f19..9d1f9ff25bfa 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -375,7 +375,7 @@ brcmf_msgbuf_get_pktid(struct device *dev, struct brcmf_msgbuf_pktids *pktids,  	struct brcmf_msgbuf_pktid *pktid;  	struct sk_buff *skb; -	if (idx >= pktids->array_size) { +	if (idx < 0 || idx >= pktids->array_size) {  		brcmf_err("Invalid packet id %d (max %d)\n", idx,  			  pktids->array_size);  		return NULL; @@ -747,7 +747,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)  		tx_msghdr = (struct msgbuf_tx_msghdr *)ret_ptr;  		tx_msghdr->msg.msgtype = MSGBUF_TYPE_TX_POST; -		tx_msghdr->msg.request_id = cpu_to_le32(pktid); +		tx_msghdr->msg.request_id = cpu_to_le32(pktid + 1);  		tx_msghdr->msg.ifidx = brcmf_flowring_ifidx_get(flow, flowid);  		tx_msghdr->flags = BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3;  		tx_msghdr->flags |= (skb->priority & 0x07) << @@ -884,7 +884,7 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)  	u16 flowid;  	tx_status = (struct msgbuf_tx_status *)buf; -	idx = le32_to_cpu(tx_status->msg.request_id); +	idx = le32_to_cpu(tx_status->msg.request_id) - 1;  	flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id);  	flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;  	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 58a6bc379358..83e4938527f4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -345,6 +345,10 @@ static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {  	BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE  }; +static void brcmf_pcie_setup(struct device *dev, int ret, +			     struct brcmf_fw_request *fwreq); +static struct brcmf_fw_request * +brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo);  static u32  brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset) @@ -671,6 +675,7 @@ static int  brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)  {  	struct brcmf_pcie_shared_info *shared; +	struct brcmf_core *core;  	u32 addr;  	u32 cur_htod_mb_data;  	u32 i; @@ -694,7 +699,11 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)  	brcmf_pcie_write_tcm32(devinfo, addr, htod_mb_data);  	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1); -	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1); + +	/* Send mailbox interrupt twice as a hardware workaround */ +	core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); +	if (core->rev <= 13) +		pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);  	return 0;  } @@ -730,7 +739,7 @@ static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)  	}  	if (dtoh_mb_data & BRCMF_D2H_DEV_FWHALT) {  		brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n"); -		brcmf_dev_coredump(&devinfo->pdev->dev); +		brcmf_fw_crashed(&devinfo->pdev->dev);  	}  } @@ -755,15 +764,22 @@ static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)  		  console->base_addr, console->buf_addr, console->bufsize);  } - -static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo) +/** + * brcmf_pcie_bus_console_read - reads firmware messages + * + * @error: specifies if error has occurred (prints messages unconditionally) + */ +static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo, +					bool error)  { +	struct pci_dev *pdev = devinfo->pdev; +	struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);  	struct brcmf_pcie_console *console;  	u32 addr;  	u8 ch;  	u32 newidx; -	if (!BRCMF_FWCON_ON()) +	if (!error && !BRCMF_FWCON_ON())  		return;  	console = &devinfo->shared.console; @@ -787,7 +803,10 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo)  		}  		if (ch == '\n') {  			console->log_str[console->log_idx] = 0; -			pr_debug("CONSOLE: %s", console->log_str); +			if (error) +				brcmf_err(bus, "CONSOLE: %s", console->log_str); +			else +				pr_debug("CONSOLE: %s", console->log_str);  			console->log_idx = 0;  		}  	} @@ -848,7 +867,7 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)  							&devinfo->pdev->dev);  		}  	} -	brcmf_pcie_bus_console_read(devinfo); +	brcmf_pcie_bus_console_read(devinfo, false);  	if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)  		brcmf_pcie_intr_enable(devinfo);  	devinfo->in_irq = false; @@ -1409,6 +1428,38 @@ int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name)  	return 0;  } +static int brcmf_pcie_reset(struct device *dev) +{ +	struct brcmf_bus *bus_if = dev_get_drvdata(dev); +	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; +	struct brcmf_pciedev_info *devinfo = buspub->devinfo; +	struct brcmf_fw_request *fwreq; +	int err; + +	brcmf_pcie_bus_console_read(devinfo, true); + +	brcmf_detach(dev); + +	brcmf_pcie_release_irq(devinfo); +	brcmf_pcie_release_scratchbuffers(devinfo); +	brcmf_pcie_release_ringbuffers(devinfo); +	brcmf_pcie_reset_device(devinfo); + +	fwreq = brcmf_pcie_prepare_fw_request(devinfo); +	if (!fwreq) { +		dev_err(dev, "Failed to prepare FW request\n"); +		return -ENOMEM; +	} + +	err = brcmf_fw_get_firmwares(dev, fwreq, brcmf_pcie_setup); +	if (err) { +		dev_err(dev, "Failed to prepare FW request\n"); +		kfree(fwreq); +	} + +	return err; +} +  static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {  	.txdata = brcmf_pcie_tx,  	.stop = brcmf_pcie_down, @@ -1418,6 +1469,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {  	.get_ramsize = brcmf_pcie_get_ramsize,  	.get_memdump = brcmf_pcie_get_memdump,  	.get_fwname = brcmf_pcie_get_fwname, +	.reset = brcmf_pcie_reset,  }; @@ -1778,7 +1830,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,  	if (brcmf_attach(&devinfo->pdev->dev, devinfo->settings) == 0)  		return; -	brcmf_pcie_bus_console_read(devinfo); +	brcmf_pcie_bus_console_read(devinfo, false);  fail:  	device_release_driver(dev); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c index 024c643052bc..c7964ccdda69 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c @@ -67,16 +67,22 @@ fail:  	return -ENOMEM;  } -void brcmf_proto_detach(struct brcmf_pub *drvr) +void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr)  {  	brcmf_dbg(TRACE, "Enter\n");  	if (drvr->proto) {  		if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) -			brcmf_proto_bcdc_detach(drvr); +			brcmf_proto_bcdc_detach_post_delif(drvr);  		else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF)  			brcmf_proto_msgbuf_detach(drvr);  		kfree(drvr->proto);  		drvr->proto = NULL;  	}  } + +void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr) +{ +	if (drvr->proto && drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) +		brcmf_proto_bcdc_detach_pre_delif(drvr); +} diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h index d3c3b9a815ad..72355aea9028 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h @@ -54,7 +54,8 @@ struct brcmf_proto {  int brcmf_proto_attach(struct brcmf_pub *drvr); -void brcmf_proto_detach(struct brcmf_pub *drvr); +void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr); +void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr);  static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,  				      struct sk_buff *skb, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 4d104ab80fd8..22b73da42822 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -622,6 +622,7 @@ BRCMF_FW_DEF(43430A0, "brcmfmac43430a0-sdio");  /* Note the names are not postfixed with a1 for backward compatibility */  BRCMF_FW_DEF(43430A1, "brcmfmac43430-sdio");  BRCMF_FW_DEF(43455, "brcmfmac43455-sdio"); +BRCMF_FW_DEF(43456, "brcmfmac43456-sdio");  BRCMF_FW_DEF(4354, "brcmfmac4354-sdio");  BRCMF_FW_DEF(4356, "brcmfmac4356-sdio");  BRCMF_FW_DEF(4373, "brcmfmac4373-sdio"); @@ -642,7 +643,8 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {  	BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),  	BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0),  	BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1), -	BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455), +	BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0x00000200, 43456), +	BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFDC0, 43455),  	BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),  	BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),  	BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373), @@ -1090,8 +1092,8 @@ static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)  	/* dongle indicates the firmware has halted/crashed */  	if (hmb_data & HMB_DATA_FWHALT) { -		brcmf_err("mailbox indicates firmware halted\n"); -		brcmf_dev_coredump(&sdiod->func1->dev); +		brcmf_dbg(SDIO, "mailbox indicates firmware halted\n"); +		brcmf_fw_crashed(&sdiod->func1->dev);  	}  	/* Dongle recomposed rx frames, accept them again */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index e9cbfd077710..75fcd6752edc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -160,7 +160,7 @@ struct brcmf_usbdev_info {  	struct usb_device *usbdev;  	struct device *dev; -	struct mutex dev_init_lock; +	struct completion dev_init_done;  	int ctl_in_pipe, ctl_out_pipe;  	struct urb *ctl_urb; /* URB for control endpoint */ @@ -445,22 +445,17 @@ fail:  } -static void brcmf_usb_free_q(struct list_head *q, bool pending) +static void brcmf_usb_free_q(struct list_head *q)  {  	struct brcmf_usbreq *req, *next; -	int i = 0; +  	list_for_each_entry_safe(req, next, q, list) {  		if (!req->urb) {  			brcmf_err("bad req\n");  			break;  		} -		i++; -		if (pending) { -			usb_kill_urb(req->urb); -		} else { -			usb_free_urb(req->urb); -			list_del_init(&req->list); -		} +		usb_free_urb(req->urb); +		list_del_init(&req->list);  	}  } @@ -682,12 +677,18 @@ static int brcmf_usb_up(struct device *dev)  static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo)  { +	int i; +  	if (devinfo->ctl_urb)  		usb_kill_urb(devinfo->ctl_urb);  	if (devinfo->bulk_urb)  		usb_kill_urb(devinfo->bulk_urb); -	brcmf_usb_free_q(&devinfo->tx_postq, true); -	brcmf_usb_free_q(&devinfo->rx_postq, true); +	if (devinfo->tx_reqs) +		for (i = 0; i < devinfo->bus_pub.ntxq; i++) +			usb_kill_urb(devinfo->tx_reqs[i].urb); +	if (devinfo->rx_reqs) +		for (i = 0; i < devinfo->bus_pub.nrxq; i++) +			usb_kill_urb(devinfo->rx_reqs[i].urb);  }  static void brcmf_usb_down(struct device *dev) @@ -1023,8 +1024,8 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo)  	brcmf_dbg(USB, "Enter, devinfo %p\n", devinfo);  	/* free the URBS */ -	brcmf_usb_free_q(&devinfo->rx_freeq, false); -	brcmf_usb_free_q(&devinfo->tx_freeq, false); +	brcmf_usb_free_q(&devinfo->rx_freeq); +	brcmf_usb_free_q(&devinfo->tx_freeq);  	usb_free_urb(devinfo->ctl_urb);  	usb_free_urb(devinfo->bulk_urb); @@ -1193,11 +1194,11 @@ static void brcmf_usb_probe_phase2(struct device *dev, int ret,  	if (ret)  		goto error; -	mutex_unlock(&devinfo->dev_init_lock); +	complete(&devinfo->dev_init_done);  	return;  error:  	brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret); -	mutex_unlock(&devinfo->dev_init_lock); +	complete(&devinfo->dev_init_done);  	device_release_driver(dev);  } @@ -1265,7 +1266,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)  		if (ret)  			goto fail;  		/* we are done */ -		mutex_unlock(&devinfo->dev_init_lock); +		complete(&devinfo->dev_init_done);  		return 0;  	}  	bus->chip = bus_pub->devid; @@ -1325,11 +1326,10 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)  	devinfo->usbdev = usb;  	devinfo->dev = &usb->dev; -	/* Take an init lock, to protect for disconnect while still loading. +	/* Init completion, to protect for disconnect while still loading.  	 * Necessary because of the asynchronous firmware load construction  	 */ -	mutex_init(&devinfo->dev_init_lock); -	mutex_lock(&devinfo->dev_init_lock); +	init_completion(&devinfo->dev_init_done);  	usb_set_intfdata(intf, devinfo); @@ -1407,7 +1407,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)  	return 0;  fail: -	mutex_unlock(&devinfo->dev_init_lock); +	complete(&devinfo->dev_init_done);  	kfree(devinfo);  	usb_set_intfdata(intf, NULL);  	return ret; @@ -1422,7 +1422,7 @@ brcmf_usb_disconnect(struct usb_interface *intf)  	devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);  	if (devinfo) { -		mutex_lock(&devinfo->dev_init_lock); +		wait_for_completion(&devinfo->dev_init_done);  		/* Make sure that devinfo still exists. Firmware probe routines  		 * may have released the device and cleared the intfdata.  		 */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c index 8eff2753abad..d493021f6031 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c @@ -35,9 +35,10 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy,  	struct brcmf_if *ifp;  	const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;  	struct sk_buff *reply; -	int ret, payload, ret_len; +	unsigned int payload, ret_len;  	void *dcmd_buf = NULL, *wr_pointer;  	u16 msglen, maxmsglen = PAGE_SIZE - 0x100; +	int ret;  	if (len < sizeof(*cmdhdr)) {  		brcmf_err("vendor command too short: %d\n", len); @@ -65,7 +66,7 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy,  			brcmf_err("oversize return buffer %d\n", ret_len);  			ret_len = BRCMF_DCMD_MAXLEN;  		} -		payload = max(ret_len, len) + 1; +		payload = max_t(unsigned int, ret_len, len) + 1;  		dcmd_buf = vzalloc(payload);  		if (NULL == dcmd_buf)  			return -ENOMEM; |