Ejemplo n.º 1
0
/*
 * Drain the transmit queues and reclaim resources.
 */
static void
ath_drain_txq(struct ath_softc *sc)
{
#ifdef ATH_SUPPORT_HTC
    u_int16_t i;
    struct ath_hal *ah = sc->sc_ah;
	
    /* drain all host endpoints */
    for (i = 0; i < NUM_TX_EP; i++)
        if (ATH_TXQ_SETUP(sc, i))
            ath_tx_drainep(sc, &sc->sc_txep[i]);
	
    HTCDrainAllEp(sc->sc_host_htc_handle);
	
    /* stop target wireless DMA */
    if (!sc->sc_invalid) {
        for (i = 0; i < NUM_TX_EP; i++)
            if (ATH_TXQ_SETUP(sc, i)) {
                u_int32_t hwq_num;
				
                hwq_num = adf_os_htonl(sc->sc_txep[i].hwq_num);
                ath_hal_tx99_tx_stopdma(ah, hwq_num);
            }
    }
    ath_hal_tx99_drain_alltxq(ah);
#else
    /* stop beacon queue. stop and abort all tx qs, flush ath buffer queue */
    ath_draintxq(sc, AH_FALSE, 0);  /* stop xmit side */
#endif
}
Ejemplo n.º 2
0
static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
					   struct ieee80211_vif *vif)
{
	struct ath_softc *sc = hw->priv;
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
	struct ath_buf *bf;
	struct ath_vif *avp;
	struct sk_buff *skb;
	struct ath_txq *cabq;
	struct ieee80211_tx_info *info;
	int cabq_depth;

	ath9k_reset_beacon_status(sc);

	avp = (void *)vif->drv_priv;
	cabq = sc->beacon.cabq;

	if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active)
		return NULL;

	/* Release the old beacon first */

	bf = avp->av_bcbuf;
	skb = bf->bf_mpdu;
	if (skb) {
		dma_unmap_single(sc->dev, bf->bf_buf_addr,
				 skb->len, DMA_TO_DEVICE);
		dev_kfree_skb_any(skb);
		bf->bf_buf_addr = 0;
	}

	/* Get a new beacon from mac80211 */

	skb = ieee80211_beacon_get(hw, vif);
	bf->bf_mpdu = skb;
	if (skb == NULL)
		return NULL;
	((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
		avp->tsf_adjust;

	info = IEEE80211_SKB_CB(skb);
	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
		/*
		 * TODO: make sure the seq# gets assigned properly (vs. other
		 * TX frames)
		 */
		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
		sc->tx.seq_no += 0x10;
		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
	}

	bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
					 skb->len, DMA_TO_DEVICE);
	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
		dev_kfree_skb_any(skb);
		bf->bf_mpdu = NULL;
		bf->bf_buf_addr = 0;
		ath_err(common, "dma_mapping_error on beaconing\n");
		return NULL;
	}

	skb = ieee80211_get_buffered_bc(hw, vif);

	/*
	 * if the CABQ traffic from previous DTIM is pending and the current
	 *  beacon is also a DTIM.
	 *  1) if there is only one vif let the cab traffic continue.
	 *  2) if there are more than one vif and we are using staggered
	 *     beacons, then drain the cabq by dropping all the frames in
	 *     the cabq so that the current vifs cab traffic can be scheduled.
	 */
	spin_lock_bh(&cabq->axq_lock);
	cabq_depth = cabq->axq_depth;
	spin_unlock_bh(&cabq->axq_lock);

	if (skb && cabq_depth) {
		if (sc->nvifs > 1) {
			ath_dbg(common, BEACON,
				"Flushing previous cabq traffic\n");
			ath_draintxq(sc, cabq, false);
		}
	}

	ath_beacon_setup(sc, vif, bf, info->control.rates[0].idx);

	while (skb) {
		ath_tx_cabq(hw, skb);
		skb = ieee80211_get_buffered_bc(hw, vif);
	}

	return bf;
}
Ejemplo n.º 3
0
void ath_cont_data(struct ath_softc *sc ,int val)
{
  static struct sk_buff *skb = NULL;
  struct ieee80211_frame *hdr;
  static struct ieee80211com *ic;
  static struct ath_buf *bf,*prev,*first;
  static struct ath_desc *ds;
  static struct ath_hal *ah;
  static STAILQ_HEAD(tpc_buf,ath_buf) tmp_q;
  static int is_inited=0;
  struct ath_txq *txq;
  const HAL_RATE_TABLE *rt;
  u_int8_t *p;
  u_int32_t flags, txrate, r,i;
  u_int16_t hdrlen, framelen, dmalen,delay=0;
#define	MIN(a,b)	((a) < (b) ? (a) : (b))

  if(is_inited == 0)
  {
    STAILQ_INIT(&tmp_q);
    is_inited=1;
  }
	
  /* enter CONT_DATA mode */
  if (val && skb==NULL) {
    skb = ath_alloc_skb(4096, 32);
    if (skb == NULL)
      goto out;

    /* build output packet */
    hdr = (struct ieee80211_frame *)skb_put(skb, sizeof(*hdr));
    IEEE80211_ADDR_COPY(&hdr->i_addr1, test_addr);
    IEEE80211_ADDR_COPY(&hdr->i_addr2, test_addr);
    IEEE80211_ADDR_COPY(&hdr->i_addr3, test_addr);
    hdr->i_dur[0] = 0x0;
    hdr->i_dur[1] = 0x0;
    hdr->i_seq[0] = 0x5a;
    hdr->i_seq[1] = 0x5a;
    hdr->i_fc[0] = IEEE80211_FC0_TYPE_DATA;
    hdr->i_fc[1] = 0;
    hdrlen = sizeof(*hdr);
    for(r=0; r<2000; ) {
      p = skb_put(skb, sizeof(PN9Data));
      memcpy(p, PN9Data, sizeof(PN9Data));
      r += sizeof(PN9Data);
    }
    framelen = hdrlen + r + IEEE80211_CRC_LEN;

    ic = &sc->sc_ic;
    ah = sc->sc_ah;
	rt = sc->sc_currates;
	if (rt==NULL) {
	  printk("no rate table\n");
	  goto out;
	}
	txrate = rt->info[rt->rateCount-1].rateCode;	/* send at highest rate */
	{
	  int rix;
	  if (sc->sc_txrate==0)
	    sc->sc_txrate = 6000;
	  for(rix=0; rix<rt->rateCount; rix++) {
	    if (rt->info[rix].rateKbps==sc->sc_txrate) {
	      txrate = rt->info[rix].rateCode;
	      printk("txrate set to %dKbps\n", sc->sc_txrate);
	      break;
	    }
	  }
	}
    ath_draintxq(sc);
    prev=first=NULL;
    /* send 20 frames for the Power Amp to settle down */
    for(i=0;i<20;++i)
    {
	ATH_TXBUF_LOCK_BH(sc);						

	bf = STAILQ_FIRST(&sc->sc_txbuf);
	if (bf != NULL) {
	  STAILQ_REMOVE_HEAD(&sc->sc_txbuf,bf_list);
	}
	ATH_TXBUF_UNLOCK_BH(sc);				
	
	if (bf==NULL) {
	    printk("no tx buf\n");
	    goto out; 
	}
        if(!i)  first=bf;
	framelen = skb->len + IEEE80211_CRC_LEN;
	dmalen = skb->len;
	txq = sc->sc_ac2q[WME_AC_VO];

	bf->bf_skbaddr = bus_map_single(sc->sc_bdev, skb->data, framelen, BUS_DMA_TODEVICE);
	bf->bf_skb = skb;
	bf->bf_node = 0;
	flags = HAL_TXDESC_CLRDMASK;  
	ds = bf->bf_desc;
        if(prev)
	  prev->bf_desc->ds_link = bf->bf_daddr;		/* link from prev desc  */
	ds->ds_data = bf->bf_skbaddr;

	printk("txpower set to %d\n", sc->sc_txpower);
	r = ath_hal_setuptxdesc(ah, ds, framelen, hdrlen,
				HAL_PKT_TYPE_NORMAL,
				sc->sc_txpower,
				txrate,			    /* tx rate */
				15,			    /* max retries */
				HAL_TXKEYIX_INVALID,	    /* no WEP */
				1,			    /* select Omni Antenna 0 */
				flags,
				0,			    /* rts/cts rate */
				0			    /* rts/cts duration */
				);

	if (r==AH_FALSE) {
	  printk("fail setuptxdesc r(%d)\n", r);
	  goto out;
	}  

	r = ath_hal_filltxdesc(ah, ds, skb->len, AH_TRUE, AH_TRUE,ds);
	if (r==AH_FALSE) {
	  printk("fail fill tx desc r(%d)\n", r);
	  goto out;
	}
	ath_hal_setupxtxdesc(ah, ds
			     , txrate, 15	/* series 1 */
			     , txrate, 15	/* series 2 */
			     , txrate, 15	/* series 3 */
			     );

        /* insert the buffers in to tmp_q */
        STAILQ_INSERT_HEAD(&tmp_q,bf,bf_list);
#if 0
	ATH_TXQ_LOCK_BH(txq);
	ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
	ATH_TXQ_UNLOCK_BH(txq);
#endif

        prev=bf;
      }
      ath_hal_intrset(ah, 0);	    	/* disable interrupts */
      //sc->sc_imask = HAL_INT_RX | HAL_INT_TX
      //		  | HAL_INT_RXEOL | HAL_INT_RXORN
      //		  | HAL_INT_FATAL | HAL_INT_GLOBAL;
      sc->sc_imask = 0; 
      //ath_hal_intrset(ah, sc->sc_imask);

      bf->bf_desc->ds_link = NULL;
      r = ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
      ath_hal_txstart(ah, txq->axq_qnum);

      while(ath_hal_txprocdesc(ah,bf->bf_desc)  == HAL_EINPROGRESS)
      {
        udelay(2000);
        ++delay;
      }
      
      /* sleep for 20ms */
      udelay(20000);
      printk("took %d msec to transmit the 20 frames \n",2*delay);

      /* start TX99 mode */
      ath_stoprecv(sc);		    	/* stop recv side */
      bf->bf_desc->ds_link = first->bf_daddr;		/* link to self */
      ath_hal_getdiagstate(ah, 19,(void *) sc->sc_prefetch,9,NULL,NULL);
      ath_hal_getdiagstate(ah, 19, txq->axq_qnum, val,NULL,NULL);
      ath_hal_txstart(ah, txq->axq_qnum);
  }

  /* leave CONT_DATA mode, reset the chip */
  if (val==0 && skb) {
    int j=0;
    ath_hal_getdiagstate(ah, 19, 0, 0,NULL,NULL);
    /* insert the buffers back into txbuf list */

	ATH_TXBUF_LOCK_BH(sc);						

        bf = STAILQ_FIRST(&tmp_q);
        while(bf)
	{
	  bf->bf_skb=NULL;
	     STAILQ_REMOVE_HEAD(&tmp_q,bf_list);
             STAILQ_INSERT_HEAD(&sc->sc_txbuf,bf,bf_list);
             bf = STAILQ_FIRST(&tmp_q);
	     ++j;
	}
	ATH_TXBUF_UNLOCK_BH(sc);				
        printk("inserted back %d buffers \n",j);
    ic->ic_reset(ic->ic_dev);
    skb = NULL;
    bf = NULL;
  }

  if (val==7 && skb) {
    ath_hal_getdiagstate(ah, 19, ds, 7,NULL,NULL);
  }

 out:
  return;
#undef MIN
}