⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_ath.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
	HAL_BOOL ret;	unsigned long __axq_lockflags[HAL_NUM_TX_QUEUES];	struct ath_txq * txq;	int i; 	u_int8_t old_privFlags = sc->sc_curchan.privFlags;	/* ath_hal_reset() resets all TXDP pointers, so we need to	 * lock all TXQ to avoid race condition with	 * ath_tx_txqaddbuf() and ath_tx_processq() */	for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {		if (ATH_TXQ_SETUP(sc, i)) {			txq = &sc->sc_txq[i];			spin_lock_irqsave(&txq->axq_lock, __axq_lockflags[i]);		}	}	ret = ath_hal_reset(sc->sc_ah, sc->sc_opmode, channel, bChannelChange, status);	/* Restore all TXDP pointers, if appropriate, and unlock in	 * the reverse order we locked */	for (i = HAL_NUM_TX_QUEUES - 1; i >= 0; i--) {		/* only take care of configured TXQ */		if (ATH_TXQ_SETUP(sc, i)) {			struct ath_buf *bf;			u_int32_t txdp;			txq = &sc->sc_txq[i];			/* Check that TXDP is NULL */			txdp = ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum);			if (txdp != 0) {				DPRINTF(sc, ATH_DEBUG_WATCHDOG,						"TXQ%d: BUG TXDP:%08x is "						"not NULL\n",						txq->axq_qnum, txdp);			}			/* We restore TXDP to the first "In Progress" TX			 * descriptor. We skip "Done" TX descriptors in			 * order to avoid sending duplicate packets */			STAILQ_FOREACH(bf, &txq->axq_q, bf_list) {				if (ath_hal_txprocdesc(sc->sc_ah,						       bf->bf_desc,					&bf->bf_dsstatus.ds_txstat) ==				    HAL_EINPROGRESS) {					DPRINTF(sc, ATH_DEBUG_WATCHDOG,						"TXQ%d: restoring"						" TXDP:%08llx\n", 						txq->axq_qnum, 						(u_int64_t)bf->bf_daddr);					ath_hw_puttxbuf(sc, txq->axq_qnum,							bf->bf_daddr,							__func__);					ath_hal_txstart(sc->sc_ah,							txq->axq_qnum);				}			}			spin_unlock_irqrestore(&txq->axq_lock,					__axq_lockflags[i]);		}	}	/* On failure, we return immediately */	if (!ret)		return ret; 	/* Do the same as in ath_getchannels() */ 	ath_radar_correct_dfs_flags(sc, channel);  	/* Restore CHANNEL_DFS_CLEAR and CHANNEL_INTERFERENCE flags */#define CHANNEL_DFS_FLAGS	(CHANNEL_DFS_CLEAR|CHANNEL_INTERFERENCE)	channel->privFlags = (channel->privFlags & ~CHANNEL_DFS_FLAGS) | 		(old_privFlags & CHANNEL_DFS_FLAGS); 	/* On success, we update sc->sc_curchan which can be needed by other	 * functions below , like ath_radar_update() at least */	sc->sc_curchan = *channel;#ifdef ATH_CAP_TPC	if (sc->sc_hastpc && (hal_tpc != ath_hal_gettpc(sc->sc_ah))) {		EPRINTF(sc, "TPC HAL capability out of sync.  Got %d!\n",				ath_hal_gettpc(sc->sc_ah));		ath_hal_settpc(sc->sc_ah, hal_tpc);	}#endif#if 0 /* Setting via HAL does not work, so it is done manually below. */	if (sc->sc_hasintmit)		ath_hal_setintmit(sc->sc_ah, sc->sc_useintmit);#endif	ath_override_intmit_if_disabled(sc);	if (sc->sc_dmasize_stomp)		ath_hal_set_dmasize_pcie(sc->sc_ah);	if (sc->sc_softled)		ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin);	ath_update_txpow(sc);		/* Update TX power state. */	ath_hal_setdiversity(sc->sc_ah, sc->sc_diversity);	ath_setdefantenna(sc, sc->sc_rxantenna);	/* XXX: Any other clobbered features? */	ath_radar_update(sc);	ath_rp_flush(sc);	return ret;}/* Returns true if we can transmit any frames : this is not the case if : * - we are on a DFS channel * - 802.11h is enabled * - Channel Availability Check is not done or a radar has been detected */static intath_chan_unavail(struct ath_softc *sc){	return sc->sc_dfs_cac ||		((sc->sc_curchan.privFlags & CHANNEL_DFS) &&		 (sc->sc_curchan.privFlags & CHANNEL_INTERFERENCE));}static inline int_ath_cac_running_dbgmsg(struct ath_softc *sc, const char *func){	int b = sc->sc_dfs_cac;	if (b)		DPRINTF(sc, ATH_DEBUG_DOTH,				"%s: Invoked a transmit function during DFS "				"channel availability check!\n", func);	return b;}static inline int_ath_chan_unavail_dbgmsg(struct ath_softc *sc, const char *func){	int b = ath_chan_unavail(sc);	if (b)		DPRINTF(sc, ATH_DEBUG_DOTH,				"%s: Invoked a transmit function during DFS "				"channel availability check OR while radar "				"interference is detected!\n", func);	return b;}/* Extend 15-bit timestamp from RX descriptor to a full 64-bit TSF using the * provided hardware TSF. The result is the closest value relative to hardware * TSF. *//* NB: Not all chipsets return the same precision rstamp */static __inline u_int64_tath_extend_tsf(u_int64_t tsf, u_int32_t rstamp){#define TSTAMP_RX_MASK  0x7fff	u_int64_t result;	result = (tsf & ~TSTAMP_RX_MASK) | rstamp;	if (result > tsf) {		if ((result - tsf) > (TSTAMP_RX_MASK / 2))			result -= (TSTAMP_RX_MASK + 1);	} else {		if ((tsf - result) > (TSTAMP_RX_MASK / 2))			result += (TSTAMP_RX_MASK + 1);	}	return result;}/* Swap transmit descriptor pointer for HW. */static __inline u_int32_tath_ds_link_swap(u_int32_t dp){#ifdef AH_NEED_DESC_SWAP	return swab32(dp);#else	return (dp);#endif}static __inline u_int32_tath_get_last_ds_link(struct ath_txq *txq){	struct ath_desc *ds = ath_txq_last_desc(txq);	return (ds ? ds->ds_link : 0);}static voidath_intr_process_rx_descriptors(struct ath_softc *sc, int *pneedmark, u_int64_t hw_tsf){	struct ath_hal *ah = sc->sc_ah;	struct ath_desc *ds;	struct ath_rx_status *rs;	struct sk_buff *skb;	struct ieee80211_node *ni;	struct ath_node *an;	struct ieee80211_qosframe *qwh;	struct ath_txq *uapsd_xmit_q = sc->sc_uapsdq;	struct ieee80211com *ic = &sc->sc_ic;	int ac, retval;	u_int32_t last_rs_tstamp = 0;	int check_for_radar = 0;	struct ath_buf *prev_rxbufcur;	u_int8_t tid;	u_int16_t frame_seq;	int count = 0;	int rollover = 0;#define	PA2DESC(_sc, _pa) \	((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \		((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))	/* XXXAPSD: build in check against max triggers we could see	 *          based on ic->ic_uapsdmaxtriggers. */	/* Do not move hw_tsf processing and noise processing out to the rx	 * tasklet.  The ONLY place we can properly correct for TSF errors and	 * get accurate noise floor information is in the interrupt handler.	 * We collect the first hw_tsf in the ath_intr (the interrupt handler)	 * so it can be passed to some helper functions... later in this 	 * function, however, we read it again to perform rollover adjustments.	 *	 * The HW returns a 15-bit TS on rx.  We get interrupts after multiple	 * packets are queued up.  Sometimes (read often), the 15-bit counter	 * in the hardware has rolled over one or more times.  We correct for	 * this in the interrupt function and store the adjusted TSF in the	 * buffer.	 *	 * We also store noise during interrupt, since HW does not log	 * this per packet and the rx queue is too late. Multiple interrupts	 * will have occurred, and the noise value at that point is totally	 * unrelated to conditions during receiption.  This is as close as we	 * get to reality.  This value is used in monitor mode and by tools like	 * Wireshark and Kismet.	 */	ATH_RXBUF_LOCK_IRQ(sc);	if (sc->sc_rxbufcur == NULL)		sc->sc_rxbufcur = STAILQ_FIRST(&sc->sc_rxbuf);	prev_rxbufcur = sc->sc_rxbufcur;	/* FIRST PASS - PROCESS DESCRIPTORS */	{		struct ath_buf *bf;		for (bf = prev_rxbufcur; bf; bf = STAILQ_NEXT(bf, bf_list)) {			ds = bf->bf_desc;			if (ds->ds_link == bf->bf_daddr) {				/* NB: never process the self-linked entry at				 * the end */				break;			}			if (bf->bf_status & ATH_BUFSTATUS_RXDESC_DONE) {				/* already processed this buffer (shouldn't				 * occur if we change code to always process				 * descriptors in rx intr handler - as opposed				 * to sometimes processing in the rx tasklet) */				continue;			}			skb = bf->bf_skb;			if (skb == NULL) {				EPRINTF(sc, "Dropping; skb is NULL in received ath_buf.\n");				continue;			}			/* XXXAPSD: consider new HAL call that does only the			 *          subset of ath_hal_rxprocdesc we require			 *          for trigger search. */			/* NB: descriptor memory doesn't need to be sync'd			 *     due to the way it was allocated. */			/* Must provide the virtual address of the current			 * descriptor, the physical address, and the virtual			 * address of the next descriptor in the h/w chain.			 * This allows the HAL to look ahead to see if the			 * hardware is done with a descriptor by checking the			 * done bit in the following descriptor and the address			 * of the current descriptor the DMA engine is working			 * on.  All this is necessary because of our use of			 * a self-linked list to avoid rx overruns. */			rs = &bf->bf_dsstatus.ds_rxstat;			retval = ath_hal_rxprocdesc(ah, ds, bf->bf_daddr,						    PA2DESC(sc, ds->ds_link),						    hw_tsf, rs);			if (HAL_EINPROGRESS == retval)				break;			/* update the per packet TSF with rs_tstamp */			bf->bf_tsf     = rs->rs_tstamp;			bf->bf_status |= ATH_BUFSTATUS_RXTSTAMP;			count ++;			DPRINTF(sc, ATH_DEBUG_TSF,				"rs_tstamp=%10llx count=%d\n",				bf->bf_tsf, count);			/* compute rollover */			if (last_rs_tstamp > rs->rs_tstamp) {				rollover ++;				DPRINTF(sc, ATH_DEBUG_TSF,					"%d rollover detected\n",					rollover);			}			last_rs_tstamp = rs->rs_tstamp;			/* Do not allow negative RSSI values */			if (rs->rs_rssi < 0)				rs->rs_rssi = 0;			/* Capture noise per-interrupt, since it may change			 * by the time the receive queue gets around to			 * processing these buffers, and multiple interrupts			 * may have occurred in the intervening timeframe. */			bf->bf_channoise = ic->ic_channoise;			if ((HAL_RXERR_PHY == rs->rs_status) &&			    (HAL_PHYERR_RADAR == (rs->rs_phyerr & 0x1f)) &&			    !(bf->bf_status & ATH_BUFSTATUS_RADAR_DONE) &&			    (ic->ic_flags & IEEE80211_F_DOTH))				check_for_radar = 1;			/* XXX: We do not support frames spanning multiple			 *      descriptors */			bf->bf_status |= ATH_BUFSTATUS_RXDESC_DONE;			if (rs->rs_status) {				/* Skip past the error now */				continue;			}			/* Prepare wireless header for examination */			bus_dma_sync_single(sc->sc_bdev, bf->bf_skbaddr,					sizeof(struct ieee80211_qosframe),					BUS_DMA_FROMDEVICE);			qwh = (struct ieee80211_qosframe *)skb->data;			/* Find the node; it MUST be in the keycache. */			if (rs->rs_keyix == HAL_RXKEYIX_INVALID ||			    (ni = sc->sc_keyixmap[rs->rs_keyix]) == NULL) {				/*				 * XXX: this can occur if WEP mode is used for				 *      non-Atheros clients (since we do not				 *      know which of the 4 WEP keys will be				 *      used at association time, so cannot				 *      setup a key-cache entry.				 *      The Atheros client can convey this in				 *      the Atheros IE.)				 *				 *      The fix is to use the hash lookup on				 *      the node here.				 */#if 0				/* This print is very chatty, so removing for now. */				DPRINTF(sc, ATH_DEBUG_UAPSD, "U-APSD node (" MAC_FMT ") "					"has invalid keycache entry\n",					MAC_ADDR(qwh->i_addr2));#endif				continue;			}			if (!(ni->ni_flags & IEEE80211_NODE_UAPSD))				continue;			/*			 * Must deal with change of state here, since otherwise			 * there would be a race (on two quick frames from STA)			 * between this code and the tasklet where we would:			 *   - miss a trigger on entry to PS if we're already			 *     trigger hunting			 *   - generate spurious SP on exit (due to frame			 *     following exit frame)			 */			if ((!!(qwh->i_fc[1] & IEEE80211_FC1_PWR_MGT) !=			     !!(ni->ni_flags & IEEE80211_NODE_PWR_MGT))) {				/*				 * NB: do not require lock here since this runs				 * at intr "proper" time and cannot be				 * interrupted by RX tasklet (code there has				 * lock). May want to place a macro here				 * (that does nothing) to make this more clear.				 */				ni->ni_flags |= IEEE80211_NODE_PS_CHANGED;				ni->ni_pschangeseq = *(__le16 *)(&qwh->i_seq[0]);				ni->ni_flags &= ~IEEE80211_NODE_UAPSD_SP;				ni->ni_flags ^= IEEE80211_NODE_PWR_MGT;				if (qwh->i_fc[1] & IEEE80211_FC1_PWR_MGT) {					ni->ni_flags |=						IEEE80211_NODE_UAPSD_TRIG;					ic->ic_uapsdmaxtriggers++;					WME_UAPSD_NODE_TRIGSEQINIT(ni);					DPRINTF(sc, ATH_DEBUG_UAPSD,						"Node (" MAC_FMT ") became U-APSD "						"triggerable (%d)\n",						MAC_ADDR(qwh->i_addr2),						ic->ic_uapsdmaxtriggers);				} else {					ni->ni_flags &=						~IEEE80211_NODE_UAPSD_TRIG;					ic->ic_uapsdmaxtriggers--;					DPRINTF(sc, ATH_DEBUG_UAPSD,						"Node (" MAC_FMT ") no longer U-APSD"						" triggerable (%d)\n",						MAC_ADDR(qwh->i_addr2),						ic->ic_uapsdmaxtriggers);					/*					 * XXX: Rapidly thrashing sta could get					 * out-of-order frames due this flush					

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -