From 4c1a6bea7c3705292c9e58b66186252e7371a461 Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 30 Aug 2015 21:54:33 +0000 Subject: [PATCH] Migrate the stats API for iwn(4) into a cdev ioctl, rather than tying into the vap. This allows for possible hardware interaction without needing a vap configured. --- sys/dev/iwn/if_iwn.c | 75 +++++++++++++++++++++++++++++++++----- sys/dev/iwn/if_iwn_ioctl.h | 9 ++++- sys/dev/iwn/if_iwnvar.h | 1 + 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index cfed420ce8dd..53de8e454e2d 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -39,11 +39,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -378,6 +380,19 @@ MODULE_DEPEND(iwn, firmware, 1, 1, 1); MODULE_DEPEND(iwn, pci, 1, 1, 1); MODULE_DEPEND(iwn, wlan, 1, 1, 1); +static d_ioctl_t iwn_cdev_ioctl; +static d_open_t iwn_cdev_open; +static d_close_t iwn_cdev_close; + +static struct cdevsw iwn_cdevsw = { + .d_version = D_VERSION, + .d_flags = 0, + .d_open = iwn_cdev_open, + .d_close = iwn_cdev_close, + .d_ioctl = iwn_cdev_ioctl, + .d_name = "iwn", +}; + static int iwn_probe(device_t dev) { @@ -704,6 +719,15 @@ iwn_attach(device_t dev) if (bootverbose) ieee80211_announce(ic); DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); + + /* Add debug ioctl right at the end */ + sc->sc_cdev = make_dev(&iwn_cdevsw, device_get_unit(dev), + UID_ROOT, GID_WHEEL, 0600, "%s", device_get_nameunit(dev)); + if (sc->sc_cdev == NULL) { + device_printf(dev, "failed to create debug character device\n"); + } else { + sc->sc_cdev->si_drv1 = sc; + } return 0; fail: iwn_detach(dev); @@ -1416,6 +1440,11 @@ iwn_detach(device_t dev) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem), sc->mem); + if (sc->sc_cdev) { + destroy_dev(sc->sc_cdev); + sc->sc_cdev = NULL; + } + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n", __func__); IWN_LOCK_DESTROY(sc); return 0; @@ -4999,18 +5028,37 @@ iwn_watchdog(void *arg) } static int -iwn_ioctl(struct ieee80211com *ic, u_long cmd, void *data) +iwn_cdev_open(struct cdev *dev, int flags, int type, struct thread *td) { - struct ifreq *ifr = data; - struct iwn_softc *sc = ic->ic_softc; - int error = 0; - + + return (0); +} + +static int +iwn_cdev_close(struct cdev *dev, int flags, int type, struct thread *td) +{ + + return (0); +} + +static int +iwn_cdev_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag, + struct thread *td) +{ + int rc; + struct iwn_softc *sc = dev->si_drv1; + struct iwn_ioctl_data *d; + + rc = priv_check(td, PRIV_DRIVER); + if (rc != 0) + return (0); + switch (cmd) { case SIOCGIWNSTATS: + d = (struct iwn_ioctl_data *) data; IWN_LOCK(sc); /* XXX validate permissions/memory/etc? */ - error = copyout(&sc->last_stat, ifr->ifr_data, - sizeof(struct iwn_stats)); + rc = copyout(&sc->last_stat, d->dst_addr, sizeof(struct iwn_stats)); IWN_UNLOCK(sc); break; case SIOCZIWNSTATS: @@ -5019,10 +5067,17 @@ iwn_ioctl(struct ieee80211com *ic, u_long cmd, void *data) IWN_UNLOCK(sc); break; default: - error = ENOTTY; + rc = EINVAL; break; } - return (error); + return (rc); +} + +static int +iwn_ioctl(struct ieee80211com *ic, u_long cmd, void *data) +{ + + return (ENOTTY); } static void @@ -8979,3 +9034,5 @@ iwn_debug_register(struct iwn_softc *sc) DPRINTF(sc, IWN_DEBUG_REGISTER,"%s","\n"); } #endif + + diff --git a/sys/dev/iwn/if_iwn_ioctl.h b/sys/dev/iwn/if_iwn_ioctl.h index 1acf4649e257..c289683ed0e2 100644 --- a/sys/dev/iwn/if_iwn_ioctl.h +++ b/sys/dev/iwn/if_iwn_ioctl.h @@ -18,8 +18,13 @@ #ifndef __IF_IWN_IOCTL_H__ #define __IF_IWN_IOCTL_H__ +struct iwn_ioctl_data { + void *dst_addr; + int dst_len; +}; + /* XXX how should I pick appropriate ioctl numbers? */ -#define SIOCGIWNSTATS _IOWR('i', 145, struct ifreq) -#define SIOCZIWNSTATS _IOWR('i', 146, struct ifreq) +#define SIOCGIWNSTATS _IOWR('f', 145, struct iwn_ioctl_data) +#define SIOCZIWNSTATS _IOWR('f', 146, struct iwn_ioctl_data) #endif /* __IF_IWN_IOCTL_H__ */ diff --git a/sys/dev/iwn/if_iwnvar.h b/sys/dev/iwn/if_iwnvar.h index ed275bf7c4f4..797a21c71caa 100644 --- a/sys/dev/iwn/if_iwnvar.h +++ b/sys/dev/iwn/if_iwnvar.h @@ -235,6 +235,7 @@ struct iwn_vap { struct iwn_softc { device_t sc_dev; int sc_debug; + struct cdev *sc_cdev; struct mtx sc_mtx; struct ieee80211com sc_ic; struct mbufq sc_snd;