Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / drivers / s390 / net / qeth.h
index 9a064d4..821383d 100644 (file)
@@ -176,7 +176,6 @@ extern struct ccwgroup_driver qeth_ccwgroup_driver;
 /**
  * card stuff
  */
-#ifdef CONFIG_QETH_PERF_STATS
 struct qeth_perf_stats {
        unsigned int bufs_rec;
        unsigned int bufs_sent;
@@ -211,8 +210,10 @@ struct qeth_perf_stats {
        unsigned int large_send_cnt;
        unsigned int sg_skbs_sent;
        unsigned int sg_frags_sent;
+       /* initial values when measuring starts */
+       unsigned long initial_rx_packets;
+       unsigned long initial_tx_packets;
 };
-#endif /* CONFIG_QETH_PERF_STATS */
 
 /* Routing stuff */
 struct qeth_routing_info {
@@ -376,7 +377,7 @@ struct qeth_hdr_osn {
        __u8 reserved3[18];
        __u32 ccid;
 } __attribute__ ((packed));
-                                           
+
 struct qeth_hdr {
        union {
                struct qeth_hdr_layer2 l2;
@@ -462,6 +463,7 @@ enum qeth_qdio_info_states {
        QETH_QDIO_UNINITIALIZED,
        QETH_QDIO_ALLOCATED,
        QETH_QDIO_ESTABLISHED,
+       QETH_QDIO_CLEANING
 };
 
 struct qeth_buffer_pool_entry {
@@ -536,7 +538,7 @@ struct qeth_qdio_out_q {
 } __attribute__ ((aligned(256)));
 
 struct qeth_qdio_info {
-       volatile enum qeth_qdio_info_states state;
+       atomic_t state;
        /* input */
        struct qeth_qdio_q *in_q;
        struct qeth_qdio_buffer_pool in_buf_pool;
@@ -767,6 +769,7 @@ struct qeth_card_options {
        int fake_ll;
        int layer2;
        enum qeth_large_send_types large_send;
+       int performance_stats;
 };
 
 /*
@@ -819,13 +822,11 @@ struct qeth_card {
        struct list_head cmd_waiter_list;
        /* QDIO buffer handling */
        struct qeth_qdio_info qdio;
-#ifdef CONFIG_QETH_PERF_STATS
        struct qeth_perf_stats perf_stats;
-#endif /* CONFIG_QETH_PERF_STATS */
        int use_hard_stop;
        int (*orig_hard_header)(struct sk_buff *,struct net_device *,
                                unsigned short,void *,void *,unsigned);
-       struct qeth_osn_info osn_info; 
+       struct qeth_osn_info osn_info;
 };
 
 struct qeth_card_list_struct {
@@ -859,23 +860,18 @@ qeth_get_ipa_adp_type(enum qeth_link_types link_type)
        }
 }
 
-static inline int
-qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size)
+static inline struct sk_buff *
+qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size)
 {
-       struct sk_buff *new_skb = NULL;
-
-       if (skb_headroom(*skb) < size){
-               new_skb = skb_realloc_headroom(*skb, size);
-               if (!new_skb) {
-                        PRINT_ERR("qeth_prepare_skb: could "
-                                  "not realloc headroom for qeth_hdr "
-                                  "on interface %s", QETH_CARD_IFNAME(card));
-                        return -ENOMEM;
-                }
-               kfree_skb(*skb);
-                *skb = new_skb;
-       }
-       return 0;
+       struct sk_buff *new_skb = skb;
+
+       if (skb_headroom(skb) >= size)
+               return skb;
+       new_skb = skb_realloc_headroom(skb, size);
+       if (!new_skb) 
+               PRINT_ERR("Could not realloc headroom for qeth_hdr "
+                         "on interface %s", QETH_CARD_IFNAME(card));
+       return new_skb;
 }
 
 static inline struct sk_buff *
@@ -885,16 +881,15 @@ qeth_pskb_unshare(struct sk_buff *skb, int pri)
         if (!skb_cloned(skb))
                 return skb;
         nskb = skb_copy(skb, pri);
-        kfree_skb(skb); /* free our shared copy */
         return nskb;
 }
 
 static inline void *
-qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
+qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size)
 {
         void *hdr;
 
-       hdr = (void *) skb_push(*skb, size);
+       hdr = (void *) skb_push(skb, size);
         /*
          * sanity check, the Linux memory allocation scheme should
          * never present us cases like this one (the qdio header size plus
@@ -903,8 +898,7 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
         if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
             (((unsigned long) hdr + size +
               QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
-                PRINT_ERR("qeth_prepare_skb: misaligned "
-                          "packet on interface %s. Discarded.",
+                PRINT_ERR("Misaligned packet on interface %s. Discarded.",
                           QETH_CARD_IFNAME(card));
                 return NULL;
         }
@@ -944,7 +938,7 @@ qeth_get_netdev_flags(struct qeth_card *card)
                return 0;
        switch (card->info.type) {
        case QETH_CARD_TYPE_IQD:
-       case QETH_CARD_TYPE_OSN:        
+       case QETH_CARD_TYPE_OSN:
                return IFF_NOARP;
 #ifdef CONFIG_QETH_IPV6
        default:
@@ -981,7 +975,7 @@ static inline int
 qeth_get_max_mtu_for_card(int cardtype)
 {
        switch (cardtype) {
-               
+
        case QETH_CARD_TYPE_UNKNOWN:
        case QETH_CARD_TYPE_OSAE:
        case QETH_CARD_TYPE_OSN:
@@ -1056,13 +1050,11 @@ qeth_get_arphdr_type(int cardtype, int linktype)
        }
 }
 
-#ifdef CONFIG_QETH_PERF_STATS
 static inline int
 qeth_get_micros(void)
 {
        return (int) (get_clock() >> 12);
 }
-#endif
 
 static inline int
 qeth_get_qdio_q_format(struct qeth_card *card)
@@ -1075,16 +1067,6 @@ qeth_get_qdio_q_format(struct qeth_card *card)
        }
 }
 
-static inline int
-qeth_isdigit(char * buf)
-{
-       while (*buf) {
-               if (!isdigit(*buf++))
-                       return 0;
-       }
-       return 1;
-}
-
 static inline int
 qeth_isxdigit(char * buf)
 {
@@ -1104,33 +1086,18 @@ qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
 static inline int
 qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
 {
-       const char *start, *end;
-       char abuf[4];
-       char *tmp;
-       int len;
-       int i;
-
-       start = buf;
-       for (i = 0; i < 4; i++) {
-               if (i == 3) {
-                       end = strchr(start,0xa);
-                       if (end)
-                               len = end - start;
-                       else            
-                               len = strlen(start);
-               }
-               else {
-                       end = strchr(start, '.');
-                       len = end - start;
-               }
-               if ((len <= 0) || (len > 3))
-                       return -EINVAL;
-               memset(abuf, 0, 4);
-               strncpy(abuf, start, len);
-               if (!qeth_isdigit(abuf))
+       int count = 0, rc = 0;
+       int in[4];
+       char c;
+
+       rc = sscanf(buf, "%u.%u.%u.%u%c",
+                   &in[0], &in[1], &in[2], &in[3], &c);
+       if (rc != 4 && (rc != 5 || c != '\n'))
+               return -EINVAL;
+       for (count = 0; count < 4; count++) {
+               if (in[count] > 255)
                        return -EINVAL;
-               addr[i] = simple_strtoul(abuf, &tmp, 10);
-               start = end + 1;
+               addr[count] = in[count];
        }
        return 0;
 }
@@ -1149,36 +1116,50 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf)
 static inline int
 qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
 {
-       const char *start, *end;
-       u16 *tmp_addr;
-       char abuf[5];
-       char *tmp;
-       int len;
-       int i;
-
-       tmp_addr = (u16 *)addr;
-       start = buf;
-       for (i = 0; i < 8; i++) {
-               if (i == 7) {
-                       end = strchr(start,0xa);
-                       if (end)
-                               len = end - start;
-                       else
-                               len = strlen(start);
-               }
-               else {
-                       end = strchr(start, ':');
-                       len = end - start;
+       const char *end, *end_tmp, *start;
+       __u16 *in;
+        char num[5];
+        int num2, cnt, out, found, save_cnt;
+        unsigned short in_tmp[8] = {0, };
+
+       cnt = out = found = save_cnt = num2 = 0;
+        end = start = buf;
+       in = (__u16 *) addr;
+       memset(in, 0, 16);
+        while (*end) {
+                end = strchr(start,':');
+                if (end == NULL) {
+                        end = buf + strlen(buf);
+                       if ((end_tmp = strchr(start, '\n')) != NULL)
+                               end = end_tmp;
+                       out = 1;
+                }
+                if ((end - start)) {
+                        memset(num, 0, 5);
+                       if ((end - start) > 4)
+                               return -EINVAL;
+                        memcpy(num, start, end - start);
+                       if (!qeth_isxdigit(num))
+                               return -EINVAL;
+                        sscanf(start, "%x", &num2);
+                        if (found)
+                                in_tmp[save_cnt++] = num2;
+                        else
+                                in[cnt++] = num2;
+                        if (out)
+                                break;
+                } else {
+                       if (found)
+                               return -EINVAL;
+                        found = 1;
                }
-               if ((len <= 0) || (len > 4))
-                       return -EINVAL;
-               memset(abuf, 0, 5);
-               strncpy(abuf, start, len);
-               if (!qeth_isxdigit(abuf))
-                       return -EINVAL;
-               tmp_addr[i] = simple_strtoul(abuf, &tmp, 16);
-               start = end + 1;
-       }
+               start = ++end;
+        }
+       if (cnt + save_cnt > 8)
+               return -EINVAL;
+        cnt = 7;
+       while (save_cnt)
+                in[cnt--] = in_tmp[--save_cnt];
        return 0;
 }
 
@@ -1259,5 +1240,5 @@ qeth_osn_register(unsigned char *read_dev_no,
 
 extern void
 qeth_osn_deregister(struct net_device *);
-               
+
 #endif /* __QETH_H__ */