Beispiel #1
0
void ath_rx99_ctl(struct ath_softc *sc ,int val)
{
	struct ath_hal *ah = sc->sc_ah;
	if(val && !sc->sc_txrx99.rx99mode) {
		sc->sc_txrx99.prev_hard_start = sc->sc_dev.hard_start_xmit;
		sc->sc_txrx99.prev_mgt_start = sc->sc_ic.ic_mgtstart;
		sc->sc_dev.hard_start_xmit = ath_rx99_hardstart;
		sc->sc_ic.ic_mgtstart = ath_rx99_mgtstart;
		/*
		 * Disable interrupts.
		 */
        sc->sc_txrx99.imask=sc->sc_imask;
        sc->sc_imask  &=  (~(HAL_INT_SWBA | HAL_INT_BMISS));
		ath_hal_intrset(ah, sc->sc_imask );
	}
    else {
		if(!val && sc->sc_txrx99.rx99mode) {
			sc->sc_dev.hard_start_xmit = sc->sc_txrx99.prev_hard_start;
			sc->sc_ic.ic_mgtstart = sc->sc_txrx99.prev_mgt_start;
			sc->sc_txrx99.prev_hard_start = sc->sc_txrx99.prev_mgt_start=NULL;
		    sc->sc_imask |= (sc->sc_txrx99.imask & (HAL_INT_SWBA | HAL_INT_BMISS));
			ath_hal_intrset(ah, sc->sc_imask);
            sc->sc_txrx99.imask=0;
        }
    }
    sc->sc_txrx99.rx99mode=val;
}
Beispiel #2
0
void enable_beacons(struct ath_softc *sc)
{
    SPECTRAL_DPRINTK(sc, ATH_DEBUG_SPECTRAL2,"Turning ON SWBA and BMISS interrupts before imask = 0x%x\n", ath_hal_intrget(sc->sc_ah));
    sc->sc_imask |= (HAL_INT_SWBA | HAL_INT_BMISS);
    ath_hal_intrset(sc->sc_ah, sc->sc_imask);
    SPECTRAL_DPRINTK(sc, ATH_DEBUG_SPECTRAL2,"AFTER imask = 0x%x\n", ath_hal_intrget(sc->sc_ah));
}
Beispiel #3
0
static void
ath_pwrsave_set_state_sync(struct ath_softc *sc)
{
    struct ath_hal *ah = sc->sc_ah;
    ATH_PWRSAVE_STATE newstate = (sc)->sc_pwrsave.ps_set_state;

    if(sc->sc_pwrsave.ps_pwrsave_state == newstate) 
        return;
    if (sc->sc_removed) 
        return;

    switch (sc->sc_pwrsave.ps_pwrsave_state) {

    case ATH_PWRSAVE_NETWORK_SLEEP:
        switch (newstate) {
        case ATH_PWRSAVE_AWAKE:
            if (!ATH_PS_ALWAYS_AWAKE(sc)){
                ath_hal_setpower(ah, HAL_PM_AWAKE);

                /* 
                 * Must clear RxAbort bit manually if hardware does not support 
                 * automatic sleep after waking up for TIM.
                 */
                if (! sc->sc_hasautosleep) {
                    u_int32_t    imask;
            
                    ath_hal_setrxabort(ah, 0);
                
                    /* Disable TIM_TIMER interrupt */
                    imask = ath_hal_intrget(ah);

                    if ((imask & HAL_INT_TIM_TIMER) ||
                        ((imask & HAL_INT_TSFOOR) == 0)) {
                        sc->sc_imask &= ~HAL_INT_TIM_TIMER;
                        imask &= ~HAL_INT_TIM_TIMER;

                        imask |= HAL_INT_TSFOOR;
                        sc->sc_imask |= HAL_INT_TSFOOR;

                        ath_hal_intrset(ah, imask);
                    }
                }
            }
#if ATH_TX_DUTY_CYCLE
            if (sc->sc_tx_dc_enable) {
                u_int32_t duration;
                /* re-arm tx duty cycle */
                DPRINTF(sc, ATH_DEBUG_ANY, "%s: %d=>%d: re-enable quiet time: %u%% active\n", 
                        __func__, sc->sc_pwrsave.ps_pwrsave_state, newstate, sc->sc_tx_dc_active_pct);
                if (sc->sc_opmode == HAL_M_HOSTAP && sc->sc_nbcnvaps != 0) {
                    ath_beacon_config(sc, ATH_BEACON_CONFIG_REASON_RESET, ATH_IF_ID_ANY);
                }else  if (sc->sc_nvaps){
                    duration = ((100-sc->sc_tx_dc_active_pct)*sc->sc_tx_dc_period)/100;
                    ath_hal_setQuiet(sc->sc_ah, sc->sc_tx_dc_period, duration, 0, AH_TRUE);
                }
            }
#endif
            break;
        case ATH_PWRSAVE_FULL_SLEEP:
            /*
             * Stop both receive PCU and DMA before going full sleep to prevent deaf mute.
             */
            ath_hal_setrxabort(ah, 1);
            ath_hal_stopdmarecv(ah, 0); 
            ath_hal_setpower(ah, HAL_PM_FULL_SLEEP);
            break;

        default:
            break;
        }
        break;

    case ATH_PWRSAVE_AWAKE:
        switch (newstate) {
        case ATH_PWRSAVE_NETWORK_SLEEP:
	        if (!ATH_PS_ALWAYS_AWAKE(sc)){
                /* 
                 * Chips that do not support automatic sleep after waking up to 
                 * receive TIM must make sure at least one beacon is received 
                 * before reentering network sleep.
                 */
#if ATH_TX_DUTY_CYCLE
                if (sc->sc_tx_dc_enable) {
                    /* disarm tx duty cycle */
                    DPRINTF(sc, ATH_DEBUG_ANY, "%s: %d=>%d: disable quiet time: %u%% active\n", 
                            __func__, sc->sc_pwrsave.ps_pwrsave_state, newstate, sc->sc_tx_dc_active_pct);
                    ath_hal_setQuiet(sc->sc_ah, 0, 0, 0, AH_FALSE);
                }
#endif
                if (! sc->sc_hasautosleep) {
                    /* 
                     * Do not enter network sleep if no beacon received
                     */
                    if (! sc->sc_waitbeacon) {
                        u_int32_t    imask;
                        
                        /* Enable TIM_TIMER interrupt */
                        imask = ath_hal_intrget(ah);
                        
                        if (((imask & HAL_INT_TIM_TIMER) == 0) ||
                            (imask & HAL_INT_TSFOOR)){
                            sc->sc_imask |= HAL_INT_TIM_TIMER;
                            imask |= HAL_INT_TIM_TIMER;

                            imask &= ~HAL_INT_TSFOOR;
                            sc->sc_imask &= ~HAL_INT_TSFOOR;

                            ath_hal_intrset(ah, imask);
                        } 
                        
                        /* Stop RX state machine */
                        if (ath_hal_setrxabort(ah, 1)) {
                            ath_hal_setpower(ah, HAL_PM_NETWORK_SLEEP);
                        }
                    }
                }
                else {
                    ath_hal_setpower(ah, HAL_PM_NETWORK_SLEEP);
                }
            }
            break;
        case ATH_PWRSAVE_FULL_SLEEP:
            /*
             *  Must abort rx prior to full sleep for 2 reasons:
             *
             * 1. Hardware does not support automatic sleep (sc_hasautosleep=0)
             *    after waking up for TIM.
             * 2. WAR for EV68448 - card disappearance.
             *    Ideally, rx would be stopped at a higher level
             *    but the code was removed because it broke RFKILL (see EV66300).
             * 3. Stop both receive PCU and DMA before going full sleep to prevent deaf mute.
             */
#if ATH_TX_DUTY_CYCLE
            if (sc->sc_tx_dc_enable) {
                /* disarm tx duty cycle */
                DPRINTF(sc, ATH_DEBUG_ANY, "%s: %d=>%d: disable quiet time: %u%% active\n", 
                        __func__, sc->sc_pwrsave.ps_pwrsave_state, newstate, sc->sc_tx_dc_active_pct);
                ath_hal_setQuiet(sc->sc_ah, 0, 0, 0, AH_FALSE);
            }
#endif
            ath_hal_setrxabort(ah, 1);
            ath_hal_stopdmarecv(ah, 0); 
            ath_hal_setpower(ah, HAL_PM_FULL_SLEEP);
            break;

        default:
            break;
        }
        break;

    case ATH_PWRSAVE_FULL_SLEEP:
        switch (newstate) {
        case ATH_PWRSAVE_AWAKE:
            ath_hal_setpower(ah, HAL_PM_AWAKE);

            /* 
             * Must clear RxAbort bit manually if hardware does not support 
             * automatic sleep after waking up for TIM.
             */
            if (! sc->sc_hasautosleep) {
                u_int32_t    imask;
            
                ath_hal_setrxabort(ah, 0);
                
                /* Disable TIM_TIMER interrupt */
                imask = ath_hal_intrget(ah);
                if (imask & HAL_INT_TIM_TIMER) {
                    sc->sc_imask &= ~HAL_INT_TIM_TIMER;
                    ath_hal_intrset(ah, imask & ~HAL_INT_TIM_TIMER);
                }
            }
#if ATH_TX_DUTY_CYCLE
            if (sc->sc_tx_dc_enable) {
                u_int32_t duration;
                /* re-arm tx duty cycle */
                DPRINTF(sc, ATH_DEBUG_ANY, "%s: %d=>%d: re-enable quiet time: %u%% active\n", 
                        __func__, sc->sc_pwrsave.ps_pwrsave_state, newstate, sc->sc_tx_dc_active_pct);
                if (sc->sc_opmode == HAL_M_HOSTAP && sc->sc_nbcnvaps != 0) {
                    ath_beacon_config(sc, ATH_BEACON_CONFIG_REASON_RESET, ATH_IF_ID_ANY);
                }else if (sc->sc_nvaps){
                    duration = ((100-sc->sc_tx_dc_active_pct)*sc->sc_tx_dc_period)/100;
                    ath_hal_setQuiet(sc->sc_ah, sc->sc_tx_dc_period, duration, 0, AH_TRUE);
                }
            }
#endif
            break;
        default:
            break;
        }
    default:
        break;

    }
    sc->sc_pwrsave.ps_pwrsave_state = newstate;

    /* If chip has been put in full sleep, make sure full reset is called */
    if (sc->sc_pwrsave.ps_pwrsave_state == ATH_PWRSAVE_FULL_SLEEP)
        sc->sc_full_reset = 1;
}
Beispiel #4
0
/*
 * To enable PHY (radio on)
 */
int
ath_radio_enable(ath_dev_t dev)
{
    struct ath_softc *sc = ATH_DEV_TO_SC(dev);
    struct ath_hal *ah = sc->sc_ah;
    HAL_STATUS status;
    HAL_HT_MACMODE ht_macmode = sc->sc_ieee_ops->cwm_macmode(sc->sc_ieee);

    if (sc->sc_invalid)
        return -EIO;
    
#if ATH_RESET_SERIAL
    ATH_RESET_ACQUIRE_MUTEX(sc);
#endif    
    ATH_PS_WAKEUP(sc);

    ath_pwrsave_awake(sc);

    /* Turn off PCIE ASPM when card is active */
    ath_pcie_pwrsave_enable_on_phystate_change(sc, 0);

    ATH_USB_TX_STOP(sc->sc_osdev);
#if ATH_C3_WAR
    STOP_C3_WAR_TIMER(sc);
#endif
#if !ATH_RESET_SERIAL
    ATH_LOCK_PCI_IRQ(sc);
#endif
    if (!ath_hal_reset(ah, sc->sc_opmode, &sc->sc_curchan,
                       ht_macmode,
                       sc->sc_tx_chainmask, sc->sc_rx_chainmask,
                       sc->sc_ht_extprotspacing, AH_FALSE, &status,
                       sc->sc_scanning)) {
        printk("%s: unable to reset hardware; hal status %u\n",
               __func__, status);
    }
#if !ATH_RESET_SERIAL
    ATH_UNLOCK_PCI_IRQ(sc);
#endif

    ath_update_txpow(sc, sc->tx_power); /* update tx power state */

    ath_beacon_config(sc, ATH_BEACON_CONFIG_REASON_RESET, ATH_IF_ID_ANY);   /* restart beacons */
    ath_hal_intrset(ah, sc->sc_imask);

    ath_wmi_start_recv(sc);
    if (ATH_STARTRECV(sc) != 0)    { /* restart recv */
        printk("%s: unable to start recv logic\n",
               __func__);
    }

    ATH_USB_TX_START(sc->sc_osdev);
    /*
     * notify LED module radio has been turned on
     * This function will access the hw, so we must call it after 
     * the power save function.
     */
    ath_led_enable(&sc->sc_led_control);

    ATH_PS_SLEEP(sc);
#if ATH_RESET_SERIAL
    ATH_RESET_RELEASE_MUTEX(sc);
#endif

    return 0;
}
Beispiel #5
0
/*
 * To disable PHY (radio off)
 */
int
ath_radio_disable(ath_dev_t dev)
{
    struct ath_softc *sc = ATH_DEV_TO_SC(dev);
    struct ath_hal *ah = sc->sc_ah;
    HAL_STATUS status;
    HAL_HT_MACMODE ht_macmode = sc->sc_ieee_ops->cwm_macmode(sc->sc_ieee);

    if (sc->sc_invalid)
        return -EIO;

#if ATH_RESET_SERIAL
    ATH_RESET_ACQUIRE_MUTEX(sc);
    ATH_RESET_LOCK(sc);
    atomic_inc(&sc->sc_hold_reset);
    ath_reset_wait_tx_rx_finished(sc);
    ATH_RESET_UNLOCK(sc);
#endif

    ATH_PS_WAKEUP(sc);
    
    /*
     * notify LED module radio has been turned off
     * This function will access the hw, so we must call it before 
     * the power save function.
     */
    ath_led_disable(&sc->sc_led_control);

    ath_hal_intrset(ah, 0);    /* disable interrupts */

    ath_reset_draintxq(sc, AH_FALSE, 0); /* stop xmit side */
    ATH_USB_TX_STOP(sc->sc_osdev);
    ATH_HTC_DRAINTXQ(sc);          /* stop target xmit */
    ATH_STOPRECV(sc, 0);        /* stop recv side */
    ath_flushrecv(sc);      /* flush recv queue */

#if ATH_C3_WAR
    STOP_C3_WAR_TIMER(sc);
#endif
#if !ATH_RESET_SERIAL
    ATH_LOCK_PCI_IRQ(sc);
#endif
    if (!ath_hal_reset(ah, sc->sc_opmode, &sc->sc_curchan,
                       ht_macmode,
                       sc->sc_tx_chainmask, sc->sc_rx_chainmask,
                       sc->sc_ht_extprotspacing, AH_FALSE, &status,
                       sc->sc_scanning)) {
        printk("%s: unable to reset hardware; hal status %u\n",
               __func__, status);
    }
    ATH_HTC_ABORTTXQ(sc);
#if !ATH_RESET_SERIAL
    ATH_UNLOCK_PCI_IRQ(sc);
#endif

    ATH_USB_TX_START(sc->sc_osdev);
    ath_hal_phydisable(ah);

#ifdef ATH_RFKILL
    if (sc->sc_hasrfkill) {
        ath_hal_intrset(ah, HAL_INT_GLOBAL | HAL_INT_GPIO);    /* Enable interrupt to capture GPIO event */
    }
#endif
    
    /* Turn on PCIE ASPM during RF Silence */
    ath_pcie_pwrsave_enable_on_phystate_change(sc, 1);
    /*
     * XXX TODO: We should put chip to forced sleep when radio is disabled. 
     */

    ath_pwrsave_fullsleep(sc);
    ATH_PS_SLEEP(sc);
#if ATH_RESET_SERIAL
    atomic_dec(&sc->sc_hold_reset);
    ATH_RESET_RELEASE_MUTEX(sc);
#endif

    return 0;
}
Beispiel #6
0
void ath_cont_data(struct ath_softc *sc ,int val,ath_callback ath_draintxq, ath_callback ath_stoprecv)
{
  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(ath_hal_getdiagstate(sc->sc_ah, 19,0,10,NULL,NULL) == AH_FALSE)
  {
	  printk("HAL does not support TX99 mode \n");
	  printk("compile HAL with AH_PRIVATE_DIAG turned on \n");
      return;
  } 
  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_txrx99.txrate==0)
	    sc->sc_txrx99.txrate = 6000;
	  for(rix=0; rix<rt->rateCount; rix++) {
	    if (rt->info[rix].rateKbps==sc->sc_txrx99.txrate) {
	      txrate = rt->info[rix].rateCode;
	      printk("txrate set to %dKbps\n", sc->sc_txrx99.txrate);
	      break;
	    }
	  }
	}
    ath_draintxq(sc);
    prev=first=NULL;
	printk("txpower set to %d\n", sc->sc_txrx99.txpower);
    /* 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;

	r = ath_hal_setuptxdesc(ah, ds, framelen, hdrlen,
				HAL_PKT_TYPE_NORMAL,
				sc->sc_txrx99.txpower,
				txrate,			    /* tx rate */
				1,			    /* 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);

        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 = 0;
      r = ath_hal_puttxbuf(ah, txq->axq_qnum, first->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_txrx99.prefetch,9,NULL,NULL);
      ath_hal_getdiagstate(ah, 19, (void *)txq->axq_qnum, val,NULL,NULL);
      r = ath_hal_puttxbuf(ah, txq->axq_qnum, first->bf_daddr);
      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);
  }

  sc->sc_txrx99.tx99mode=val;
 out:
  return;
#undef MIN
}