[Madwifi-cvs] revision 2466 committed
Status: Beta
Brought to you by:
otaku
From: Michael T. <svn...@ma...> - 2007-06-15 23:56:40
|
Project : madwifi Revision : 2466 Author : mtaylor (Michael Taylor) Date : 2007-06-16 01:56:35 +0200 (Sat, 16 Jun 2007) Log Message : Patch 1370. Improved locking of atheros driver - esp against races between running driver and external requests, and concurrent external requests. Affected Files: * trunk/ath/if_ath.c updated * trunk/ath/if_athvar.h updated Modified: trunk/ath/if_ath.c =================================================================== --- trunk/ath/if_ath.c 2007-06-15 23:13:27 UTC (rev 2465) +++ trunk/ath/if_ath.c 2007-06-15 23:56:35 UTC (rev 2466) @@ -1831,7 +1831,7 @@ HAL_STATUS status; int error = 0; - ATH_LOCK(sc); + ATH_LOCK_IRQ(sc); DPRINTF(sc, ATH_DEBUG_RESET, "%s: mode %d\n", __func__, ic->ic_opmode); @@ -1931,7 +1931,7 @@ #endif done: - ATH_UNLOCK(sc); + ATH_UNLOCK_IRQ(sc); return error; } @@ -2009,7 +2009,7 @@ struct ath_softc *sc = dev->priv; int error; - ATH_LOCK(sc); + ATH_LOCK_IRQ(sc); if (!sc->sc_invalid) ath_hal_setpower(sc->sc_ah, HAL_PM_AWAKE, AH_TRUE); @@ -2030,7 +2030,7 @@ ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP); } #endif - ATH_UNLOCK(sc); + ATH_UNLOCK_IRQ(sc); return error; } @@ -9048,7 +9048,7 @@ mac->sa_data[0], mac->sa_data[1], mac->sa_data[2], mac->sa_data[3], mac->sa_data[4], mac->sa_data[5]); - ATH_LOCK(sc); + ATH_LOCK_IRQ(sc); /* XXX not right for multiple VAPs */ IEEE80211_ADDR_COPY(ic->ic_myaddr, mac->sa_data); IEEE80211_ADDR_COPY(dev->dev_addr, mac->sa_data); @@ -9056,7 +9056,7 @@ if ((dev->flags & IFF_RUNNING) && !sc->sc_invalid) { error = ath_reset(dev); } - ATH_UNLOCK(sc); + ATH_UNLOCK_IRQ(sc); return error; } @@ -9074,7 +9074,7 @@ } DPRINTF(sc, ATH_DEBUG_ANY, "%s: %d\n", __func__, mtu); - ATH_LOCK(sc); + ATH_LOCK_IRQ(sc); dev->mtu = mtu; if ((dev->flags & IFF_RUNNING) && !sc->sc_invalid) { /* NB: the rx buffers may need to be reallocated */ @@ -9082,7 +9082,7 @@ error = ath_reset(dev); tasklet_enable(&sc->sc_rxtq); } - ATH_UNLOCK(sc); + ATH_UNLOCK_IRQ(sc); return error; } @@ -9153,39 +9153,44 @@ { struct ath_softc *sc = dev->priv; struct ieee80211com *ic = &sc->sc_ic; - int error; + int error = -EINVAL; - ATH_LOCK(sc); - switch (cmd) { - case SIOCGATHSTATS: - sc->sc_stats.ast_tx_packets = sc->sc_devstats.tx_packets; - sc->sc_stats.ast_rx_packets = sc->sc_devstats.rx_packets; - sc->sc_stats.ast_rx_rssi = ieee80211_getrssi(ic); - if (copy_to_user(ifr->ifr_data, &sc->sc_stats, sizeof (sc->sc_stats))) - error = -EFAULT; - else - error = 0; - break; - case SIOCGATHDIAG: - if (!capable(CAP_NET_ADMIN)) - error = -EPERM; - else - error = ath_ioctl_diag(sc, (struct ath_diag *) ifr); - break; - case SIOCETHTOOL: - if (copy_from_user(&cmd, ifr->ifr_data, sizeof(cmd))) - error = -EFAULT; - else - error = ath_ioctl_ethtool(sc, cmd, ifr->ifr_data); - break; - case SIOC80211IFCREATE: + if(SIOC80211IFCREATE == cmd) { + /* XXX: We cannot currently disable interrupts when + * calling ieee80211_ioctl_create_vap. */ + spin_lock(&sc->sc_lock); error = ieee80211_ioctl_create_vap(ic, ifr, dev); - break; - default: - error = -EINVAL; - break; + spin_unlock(&sc->sc_lock); } - ATH_UNLOCK(sc); + else { + ATH_LOCK_IRQ(sc); + switch (cmd) { + case SIOCGATHSTATS: + sc->sc_stats.ast_tx_packets = sc->sc_devstats.tx_packets; + sc->sc_stats.ast_rx_packets = sc->sc_devstats.rx_packets; + sc->sc_stats.ast_rx_rssi = ieee80211_getrssi(ic); + if (copy_to_user(ifr->ifr_data, &sc->sc_stats, sizeof (sc->sc_stats))) + error = -EFAULT; + else + error = 0; + break; + case SIOCGATHDIAG: + if (!capable(CAP_NET_ADMIN)) + error = -EPERM; + else + error = ath_ioctl_diag(sc, (struct ath_diag *) ifr); + break; + case SIOCETHTOOL: + if (copy_from_user(&cmd, ifr->ifr_data, sizeof(cmd))) + error = -EFAULT; + else + error = ath_ioctl_ethtool(sc, cmd, ifr->ifr_data); + break; + default: + break; + } + ATH_UNLOCK_IRQ(sc); + } return error; } @@ -9233,6 +9238,7 @@ u_int val; int ret; + ATH_LOCK_IRQ(sc); ctl->data = &val; ctl->maxlen = sizeof(val); if (write) { @@ -9282,7 +9288,7 @@ * 2 = antenna port 2 */ if (val > 2) - return -EINVAL; + ret = -EINVAL; else sc->sc_txantenna = val; break; @@ -9294,7 +9300,7 @@ * 2 = antenna port 2 */ if (val > 2) - return -EINVAL; + ret = -EINVAL; else ath_setdefantenna(sc, val); break; @@ -9304,10 +9310,10 @@ * 1 = allow use of diversity */ if (val > 1) - return -EINVAL; + ret = -EINVAL; /* Don't enable diversity if XR is enabled */ if (((!sc->sc_hasdiversity) || (sc->sc_xrtxq != NULL)) && val) - return -EINVAL; + ret = -EINVAL; sc->sc_diversity = val; ath_hal_setdiversity(ah, val); break; @@ -9326,7 +9332,7 @@ ((ic->ic_caps & IEEE80211_C_WME) && !(ic->ic_caps & IEEE80211_C_WME_TKIPMIC) && (ic->ic_flags & IEEE80211_F_WME))) - return -EINVAL; + ret = -EINVAL; ath_hal_settkipmic(ah, val); break; @@ -9353,7 +9359,8 @@ ath_set_ack_bitrate(sc, sc->sc_ackrate); break; default: - return -EINVAL; + ret = -EINVAL; + break; } } } else { @@ -9412,10 +9419,12 @@ val = sc->sc_ackrate; break; default: - return -EINVAL; + ret = -EINVAL; + break; } ret = ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos); } + ATH_UNLOCK_IRQ(sc); return ret; } Modified: trunk/ath/if_athvar.h =================================================================== --- trunk/ath/if_athvar.h 2007-06-15 23:13:27 UTC (rev 2465) +++ trunk/ath/if_athvar.h 2007-06-15 23:56:35 UTC (rev 2466) @@ -526,7 +526,7 @@ struct ieee80211com sc_ic; /* NB: must be first */ struct net_device *sc_dev; void __iomem *sc_iobase; /* address of the device */ - struct semaphore sc_lock; /* dev-level lock */ + spinlock_t sc_lock; /* dev-level lock */ struct net_device_stats sc_devstats; /* device statistics */ struct ath_stats sc_stats; /* private statistics */ int devid; @@ -720,10 +720,16 @@ spin_unlock_irqrestore(&(_sc)->sc_rxbuflock, __rxbuflockflags); /* Protects the device from concurrent accesses */ -#define ATH_LOCK_INIT(_sc) init_MUTEX(&(_sc)->sc_lock) +#define ATH_LOCK_INIT(_sc) spin_lock_init(&(_sc)->sc_lock) #define ATH_LOCK_DESTROY(_sc) -#define ATH_LOCK(_sc) down(&(_sc)->sc_lock) -#define ATH_UNLOCK(_sc) up(&(_sc)->sc_lock) +#define ATH_LOCK_IRQ(_sc) do { \ + unsigned long __lockflags; \ + spin_lock_irqsave(&(_sc)->sc_lock, __lockflags); +#define ATH_UNLOCK_IRQ(_sc) \ + spin_unlock_irqrestore(&(_sc)->sc_lock, __lockflags); \ +} while (0) +#define ATH_UNLOCK_IRQ_EARLY(_sc) \ + spin_unlock_irqrestore(&(_sc)->sc_lock, __lockflags); int ath_attach(u_int16_t, struct net_device *, HAL_BUS_TAG); int ath_detach(struct net_device *); |