vserver 1.9.5.x5
[linux-2.6.git] / drivers / net / arcnet / arcnet.c
index 5d30467..fdd83f1 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/init.h>
 #include <linux/arcdevice.h>
 
-
 /* "do nothing" functions for protocol drivers */
 static void null_rx(struct net_device *dev, int bufnum,
                    struct archdr *pkthdr, int length);
@@ -69,29 +68,31 @@ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
  * arc_proto_default instead.  It also must not be NULL; if you would like
  * to set it to NULL, set it to &arc_proto_null instead.
  */
-struct ArcProto *arc_proto_map[256], *arc_proto_default, *arc_bcast_proto;
+ struct ArcProto *arc_proto_map[256], *arc_proto_default,
+   *arc_bcast_proto, *arc_raw_proto;
 
 struct ArcProto arc_proto_null =
 {
        .suffix         = '?',
        .mtu            = XMTU,
+       .is_ip          = 0,
        .rx             = null_rx,
        .build_header   = null_build_header,
        .prepare_tx     = null_prepare_tx,
+       .continue_tx    = NULL,
+       .ack_tx         = NULL
 };
 
-static spinlock_t arcnet_lock = SPIN_LOCK_UNLOCKED;
-
 /* Exported function prototypes */
 int arcnet_debug = ARCNET_DEBUG;
 
 EXPORT_SYMBOL(arc_proto_map);
 EXPORT_SYMBOL(arc_proto_default);
 EXPORT_SYMBOL(arc_bcast_proto);
+EXPORT_SYMBOL(arc_raw_proto);
 EXPORT_SYMBOL(arc_proto_null);
 EXPORT_SYMBOL(arcnet_unregister_proto);
 EXPORT_SYMBOL(arcnet_debug);
-EXPORT_SYMBOL(arcdev_setup);
 EXPORT_SYMBOL(alloc_arcdev);
 EXPORT_SYMBOL(arcnet_interrupt);
 
@@ -108,7 +109,7 @@ static struct net_device_stats *arcnet_get_stats(struct net_device *dev);
 static int go_tx(struct net_device *dev);
 
 static int debug = ARCNET_DEBUG;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0);
 MODULE_LICENSE("GPL");
 
 static int __init arcnet_init(void)
@@ -131,7 +132,7 @@ static int __init arcnet_init(void)
 #endif
 
        /* initialize the protocol map */
-       arc_proto_default = arc_bcast_proto = &arc_proto_null;
+       arc_raw_proto = arc_proto_default = arc_bcast_proto = &arc_proto_null;
        for (count = 0; count < 256; count++)
                arc_proto_map[count] = arc_proto_default;
 
@@ -155,7 +156,8 @@ module_exit(arcnet_exit);
  * Dump the contents of an sk_buff
  */
 #if ARCNET_DEBUG_MAX & D_SKB
-void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc)
+void arcnet_dump_skb(struct net_device *dev,
+                    struct sk_buff *skb, char *desc)
 {
        int i;
 
@@ -176,18 +178,22 @@ EXPORT_SYMBOL(arcnet_dump_skb);
  * Dump the contents of an ARCnet buffer
  */
 #if (ARCNET_DEBUG_MAX & (D_RX | D_TX))
-void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc)
+void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc,
+                       int take_arcnet_lock)
 {
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
        int i, length;
-       unsigned long flags;
+       unsigned long flags = 0;
        static uint8_t buf[512];
 
        /* hw.copy_from_card expects IRQ context so take the IRQ lock
           to keep it single threaded */
-       spin_lock_irqsave(&arcnet_lock, flags);
+       if(take_arcnet_lock)
+               spin_lock_irqsave(&lp->lock, flags);
+
        lp->hw.copy_from_card(dev, bufnum, 0, buf, 512);
-       spin_unlock_irqrestore(&arcnet_lock, flags);
+       if(take_arcnet_lock)
+               spin_unlock_irqrestore(&lp->lock, flags);
 
        /* if the offset[0] byte is nonzero, this is a 256-byte packet */
        length = (buf[2] ? 256 : 512);
@@ -219,6 +225,8 @@ void arcnet_unregister_proto(struct ArcProto *proto)
                arc_proto_default = &arc_proto_null;
        if (arc_bcast_proto == proto)
                arc_bcast_proto = arc_proto_default;
+       if (arc_raw_proto == proto)
+               arc_raw_proto = arc_proto_default;
 
        for (count = 0; count < 256; count++) {
                if (arc_proto_map[count] == proto)
@@ -261,8 +269,11 @@ static int get_arcbuf(struct net_device *dev)
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
        int buf = -1, i;
 
-       if (!atomic_dec_and_test(&lp->buf_lock))        /* already in this function */
-               BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n", lp->buf_lock.counter);
+       if (!atomic_dec_and_test(&lp->buf_lock)) {
+               /* already in this function */
+               BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n",
+                      lp->buf_lock.counter);
+       }
        else {                  /* we can continue */
                if (lp->next_buf >= 5)
                        lp->next_buf -= 5;
@@ -305,14 +316,14 @@ static int choose_mtu(void)
 
 
 /* Setup a struct device for ARCnet. */
-void arcdev_setup(struct net_device *dev)
+static void arcdev_setup(struct net_device *dev)
 {
        dev->type = ARPHRD_ARCNET;
        dev->hard_header_len = sizeof(struct archdr);
        dev->mtu = choose_mtu();
 
        dev->addr_len = ARCNET_ALEN;
-       dev->tx_queue_len = 30;
+       dev->tx_queue_len = 100;
        dev->broadcast[0] = 0x00;       /* for us, broadcasts are address 0 */
        dev->watchdog_timeo = TX_TIMEOUT;
 
@@ -334,8 +345,16 @@ void arcdev_setup(struct net_device *dev)
 
 struct net_device *alloc_arcdev(char *name)
 {
-       return alloc_netdev(sizeof(struct arcnet_local),
-                           name && *name ? name : "arc%d", arcdev_setup);
+       struct net_device *dev;
+
+       dev = alloc_netdev(sizeof(struct arcnet_local),
+                          name && *name ? name : "arc%d", arcdev_setup);
+       if(dev) {
+               struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+               spin_lock_init(&lp->lock);
+       }
+
+       return dev;
 }
 
 /*
@@ -351,6 +370,8 @@ static int arcnet_open(struct net_device *dev)
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
        int count, newmtu, error;
 
+       BUGMSG(D_INIT,"opened.");
+
        if (!try_module_get(lp->hw.owner))
                return -ENODEV;
 
@@ -377,6 +398,8 @@ static int arcnet_open(struct net_device *dev)
        if (newmtu < dev->mtu)
                dev->mtu = newmtu;
 
+       BUGMSG(D_INIT, "arcnet_open: mtu: %d.\n", dev->mtu);
+
        /* autodetect the encapsulation for each host. */
        memset(lp->default_proto, 0, sizeof(lp->default_proto));
 
@@ -390,6 +413,7 @@ static int arcnet_open(struct net_device *dev)
 
        /* initialize buffers */
        atomic_set(&lp->buf_lock, 1);
+
        lp->next_buf = lp->first_free_buf = 0;
        release_arcbuf(dev, 0);
        release_arcbuf(dev, 1);
@@ -411,17 +435,24 @@ static int arcnet_open(struct net_device *dev)
                BUGMSG(D_NORMAL, "WARNING!  Station address FF may confuse "
                       "DOS networking programs!\n");
 
-       if (ASTATUS() & RESETflag)
+       BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+       if (ASTATUS() & RESETflag) {
+               BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
                ACOMMAND(CFLAGScmd | RESETclear);
+       }
+
 
+       BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
        /* make sure we're ready to receive IRQ's. */
        AINTMASK(0);
        udelay(1);              /* give it time to set the mask before
                                 * we reset it again. (may not even be
                                 * necessary)
                                 */
+       BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
        lp->intmask = NORXflag | RECONflag;
        AINTMASK(lp->intmask);
+       BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
 
        netif_start_queue(dev);
 
@@ -467,32 +498,41 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
               daddr ? *(uint8_t *) daddr : -1,
               type, type, len);
 
-       if (len != skb->len)
+       if (skb->len!=0 && len != skb->len)
                BUGMSG(D_NORMAL, "arcnet_header: Yikes!  skb->len(%d) != len(%d)!\n",
                       skb->len, len);
 
-       /*
-        * if the dest addr isn't provided, we can't choose an encapsulation!
-        * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a
-        * real header when we do rebuild_header. 
-        */
-       if (!daddr) {
+
+       /* Type is host order - ? */
+       if(type == ETH_P_ARCNET) {
+               proto = arc_raw_proto;
+               BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n",proto->suffix);
+               _daddr = daddr ? *(uint8_t *) daddr : 0;
+       }
+       else if (!daddr) {
+               /*
+                * if the dest addr isn't provided, we can't choose an encapsulation!
+                * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a
+                * real header when we do rebuild_header.
+                */
                *(uint16_t *) skb_push(skb, 2) = type;
                if (skb->nh.raw - skb->mac.raw != 2)
                        BUGMSG(D_NORMAL, "arcnet_header: Yikes!  diff (%d) is not 2!\n",
                               (int)(skb->nh.raw - skb->mac.raw));
                return -2;      /* return error -- can't transmit yet! */
        }
-       /* otherwise, we can just add the header as usual. */
-       _daddr = *(uint8_t *) daddr;
-       proto_num = lp->default_proto[_daddr];
-       proto = arc_proto_map[proto_num];
-       BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n",
-              proto_num, proto->suffix);
-       if (proto == &arc_proto_null && arc_bcast_proto != proto) {
-               BUGMSG(D_DURING, "actually, let's use '%c' instead.\n",
-                      arc_bcast_proto->suffix);
-               proto = arc_bcast_proto;
+       else {
+               /* otherwise, we can just add the header as usual. */
+               _daddr = *(uint8_t *) daddr;
+               proto_num = lp->default_proto[_daddr];
+               proto = arc_proto_map[proto_num];
+               BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n",
+                      proto_num, proto->suffix);
+               if (proto == &arc_proto_null && arc_bcast_proto != proto) {
+                       BUGMSG(D_DURING, "actually, let's use '%c' instead.\n",
+                              arc_bcast_proto->suffix);
+                       proto = arc_bcast_proto;
+               }
        }
        return proto->build_header(skb, dev, type, _daddr);
 }
@@ -519,6 +559,7 @@ static int arcnet_rebuild_header(struct sk_buff *skb)
                return 0;
        }
        type = *(uint16_t *) skb_pull(skb, 2);
+       BUGMSG(D_DURING, "rebuild header for protocol %Xh\n", type);
 
        if (type == ETH_P_IP) {
 #ifdef CONFIG_INET
@@ -555,10 +596,12 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
        struct arc_rfc1201 *soft;
        struct ArcProto *proto;
        int txbuf;
+       unsigned long flags;
+       int freeskb = 0;
 
        BUGMSG(D_DURING,
-              "transmit requested (status=%Xh, txbufs=%d/%d, len=%d)\n",
-              ASTATUS(), lp->cur_tx, lp->next_tx, skb->len);
+              "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
+              ASTATUS(), lp->cur_tx, lp->next_tx, skb->len,skb->protocol);
 
        pkt = (struct archdr *) skb->data;
        soft = &pkt->soft.rfc1201;
@@ -578,38 +621,49 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
        /* We're busy transmitting a packet... */
        netif_stop_queue(dev);
 
+       spin_lock_irqsave(&lp->lock, flags);
        AINTMASK(0);
 
        txbuf = get_arcbuf(dev);
        if (txbuf != -1) {
-               if (proto->prepare_tx(dev, pkt, skb->len, txbuf)) {
-                       /* done right away */
+               if (proto->prepare_tx(dev, pkt, skb->len, txbuf) &&
+                   !proto->ack_tx) {
+                       /* done right away and we don't want to acknowledge
+                          the package later - forget about it now */
                        lp->stats.tx_bytes += skb->len;
-                       dev_kfree_skb(skb);
+                       freeskb = 1;
                } else {
                        /* do it the 'split' way */
                        lp->outgoing.proto = proto;
                        lp->outgoing.skb = skb;
                        lp->outgoing.pkt = pkt;
 
-                       if (!proto->continue_tx)
-                               BUGMSG(D_NORMAL, "bug! prep_tx==0, but no continue_tx!\n");
-                       else if (proto->continue_tx(dev, txbuf)) {
-                               BUGMSG(D_NORMAL,
-                                      "bug! continue_tx finished the first time! "
-                                      "(proto='%c')\n", proto->suffix);
+                       if (proto->continue_tx &&
+                           proto->continue_tx(dev, txbuf)) {
+                         BUGMSG(D_NORMAL,
+                                "bug! continue_tx finished the first time! "
+                                "(proto='%c')\n", proto->suffix);
                        }
                }
 
                lp->next_tx = txbuf;
-       } else
-               dev_kfree_skb(skb);
+       } else {
+               freeskb = 1;
+       }
 
+       BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
        /* make sure we didn't ignore a TX IRQ while we were in here */
        AINTMASK(0);
-       lp->intmask |= TXFREEflag;
+
+       BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+       lp->intmask |= TXFREEflag|EXCNAKflag;
        AINTMASK(lp->intmask);
+       BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
 
+       spin_unlock_irqrestore(&lp->lock, flags);
+       if (freeskb) {
+               dev_kfree_skb(skb);
+       }
        return 0;               /* no need to try again */
 }
 
@@ -628,7 +682,7 @@ static int go_tx(struct net_device *dev)
        if (lp->cur_tx != -1 || lp->next_tx == -1)
                return 0;
 
-       BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx");
+       BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0);
 
        lp->cur_tx = lp->next_tx;
        lp->next_tx = -1;
@@ -640,7 +694,8 @@ static int go_tx(struct net_device *dev)
        lp->stats.tx_packets++;
        lp->lasttrans_dest = lp->lastload_dest;
        lp->lastload_dest = 0;
-       lp->intmask |= TXFREEflag;
+       lp->excnak_pending = 0;
+       lp->intmask |= TXFREEflag|EXCNAKflag;
 
        return 1;
 }
@@ -654,7 +709,7 @@ static void arcnet_timeout(struct net_device *dev)
        int status = ASTATUS();
        char *msg;
 
-       spin_lock_irqsave(&arcnet_lock, flags);
+       spin_lock_irqsave(&lp->lock, flags);
        if (status & TXFREEflag) {      /* transmit _DID_ finish */
                msg = " - missed IRQ?";
        } else {
@@ -665,12 +720,12 @@ static void arcnet_timeout(struct net_device *dev)
        }
        lp->stats.tx_errors++;
 
-       /* make sure we didn't miss a TX IRQ */
+       /* make sure we didn't miss a TX or a EXC NAK IRQ */
        AINTMASK(0);
-       lp->intmask |= TXFREEflag;
+       lp->intmask |= TXFREEflag|EXCNAKflag;
        AINTMASK(lp->intmask);
        
-       spin_unlock_irqrestore(&arcnet_lock, flags);
+       spin_unlock_irqrestore(&lp->lock, flags);
 
        if (jiffies - lp->last_timeout > 10*HZ) {
                BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n",
@@ -692,18 +747,19 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct net_device *dev = dev_id;
        struct arcnet_local *lp;
-       int recbuf, status, didsomething, boguscount;
+       int recbuf, status, diagstatus, didsomething, boguscount;
+       int retval = IRQ_NONE;
 
        BUGMSG(D_DURING, "\n");
 
        BUGMSG(D_DURING, "in arcnet_interrupt\n");
-
-       spin_lock(&arcnet_lock);
        
        lp = (struct arcnet_local *) dev->priv;
        if (!lp)
                BUG();
                
+       spin_lock(&lp->lock);
+
        /*
         * RESET flag was enabled - if device is not running, we must clear it right
         * away (but nothing else).
@@ -712,7 +768,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                if (ASTATUS() & RESETflag)
                        ACOMMAND(CFLAGScmd | RESETclear);
                AINTMASK(0);
-               spin_unlock(&arcnet_lock);
+               spin_unlock(&lp->lock);
                return IRQ_HANDLED;
        }
 
@@ -722,6 +778,10 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        boguscount = 5;
        do {
                status = ASTATUS();
+                diagstatus = (status >> 8) & 0xFF;
+
+               BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n",
+                       __FILE__,__LINE__,__FUNCTION__,status);
                didsomething = 0;
 
                /*
@@ -761,24 +821,55 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        }
                        didsomething++;
                }
+
+               if((diagstatus & EXCNAKflag)) {
+                       BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n",
+                              diagstatus);
+
+                        ACOMMAND(NOTXcmd);      /* disable transmit */
+                        lp->excnak_pending = 1;
+
+                        ACOMMAND(EXCNAKclear);
+                       lp->intmask &= ~(EXCNAKflag);
+                        didsomething++;
+                }
+
+
                /* a transmit finished, and we're interested in it. */
                if ((status & lp->intmask & TXFREEflag) || lp->timed_out) {
-                       lp->intmask &= ~TXFREEflag;
+                       lp->intmask &= ~(TXFREEflag|EXCNAKflag);
 
                        BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status);
 
-                       if (lp->cur_tx != -1 && !(status & TXACKflag) && !lp->timed_out) {
-                               if (lp->lasttrans_dest != 0) {
-                                       BUGMSG(D_EXTRA, "transmit was not acknowledged! "
-                                           "(status=%Xh, dest=%02Xh)\n",
-                                            status, lp->lasttrans_dest);
-                                       lp->stats.tx_errors++;
-                                       lp->stats.tx_carrier_errors++;
-                               } else {
-                                       BUGMSG(D_DURING,
-                                              "broadcast was not acknowledged; that's normal "
-                                           "(status=%Xh, dest=%02Xh)\n",
-                                            status, lp->lasttrans_dest);
+                       if (lp->cur_tx != -1 && !lp->timed_out) {
+                               if(!(status & TXACKflag)) {
+                                       if (lp->lasttrans_dest != 0) {
+                                               BUGMSG(D_EXTRA,
+                                                      "transmit was not acknowledged! "
+                                                      "(status=%Xh, dest=%02Xh)\n",
+                                                      status, lp->lasttrans_dest);
+                                               lp->stats.tx_errors++;
+                                               lp->stats.tx_carrier_errors++;
+                                       } else {
+                                               BUGMSG(D_DURING,
+                                                      "broadcast was not acknowledged; that's normal "
+                                                      "(status=%Xh, dest=%02Xh)\n",
+                                                      status, lp->lasttrans_dest);
+                                       }
+                               }
+
+                               if (lp->outgoing.proto &&
+                                   lp->outgoing.proto->ack_tx) {
+                                 int ackstatus;
+                                 if(status & TXACKflag)
+                                    ackstatus=2;
+                                  else if(lp->excnak_pending)
+                                    ackstatus=1;
+                                  else
+                                    ackstatus=0;
+
+                                  lp->outgoing.proto
+                                    ->ack_tx(dev, ackstatus);
                                }
                        }
                        if (lp->cur_tx != -1)
@@ -798,8 +889,11 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                        if (lp->outgoing.proto->continue_tx(dev, txbuf)) {
                                                /* that was the last segment */
                                                lp->stats.tx_bytes += lp->outgoing.skb->len;
-                                               dev_kfree_skb_irq(lp->outgoing.skb);
-                                               lp->outgoing.proto = NULL;
+                                               if(!lp->outgoing.proto->ack_tx)
+                                                 {
+                                                   dev_kfree_skb_irq(lp->outgoing.skb);
+                                                   lp->outgoing.proto = NULL;
+                                                 }
                                        }
                                        lp->next_tx = txbuf;
                                }
@@ -810,7 +904,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                }
                /* now process the received packet, if any */
                if (recbuf != -1) {
-                       BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq");
+                       BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq", 0);
 
                        arcnet_rx(dev, recbuf);
                        release_arcbuf(dev, recbuf);
@@ -868,6 +962,10 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
                        BUGMSG(D_DURING, "not recon: clearing counters anyway.\n");
                }
+
+               if(didsomething) {
+                       retval |= IRQ_HANDLED;
+               }
        }
        while (--boguscount && didsomething);
 
@@ -880,8 +978,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        udelay(1);
        AINTMASK(lp->intmask);
        
-       spin_unlock(&arcnet_lock);
-       return IRQ_RETVAL(didsomething);
+       spin_unlock(&lp->lock);
+       return retval;
 }
 
 
@@ -908,7 +1006,7 @@ void arcnet_rx(struct net_device *dev, int bufnum)
        }
 
        /* get the full header, if possible */
-       if (sizeof(pkt.soft) < length)
+       if (sizeof(pkt.soft) <= length)
                lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft));
        else {
                memset(&pkt.soft, 0, sizeof(pkt.soft));
@@ -923,7 +1021,7 @@ void arcnet_rx(struct net_device *dev, int bufnum)
        lp->stats.rx_bytes += length + ARC_HDR_SIZE;
 
        /* call the right receiver for the protocol */
-       if (arc_proto_map[soft->proto] != &arc_proto_null) {
+       if (arc_proto_map[soft->proto]->is_ip) {
                BUGLVL(D_PROTO) {
                        struct ArcProto
                        *oldp = arc_proto_map[lp->default_proto[pkt.hard.source]],