--- kerror.c.old Thu Jul 17 10:53:19 2003 +++ kerror.c Thu Jul 17 10:54:55 2003 @@ -3,10 +3,12 @@ * Copyright (C) 2003 David S. Miller (davem@redhat.com) * June 2003 - Jim Keniston and Dan Stekloff (kenistoj and dsteklof@us.ibm.com) * Fixed a couple of bugs and added iovec interface. + * July 2003 - Jim Keniston - Added handling of packets logged from IRQ context. */ #include #include +#include #include #include #include @@ -17,6 +19,33 @@ static struct sock *kerror_nl; +/* Packets logged from IRQ context are queued for broadcast by a tasklet. */ +static struct sk_buff_head delayed_pkts; +static void broadcast_delayed_pkts(unsigned long); +static DECLARE_TASKLET(delayed_pkts_tasklet, broadcast_delayed_pkts, 0); + +/** + * delayed_broadcast() - Schedule a tasklet to broadcast a packet. + * We want to broadcast the indicated packet, but can't because we're + * in a hardware interrupt and so can't call netlink_broadcast(). + * Schedule a tasklet to do the job. + * + * @skb: the socket buffer to broadcast + */ +static void delayed_broadcast(struct sk_buff *skb) +{ + skb_queue_tail(&delayed_pkts, skb); + tasklet_schedule(&delayed_pkts_tasklet); +} + +static void broadcast_delayed_pkts(unsigned long ignored) +{ + struct sk_buff *skb; + while ((skb = skb_dequeue(&delayed_pkts)) != NULL) { + (void) netlink_broadcast(kerror_nl, skb, 0, ~0, GFP_ATOMIC); + } +} + /** * kernel_error_event_iov() - Broadcast packet to NETLINK_KERROR sockets. * @iov: the packet's data @@ -54,6 +83,11 @@ NETLINK_CB(skb).dst_groups = groups; + if (in_irq()) { + delayed_broadcast(skb); + return -EINPROGRESS; + } + return netlink_broadcast(kerror_nl, skb, 0, ~0, GFP_ATOMIC); nlmsg_failure: @@ -85,6 +119,7 @@ if (kerror_nl == NULL) panic("kerror_init: cannot initialize kerror_nl\n"); + skb_queue_head_init(&delayed_pkts); return 0; }