diff --git a/sys/dev/ath/if_ath_lna_div.c b/sys/dev/ath/if_ath_lna_div.c
index 1b20591fc64e..0755bb667716 100644
--- a/sys/dev/ath/if_ath_lna_div.c
+++ b/sys/dev/ath/if_ath_lna_div.c
@@ -1,1016 +1,1010 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
  * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer,
  *    without modification.
  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
  *    redistribution must be conditioned upon including a substantially
  *    similar Disclaimer requirement for further binary redistribution.
  *
  * NO WARRANTY
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGES.
  */
 #include <sys/cdefs.h>
 /*
  * This module handles LNA diversity for those chips which implement LNA
  * mixing (AR9285/AR9485.)
  */
 #include "opt_ath.h"
 #include "opt_inet.h"
 #include "opt_wlan.h"
 
 #include <sys/param.h>
 #include <sys/systm.h> 
 #include <sys/sysctl.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/errno.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
 #include <sys/bus.h>
 
 #include <sys/socket.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
 #include <net/if_media.h>
 #include <net/if_arp.h>
 #include <net/ethernet.h>		/* XXX for ether_sprintf */
 
 #include <net80211/ieee80211_var.h>
 
 #include <net/bpf.h>
 
 #ifdef INET
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 #endif
 
 #include <dev/ath/if_athvar.h>
 #include <dev/ath/if_ath_debug.h>
 #include <dev/ath/if_ath_lna_div.h>
 
 /* Linux compatibility macros */
 /*
  * XXX these don't handle rounding, underflow, overflow, wrapping!
  */
 #define	msecs_to_jiffies(a)		( (a) * hz / 1000 )
 
 /*
  * Methods which are required
  */
 
 /*
  * Attach the LNA diversity to the given interface
  */
 int
 ath_lna_div_attach(struct ath_softc *sc)
 {
 	struct if_ath_ant_comb_state *ss;
 	HAL_ANT_COMB_CONFIG div_ant_conf;
 
 	/* Only do this if diversity is enabled */
 	if (! ath_hal_hasdivantcomb(sc->sc_ah))
 		return (0);
 
 	ss = malloc(sizeof(struct if_ath_ant_comb_state),
 	    M_TEMP, M_WAITOK | M_ZERO);
-	if (ss == NULL) {
-		device_printf(sc->sc_dev, "%s: failed to allocate\n",
-		    __func__);
-		/* Don't fail at this point */
-		return (0);
-	}
 
 	/* Fetch the hardware configuration */
 	OS_MEMZERO(&div_ant_conf, sizeof(div_ant_conf));
 	ath_hal_div_comb_conf_get(sc->sc_ah, &div_ant_conf);
 
 	/* Figure out what the hardware specific bits should be */
 	if ((div_ant_conf.antdiv_configgroup == HAL_ANTDIV_CONFIG_GROUP_1) ||
 	    (div_ant_conf.antdiv_configgroup == HAL_ANTDIV_CONFIG_GROUP_2)) {
 		ss->lna1_lna2_delta = -9;
 	} else {
 		ss->lna1_lna2_delta = -3;
 	}
 
 	/* Let's flip this on */
 	sc->sc_lna_div = ss;
 	sc->sc_dolnadiv = 1;
 
 	return (0);
 }
 
 /*
  * Detach the LNA diversity state from the given interface
  */
 int
 ath_lna_div_detach(struct ath_softc *sc)
 {
 	if (sc->sc_lna_div != NULL) {
 		free(sc->sc_lna_div, M_TEMP);
 		sc->sc_lna_div = NULL;
 	}
 	sc->sc_dolnadiv = 0;
 	return (0);
 }
 
 /*
  * Enable LNA diversity on the current channel if it's required.
  */
 int
 ath_lna_div_enable(struct ath_softc *sc, const struct ieee80211_channel *chan)
 {
 
 	return (0);
 }
 
 /*
  * Handle ioctl requests from the diagnostic interface.
  *
  * The initial part of this code resembles ath_ioctl_diag();
  * it's likely a good idea to reduce duplication between
  * these two routines.
  */
 int
 ath_lna_div_ioctl(struct ath_softc *sc, struct ath_diag *ad)
 {
 	unsigned int id = ad->ad_id & ATH_DIAG_ID;
 	void *indata = NULL;
 	void *outdata = NULL;
 	u_int32_t insize = ad->ad_in_size;
 	u_int32_t outsize = ad->ad_out_size;
 	int error = 0;
 //	int val;
 
 	if (ad->ad_id & ATH_DIAG_IN) {
 		/*
 		 * Copy in data.
 		 */
 		indata = malloc(insize, M_TEMP, M_NOWAIT);
 		if (indata == NULL) {
 			error = ENOMEM;
 			goto bad;
 		}
 		error = copyin(ad->ad_in_data, indata, insize);
 		if (error)
 			goto bad;
 	}
 	if (ad->ad_id & ATH_DIAG_DYN) {
 		/*
 		 * Allocate a buffer for the results (otherwise the HAL
 		 * returns a pointer to a buffer where we can read the
 		 * results).  Note that we depend on the HAL leaving this
 		 * pointer for us to use below in reclaiming the buffer;
 		 * may want to be more defensive.
 		 */
 		outdata = malloc(outsize, M_TEMP, M_NOWAIT | M_ZERO);
 		if (outdata == NULL) {
 			error = ENOMEM;
 			goto bad;
 		}
 	}
 	switch (id) {
 		default:
 			error = EINVAL;
 			goto bad;
 	}
 	if (outsize < ad->ad_out_size)
 		ad->ad_out_size = outsize;
 	if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size))
 		error = EFAULT;
 bad:
 	if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
 		free(indata, M_TEMP);
 	if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
 		free(outdata, M_TEMP);
 	return (error);
 }
 
 /*
  * XXX need to low_rssi_thresh config from ath9k, to support CUS198
  * antenna diversity correctly.
  */
 static HAL_BOOL
 ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, int mindelta,
     int main_rssi_avg, int alt_rssi_avg, int pkt_count)
 {
 	return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
 		(alt_rssi_avg > main_rssi_avg + maxdelta)) ||
 		(alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50);
 }
 
 static void
 ath_lnaconf_alt_good_scan(struct if_ath_ant_comb_state *antcomb,
     HAL_ANT_COMB_CONFIG *ant_conf, int main_rssi_avg)
 {
 	antcomb->quick_scan_cnt = 0;
 
 	if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA2)
 		antcomb->rssi_lna2 = main_rssi_avg;
 	else if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA1)
 		antcomb->rssi_lna1 = main_rssi_avg;
 
 	switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) {
 	case (0x10): /* LNA2 A-B */
 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->first_quick_scan_conf =
 			HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA1;
 		break;
 	case (0x20): /* LNA1 A-B */
 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->first_quick_scan_conf =
 			HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2;
 		break;
 	case (0x21): /* LNA1 LNA2 */
 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA2;
 		antcomb->first_quick_scan_conf =
 			HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->second_quick_scan_conf =
 			HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		break;
 	case (0x12): /* LNA2 LNA1 */
 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1;
 		antcomb->first_quick_scan_conf =
 			HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->second_quick_scan_conf =
 			HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		break;
 	case (0x13): /* LNA2 A+B */
 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		antcomb->first_quick_scan_conf =
 			HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA1;
 		break;
 	case (0x23): /* LNA1 A+B */
 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		antcomb->first_quick_scan_conf =
 			HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2;
 		break;
 	default:
 		break;
 	}
 }
 
 static void
 ath_select_ant_div_from_quick_scan(struct if_ath_ant_comb_state *antcomb,
     HAL_ANT_COMB_CONFIG *div_ant_conf, int main_rssi_avg,
     int alt_rssi_avg, int alt_ratio)
 {
 	/* alt_good */
 	switch (antcomb->quick_scan_cnt) {
 	case 0:
 		/* set alt to main, and alt to first conf */
 		div_ant_conf->main_lna_conf = antcomb->main_conf;
 		div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf;
 		break;
 	case 1:
 		/* set alt to main, and alt to first conf */
 		div_ant_conf->main_lna_conf = antcomb->main_conf;
 		div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf;
 		antcomb->rssi_first = main_rssi_avg;
 		antcomb->rssi_second = alt_rssi_avg;
 
 		if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) {
 			/* main is LNA1 */
 			if (ath_is_alt_ant_ratio_better(alt_ratio,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
 						main_rssi_avg, alt_rssi_avg,
 						antcomb->total_pkt_count))
 				antcomb->first_ratio = AH_TRUE;
 			else
 				antcomb->first_ratio = AH_FALSE;
 		} else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) {
 			if (ath_is_alt_ant_ratio_better(alt_ratio,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
 						main_rssi_avg, alt_rssi_avg,
 						antcomb->total_pkt_count))
 				antcomb->first_ratio = AH_TRUE;
 			else
 				antcomb->first_ratio = AH_FALSE;
 		} else {
 			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
 			    (alt_rssi_avg > main_rssi_avg +
 			    ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
 			    (alt_rssi_avg > main_rssi_avg)) &&
 			    (antcomb->total_pkt_count > 50))
 				antcomb->first_ratio = AH_TRUE;
 			else
 				antcomb->first_ratio = AH_FALSE;
 		}
 		break;
 	case 2:
 		antcomb->alt_good = AH_FALSE;
 		antcomb->scan_not_start = AH_FALSE;
 		antcomb->scan = AH_FALSE;
 		antcomb->rssi_first = main_rssi_avg;
 		antcomb->rssi_third = alt_rssi_avg;
 
 		if (antcomb->second_quick_scan_conf == HAL_ANT_DIV_COMB_LNA1)
 			antcomb->rssi_lna1 = alt_rssi_avg;
 		else if (antcomb->second_quick_scan_conf ==
 			 HAL_ANT_DIV_COMB_LNA2)
 			antcomb->rssi_lna2 = alt_rssi_avg;
 		else if (antcomb->second_quick_scan_conf ==
 			 HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2) {
 			if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2)
 				antcomb->rssi_lna2 = main_rssi_avg;
 			else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1)
 				antcomb->rssi_lna1 = main_rssi_avg;
 		}
 
 		if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
 		    ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)
 			div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA2;
 		else
 			div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA1;
 
 		if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) {
 			if (ath_is_alt_ant_ratio_better(alt_ratio,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
 						main_rssi_avg, alt_rssi_avg,
 						antcomb->total_pkt_count))
 				antcomb->second_ratio = AH_TRUE;
 			else
 				antcomb->second_ratio = AH_FALSE;
 		} else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) {
 			if (ath_is_alt_ant_ratio_better(alt_ratio,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
 						main_rssi_avg, alt_rssi_avg,
 						antcomb->total_pkt_count))
 				antcomb->second_ratio = AH_TRUE;
 			else
 				antcomb->second_ratio = AH_FALSE;
 		} else {
 			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
 			    (alt_rssi_avg > main_rssi_avg +
 			    ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
 			    (alt_rssi_avg > main_rssi_avg)) &&
 			    (antcomb->total_pkt_count > 50))
 				antcomb->second_ratio = AH_TRUE;
 			else
 				antcomb->second_ratio = AH_FALSE;
 		}
 
 		/* set alt to the conf with maximun ratio */
 		if (antcomb->first_ratio && antcomb->second_ratio) {
 			if (antcomb->rssi_second > antcomb->rssi_third) {
 				/* first alt*/
 				if ((antcomb->first_quick_scan_conf ==
 				    HAL_ANT_DIV_COMB_LNA1) ||
 				    (antcomb->first_quick_scan_conf ==
 				    HAL_ANT_DIV_COMB_LNA2))
 					/* Set alt LNA1 or LNA2*/
 					if (div_ant_conf->main_lna_conf ==
 					    HAL_ANT_DIV_COMB_LNA2)
 						div_ant_conf->alt_lna_conf =
 							HAL_ANT_DIV_COMB_LNA1;
 					else
 						div_ant_conf->alt_lna_conf =
 							HAL_ANT_DIV_COMB_LNA2;
 				else
 					/* Set alt to A+B or A-B */
 					div_ant_conf->alt_lna_conf =
 						antcomb->first_quick_scan_conf;
 			} else if ((antcomb->second_quick_scan_conf ==
 				   HAL_ANT_DIV_COMB_LNA1) ||
 				   (antcomb->second_quick_scan_conf ==
 				   HAL_ANT_DIV_COMB_LNA2)) {
 				/* Set alt LNA1 or LNA2 */
 				if (div_ant_conf->main_lna_conf ==
 				    HAL_ANT_DIV_COMB_LNA2)
 					div_ant_conf->alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 				else
 					div_ant_conf->alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 			} else {
 				/* Set alt to A+B or A-B */
 				div_ant_conf->alt_lna_conf =
 					antcomb->second_quick_scan_conf;
 			}
 		} else if (antcomb->first_ratio) {
 			/* first alt */
 			if ((antcomb->first_quick_scan_conf ==
 			    HAL_ANT_DIV_COMB_LNA1) ||
 			    (antcomb->first_quick_scan_conf ==
 			    HAL_ANT_DIV_COMB_LNA2))
 					/* Set alt LNA1 or LNA2 */
 				if (div_ant_conf->main_lna_conf ==
 				    HAL_ANT_DIV_COMB_LNA2)
 					div_ant_conf->alt_lna_conf =
 							HAL_ANT_DIV_COMB_LNA1;
 				else
 					div_ant_conf->alt_lna_conf =
 							HAL_ANT_DIV_COMB_LNA2;
 			else
 				/* Set alt to A+B or A-B */
 				div_ant_conf->alt_lna_conf =
 						antcomb->first_quick_scan_conf;
 		} else if (antcomb->second_ratio) {
 				/* second alt */
 			if ((antcomb->second_quick_scan_conf ==
 			    HAL_ANT_DIV_COMB_LNA1) ||
 			    (antcomb->second_quick_scan_conf ==
 			    HAL_ANT_DIV_COMB_LNA2))
 				/* Set alt LNA1 or LNA2 */
 				if (div_ant_conf->main_lna_conf ==
 				    HAL_ANT_DIV_COMB_LNA2)
 					div_ant_conf->alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 				else
 					div_ant_conf->alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 			else
 				/* Set alt to A+B or A-B */
 				div_ant_conf->alt_lna_conf =
 						antcomb->second_quick_scan_conf;
 		} else {
 			/* main is largest */
 			if ((antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) ||
 			    (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2))
 				/* Set alt LNA1 or LNA2 */
 				if (div_ant_conf->main_lna_conf ==
 				    HAL_ANT_DIV_COMB_LNA2)
 					div_ant_conf->alt_lna_conf =
 							HAL_ANT_DIV_COMB_LNA1;
 				else
 					div_ant_conf->alt_lna_conf =
 							HAL_ANT_DIV_COMB_LNA2;
 			else
 				/* Set alt to A+B or A-B */
 				div_ant_conf->alt_lna_conf = antcomb->main_conf;
 		}
 		break;
 	default:
 		break;
 	}
 }
 
 static void
 ath_ant_adjust_fast_divbias(struct if_ath_ant_comb_state *antcomb,
     int alt_ratio, int alt_ant_ratio_th, u_int config_group,
     HAL_ANT_COMB_CONFIG *pdiv_ant_conf)
 {
 
 	if (config_group == HAL_ANTDIV_CONFIG_GROUP_1) {
 		switch ((pdiv_ant_conf->main_lna_conf << 4)
 		    | pdiv_ant_conf->alt_lna_conf) {
 		case (0x01): //A-B LNA2
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x02): //A-B LNA1
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x03): //A-B A+B
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x10): //LNA2 A-B
 			if ((antcomb->scan == 0)
 			    && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
 				pdiv_ant_conf->fast_div_bias = 0x3f;
 			} else {
 				pdiv_ant_conf->fast_div_bias = 0x1;
 			}
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x12): //LNA2 LNA1
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 			case (0x13): //LNA2 A+B
 			if ((antcomb->scan == 0)
 			    && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
 				pdiv_ant_conf->fast_div_bias = 0x3f;
 			} else {
 				pdiv_ant_conf->fast_div_bias = 0x1;
 			}
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x20): //LNA1 A-B
 			if ((antcomb->scan == 0)
 			    && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
 				pdiv_ant_conf->fast_div_bias = 0x3f;
 			} else {
 				pdiv_ant_conf->fast_div_bias = 0x1;
 			}
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x21): //LNA1 LNA2
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x23): //LNA1 A+B
 			if ((antcomb->scan == 0)
 			    && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
 				pdiv_ant_conf->fast_div_bias = 0x3f;
 			} else {
 				pdiv_ant_conf->fast_div_bias = 0x1;
 			}
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x30): //A+B A-B
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x31): //A+B LNA2
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x32): //A+B LNA1
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		default:
 			break;
 		}
 	} else if (config_group == HAL_ANTDIV_CONFIG_GROUP_2) {
 		switch ((pdiv_ant_conf->main_lna_conf << 4)
 		    | pdiv_ant_conf->alt_lna_conf) {
 		case (0x01): //A-B LNA2
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x02): //A-B LNA1
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x03): //A-B A+B
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x10): //LNA2 A-B
 			if ((antcomb->scan == 0)
 			    && (alt_ratio > alt_ant_ratio_th)) {
 				pdiv_ant_conf->fast_div_bias = 0x1;
 			} else {
 				pdiv_ant_conf->fast_div_bias = 0x2;
 			}
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x12): //LNA2 LNA1
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x13): //LNA2 A+B
 			if ((antcomb->scan == 0)
 			    && (alt_ratio > alt_ant_ratio_th)) {
 				pdiv_ant_conf->fast_div_bias = 0x1;
 			} else {
 				pdiv_ant_conf->fast_div_bias = 0x2;
 			}
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x20): //LNA1 A-B
 			if ((antcomb->scan == 0)
 			    && (alt_ratio > alt_ant_ratio_th)) {
 				pdiv_ant_conf->fast_div_bias = 0x1;
 			} else {
 				pdiv_ant_conf->fast_div_bias = 0x2;
 			}
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x21): //LNA1 LNA2
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x23): //LNA1 A+B
 			if ((antcomb->scan == 0)
 			    && (alt_ratio > alt_ant_ratio_th)) {
 				pdiv_ant_conf->fast_div_bias = 0x1;
 			} else {
 				pdiv_ant_conf->fast_div_bias = 0x2;
 			}
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x30): //A+B A-B
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x31): //A+B LNA2
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		case (0x32): //A+B LNA1
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			pdiv_ant_conf->main_gaintb   = 0;
 			pdiv_ant_conf->alt_gaintb    = 0;
 			break;
 		default:
 			break;
 		}
 	} else { /* DEFAULT_ANTDIV_CONFIG_GROUP */
 		switch ((pdiv_ant_conf->main_lna_conf << 4) | pdiv_ant_conf->alt_lna_conf) {
 		case (0x01): //A-B LNA2
 			pdiv_ant_conf->fast_div_bias = 0x3b;
 			break;
 		case (0x02): //A-B LNA1
 			pdiv_ant_conf->fast_div_bias = 0x3d;
 			break;
 		case (0x03): //A-B A+B
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			break;
 		case (0x10): //LNA2 A-B
 			pdiv_ant_conf->fast_div_bias = 0x7;
 			break;
 		case (0x12): //LNA2 LNA1
 			pdiv_ant_conf->fast_div_bias = 0x2;
 			break;
 		case (0x13): //LNA2 A+B
 			pdiv_ant_conf->fast_div_bias = 0x7;
 			break;
 		case (0x20): //LNA1 A-B
 			pdiv_ant_conf->fast_div_bias = 0x6;
 			break;
 		case (0x21): //LNA1 LNA2
 			pdiv_ant_conf->fast_div_bias = 0x0;
 			break;
 		case (0x23): //LNA1 A+B
 			pdiv_ant_conf->fast_div_bias = 0x6;
 			break;
 		case (0x30): //A+B A-B
 			pdiv_ant_conf->fast_div_bias = 0x1;
 			break;
 		case (0x31): //A+B LNA2
 			pdiv_ant_conf->fast_div_bias = 0x3b;
 			break;
 		case (0x32): //A+B LNA1
 			pdiv_ant_conf->fast_div_bias = 0x3d;
 			break;
 		default:
 			break;
 		}
 	}
 }
 
 /*
  * AR9485/AR933x TODO:
  * + Select a ratio based on whether RSSI is low or not; but I need
  *   to figure out what "low_rssi_th" is sourced from.
  * + What's ath_ant_div_comb_alt_check() in the reference driver do?
  * + .. and there's likely a bunch of other things to include in this.
  */
 
 /* Antenna diversity and combining */
 void
 ath_lna_rx_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs,
     unsigned long ticks, int hz)
 {
 	HAL_ANT_COMB_CONFIG div_ant_conf;
 	struct if_ath_ant_comb_state *antcomb = sc->sc_lna_div;
 	int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
 	int curr_main_set, curr_bias;
 	int main_rssi = rs->rs_rssi_ctl[0];
 	int alt_rssi = rs->rs_rssi_ctl[1];
 	int rx_ant_conf, main_ant_conf, alt_ant_conf;
 	HAL_BOOL short_scan = AH_FALSE;
 
 	rx_ant_conf = (rs->rs_rssi_ctl[2] >> 4) & ATH_ANT_RX_MASK;
 	main_ant_conf = (rs->rs_rssi_ctl[2] >> 2) & ATH_ANT_RX_MASK;
 	alt_ant_conf = (rs->rs_rssi_ctl[2] >> 0) & ATH_ANT_RX_MASK;
 
 #if 0
 	DPRINTF(sc, ATH_DEBUG_DIVERSITY,
 	    "%s: RSSI %d/%d, conf %x/%x, rxconf %x, LNA: %d; ANT: %d; "
 	    "FastDiv: %d\n",
 	    __func__,
 	    main_rssi,
 	    alt_rssi,
 	    main_ant_conf,
 	    alt_ant_conf,
 	    rx_ant_conf,
 	    !!(rs->rs_rssi_ctl[2] & 0x80),
 	    !!(rs->rs_rssi_ctl[2] & 0x40),
 	    !!(rs->rs_rssi_ext[2] & 0x40));
 #endif
 
 	/*
 	 * If LNA diversity combining isn't enabled, don't run this.
 	 */
 	if (! sc->sc_dolnadiv)
 		return;
 
 	/*
 	 * XXX this is ugly, but the HAL code attaches the
 	 * LNA diversity to the TX antenna settings.
 	 * I don't know why.
 	 */
 	if (sc->sc_txantenna != HAL_ANT_VARIABLE)
 		return;
 
 	/* Record packet only when alt_rssi is positive */
 	if (main_rssi > 0 && alt_rssi > 0) {
 		antcomb->total_pkt_count++;
 		antcomb->main_total_rssi += main_rssi;
 		antcomb->alt_total_rssi  += alt_rssi;
 		if (main_ant_conf == rx_ant_conf)
 			antcomb->main_recv_cnt++;
 		else
 			antcomb->alt_recv_cnt++;
 	}
 
 	/* Short scan check */
 	if (antcomb->scan && antcomb->alt_good) {
 		if (ieee80211_time_after(ticks, antcomb->scan_start_time +
 		    msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
 			short_scan = AH_TRUE;
 		else
 			if (antcomb->total_pkt_count ==
 			    ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
 				alt_ratio = ((antcomb->alt_recv_cnt * 100) /
 					    antcomb->total_pkt_count);
 				if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
 					short_scan = AH_TRUE;
 			}
 	}
 
 #if 0
 	DPRINTF(sc, ATH_DEBUG_DIVERSITY,
 	    "%s: total pkt=%d, aggr=%d, short_scan=%d\n",
 	    __func__,
 	    antcomb->total_pkt_count,
 	    !! (rs->rs_moreaggr),
 	    !! (short_scan));
 #endif
 
 	if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) ||
 	    rs->rs_moreaggr) && !short_scan)
 		return;
 
 	if (antcomb->total_pkt_count) {
 		alt_ratio = ((antcomb->alt_recv_cnt * 100) /
 			     antcomb->total_pkt_count);
 		main_rssi_avg = (antcomb->main_total_rssi /
 				 antcomb->total_pkt_count);
 		alt_rssi_avg = (antcomb->alt_total_rssi /
 				 antcomb->total_pkt_count);
 	}
 
 	OS_MEMZERO(&div_ant_conf, sizeof(div_ant_conf));
 
 	ath_hal_div_comb_conf_get(sc->sc_ah, &div_ant_conf);
 	curr_alt_set = div_ant_conf.alt_lna_conf;
 	curr_main_set = div_ant_conf.main_lna_conf;
 	curr_bias = div_ant_conf.fast_div_bias;
 
 	antcomb->count++;
 
 	if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) {
 		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
 			ath_lnaconf_alt_good_scan(antcomb, &div_ant_conf,
 						  main_rssi_avg);
 			antcomb->alt_good = AH_TRUE;
 		} else {
 			antcomb->alt_good = AH_FALSE;
 		}
 
 		antcomb->count = 0;
 		antcomb->scan = AH_TRUE;
 		antcomb->scan_not_start = AH_TRUE;
 	}
 
 	if (!antcomb->scan) {
 		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
 			if (curr_alt_set == HAL_ANT_DIV_COMB_LNA2) {
 				/* Switch main and alt LNA */
 				div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 				div_ant_conf.alt_lna_conf  =
 						HAL_ANT_DIV_COMB_LNA1;
 			} else if (curr_alt_set == HAL_ANT_DIV_COMB_LNA1) {
 				div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 				div_ant_conf.alt_lna_conf  =
 						HAL_ANT_DIV_COMB_LNA2;
 			}
 
 			goto div_comb_done;
 		} else if ((curr_alt_set != HAL_ANT_DIV_COMB_LNA1) &&
 			   (curr_alt_set != HAL_ANT_DIV_COMB_LNA2)) {
 			/* Set alt to another LNA */
 			if (curr_main_set == HAL_ANT_DIV_COMB_LNA2)
 				div_ant_conf.alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 			else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1)
 				div_ant_conf.alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 
 			goto div_comb_done;
 		}
 
 		if ((alt_rssi_avg < (main_rssi_avg +
 		    antcomb->lna1_lna2_delta)))
 			goto div_comb_done;
 	}
 
 	if (!antcomb->scan_not_start) {
 		switch (curr_alt_set) {
 		case HAL_ANT_DIV_COMB_LNA2:
 			antcomb->rssi_lna2 = alt_rssi_avg;
 			antcomb->rssi_lna1 = main_rssi_avg;
 			antcomb->scan = AH_TRUE;
 			/* set to A+B */
 			div_ant_conf.main_lna_conf =
 				HAL_ANT_DIV_COMB_LNA1;
 			div_ant_conf.alt_lna_conf  =
 				HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 			break;
 		case HAL_ANT_DIV_COMB_LNA1:
 			antcomb->rssi_lna1 = alt_rssi_avg;
 			antcomb->rssi_lna2 = main_rssi_avg;
 			antcomb->scan = AH_TRUE;
 			/* set to A+B */
 			div_ant_conf.main_lna_conf = HAL_ANT_DIV_COMB_LNA2;
 			div_ant_conf.alt_lna_conf  =
 				HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 			break;
 		case HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2:
 			antcomb->rssi_add = alt_rssi_avg;
 			antcomb->scan = AH_TRUE;
 			/* set to A-B */
 			div_ant_conf.alt_lna_conf =
 				HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 			break;
 		case HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2:
 			antcomb->rssi_sub = alt_rssi_avg;
 			antcomb->scan = AH_FALSE;
 			if (antcomb->rssi_lna2 >
 			    (antcomb->rssi_lna1 +
 			    ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) {
 				/* use LNA2 as main LNA */
 				if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
 				    (antcomb->rssi_add > antcomb->rssi_sub)) {
 					/* set to A+B */
 					div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 					div_ant_conf.alt_lna_conf  =
 						HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 				} else if (antcomb->rssi_sub >
 					   antcomb->rssi_lna1) {
 					/* set to A-B */
 					div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 					div_ant_conf.alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 				} else {
 					/* set to LNA1 */
 					div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 					div_ant_conf.alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 				}
 			} else {
 				/* use LNA1 as main LNA */
 				if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
 				    (antcomb->rssi_add > antcomb->rssi_sub)) {
 					/* set to A+B */
 					div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 					div_ant_conf.alt_lna_conf  =
 						HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 				} else if (antcomb->rssi_sub >
 					   antcomb->rssi_lna1) {
 					/* set to A-B */
 					div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 					div_ant_conf.alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 				} else {
 					/* set to LNA2 */
 					div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 					div_ant_conf.alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 				}
 			}
 			break;
 		default:
 			break;
 		}
 	} else {
 		if (!antcomb->alt_good) {
 			antcomb->scan_not_start = AH_FALSE;
 			/* Set alt to another LNA */
 			if (curr_main_set == HAL_ANT_DIV_COMB_LNA2) {
 				div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 				div_ant_conf.alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 			} else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1) {
 				div_ant_conf.main_lna_conf =
 						HAL_ANT_DIV_COMB_LNA1;
 				div_ant_conf.alt_lna_conf =
 						HAL_ANT_DIV_COMB_LNA2;
 			}
 			goto div_comb_done;
 		}
 	}
 
 	ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
 					   main_rssi_avg, alt_rssi_avg,
 					   alt_ratio);
 
 	antcomb->quick_scan_cnt++;
 
 div_comb_done:
 #if 0
 	ath_ant_div_conf_fast_divbias(&div_ant_conf);
 #endif
 
 	ath_ant_adjust_fast_divbias(antcomb,
 	    alt_ratio,
 	    ATH_ANT_DIV_COMB_ALT_ANT_RATIO,
 	    div_ant_conf.antdiv_configgroup,
 	    &div_ant_conf);
 
 	ath_hal_div_comb_conf_set(sc->sc_ah, &div_ant_conf);
 
 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: total_pkt_count=%d\n",
 	   __func__, antcomb->total_pkt_count);
 
 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_total_rssi=%d\n",
 	   __func__, antcomb->main_total_rssi);
 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_total_rssi=%d\n",
 	   __func__, antcomb->alt_total_rssi);
 
 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_rssi_avg=%d\n",
 	   __func__, main_rssi_avg);
 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_alt_rssi_avg=%d\n",
 	   __func__, alt_rssi_avg);
 
 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_recv_cnt=%d\n",
 	   __func__, antcomb->main_recv_cnt);
 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_recv_cnt=%d\n",
 	   __func__, antcomb->alt_recv_cnt);
 
 //	if (curr_alt_set != div_ant_conf.alt_lna_conf)
 		DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: lna_conf: %x -> %x\n",
 		    __func__, curr_alt_set, div_ant_conf.alt_lna_conf);
 //	if (curr_main_set != div_ant_conf.main_lna_conf)
 		DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_lna_conf: %x -> %x\n",
 		    __func__, curr_main_set, div_ant_conf.main_lna_conf);
 //	if (curr_bias != div_ant_conf.fast_div_bias)
 		DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: fast_div_bias: %x -> %x\n",
 		    __func__, curr_bias, div_ant_conf.fast_div_bias);
 
 	antcomb->scan_start_time = ticks;
 	antcomb->total_pkt_count = 0;
 	antcomb->main_total_rssi = 0;
 	antcomb->alt_total_rssi = 0;
 	antcomb->main_recv_cnt = 0;
 	antcomb->alt_recv_cnt = 0;
 }
diff --git a/sys/dev/ath/if_ath_pci.c b/sys/dev/ath/if_ath_pci.c
index 95e3715dda2b..6e332b6c0c3b 100644
--- a/sys/dev/ath/if_ath_pci.c
+++ b/sys/dev/ath/if_ath_pci.c
@@ -1,396 +1,391 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer,
  *    without modification.
  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
  *    redistribution must be conditioned upon including a substantially
  *    similar Disclaimer requirement for further binary redistribution.
  *
  * NO WARRANTY
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGES.
  */
 
 #include <sys/cdefs.h>
 /*
  * PCI/Cardbus front-end for the Atheros Wireless LAN controller driver.
  */
 #include "opt_ath.h"
 
 #include <sys/param.h>
 #include <sys/systm.h> 
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/errno.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
 #include <sys/bus.h>
 #include <sys/rman.h>
 
 #include <sys/socket.h>
 
 #include <net/if.h>
 #include <net/if_media.h>
 #include <net/if_arp.h>
 #include <net/ethernet.h>
 
 #include <net80211/ieee80211_var.h>
 
 #include <dev/ath/if_athvar.h>
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
 
 /* For EEPROM firmware */
 #ifdef	ATH_EEPROM_FIRMWARE
 #include <sys/linker.h>
 #include <sys/firmware.h>
 #endif	/* ATH_EEPROM_FIRMWARE */
 
 /*
  * PCI glue.
  */
 
 struct ath_pci_softc {
 	struct ath_softc	sc_sc;
 	struct resource		*sc_sr;		/* memory resource */
 	struct resource		*sc_irq;	/* irq resource */
 	void			*sc_ih;		/* interrupt handler */
 };
 
 #define	PCI_VDEVICE(v, d)			\
 	PCI_DEV(v,d)
 
 #define	PCI_DEVICE_SUB(v, d, sv, sd)		\
 	PCI_DEV(v, d), PCI_SUBDEV(sv, sd)
 
 #define	PCI_VENDOR_ID_ATHEROS		0x168c
 #define	PCI_VENDOR_ID_SAMSUNG		0x144d
 #define	PCI_VENDOR_ID_AZWAVE		0x1a3b
 #define	PCI_VENDOR_ID_FOXCONN		0x105b
 #define	PCI_VENDOR_ID_ATTANSIC		0x1969
 #define	PCI_VENDOR_ID_ASUSTEK		0x1043
 #define	PCI_VENDOR_ID_DELL		0x1028
 #define	PCI_VENDOR_ID_QMI		0x1a32
 #define	PCI_VENDOR_ID_LENOVO		0x17aa
 #define	PCI_VENDOR_ID_HP		0x103c
 
 #include "if_ath_pci_devlist.h"
 
 #define	BS_BAR	0x10
 #define	PCIR_RETRY_TIMEOUT	0x41
 #define	PCIR_CFG_PMCSR		0x48
 
 #define	DEFAULT_CACHESIZE	32
 
 static void
 ath_pci_setup(device_t dev)
 {
 	uint8_t cz;
 
 	/* XXX TODO: need to override the _system_ saved copies of this */
 
 	/*
 	 * If the cache line size is 0, force it to a reasonable
 	 * value.
 	 */
 	cz = pci_read_config(dev, PCIR_CACHELNSZ, 1);
 	if (cz == 0) {
 		pci_write_config(dev, PCIR_CACHELNSZ,
 		    DEFAULT_CACHESIZE / 4, 1);
 	}
 
 	/* Override the system latency timer */
 	pci_write_config(dev, PCIR_LATTIMER, 0xa8, 1);
 
 	/* If a PCI NIC, force wakeup */
 #ifdef	ATH_PCI_WAKEUP_WAR
 	/* XXX TODO: don't do this for non-PCI (ie, PCIe, Cardbus!) */
 	if (1) {
 		uint16_t pmcsr;
 		pmcsr = pci_read_config(dev, PCIR_CFG_PMCSR, 2);
 		pmcsr |= 3;
 		pci_write_config(dev, PCIR_CFG_PMCSR, pmcsr, 2);
 		pmcsr &= ~3;
 		pci_write_config(dev, PCIR_CFG_PMCSR, pmcsr, 2);
 	}
 #endif
 
 	/*
 	 * Disable retry timeout to keep PCI Tx retries from
 	 * interfering with C3 CPU state.
 	 */
 	pci_write_config(dev, PCIR_RETRY_TIMEOUT, 0, 1);
 }
 
 static int
 ath_pci_probe(device_t dev)
 {
 	const char* devname;
 
 	devname = ath_hal_probe(pci_get_vendor(dev), pci_get_device(dev));
 	if (devname != NULL) {
 		device_set_desc(dev, devname);
 		return BUS_PROBE_DEFAULT;
 	}
 	return ENXIO;
 }
 
 static int
 ath_pci_attach(device_t dev)
 {
 	struct ath_pci_softc *psc = device_get_softc(dev);
 	struct ath_softc *sc = &psc->sc_sc;
 	int error = ENXIO;
 	int rid;
 #ifdef	ATH_EEPROM_FIRMWARE
 	const struct firmware *fw = NULL;
 	const char *buf;
 #endif
 	const struct pci_device_table *pd;
 
 	sc->sc_dev = dev;
 
 	/* Do this lookup anyway; figure out what to do with it later */
 	pd = PCI_MATCH(dev, ath_pci_id_table);
 	if (pd)
 		sc->sc_pci_devinfo = pd->driver_data;
 
 	/*
 	 * Enable bus mastering.
 	 */
 	pci_enable_busmaster(dev);
 
 	/*
 	 * Setup other PCI bus configuration parameters.
 	 */
 	ath_pci_setup(dev);
 
 	/* 
 	 * Setup memory-mapping of PCI registers.
 	 */
 	rid = BS_BAR;
 	psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
 					    RF_ACTIVE);
 	if (psc->sc_sr == NULL) {
 		device_printf(dev, "cannot map register space\n");
 		goto bad;
 	}
 	sc->sc_st = (HAL_BUS_TAG) rman_get_bustag(psc->sc_sr);
 	sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr);
 	/*
 	 * Mark device invalid so any interrupts (shared or otherwise)
 	 * that arrive before the HAL is setup are discarded.
 	 */
 	sc->sc_invalid = 1;
 
 	ATH_LOCK_INIT(sc);
 	ATH_PCU_LOCK_INIT(sc);
 	ATH_RX_LOCK_INIT(sc);
 	ATH_TX_LOCK_INIT(sc);
 	ATH_TXSTATUS_LOCK_INIT(sc);
 
 	/*
 	 * Arrange interrupt line.
 	 */
 	rid = 0;
 	psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
 					     RF_SHAREABLE|RF_ACTIVE);
 	if (psc->sc_irq == NULL) {
 		device_printf(dev, "could not map interrupt\n");
 		goto bad1;
 	}
 	if (bus_setup_intr(dev, psc->sc_irq,
 			   INTR_TYPE_NET | INTR_MPSAFE,
 			   NULL, ath_intr, sc, &psc->sc_ih)) {
 		device_printf(dev, "could not establish interrupt\n");
 		goto bad2;
 	}
 
 	/*
 	 * Setup DMA descriptor area.
 	 */
 	if (bus_dma_tag_create(bus_get_dma_tag(dev),	/* parent */
 			       1, 0,			/* alignment, bounds */
 			       BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
 			       BUS_SPACE_MAXADDR,	/* highaddr */
 			       NULL, NULL,		/* filter, filterarg */
 			       0x3ffff,			/* maxsize XXX */
 			       ATH_MAX_SCATTER,		/* nsegments */
 			       0x3ffff,			/* maxsegsize XXX */
 			       BUS_DMA_ALLOCNOW,	/* flags */
 			       NULL,			/* lockfunc */
 			       NULL,			/* lockarg */
 			       &sc->sc_dmat)) {
 		device_printf(dev, "cannot allocate DMA tag\n");
 		goto bad3;
 	}
 
 #ifdef	ATH_EEPROM_FIRMWARE
 	/*
 	 * If there's an EEPROM firmware image, load that in.
 	 */
 	if (resource_string_value(device_get_name(dev), device_get_unit(dev),
 	    "eeprom_firmware", &buf) == 0) {
 		if (bootverbose)
 			device_printf(dev, "%s: looking up firmware @ '%s'\n",
 			    __func__, buf);
 
 		fw = firmware_get(buf);
 		if (fw == NULL) {
 			device_printf(dev, "%s: couldn't find firmware\n",
 			    __func__);
 			goto bad4;
 		}
 
 		device_printf(dev, "%s: EEPROM firmware @ %p\n",
 		    __func__, fw->data);
 		sc->sc_eepromdata =
 		    malloc(fw->datasize, M_TEMP, M_WAITOK | M_ZERO);
-		if (! sc->sc_eepromdata) {
-			device_printf(dev, "%s: can't malloc eepromdata\n",
-			    __func__);
-			goto bad4;
-		}
 		memcpy(sc->sc_eepromdata, fw->data, fw->datasize);
 		firmware_put(fw, 0);
 	}
 #endif /* ATH_EEPROM_FIRMWARE */
 
 	error = ath_attach(pci_get_device(dev), sc);
 	if (error == 0)					/* success */
 		return 0;
 
 #ifdef	ATH_EEPROM_FIRMWARE
 bad4:
 #endif
 	bus_dma_tag_destroy(sc->sc_dmat);
 bad3:
 	bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
 bad2:
 	bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
 bad1:
 	bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, psc->sc_sr);
 
 	ATH_TXSTATUS_LOCK_DESTROY(sc);
 	ATH_PCU_LOCK_DESTROY(sc);
 	ATH_RX_LOCK_DESTROY(sc);
 	ATH_TX_LOCK_DESTROY(sc);
 	ATH_LOCK_DESTROY(sc);
 
 bad:
 	return (error);
 }
 
 static int
 ath_pci_detach(device_t dev)
 {
 	struct ath_pci_softc *psc = device_get_softc(dev);
 	struct ath_softc *sc = &psc->sc_sc;
 
 	/* check if device was removed */
 	sc->sc_invalid = !bus_child_present(dev);
 
 	/*
 	 * Do a config read to clear pre-existing pci error status.
 	 */
 	(void) pci_read_config(dev, PCIR_COMMAND, 4);
 
 	ath_detach(sc);
 
 	bus_generic_detach(dev);
 	bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
 	bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
 
 	bus_dma_tag_destroy(sc->sc_dmat);
 	bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, psc->sc_sr);
 
 	if (sc->sc_eepromdata)
 		free(sc->sc_eepromdata, M_TEMP);
 
 	ATH_TXSTATUS_LOCK_DESTROY(sc);
 	ATH_PCU_LOCK_DESTROY(sc);
 	ATH_RX_LOCK_DESTROY(sc);
 	ATH_TX_LOCK_DESTROY(sc);
 	ATH_LOCK_DESTROY(sc);
 
 	return (0);
 }
 
 static int
 ath_pci_shutdown(device_t dev)
 {
 	struct ath_pci_softc *psc = device_get_softc(dev);
 
 	ath_shutdown(&psc->sc_sc);
 	return (0);
 }
 
 static int
 ath_pci_suspend(device_t dev)
 {
 	struct ath_pci_softc *psc = device_get_softc(dev);
 
 	ath_suspend(&psc->sc_sc);
 
 	return (0);
 }
 
 static int
 ath_pci_resume(device_t dev)
 {
 	struct ath_pci_softc *psc = device_get_softc(dev);
 
 	/*
 	 * Suspend/resume resets the PCI configuration space.
 	 */
 	ath_pci_setup(dev);
 
 	ath_resume(&psc->sc_sc);
 
 	return (0);
 }
 
 static device_method_t ath_pci_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		ath_pci_probe),
 	DEVMETHOD(device_attach,	ath_pci_attach),
 	DEVMETHOD(device_detach,	ath_pci_detach),
 	DEVMETHOD(device_shutdown,	ath_pci_shutdown),
 	DEVMETHOD(device_suspend,	ath_pci_suspend),
 	DEVMETHOD(device_resume,	ath_pci_resume),
 	{ 0,0 }
 };
 static driver_t ath_pci_driver = {
 	"ath",
 	ath_pci_methods,
 	sizeof (struct ath_pci_softc)
 };
 static	devclass_t ath_devclass;
 DRIVER_MODULE(if_ath_pci, pci, ath_pci_driver, ath_devclass, 0, 0);
 MODULE_VERSION(if_ath_pci, 1);
 MODULE_DEPEND(if_ath_pci, wlan, 1, 1, 1);		/* 802.11 media layer */
 MODULE_DEPEND(if_ath_pci, ath_main, 1, 1, 1);	/* if_ath driver */
 MODULE_DEPEND(if_ath_pci, ath_hal, 1, 1, 1);	/* ath HAL */
diff --git a/sys/dev/ath/if_ath_spectral.c b/sys/dev/ath/if_ath_spectral.c
index 58f21b526e93..951d66605981 100644
--- a/sys/dev/ath/if_ath_spectral.c
+++ b/sys/dev/ath/if_ath_spectral.c
@@ -1,297 +1,290 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
  * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer,
  *    without modification.
  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
  *    redistribution must be conditioned upon including a substantially
  *    similar Disclaimer requirement for further binary redistribution.
  *
  * NO WARRANTY
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGES.
  */
 #include <sys/cdefs.h>
 /*
  * Implement some basic spectral scan control logic.
  */
 #include "opt_ath.h"
 #include "opt_inet.h"
 #include "opt_wlan.h"
 
 #include <sys/param.h>
 #include <sys/systm.h> 
 #include <sys/sysctl.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/errno.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
 #include <sys/bus.h>
 
 #include <sys/socket.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
 #include <net/if_media.h>
 #include <net/if_arp.h>
 #include <net/ethernet.h>		/* XXX for ether_sprintf */
 
 #include <net80211/ieee80211_var.h>
 
 #include <net/bpf.h>
 
 #ifdef INET
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 #endif
 
 #include <dev/ath/if_athvar.h>
 #include <dev/ath/if_ath_spectral.h>
 #include <dev/ath/if_ath_misc.h>
 
 #include <dev/ath/ath_hal/ah_desc.h>
 
 struct ath_spectral_state {
 	HAL_SPECTRAL_PARAM	spectral_state;
 
 	/*
 	 * Should we enable spectral scan upon
 	 * each network interface reset/change?
 	 *
 	 * This is intended to allow spectral scan
 	 * frame reporting during channel scans.
 	 *
 	 * Later on it can morph into a larger
 	 * scale config method where it pushes
 	 * a "channel scan" config into the hardware
 	 * rather than just the spectral_state
 	 * config.
 	 */
 	int spectral_enable_after_reset;
 };
 
 /*
  * Methods which are required
  */
 
 /*
  * Attach spectral to the given interface
  */
 int
 ath_spectral_attach(struct ath_softc *sc)
 {
 	struct ath_spectral_state *ss;
 
 	/*
 	 * If spectral isn't supported, don't error - just
 	 * quietly complete.
 	 */
 	if (! ath_hal_spectral_supported(sc->sc_ah))
 		return (0);
 
 	ss = malloc(sizeof(struct ath_spectral_state),
 	    M_TEMP, M_WAITOK | M_ZERO);
-
-	if (ss == NULL) {
-		device_printf(sc->sc_dev, "%s: failed to alloc memory\n",
-		    __func__);
-		return (-ENOMEM);
-	}
-
 	sc->sc_spectral = ss;
 
 	(void) ath_hal_spectral_get_config(sc->sc_ah, &ss->spectral_state);
 
 	return (0);
 }
 
 /*
  * Detach spectral from the given interface
  */
 int
 ath_spectral_detach(struct ath_softc *sc)
 {
 
 	if (! ath_hal_spectral_supported(sc->sc_ah))
 		return (0);
 
 	if (sc->sc_spectral != NULL) {
 		free(sc->sc_spectral, M_TEMP);
 	}
 	return (0);
 }
 
 /*
  * Check whether spectral needs enabling and if so,
  * flip it on.
  */
 int
 ath_spectral_enable(struct ath_softc *sc, struct ieee80211_channel *ch)
 {
 	struct ath_spectral_state *ss = sc->sc_spectral;
 
 	/* Default to disable spectral PHY reporting */
 	sc->sc_dospectral = 0;
 
 	if (ss == NULL)
 		return (0);
 
 	if (ss->spectral_enable_after_reset) {
 		ath_hal_spectral_configure(sc->sc_ah,
 		    &ss->spectral_state);
 		(void) ath_hal_spectral_start(sc->sc_ah);
 		sc->sc_dospectral = 1;
 	}
 	return (0);
 }
 
 /*
  * Handle ioctl requests from the diagnostic interface.
  *
  * The initial part of this code resembles ath_ioctl_diag();
  * it's likely a good idea to reduce duplication between
  * these two routines.
  */
 int
 ath_ioctl_spectral(struct ath_softc *sc, struct ath_diag *ad)
 {
 	unsigned int id = ad->ad_id & ATH_DIAG_ID;
 	void *indata = NULL;
 	void *outdata = NULL;
 	u_int32_t insize = ad->ad_in_size;
 	u_int32_t outsize = ad->ad_out_size;
 	int error = 0;
 	HAL_SPECTRAL_PARAM peout;
 	HAL_SPECTRAL_PARAM *pe;
 	struct ath_spectral_state *ss = sc->sc_spectral;
 	int val;
 
 	if (! ath_hal_spectral_supported(sc->sc_ah))
 		return (EINVAL);
 
 	ATH_LOCK(sc);
 	ath_power_set_power_state(sc, HAL_PM_AWAKE);
 	ATH_UNLOCK(sc);
 
 	if (ad->ad_id & ATH_DIAG_IN) {
 		/*
 		 * Copy in data.
 		 */
 		indata = malloc(insize, M_TEMP, M_NOWAIT);
 		if (indata == NULL) {
 			error = ENOMEM;
 			goto bad;
 		}
 		error = copyin(ad->ad_in_data, indata, insize);
 		if (error)
 			goto bad;
 	}
 	if (ad->ad_id & ATH_DIAG_DYN) {
 		/*
 		 * Allocate a buffer for the results (otherwise the HAL
 		 * returns a pointer to a buffer where we can read the
 		 * results).  Note that we depend on the HAL leaving this
 		 * pointer for us to use below in reclaiming the buffer;
 		 * may want to be more defensive.
 		 */
 		outdata = malloc(outsize, M_TEMP, M_NOWAIT | M_ZERO);
 		if (outdata == NULL) {
 			error = ENOMEM;
 			goto bad;
 		}
 	}
 	switch (id) {
 		case SPECTRAL_CONTROL_GET_PARAMS:
 			memset(&peout, 0, sizeof(peout));
 			outsize = sizeof(HAL_SPECTRAL_PARAM);
 			ath_hal_spectral_get_config(sc->sc_ah, &peout);
 			pe = (HAL_SPECTRAL_PARAM *) outdata;
 			memcpy(pe, &peout, sizeof(*pe));
 			break;
 		case SPECTRAL_CONTROL_SET_PARAMS:
 			if (insize < sizeof(HAL_SPECTRAL_PARAM)) {
 				error = EINVAL;
 				break;
 			}
 			pe = (HAL_SPECTRAL_PARAM *) indata;
 			ath_hal_spectral_configure(sc->sc_ah, pe);
 			/* Save a local copy of the updated parameters */
 			ath_hal_spectral_get_config(sc->sc_ah,
 			    &ss->spectral_state);
 			break;
 		case SPECTRAL_CONTROL_START:
 			ath_hal_spectral_configure(sc->sc_ah,
 			    &ss->spectral_state);
 			(void) ath_hal_spectral_start(sc->sc_ah);
 			sc->sc_dospectral = 1;
 			/* XXX need to update the PHY mask in the driver */
 			break;
 		case SPECTRAL_CONTROL_STOP:
 			(void) ath_hal_spectral_stop(sc->sc_ah);
 			sc->sc_dospectral = 0;
 			/* XXX need to update the PHY mask in the driver */
 			break;
 		case SPECTRAL_CONTROL_ENABLE_AT_RESET:
 			if (insize < sizeof(int)) {
 				device_printf(sc->sc_dev, "%d != %d\n",
 				    insize,
 				    (int) sizeof(int));
 				error = EINVAL;
 				break;
 			}
 			if (indata == NULL) {
 				device_printf(sc->sc_dev, "indata=NULL\n");
 				error = EINVAL;
 				break;
 			}
 			val = * ((int *) indata);
 			if (val == 0)
 				ss->spectral_enable_after_reset = 0;
 			else
 				ss->spectral_enable_after_reset = 1;
 			break;
 		case SPECTRAL_CONTROL_ENABLE:
 			/* XXX TODO */
 		case SPECTRAL_CONTROL_DISABLE:
 			/* XXX TODO */
 		break;
 		default:
 			error = EINVAL;
 			goto bad;
 	}
 	if (outsize < ad->ad_out_size)
 		ad->ad_out_size = outsize;
 	if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size))
 		error = EFAULT;
 bad:
 	if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
 		free(indata, M_TEMP);
 	if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
 		free(outdata, M_TEMP);
 	ATH_LOCK(sc);
 	ath_power_restore_power_state(sc);
 	ATH_UNLOCK(sc);
 
 	return (error);
 }