vserver 2.0 rc7
[linux-2.6.git] / drivers / s390 / net / qeth.h
index 96c4243..a755b57 100644 (file)
@@ -15,7 +15,8 @@
 #include <net/addrconf.h>
 
 
-#include <asm/bitops.h>
+#include <linux/bitops.h>
+
 #include <asm/debug.h>
 #include <asm/qdio.h>
 #include <asm/ccwdev.h>
@@ -23,7 +24,7 @@
 
 #include "qeth_mpc.h"
 
-#define VERSION_QETH_H                 "$Revision: 1.110 $"
+#define VERSION_QETH_H                 "$Revision: 1.139 $"
 
 #ifdef CONFIG_QETH_IPV6
 #define QETH_VERSION_IPV6      ":IPv6"
@@ -43,7 +44,7 @@
 #define QETH_DBF_SETUP_LEN 8
 #define QETH_DBF_SETUP_INDEX 3
 #define QETH_DBF_SETUP_NR_AREAS 1
-#define QETH_DBF_SETUP_LEVEL 3
+#define QETH_DBF_SETUP_LEVEL 5
 
 #define QETH_DBF_MISC_NAME "qeth_misc"
 #define QETH_DBF_MISC_LEN 128
 #define QETH_DBF_CONTROL_LEN 256
 #define QETH_DBF_CONTROL_INDEX 3
 #define QETH_DBF_CONTROL_NR_AREAS 2
-#define QETH_DBF_CONTROL_LEVEL 2
+#define QETH_DBF_CONTROL_LEVEL 5
 
 #define QETH_DBF_TRACE_NAME "qeth_trace"
 #define QETH_DBF_TRACE_LEN 8
 #define QETH_DBF_TRACE_INDEX 2
 #define QETH_DBF_TRACE_NR_AREAS 2
 #define QETH_DBF_TRACE_LEVEL 3
+extern debug_info_t *qeth_dbf_trace;
 
 #define QETH_DBF_SENSE_NAME "qeth_sense"
 #define QETH_DBF_SENSE_LEN 64
@@ -91,7 +93,7 @@
                debug_event(qeth_dbf_##name,level,(void*)(addr),len); \
        } while (0)
 
-extern DEFINE_PER_CPU(char[256], qeth_dbf_txt_buf);
+DECLARE_PER_CPU(char[256], qeth_dbf_txt_buf);
 
 #define QETH_DBF_TEXT_(name,level,text...)                             \
        do {                                                            \
@@ -150,6 +152,8 @@ qeth_hex_dump(unsigned char *buf, size_t len)
 #define SENSE_RESETTING_EVENT_BYTE 1
 #define SENSE_RESETTING_EVENT_FLAG 0x80
 
+#define atomic_swap(a,b) xchg((int *)a.counter, b)
+
 /*
  * Common IO related definitions
  */
@@ -203,6 +207,11 @@ struct qeth_perf_stats {
        __u64 outbound_do_qdio_start_time;
        unsigned int outbound_do_qdio_cnt;
        unsigned int outbound_do_qdio_time;
+       /* eddp data */
+       unsigned int large_send_bytes;
+       unsigned int large_send_cnt;
+       unsigned int sg_skbs_sent;
+       unsigned int sg_frags_sent;
 };
 #endif /* CONFIG_QETH_PERF_STATS */
 
@@ -279,7 +288,8 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
 #define QETH_TX_TIMEOUT                100 * HZ
 #define QETH_HEADER_SIZE       32
 #define MAX_PORTNO             15
-#define QETH_FAKE_LL_LEN       ETH_HLEN
+#define QETH_FAKE_LL_LEN_ETH   ETH_HLEN
+#define QETH_FAKE_LL_LEN_TR    (sizeof(struct trh_hdr)-TR_MAXRIFLEN+sizeof(struct trllc))
 #define QETH_FAKE_LL_V6_ADDR_POS 24
 
 /*IPv6 address autoconfiguration stuff*/
@@ -327,16 +337,12 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
 #define QETH_WATERMARK_PACK_FUZZ 1
 
 #define QETH_IP_HEADER_SIZE 40
-/* VLAN defines */
-#define QETH_EXT_HDR_VLAN_FRAME        0x01
-#define QETH_EXT_HDR_TOKEN_ID          0x02
-#define QETH_EXT_HDR_INCLUDE_VLAN_TAG  0x04
 
-struct qeth_hdr {
+struct qeth_hdr_layer3 {
        __u8  id;
        __u8  flags;
-       __u16 inbound_checksum;
-       __u32 token;
+       __u16 inbound_checksum; /*TSO:__u16 seqno */
+       __u32 token;            /*TSO: __u32 reserved */
        __u16 length;
        __u8  vlan_prio;
        __u8  ext_flags;
@@ -345,6 +351,45 @@ struct qeth_hdr {
        __u8  dest_addr[16];
 } __attribute__ ((packed));
 
+struct qeth_hdr_layer2 {
+       __u8 id;
+       __u8 flags[3];
+       __u8 port_no;
+       __u8 hdr_length;
+       __u16 pkt_length;
+       __u16 seq_no;
+       __u16 vlan_id;
+       __u32 reserved;
+       __u8 reserved2[16];
+} __attribute__ ((packed));
+
+struct qeth_hdr {
+       union {
+               struct qeth_hdr_layer2 l2;
+               struct qeth_hdr_layer3 l3;
+       } hdr;
+} __attribute__ ((packed));
+
+/*TCP Segmentation Offload header*/
+struct qeth_hdr_ext_tso {
+        __u16 hdr_tot_len;
+        __u8  imb_hdr_no;
+        __u8  reserved;
+        __u8  hdr_type;
+        __u8  hdr_version;
+        __u16 hdr_len;
+        __u32 payload_len;
+        __u16 mss;
+        __u16 dg_hdr_len;
+        __u8  padding[16];
+} __attribute__ ((packed));
+
+struct qeth_hdr_tso {
+        struct qeth_hdr hdr;   /*hdr->hdr.l3.xxx*/
+       struct qeth_hdr_ext_tso ext;
+} __attribute__ ((packed));
+
+
 /* flags for qeth_hdr.flags */
 #define QETH_HDR_PASSTHRU 0x10
 #define QETH_HDR_IPV6     0x80
@@ -357,11 +402,26 @@ enum qeth_cast_flags {
        QETH_CAST_NOCAST    = 0x00,
 };
 
+enum qeth_layer2_frame_flags {
+       QETH_LAYER2_FLAG_MULTICAST = 0x01,
+       QETH_LAYER2_FLAG_BROADCAST = 0x02,
+       QETH_LAYER2_FLAG_UNICAST   = 0x04,
+       QETH_LAYER2_FLAG_VLAN      = 0x10,
+};
+
+enum qeth_header_ids {
+       QETH_HEADER_TYPE_LAYER3 = 0x01,
+       QETH_HEADER_TYPE_LAYER2 = 0x02,
+       QETH_HEADER_TYPE_TSO    = 0x03,
+};
 /* flags for qeth_hdr.ext_flags */
-#define QETH_HDR_EXT_VLAN_FRAME      0x01
-#define QETH_HDR_EXT_CSUM_HDR_REQ    0x10
-#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20
-#define QETH_HDR_EXT_SRC_MAC_ADDR    0x08
+#define QETH_HDR_EXT_VLAN_FRAME       0x01
+#define QETH_HDR_EXT_TOKEN_ID         0x02
+#define QETH_HDR_EXT_INCLUDE_VLAN_TAG 0x04
+#define QETH_HDR_EXT_SRC_MAC_ADDR     0x08
+#define QETH_HDR_EXT_CSUM_HDR_REQ     0x10
+#define QETH_HDR_EXT_CSUM_TRANSP_REQ  0x20
+#define QETH_HDR_EXT_UDP_TSO          0x40 /*bit off for TCP*/
 
 static inline int
 qeth_is_last_sbale(struct qdio_buffer_element *sbale)
@@ -416,21 +476,35 @@ struct qeth_qdio_q {
        volatile int next_buf_to_init;
 } __attribute__ ((aligned(256)));
 
+/* possible types of qeth large_send support */
+enum qeth_large_send_types {
+       QETH_LARGE_SEND_NO,
+       QETH_LARGE_SEND_EDDP,
+       QETH_LARGE_SEND_TSO,
+};
+
 struct qeth_qdio_out_buffer {
        struct qdio_buffer *buffer;
        atomic_t state;
        volatile int next_element_to_fill;
        struct sk_buff_head skb_list;
+       struct list_head ctx_list;
 };
 
 struct qeth_card;
 
+enum qeth_out_q_states {
+       QETH_OUT_Q_UNLOCKED,
+       QETH_OUT_Q_LOCKED,
+       QETH_OUT_Q_LOCKED_FLUSH,
+};
+
 struct qeth_qdio_out_q {
        struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
        struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
        int queue_no;
        struct qeth_card *card;
-       spinlock_t lock;
+       atomic_t state;
        volatile int do_pack;
        /*
         * index of buffer to be filled by driver; state EMPTY or PACKING
@@ -517,6 +591,7 @@ enum qeth_ip_types {
        QETH_IP_TYPE_NORMAL,
        QETH_IP_TYPE_VIPA,
        QETH_IP_TYPE_RXIP,
+       QETH_IP_TYPE_DEL_ALL_MC,
 };
 
 enum qeth_cmd_buffer_state {
@@ -610,14 +685,14 @@ struct qeth_seqno {
        __u32 trans_hdr;
        __u32 pdu_hdr;
        __u32 pdu_hdr_ack;
-       __u32 ipa;
+       __u16 ipa;
 };
 
 struct qeth_reply {
        struct list_head list;
        wait_queue_head_t wait_q;
        int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long);
-       int seqno;
+       u32 seqno;
        unsigned long offset;
        int received;
        int rc;
@@ -629,14 +704,22 @@ struct qeth_reply {
 #define QETH_BROADCAST_WITH_ECHO    1
 #define QETH_BROADCAST_WITHOUT_ECHO 2
 
+struct qeth_card_blkt {
+       int time_total;
+       int inter_packet;
+       int inter_packet_jumbo;
+};
+
+
+
 struct qeth_card_info {
-       char if_name[IF_NAME_LEN];
        unsigned short unit_addr2;
        unsigned short cula;
        unsigned short chpid;
        __u16 func_level;
        char mcl_level[QETH_MCL_LENGTH + 1];
        int guestlan;
+       int layer2_mac_registered;
        int portname_required;
        int portno;
        char portname[9];
@@ -647,6 +730,7 @@ struct qeth_card_info {
        int max_mtu;
        int broadcast_capable;
        int unique_id;
+       struct qeth_card_blkt blkt;
        __u32 csum_mask;
 };
 
@@ -664,6 +748,8 @@ struct qeth_card_options {
        int fake_broadcast;
        int add_hhlen;
        int fake_ll;
+       int layer2;
+       enum qeth_large_send_types large_send;
 };
 
 /*
@@ -671,8 +757,7 @@ struct qeth_card_options {
  */
 enum qeth_threads {
        QETH_SET_IP_THREAD  = 1,
-       QETH_SET_MC_THREAD  = 2,
-       QETH_RECOVER_THREAD = 4,
+       QETH_RECOVER_THREAD = 2,
 };
 
 struct qeth_card {
@@ -706,7 +791,7 @@ struct qeth_card {
        volatile unsigned long thread_running_mask;
        spinlock_t ip_lock;
        struct list_head ip_list;
-       struct list_head ip_tbd_list;
+       struct list_head *ip_tbd_list;
        struct qeth_ipato ipato;
        struct list_head cmd_waiter_list;
        /* QDIO buffer handling */
@@ -715,6 +800,8 @@ struct qeth_card {
        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_card_list_struct {
@@ -735,6 +822,8 @@ extern struct list_head qeth_notify_list;
 
 /*some helper functions*/
 
+#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
+
 inline static __u8
 qeth_get_ipa_adp_type(enum qeth_link_types link_type)
 {
@@ -746,6 +835,58 @@ qeth_get_ipa_adp_type(enum qeth_link_types link_type)
        }
 }
 
+inline static int
+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;
+                }
+                *skb = new_skb;
+       }
+       return 0;
+}
+static inline struct sk_buff *
+qeth_pskb_unshare(struct sk_buff *skb, int pri)
+{
+        struct sk_buff *nskb;
+        if (!skb_cloned(skb))
+                return skb;
+        nskb = skb_copy(skb, pri);
+        kfree_skb(skb); /* free our shared copy */
+        return nskb;
+}
+
+
+inline static void *
+qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
+{
+        void *hdr;
+
+       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
+         * the first 40 bytes of the paket cross a 4k boundary)
+         */
+        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.",
+                          QETH_CARD_IFNAME(card));
+                return NULL;
+        }
+        return hdr;
+}
+
+
 inline static int
 qeth_get_hlen(__u8 link_type)
 {
@@ -753,27 +894,29 @@ qeth_get_hlen(__u8 link_type)
        switch (link_type) {
        case QETH_LINK_TYPE_HSTR:
        case QETH_LINK_TYPE_LANE_TR:
-               return sizeof(struct qeth_hdr) + TR_HLEN;
+               return sizeof(struct qeth_hdr_tso) + TR_HLEN;
        default:
 #ifdef CONFIG_QETH_VLAN
-               return sizeof(struct qeth_hdr) + VLAN_ETH_HLEN;
+               return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN;
 #else
-               return sizeof(struct qeth_hdr) + ETH_HLEN;
+               return sizeof(struct qeth_hdr_tso) + ETH_HLEN;
 #endif
        }
 #else  /* CONFIG_QETH_IPV6 */
 #ifdef CONFIG_QETH_VLAN
-       return sizeof(struct qeth_hdr) + VLAN_HLEN;
+       return sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
 #else
-       return sizeof(struct qeth_hdr);
+       return sizeof(struct qeth_hdr_tso);
 #endif
 #endif /* CONFIG_QETH_IPV6 */
 }
 
 inline static unsigned short
-qeth_get_netdev_flags(int cardtype)
+qeth_get_netdev_flags(struct qeth_card *card)
 {
-       switch (cardtype) {
+       if (card->options.layer2)
+               return 0;
+       switch (card->info.type) {
        case QETH_CARD_TYPE_IQD:
                return IFF_NOARP;
 #ifdef CONFIG_QETH_IPV6
@@ -1027,4 +1170,14 @@ qeth_schedule_recovery(struct qeth_card *);
 
 extern int
 qeth_realloc_buffer_pool(struct qeth_card *, int);
+
+extern int
+qeth_set_large_send(struct qeth_card *);
+
+extern void
+qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
+                struct sk_buff *, int, int);
+extern void
+qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
+
 #endif /* __QETH_H__ */