xref: /freebsd/sys/dev/ath/ath_dfs/null/dfs_null.c (revision 685dc743)
148237774SAdrian Chadd /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
448237774SAdrian Chadd  * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd
548237774SAdrian Chadd  * All rights reserved.
648237774SAdrian Chadd  *
748237774SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
848237774SAdrian Chadd  * modification, are permitted provided that the following conditions
948237774SAdrian Chadd  * are met:
1048237774SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
1148237774SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
1248237774SAdrian Chadd  *    without modification.
1348237774SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1448237774SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
1548237774SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
1648237774SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
1748237774SAdrian Chadd  *
1848237774SAdrian Chadd  * NO WARRANTY
1948237774SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2048237774SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2148237774SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
2248237774SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
2348237774SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
2448237774SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2548237774SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2648237774SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2748237774SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2848237774SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2948237774SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
3048237774SAdrian Chadd  */
3148237774SAdrian Chadd #include <sys/cdefs.h>
3248237774SAdrian Chadd /*
3348237774SAdrian Chadd  * This implements an empty DFS module.
3448237774SAdrian Chadd  */
35c312fb4aSAdrian Chadd #include "opt_ath.h"
3648237774SAdrian Chadd #include "opt_inet.h"
3748237774SAdrian Chadd #include "opt_wlan.h"
3848237774SAdrian Chadd 
3948237774SAdrian Chadd #include <sys/param.h>
4048237774SAdrian Chadd #include <sys/systm.h>
4148237774SAdrian Chadd #include <sys/sysctl.h>
4248237774SAdrian Chadd #include <sys/kernel.h>
4348237774SAdrian Chadd #include <sys/lock.h>
4476039bc8SGleb Smirnoff #include <sys/malloc.h>
4548237774SAdrian Chadd #include <sys/mutex.h>
4648237774SAdrian Chadd #include <sys/errno.h>
4748237774SAdrian Chadd 
4848237774SAdrian Chadd #include <machine/bus.h>
4948237774SAdrian Chadd #include <machine/resource.h>
5048237774SAdrian Chadd #include <sys/bus.h>
5148237774SAdrian Chadd 
5248237774SAdrian Chadd #include <sys/socket.h>
5348237774SAdrian Chadd 
5448237774SAdrian Chadd #include <net/if.h>
5576039bc8SGleb Smirnoff #include <net/if_var.h>
5648237774SAdrian Chadd #include <net/if_media.h>
5748237774SAdrian Chadd #include <net/if_arp.h>
5848237774SAdrian Chadd #include <net/ethernet.h>		/* XXX for ether_sprintf */
5948237774SAdrian Chadd 
6048237774SAdrian Chadd #include <net80211/ieee80211_var.h>
6148237774SAdrian Chadd 
6248237774SAdrian Chadd #include <net/bpf.h>
6348237774SAdrian Chadd 
6448237774SAdrian Chadd #ifdef INET
6548237774SAdrian Chadd #include <netinet/in.h>
6648237774SAdrian Chadd #include <netinet/if_ether.h>
6748237774SAdrian Chadd #endif
6848237774SAdrian Chadd 
6948237774SAdrian Chadd #include <dev/ath/if_athvar.h>
7048237774SAdrian Chadd #include <dev/ath/if_athdfs.h>
7148237774SAdrian Chadd 
7248237774SAdrian Chadd #include <dev/ath/ath_hal/ah_desc.h>
7348237774SAdrian Chadd 
7448237774SAdrian Chadd /*
7548237774SAdrian Chadd  * Methods which are required
7648237774SAdrian Chadd  */
7748237774SAdrian Chadd 
7848237774SAdrian Chadd /*
7948237774SAdrian Chadd  * Attach DFS to the given interface
8048237774SAdrian Chadd  */
8148237774SAdrian Chadd int
ath_dfs_attach(struct ath_softc * sc)8248237774SAdrian Chadd ath_dfs_attach(struct ath_softc *sc)
8348237774SAdrian Chadd {
84d77363adSAdrian Chadd 	return (1);
8548237774SAdrian Chadd }
8648237774SAdrian Chadd 
8748237774SAdrian Chadd /*
8848237774SAdrian Chadd  * Detach DFS from the given interface
8948237774SAdrian Chadd  */
9048237774SAdrian Chadd int
ath_dfs_detach(struct ath_softc * sc)9148237774SAdrian Chadd ath_dfs_detach(struct ath_softc *sc)
9248237774SAdrian Chadd {
93d77363adSAdrian Chadd 	return (1);
9448237774SAdrian Chadd }
9548237774SAdrian Chadd 
9648237774SAdrian Chadd /*
97d77363adSAdrian Chadd  * Enable radar check.  Return 1 if the driver should
98d77363adSAdrian Chadd  * enable radar PHY errors, or 0 if not.
9948237774SAdrian Chadd  */
100bfa5e927SAdrian Chadd int
ath_dfs_radar_enable(struct ath_softc * sc,struct ieee80211_channel * chan)10148237774SAdrian Chadd ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan)
10248237774SAdrian Chadd {
10341059135SAdrian Chadd #if 1
104ab434358SAdrian Chadd 	HAL_PHYERR_PARAM pe;
105ab434358SAdrian Chadd 
106b7005313SAdrian Chadd 	/* Check if the hardware supports radar reporting */
107b7005313SAdrian Chadd 	/* XXX TODO: migrate HAL_CAP_RADAR/HAL_CAP_AR to somewhere public! */
108b7005313SAdrian Chadd 	if (ath_hal_getcapability(sc->sc_ah,
109b7005313SAdrian Chadd 	    HAL_CAP_PHYDIAG, 0, NULL) != HAL_OK)
110b7005313SAdrian Chadd 		return (0);
111b7005313SAdrian Chadd 
11248237774SAdrian Chadd 	/* Check if the current channel is radar-enabled */
11348237774SAdrian Chadd 	if (! IEEE80211_IS_CHAN_DFS(chan))
114bfa5e927SAdrian Chadd 		return (0);
115bfa5e927SAdrian Chadd 
116b7005313SAdrian Chadd 	/* Fetch the default parameters */
117b7005313SAdrian Chadd 	memset(&pe, '\0', sizeof(pe));
118b7005313SAdrian Chadd 	if (! ath_hal_getdfsdefaultthresh(sc->sc_ah, &pe))
119b7005313SAdrian Chadd 		return (0);
120b7005313SAdrian Chadd 
121ab434358SAdrian Chadd 	/* Enable radar PHY error reporting */
122ab434358SAdrian Chadd 	sc->sc_dodfs = 1;
123ab434358SAdrian Chadd 
124b7005313SAdrian Chadd 	/* Tell the hardware to enable radar reporting */
125ab434358SAdrian Chadd 	pe.pe_enabled = 1;
126ab434358SAdrian Chadd 
127ab434358SAdrian Chadd 	/* Flip on extension channel events only if doing HT40 */
128ab434358SAdrian Chadd 	if (IEEE80211_IS_CHAN_HT40(chan))
129ab434358SAdrian Chadd 		pe.pe_extchannel = 1;
130ab434358SAdrian Chadd 	else
131ab434358SAdrian Chadd 		pe.pe_extchannel = 0;
132ab434358SAdrian Chadd 
133ab434358SAdrian Chadd 	ath_hal_enabledfs(sc->sc_ah, &pe);
134bfa5e927SAdrian Chadd 
135be7f7a95SAdrian Chadd 	/*
136be7f7a95SAdrian Chadd 	 * Disable strong signal fast diversity - needed for
137be7f7a95SAdrian Chadd 	 * AR5212 and similar PHYs for reliable short pulse
138be7f7a95SAdrian Chadd 	 * duration.
139be7f7a95SAdrian Chadd 	 */
140be7f7a95SAdrian Chadd 	(void) ath_hal_setcapability(sc->sc_ah, HAL_CAP_DIVERSITY, 2, 0, NULL);
141be7f7a95SAdrian Chadd 
142bfa5e927SAdrian Chadd 	return (1);
143ab434358SAdrian Chadd #else
144ab434358SAdrian Chadd 	return (0);
145ab434358SAdrian Chadd #endif
14648237774SAdrian Chadd }
14748237774SAdrian Chadd 
14848237774SAdrian Chadd /*
149c9b690d3SAdrian Chadd  * Explicity disable radar reporting.
150c9b690d3SAdrian Chadd  *
151c9b690d3SAdrian Chadd  * Return 0 if it was disabled, < 0 on error.
152c9b690d3SAdrian Chadd  */
153c9b690d3SAdrian Chadd int
ath_dfs_radar_disable(struct ath_softc * sc)154c9b690d3SAdrian Chadd ath_dfs_radar_disable(struct ath_softc *sc)
155c9b690d3SAdrian Chadd {
15641059135SAdrian Chadd #if 1
157c9b690d3SAdrian Chadd 	HAL_PHYERR_PARAM pe;
158c9b690d3SAdrian Chadd 
159c9b690d3SAdrian Chadd 	(void) ath_hal_getdfsthresh(sc->sc_ah, &pe);
160c9b690d3SAdrian Chadd 	pe.pe_enabled = 0;
161c9b690d3SAdrian Chadd 	(void) ath_hal_enabledfs(sc->sc_ah, &pe);
162c9b690d3SAdrian Chadd 	return (0);
163c9b690d3SAdrian Chadd #else
164c9b690d3SAdrian Chadd 	return (0);
165c9b690d3SAdrian Chadd #endif
166c9b690d3SAdrian Chadd }
167c9b690d3SAdrian Chadd 
168c9b690d3SAdrian Chadd /*
16948237774SAdrian Chadd  * Process DFS related PHY errors
170d77363adSAdrian Chadd  *
171d77363adSAdrian Chadd  * The mbuf is not "ours" and if we want a copy, we have
172d77363adSAdrian Chadd  * to take a copy.  It'll be freed after this function returns.
17348237774SAdrian Chadd  */
17448237774SAdrian Chadd void
ath_dfs_process_phy_err(struct ath_softc * sc,struct mbuf * m,uint64_t tsf,struct ath_rx_status * rxstat)175d77363adSAdrian Chadd ath_dfs_process_phy_err(struct ath_softc *sc, struct mbuf *m,
17648237774SAdrian Chadd     uint64_t tsf, struct ath_rx_status *rxstat)
17748237774SAdrian Chadd {
17848237774SAdrian Chadd 
17948237774SAdrian Chadd }
18048237774SAdrian Chadd 
18148237774SAdrian Chadd /*
182f6b6084bSPedro F. Giffuni  * Process the radar events and determine whether a DFS event has occurred.
18348237774SAdrian Chadd  *
18448237774SAdrian Chadd  * This is designed to run outside of the RX processing path.
18548237774SAdrian Chadd  * The RX path will call ath_dfs_tasklet_needed() to see whether
18648237774SAdrian Chadd  * the task/callback running this routine needs to be called.
18748237774SAdrian Chadd  */
18848237774SAdrian Chadd int
ath_dfs_process_radar_event(struct ath_softc * sc,struct ieee80211_channel * chan)18948237774SAdrian Chadd ath_dfs_process_radar_event(struct ath_softc *sc,
19048237774SAdrian Chadd     struct ieee80211_channel *chan)
19148237774SAdrian Chadd {
192d77363adSAdrian Chadd 	return (0);
19348237774SAdrian Chadd }
19448237774SAdrian Chadd 
19548237774SAdrian Chadd /*
19636daf049SEitan Adler  * Determine whether the DFS check task needs to be queued.
19748237774SAdrian Chadd  *
19848237774SAdrian Chadd  * This is called in the RX task when the current batch of packets
19948237774SAdrian Chadd  * have been received. It will return whether there are any radar
20048237774SAdrian Chadd  * events for ath_dfs_process_radar_event() to handle.
20148237774SAdrian Chadd  */
20248237774SAdrian Chadd int
ath_dfs_tasklet_needed(struct ath_softc * sc,struct ieee80211_channel * chan)20348237774SAdrian Chadd ath_dfs_tasklet_needed(struct ath_softc *sc, struct ieee80211_channel *chan)
20448237774SAdrian Chadd {
205d77363adSAdrian Chadd 	return (0);
20648237774SAdrian Chadd }
20748237774SAdrian Chadd 
20848237774SAdrian Chadd /*
209c5f2a23cSAdrian Chadd  * Handle ioctl requests from the diagnostic interface.
210c5f2a23cSAdrian Chadd  *
211c5f2a23cSAdrian Chadd  * The initial part of this code resembles ath_ioctl_diag();
212c5f2a23cSAdrian Chadd  * it's likely a good idea to reduce duplication between
213c5f2a23cSAdrian Chadd  * these two routines.
21448237774SAdrian Chadd  */
21548237774SAdrian Chadd int
ath_ioctl_phyerr(struct ath_softc * sc,struct ath_diag * ad)21648237774SAdrian Chadd ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad)
21748237774SAdrian Chadd {
218c5f2a23cSAdrian Chadd 	unsigned int id = ad->ad_id & ATH_DIAG_ID;
219c5f2a23cSAdrian Chadd 	void *indata = NULL;
220c5f2a23cSAdrian Chadd 	void *outdata = NULL;
221c5f2a23cSAdrian Chadd 	u_int32_t insize = ad->ad_in_size;
222c5f2a23cSAdrian Chadd 	u_int32_t outsize = ad->ad_out_size;
223c5f2a23cSAdrian Chadd 	int error = 0;
224c5f2a23cSAdrian Chadd 	HAL_PHYERR_PARAM peout;
225c5f2a23cSAdrian Chadd 	HAL_PHYERR_PARAM *pe;
226c5f2a23cSAdrian Chadd 
227c5f2a23cSAdrian Chadd 	if (ad->ad_id & ATH_DIAG_IN) {
228c5f2a23cSAdrian Chadd 		/*
229c5f2a23cSAdrian Chadd 		 * Copy in data.
230c5f2a23cSAdrian Chadd 		 */
231c5f2a23cSAdrian Chadd 		indata = malloc(insize, M_TEMP, M_NOWAIT);
232c5f2a23cSAdrian Chadd 		if (indata == NULL) {
233c5f2a23cSAdrian Chadd 			error = ENOMEM;
234c5f2a23cSAdrian Chadd 			goto bad;
235c5f2a23cSAdrian Chadd 		}
236c5f2a23cSAdrian Chadd 		error = copyin(ad->ad_in_data, indata, insize);
237c5f2a23cSAdrian Chadd 		if (error)
238c5f2a23cSAdrian Chadd 			goto bad;
239c5f2a23cSAdrian Chadd 	}
240c5f2a23cSAdrian Chadd 	if (ad->ad_id & ATH_DIAG_DYN) {
241c5f2a23cSAdrian Chadd 		/*
242c5f2a23cSAdrian Chadd 		 * Allocate a buffer for the results (otherwise the HAL
243c5f2a23cSAdrian Chadd 		 * returns a pointer to a buffer where we can read the
244c5f2a23cSAdrian Chadd 		 * results).  Note that we depend on the HAL leaving this
245c5f2a23cSAdrian Chadd 		 * pointer for us to use below in reclaiming the buffer;
246c5f2a23cSAdrian Chadd 		 * may want to be more defensive.
247c5f2a23cSAdrian Chadd 		 */
248c5f2a23cSAdrian Chadd 		outdata = malloc(outsize, M_TEMP, M_NOWAIT);
249c5f2a23cSAdrian Chadd 		if (outdata == NULL) {
250c5f2a23cSAdrian Chadd 			error = ENOMEM;
251c5f2a23cSAdrian Chadd 			goto bad;
252c5f2a23cSAdrian Chadd 		}
253c5f2a23cSAdrian Chadd 	}
254c5f2a23cSAdrian Chadd 	switch (id) {
255c5f2a23cSAdrian Chadd 		case DFS_SET_THRESH:
256c5f2a23cSAdrian Chadd 			if (insize < sizeof(HAL_PHYERR_PARAM)) {
25799271119SAdrian Chadd 				error = EINVAL;
258c5f2a23cSAdrian Chadd 				break;
259c5f2a23cSAdrian Chadd 			}
260c5f2a23cSAdrian Chadd 			pe = (HAL_PHYERR_PARAM *) indata;
261c5f2a23cSAdrian Chadd 			ath_hal_enabledfs(sc->sc_ah, pe);
262c5f2a23cSAdrian Chadd 			break;
263c5f2a23cSAdrian Chadd 		case DFS_GET_THRESH:
264c5f2a23cSAdrian Chadd 			memset(&peout, 0, sizeof(peout));
265c5f2a23cSAdrian Chadd 			outsize = sizeof(HAL_PHYERR_PARAM);
266c5f2a23cSAdrian Chadd 			ath_hal_getdfsthresh(sc->sc_ah, &peout);
267c5f2a23cSAdrian Chadd 			pe = (HAL_PHYERR_PARAM *) outdata;
268c5f2a23cSAdrian Chadd 			memcpy(pe, &peout, sizeof(*pe));
269c5f2a23cSAdrian Chadd 			break;
270c5f2a23cSAdrian Chadd 		default:
27199271119SAdrian Chadd 			error = EINVAL;
272c5f2a23cSAdrian Chadd 	}
273c5f2a23cSAdrian Chadd 	if (outsize < ad->ad_out_size)
274c5f2a23cSAdrian Chadd 		ad->ad_out_size = outsize;
275c5f2a23cSAdrian Chadd 	if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size))
27699271119SAdrian Chadd 		error = EFAULT;
277c5f2a23cSAdrian Chadd bad:
278c5f2a23cSAdrian Chadd 	if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
279c5f2a23cSAdrian Chadd 		free(indata, M_TEMP);
280c5f2a23cSAdrian Chadd 	if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
281c5f2a23cSAdrian Chadd 		free(outdata, M_TEMP);
282d77363adSAdrian Chadd 	return (error);
28348237774SAdrian Chadd }
28448237774SAdrian Chadd 
28548237774SAdrian Chadd /*
28648237774SAdrian Chadd  * Get the current DFS thresholds from the HAL
28748237774SAdrian Chadd  */
28848237774SAdrian Chadd int
ath_dfs_get_thresholds(struct ath_softc * sc,HAL_PHYERR_PARAM * param)28948237774SAdrian Chadd ath_dfs_get_thresholds(struct ath_softc *sc, HAL_PHYERR_PARAM *param)
29048237774SAdrian Chadd {
29148237774SAdrian Chadd 	ath_hal_getdfsthresh(sc->sc_ah, param);
292d77363adSAdrian Chadd 	return (1);
29348237774SAdrian Chadd }
294