aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2015-07-28 15:05:44 +0100
committerMichael Brown <mcb30@ipxe.org>2015-07-28 15:14:40 +0100
commitb20d4a1522646f71ec22b541d95f9d603760a58d (patch)
tree7b3313e57278b9d0371b011c3218685c2087da12
parent76338543f9e48833e7c634d947a7ae278f38aef9 (diff)
downloadipxe-b20d4a1522646f71ec22b541d95f9d603760a58d.tar.gz
[netdevice] Allow network devices to disclaim IRQ support at runtime
VLAN and 802.11 devices use a network device operations structure that wraps an underlying structure. For example, the vlan_operations structure wraps the network device operations structure of the underlying trunk device. This can cause false positives from the current implementation of netdev_irq_supported(), which will always report that VLAN devices support interrupts since it has no visibility into the support provided by the underlying trunk device. Fix by allowing network devices to explicitly flag that interrupts are not supported, despite the presence of an irq() method. Originally-fixed-by: Wissam Shoukair <wissams@mellanox.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/include/ipxe/netdevice.h11
-rw-r--r--src/net/80211/net80211.c4
-rw-r--r--src/net/vlan.c4
3 files changed, 18 insertions, 1 deletions
diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h
index f20a81f79..a1d207ffc 100644
--- a/src/include/ipxe/netdevice.h
+++ b/src/include/ipxe/netdevice.h
@@ -430,6 +430,14 @@ struct net_device {
/** Network device receive queue processing is frozen */
#define NETDEV_RX_FROZEN 0x0004
+/** Network device interrupts are unsupported
+ *
+ * This flag can be used by a network device to indicate that
+ * interrupts are not supported despite the presence of an irq()
+ * method.
+ */
+#define NETDEV_IRQ_UNSUPPORTED 0x0008
+
/** Link-layer protocol table */
#define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" )
@@ -646,7 +654,8 @@ netdev_is_open ( struct net_device *netdev ) {
*/
static inline __attribute__ (( always_inline )) int
netdev_irq_supported ( struct net_device *netdev ) {
- return ( netdev->op->irq != NULL );
+ return ( ( netdev->op->irq != NULL ) &&
+ ! ( netdev->state & NETDEV_IRQ_UNSUPPORTED ) );
}
/**
diff --git a/src/net/80211/net80211.c b/src/net/80211/net80211.c
index 00794592e..d4970ad5c 100644
--- a/src/net/80211/net80211.c
+++ b/src/net/80211/net80211.c
@@ -805,6 +805,10 @@ int net80211_register ( struct net80211_device *dev,
NET80211_MAX_CHANNELS * sizeof ( dev->channels[0] ) );
dev->channel = 0;
+ /* Mark device as not supporting interrupts, if applicable */
+ if ( ! ops->irq )
+ dev->netdev->state |= NETDEV_IRQ_UNSUPPORTED;
+
list_add_tail ( &dev->list, &net80211_devices );
return register_netdev ( dev->netdev );
}
diff --git a/src/net/vlan.c b/src/net/vlan.c
index 49e3257a0..f515c2dc9 100644
--- a/src/net/vlan.c
+++ b/src/net/vlan.c
@@ -389,6 +389,10 @@ int vlan_create ( struct net_device *trunk, unsigned int tag,
snprintf ( netdev->name, sizeof ( netdev->name ), "%s-%d",
trunk->name, vlan->tag );
+ /* Mark device as not supporting interrupts, if applicable */
+ if ( ! netdev_irq_supported ( trunk ) )
+ netdev->state |= NETDEV_IRQ_UNSUPPORTED;
+
/* Register VLAN device */
if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
DBGC ( netdev, "VLAN %s could not register: %s\n",