static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
 {
-       u16 head_len;
        struct sk_buff *skb = *skb_p;
 
-       switch (skb->protocol) {
-       case cpu_to_be16(NLPID_CCITT_ANSI_LMI):
-               head_len = 4;
-               skb_push(skb, head_len);
-               skb->data[3] = NLPID_CCITT_ANSI_LMI;
-               break;
-
-       case cpu_to_be16(NLPID_CISCO_LMI):
-               head_len = 4;
-               skb_push(skb, head_len);
-               skb->data[3] = NLPID_CISCO_LMI;
-               break;
-
-       case cpu_to_be16(ETH_P_IP):
-               head_len = 4;
-               skb_push(skb, head_len);
-               skb->data[3] = NLPID_IP;
-               break;
-
-       case cpu_to_be16(ETH_P_IPV6):
-               head_len = 4;
-               skb_push(skb, head_len);
-               skb->data[3] = NLPID_IPV6;
-               break;
-
-       case cpu_to_be16(ETH_P_802_3):
-               head_len = 10;
-               if (skb_headroom(skb) < head_len) {
-                       struct sk_buff *skb2 = skb_realloc_headroom(skb,
-                                                                   head_len);
+       if (!skb->dev) { /* Control packets */
+               switch (dlci) {
+               case LMI_CCITT_ANSI_DLCI:
+                       skb_push(skb, 4);
+                       skb->data[3] = NLPID_CCITT_ANSI_LMI;
+                       break;
+
+               case LMI_CISCO_DLCI:
+                       skb_push(skb, 4);
+                       skb->data[3] = NLPID_CISCO_LMI;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+
+       } else if (skb->dev->type == ARPHRD_DLCI) {
+               switch (skb->protocol) {
+               case htons(ETH_P_IP):
+                       skb_push(skb, 4);
+                       skb->data[3] = NLPID_IP;
+                       break;
+
+               case htons(ETH_P_IPV6):
+                       skb_push(skb, 4);
+                       skb->data[3] = NLPID_IPV6;
+                       break;
+
+               default:
+                       skb_push(skb, 10);
+                       skb->data[3] = FR_PAD;
+                       skb->data[4] = NLPID_SNAP;
+                       /* OUI 00-00-00 indicates an Ethertype follows */
+                       skb->data[5] = 0x00;
+                       skb->data[6] = 0x00;
+                       skb->data[7] = 0x00;
+                       /* This should be an Ethertype: */
+                       *(__be16 *)(skb->data + 8) = skb->protocol;
+               }
+
+       } else if (skb->dev->type == ARPHRD_ETHER) {
+               if (skb_headroom(skb) < 10) {
+                       struct sk_buff *skb2 = skb_realloc_headroom(skb, 10);
                        if (!skb2)
                                return -ENOBUFS;
                        dev_kfree_skb(skb);
                        skb = *skb_p = skb2;
                }
-               skb_push(skb, head_len);
+               skb_push(skb, 10);
                skb->data[3] = FR_PAD;
                skb->data[4] = NLPID_SNAP;
-               skb->data[5] = FR_PAD;
+               /* OUI 00-80-C2 stands for the 802.1 organization */
+               skb->data[5] = 0x00;
                skb->data[6] = 0x80;
                skb->data[7] = 0xC2;
+               /* PID 00-07 stands for Ethernet frames without FCS */
                skb->data[8] = 0x00;
-               skb->data[9] = 0x07; /* bridged Ethernet frame w/out FCS */
-               break;
+               skb->data[9] = 0x07;
 
-       default:
-               head_len = 10;
-               skb_push(skb, head_len);
-               skb->data[3] = FR_PAD;
-               skb->data[4] = NLPID_SNAP;
-               skb->data[5] = FR_PAD;
-               skb->data[6] = FR_PAD;
-               skb->data[7] = FR_PAD;
-               *(__be16*)(skb->data + 8) = skb->protocol;
+       } else {
+               return -EINVAL;
        }
 
        dlci_to_q922(skb->data, dlci);
                                skb_put(skb, pad);
                                memset(skb->data + len, 0, pad);
                        }
-                       skb->protocol = cpu_to_be16(ETH_P_802_3);
                }
+               skb->dev = dev;
                if (!fr_hard_header(&skb, pvc->dlci)) {
                        dev->stats.tx_bytes += skb->len;
                        dev->stats.tx_packets++;
        memset(skb->data, 0, len);
        skb_reserve(skb, 4);
        if (lmi == LMI_CISCO) {
-               skb->protocol = cpu_to_be16(NLPID_CISCO_LMI);
                fr_hard_header(&skb, LMI_CISCO_DLCI);
        } else {
-               skb->protocol = cpu_to_be16(NLPID_CCITT_ANSI_LMI);
                fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI);
        }
        data = skb_tail_pointer(skb);