summaryrefslogtreecommitdiffstats
path: root/sys/dev/firewire/if_fwip.c
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2005-10-01 18:56:19 +0000
committerglebius <glebius@FreeBSD.org>2005-10-01 18:56:19 +0000
commitf41a83bf429b15386f43f43f3f5326d4ece7bfce (patch)
treeb78f9e953b7b58b2789d042cf37cc725045fdcf1 /sys/dev/firewire/if_fwip.c
parent6c6c328bd0bbb1d9f6b3230a33d194bf961b0eae (diff)
downloadFreeBSD-src-f41a83bf429b15386f43f43f3f5326d4ece7bfce.zip
FreeBSD-src-f41a83bf429b15386f43f43f3f5326d4ece7bfce.tar.gz
Big polling(4) cleanup.
o Axe poll in trap. o Axe IFF_POLLING flag from if_flags. o Rework revision 1.21 (Giant removal), in such a way that poll_mtx is not dropped during call to polling handler. This fixes problem with idle polling. o Make registration and deregistration from polling in a functional way, insted of next tick/interrupt. o Obsolete kern.polling.enable. Polling is turned on/off with ifconfig. Detailed kern_poll.c changes: - Remove polling handler flags, introduced in 1.21. The are not needed now. - Forget and do not check if_flags, if_capenable and if_drv_flags. - Call all registered polling handlers unconditionally. - Do not drop poll_mtx, when entering polling handlers. - In ether_poll() NET_LOCK_GIANT prior to locking poll_mtx. - In netisr_poll() axe the block, where polling code asks drivers to unregister. - In netisr_poll() and ether_poll() do polling always, if any handlers are present. - In ether_poll_[de]register() remove a lot of error hiding code. Assert that arguments are correct, instead. - In ether_poll_[de]register() use standard return values in case of error or success. - Introduce poll_switch() that is a sysctl handler for kern.polling.enable. poll_switch() goes through interface list and enabled/disables polling. A message that kern.polling.enable is deprecated is printed. Detailed driver changes: - On attach driver announces IFCAP_POLLING in if_capabilities, but not in if_capenable. - On detach driver calls ether_poll_deregister() if polling is enabled. - In polling handler driver obtains its lock and checks IFF_DRV_RUNNING flag. If there is no, then unlocks and returns. - In ioctl handler driver checks for IFCAP_POLLING flag requested to be set or cleared. Driver first calls ether_poll_[de]register(), then obtains driver lock and [dis/en]ables interrupts. - In interrupt handler driver checks IFCAP_POLLING flag in if_capenable. If present, then returns.This is important to protect from spurious interrupts. Reviewed by: ru, sam, jhb
Diffstat (limited to 'sys/dev/firewire/if_fwip.c')
-rw-r--r--sys/dev/firewire/if_fwip.c78
1 files changed, 47 insertions, 31 deletions
diff --git a/sys/dev/firewire/if_fwip.c b/sys/dev/firewire/if_fwip.c
index 20916bc..b3fdda4 100644
--- a/sys/dev/firewire/if_fwip.c
+++ b/sys/dev/firewire/if_fwip.c
@@ -107,19 +107,6 @@ SYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RW, &rx_queue_len,
TUNABLE_INT("hw.firewire.fwip.rx_queue_len", &rx_queue_len);
#ifdef DEVICE_POLLING
-#define FWIP_POLL_REGISTER(func, fwip, ifp) \
- if (ether_poll_register(func, ifp)) { \
- struct firewire_comm *fc = (fwip)->fd.fc; \
- fc->set_intr(fc, 0); \
- }
-
-#define FWIP_POLL_DEREGISTER(fwip, ifp) \
- do { \
- struct firewire_comm *fc = (fwip)->fd.fc; \
- ether_poll_deregister(ifp); \
- fc->set_intr(fc, 1); \
- } while(0) \
-
static poll_handler_t fwip_poll;
static void
@@ -128,19 +115,15 @@ fwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
struct fwip_softc *fwip;
struct firewire_comm *fc;
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ return;
+
fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
fc = fwip->fd.fc;
- if (cmd == POLL_DEREGISTER) {
- /* enable interrupts */
- fc->set_intr(fc, 1);
- return;
- }
fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count);
}
-#else
-#define FWIP_POLL_REGISTER(func, fwip, ifp)
-#define FWIP_POLL_DEREGISTER(fwip, ifp)
-#endif
+#endif /* DEVICE_POLLING */
+
static void
fwip_identify(driver_t *driver, device_t parent)
{
@@ -214,6 +197,9 @@ fwip_attach(device_t dev)
ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|
IFF_NEEDSGIANT);
ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE;
+#ifdef DEVICE_POLLING
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif
s = splimp();
firewire_ifattach(ifp, hwaddr);
@@ -234,8 +220,6 @@ fwip_stop(struct fwip_softc *fwip)
fc = fwip->fd.fc;
- FWIP_POLL_DEREGISTER(fwip, ifp);
-
if (fwip->dma_ch >= 0) {
xferq = fc->ir[fwip->dma_ch];
@@ -279,14 +263,22 @@ static int
fwip_detach(device_t dev)
{
struct fwip_softc *fwip;
+ struct ifnet *ifp;
int s;
fwip = (struct fwip_softc *)device_get_softc(dev);
+ ifp = fwip->fw_softc.fwip_ifp;
+
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING)
+ ether_poll_deregister(ifp);
+#endif
+
s = splimp();
fwip_stop(fwip);
- firewire_ifdetach(fwip->fw_softc.fwip_ifp);
- if_free(fwip->fw_softc.fwip_ifp);
+ firewire_ifdetach(ifp);
+ if_free(ifp);
splx(s);
return 0;
@@ -408,7 +400,6 @@ found:
ifp->if_flags &= ~IFF_OACTIVE;
#endif
- FWIP_POLL_REGISTER(fwip_poll, fwip, ifp);
#if 0
/* attempt to start output */
fwip_start(ifp);
@@ -444,7 +435,34 @@ fwip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCADDMULTI:
case SIOCDELMULTI:
break;
-
+ case SIOCSIFCAP:
+#ifdef DEVICE_POLLING
+ {
+ struct ifreq *ifr = (struct ifreq *) data;
+ struct firewire_comm *fc = fc = fwip->fd.fc;
+
+ if (ifr->ifr_reqcap & IFCAP_POLLING &&
+ !(ifp->if_capenable & IFCAP_POLLING)) {
+ error = ether_poll_register(fwip_poll, ifp);
+ if (error)
+ return(error);
+ /* Disable interrupts */
+ fc->set_intr(fc, 0);
+ ifp->if_capenable |= IFCAP_POLLING;
+ return (error);
+
+ }
+ if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
+ ifp->if_capenable & IFCAP_POLLING) {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupts. */
+ fc->set_intr(fc, 1);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ return (error);
+ }
+ }
+#endif /* DEVICE_POLLING */
+ break;
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
default:
#else
@@ -757,9 +775,7 @@ fwip_stream_input(struct fw_xferq *xferq)
fwip = (struct fwip_softc *)xferq->sc;
ifp = fwip->fw_softc.fwip_ifp;
-#if 0
- FWIP_POLL_REGISTER(fwip_poll, fwip, ifp);
-#endif
+
while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) {
STAILQ_REMOVE_HEAD(&xferq->stvalid, link);
fp = mtod(sxfer->mbuf, struct fw_pkt *);
OpenPOWER on IntegriCloud