aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/hw/nes/nes.h2
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.h2
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c701
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h91
-rw-r--r--drivers/infiniband/hw/nes/nes_utils.c3
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c26
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.h7
7 files changed, 607 insertions, 225 deletions
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index bf1720f7f35f..bcc6abc4faff 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -523,7 +523,7 @@ int nes_cm_disconn(struct nes_qp *);
523void nes_cm_disconn_worker(void *); 523void nes_cm_disconn_worker(void *);
524 524
525/* nes_verbs.c */ 525/* nes_verbs.c */
526int nes_hw_modify_qp(struct nes_device *, struct nes_qp *, u32, u32); 526int nes_hw_modify_qp(struct nes_device *, struct nes_qp *, u32, u32, u32);
527int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *); 527int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *);
528struct nes_ib_device *nes_init_ofa_device(struct net_device *); 528struct nes_ib_device *nes_init_ofa_device(struct net_device *);
529void nes_destroy_ofa_device(struct nes_ib_device *); 529void nes_destroy_ofa_device(struct nes_ib_device *);
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index 8b7e7c0e496e..90e8e4d8a5ce 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -410,8 +410,6 @@ struct nes_cm_ops {
410int schedule_nes_timer(struct nes_cm_node *, struct sk_buff *, 410int schedule_nes_timer(struct nes_cm_node *, struct sk_buff *,
411 enum nes_timer_type, int, int); 411 enum nes_timer_type, int, int);
412 412
413int nes_cm_disconn(struct nes_qp *);
414
415int nes_accept(struct iw_cm_id *, struct iw_cm_conn_param *); 413int nes_accept(struct iw_cm_id *, struct iw_cm_conn_param *);
416int nes_reject(struct iw_cm_id *, const void *, u8); 414int nes_reject(struct iw_cm_id *, const void *, u8);
417int nes_connect(struct iw_cm_id *, struct iw_cm_conn_param *); 415int nes_connect(struct iw_cm_id *, struct iw_cm_conn_param *);
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 2a0c5a18e139..297026f0c138 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -74,6 +74,8 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
74static void process_critical_error(struct nes_device *nesdev); 74static void process_critical_error(struct nes_device *nesdev);
75static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); 75static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number);
76static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); 76static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode);
77static void nes_terminate_timeout(unsigned long context);
78static void nes_terminate_start_timer(struct nes_qp *nesqp);
77 79
78#ifdef CONFIG_INFINIBAND_NES_DEBUG 80#ifdef CONFIG_INFINIBAND_NES_DEBUG
79static unsigned char *nes_iwarp_state_str[] = { 81static unsigned char *nes_iwarp_state_str[] = {
@@ -2903,6 +2905,383 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
2903} 2905}
2904 2906
2905 2907
2908static u8 *locate_mpa(u8 *pkt, u32 aeq_info)
2909{
2910 u16 pkt_len;
2911
2912 if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {
2913 /* skip over ethernet header */
2914 pkt_len = be16_to_cpu(*(u16 *)(pkt + ETH_HLEN - 2));
2915 pkt += ETH_HLEN;
2916
2917 /* Skip over IP and TCP headers */
2918 pkt += 4 * (pkt[0] & 0x0f);
2919 pkt += 4 * ((pkt[12] >> 4) & 0x0f);
2920 }
2921 return pkt;
2922}
2923
2924/* Determine if incoming error pkt is rdma layer */
2925static u32 iwarp_opcode(struct nes_qp *nesqp, u32 aeq_info)
2926{
2927 u8 *pkt;
2928 u16 *mpa;
2929 u32 opcode = 0xffffffff;
2930
2931 if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) {
2932 pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET;
2933 mpa = (u16 *)locate_mpa(pkt, aeq_info);
2934 opcode = be16_to_cpu(mpa[1]) & 0xf;
2935 }
2936
2937 return opcode;
2938}
2939
2940/* Build iWARP terminate header */
2941static int nes_bld_terminate_hdr(struct nes_qp *nesqp, u16 async_event_id, u32 aeq_info)
2942{
2943 u8 *pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET;
2944 u16 ddp_seg_len;
2945 int copy_len = 0;
2946 u8 is_tagged = 0;
2947 struct nes_terminate_hdr *termhdr;
2948
2949 termhdr = (struct nes_terminate_hdr *)nesqp->hwqp.q2_vbase;
2950 memset(termhdr, 0, 64);
2951
2952 if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) {
2953
2954 /* Use data from offending packet to fill in ddp & rdma hdrs */
2955 pkt = locate_mpa(pkt, aeq_info);
2956 ddp_seg_len = be16_to_cpu(*(u16 *)pkt);
2957 if (ddp_seg_len) {
2958 copy_len = 2;
2959 termhdr->hdrct = DDP_LEN_FLAG;
2960 if (pkt[2] & 0x80) {
2961 is_tagged = 1;
2962 if (ddp_seg_len >= TERM_DDP_LEN_TAGGED) {
2963 copy_len += TERM_DDP_LEN_TAGGED;
2964 termhdr->hdrct |= DDP_HDR_FLAG;
2965 }
2966 } else {
2967 if (ddp_seg_len >= TERM_DDP_LEN_UNTAGGED) {
2968 copy_len += TERM_DDP_LEN_UNTAGGED;
2969 termhdr->hdrct |= DDP_HDR_FLAG;
2970 }
2971
2972 if (ddp_seg_len >= (TERM_DDP_LEN_UNTAGGED + TERM_RDMA_LEN)) {
2973 if ((pkt[3] & RDMA_OPCODE_MASK) == RDMA_READ_REQ_OPCODE) {
2974 copy_len += TERM_RDMA_LEN;
2975 termhdr->hdrct |= RDMA_HDR_FLAG;
2976 }
2977 }
2978 }
2979 }
2980 }
2981
2982 switch (async_event_id) {
2983 case NES_AEQE_AEID_AMP_UNALLOCATED_STAG:
2984 switch (iwarp_opcode(nesqp, aeq_info)) {
2985 case IWARP_OPCODE_WRITE:
2986 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;
2987 termhdr->error_code = DDP_TAGGED_INV_STAG;
2988 break;
2989 default:
2990 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
2991 termhdr->error_code = RDMAP_INV_STAG;
2992 }
2993 break;
2994 case NES_AEQE_AEID_AMP_INVALID_STAG:
2995 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
2996 termhdr->error_code = RDMAP_INV_STAG;
2997 break;
2998 case NES_AEQE_AEID_AMP_BAD_QP:
2999 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3000 termhdr->error_code = DDP_UNTAGGED_INV_QN;
3001 break;
3002 case NES_AEQE_AEID_AMP_BAD_STAG_KEY:
3003 case NES_AEQE_AEID_AMP_BAD_STAG_INDEX:
3004 switch (iwarp_opcode(nesqp, aeq_info)) {
3005 case IWARP_OPCODE_SEND_INV:
3006 case IWARP_OPCODE_SEND_SE_INV:
3007 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;
3008 termhdr->error_code = RDMAP_CANT_INV_STAG;
3009 break;
3010 default:
3011 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3012 termhdr->error_code = RDMAP_INV_STAG;
3013 }
3014 break;
3015 case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
3016 if (aeq_info & (NES_AEQE_Q2_DATA_ETHERNET | NES_AEQE_Q2_DATA_MPA)) {
3017 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;
3018 termhdr->error_code = DDP_TAGGED_BOUNDS;
3019 } else {
3020 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3021 termhdr->error_code = RDMAP_INV_BOUNDS;
3022 }
3023 break;
3024 case NES_AEQE_AEID_AMP_RIGHTS_VIOLATION:
3025 case NES_AEQE_AEID_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS:
3026 case NES_AEQE_AEID_PRIV_OPERATION_DENIED:
3027 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3028 termhdr->error_code = RDMAP_ACCESS;
3029 break;
3030 case NES_AEQE_AEID_AMP_TO_WRAP:
3031 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3032 termhdr->error_code = RDMAP_TO_WRAP;
3033 break;
3034 case NES_AEQE_AEID_AMP_BAD_PD:
3035 switch (iwarp_opcode(nesqp, aeq_info)) {
3036 case IWARP_OPCODE_WRITE:
3037 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;
3038 termhdr->error_code = DDP_TAGGED_UNASSOC_STAG;
3039 break;
3040 case IWARP_OPCODE_SEND_INV:
3041 case IWARP_OPCODE_SEND_SE_INV:
3042 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3043 termhdr->error_code = RDMAP_CANT_INV_STAG;
3044 break;
3045 default:
3046 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;
3047 termhdr->error_code = RDMAP_UNASSOC_STAG;
3048 }
3049 break;
3050 case NES_AEQE_AEID_LLP_RECEIVED_MARKER_AND_LENGTH_FIELDS_DONT_MATCH:
3051 termhdr->layer_etype = (LAYER_MPA << 4) | DDP_LLP;
3052 termhdr->error_code = MPA_MARKER;
3053 break;
3054 case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
3055 termhdr->layer_etype = (LAYER_MPA << 4) | DDP_LLP;
3056 termhdr->error_code = MPA_CRC;
3057 break;
3058 case NES_AEQE_AEID_LLP_SEGMENT_TOO_LARGE:
3059 case NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL:
3060 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_CATASTROPHIC;
3061 termhdr->error_code = DDP_CATASTROPHIC_LOCAL;
3062 break;
3063 case NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC:
3064 case NES_AEQE_AEID_DDP_NO_L_BIT:
3065 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_CATASTROPHIC;
3066 termhdr->error_code = DDP_CATASTROPHIC_LOCAL;
3067 break;
3068 case NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN:
3069 case NES_AEQE_AEID_DDP_INVALID_MSN_RANGE_IS_NOT_VALID:
3070 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3071 termhdr->error_code = DDP_UNTAGGED_INV_MSN_RANGE;
3072 break;
3073 case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
3074 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3075 termhdr->error_code = DDP_UNTAGGED_INV_TOO_LONG;
3076 break;
3077 case NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION:
3078 if (is_tagged) {
3079 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;
3080 termhdr->error_code = DDP_TAGGED_INV_DDP_VER;
3081 } else {
3082 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3083 termhdr->error_code = DDP_UNTAGGED_INV_DDP_VER;
3084 }
3085 break;
3086 case NES_AEQE_AEID_DDP_UBE_INVALID_MO:
3087 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3088 termhdr->error_code = DDP_UNTAGGED_INV_MO;
3089 break;
3090 case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
3091 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3092 termhdr->error_code = DDP_UNTAGGED_INV_MSN_NO_BUF;
3093 break;
3094 case NES_AEQE_AEID_DDP_UBE_INVALID_QN:
3095 termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;
3096 termhdr->error_code = DDP_UNTAGGED_INV_QN;
3097 break;
3098 case NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION:
3099 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;
3100 termhdr->error_code = RDMAP_INV_RDMAP_VER;
3101 break;
3102 case NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE:
3103 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;
3104 termhdr->error_code = RDMAP_UNEXPECTED_OP;
3105 break;
3106 default:
3107 termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;
3108 termhdr->error_code = RDMAP_UNSPECIFIED;
3109 break;
3110 }
3111
3112 if (copy_len)
3113 memcpy(termhdr + 1, pkt, copy_len);
3114
3115 return sizeof(struct nes_terminate_hdr) + copy_len;
3116}
3117
3118static void nes_terminate_connection(struct nes_device *nesdev, struct nes_qp *nesqp,
3119 struct nes_hw_aeqe *aeqe, enum ib_event_type eventtype)
3120{
3121 u64 context;
3122 unsigned long flags;
3123 u32 aeq_info;
3124 u16 async_event_id;
3125 u8 tcp_state;
3126 u8 iwarp_state;
3127 u32 termlen = 0;
3128 u32 mod_qp_flags = NES_CQP_QP_IWARP_STATE_TERMINATE |
3129 NES_CQP_QP_TERM_DONT_SEND_FIN;
3130 struct nes_adapter *nesadapter = nesdev->nesadapter;
3131
3132 if (nesqp->term_flags & NES_TERM_SENT)
3133 return; /* Sanity check */
3134
3135 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
3136 tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
3137 iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
3138 async_event_id = (u16)aeq_info;
3139
3140 context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
3141 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];
3142 if (!context) {
3143 WARN_ON(!context);
3144 return;
3145 }
3146
3147 nesqp = (struct nes_qp *)(unsigned long)context;
3148 spin_lock_irqsave(&nesqp->lock, flags);
3149 nesqp->hw_iwarp_state = iwarp_state;
3150 nesqp->hw_tcp_state = tcp_state;
3151 nesqp->last_aeq = async_event_id;
3152 nesqp->terminate_eventtype = eventtype;
3153 spin_unlock_irqrestore(&nesqp->lock, flags);
3154
3155 if (nesadapter->send_term_ok)
3156 termlen = nes_bld_terminate_hdr(nesqp, async_event_id, aeq_info);
3157 else
3158 mod_qp_flags |= NES_CQP_QP_TERM_DONT_SEND_TERM_MSG;
3159
3160 nes_terminate_start_timer(nesqp);
3161 nesqp->term_flags |= NES_TERM_SENT;
3162 nes_hw_modify_qp(nesdev, nesqp, mod_qp_flags, termlen, 0);
3163}
3164
3165static void nes_terminate_send_fin(struct nes_device *nesdev,
3166 struct nes_qp *nesqp, struct nes_hw_aeqe *aeqe)
3167{
3168 u32 aeq_info;
3169 u16 async_event_id;
3170 u8 tcp_state;
3171 u8 iwarp_state;
3172 unsigned long flags;
3173
3174 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
3175 tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
3176 iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
3177 async_event_id = (u16)aeq_info;
3178
3179 spin_lock_irqsave(&nesqp->lock, flags);
3180 nesqp->hw_iwarp_state = iwarp_state;
3181 nesqp->hw_tcp_state = tcp_state;
3182 nesqp->last_aeq = async_event_id;
3183 spin_unlock_irqrestore(&nesqp->lock, flags);
3184
3185 /* Send the fin only */
3186 nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_TERMINATE |
3187 NES_CQP_QP_TERM_DONT_SEND_TERM_MSG, 0, 0);
3188}
3189
3190/* Cleanup after a terminate sent or received */
3191static void nes_terminate_done(struct nes_qp *nesqp, int timeout_occurred)
3192{
3193 u32 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;
3194 unsigned long flags;
3195 struct nes_vnic *nesvnic = to_nesvnic(nesqp->ibqp.device);
3196 struct nes_device *nesdev = nesvnic->nesdev;
3197 u8 first_time = 0;
3198
3199 spin_lock_irqsave(&nesqp->lock, flags);
3200 if (nesqp->hte_added) {
3201 nesqp->hte_added = 0;
3202 next_iwarp_state |= NES_CQP_QP_DEL_HTE;
3203 }
3204
3205 first_time = (nesqp->term_flags & NES_TERM_DONE) == 0;
3206 nesqp->term_flags |= NES_TERM_DONE;
3207 spin_unlock_irqrestore(&nesqp->lock, flags);
3208
3209 /* Make sure we go through this only once */
3210 if (first_time) {
3211 if (timeout_occurred == 0)
3212 del_timer(&nesqp->terminate_timer);
3213 else
3214 next_iwarp_state |= NES_CQP_QP_RESET;
3215
3216 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);
3217 nes_cm_disconn(nesqp);
3218 }
3219}
3220
3221static void nes_terminate_received(struct nes_device *nesdev,
3222 struct nes_qp *nesqp, struct nes_hw_aeqe *aeqe)
3223{
3224 u32 aeq_info;
3225 u8 *pkt;
3226 u32 *mpa;
3227 u8 ddp_ctl;
3228 u8 rdma_ctl;
3229 u16 aeq_id = 0;
3230
3231 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
3232 if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) {
3233 /* Terminate is not a performance path so the silicon */
3234 /* did not validate the frame - do it now */
3235 pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET;
3236 mpa = (u32 *)locate_mpa(pkt, aeq_info);
3237 ddp_ctl = (be32_to_cpu(mpa[0]) >> 8) & 0xff;
3238 rdma_ctl = be32_to_cpu(mpa[0]) & 0xff;
3239 if ((ddp_ctl & 0xc0) != 0x40)
3240 aeq_id = NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC;
3241 else if ((ddp_ctl & 0x03) != 1)
3242 aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION;
3243 else if (be32_to_cpu(mpa[2]) != 2)
3244 aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_QN;
3245 else if (be32_to_cpu(mpa[3]) != 1)
3246 aeq_id = NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN;
3247 else if (be32_to_cpu(mpa[4]) != 0)
3248 aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_MO;
3249 else if ((rdma_ctl & 0xc0) != 0x40)
3250 aeq_id = NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION;
3251
3252 if (aeq_id) {
3253 /* Bad terminate recvd - send back a terminate */
3254 aeq_info = (aeq_info & 0xffff0000) | aeq_id;
3255 aeqe->aeqe_words[NES_AEQE_MISC_IDX] = cpu_to_le32(aeq_info);
3256 nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
3257 return;
3258 }
3259 }
3260
3261 nesqp->term_flags |= NES_TERM_RCVD;
3262 nesqp->terminate_eventtype = IB_EVENT_QP_FATAL;
3263 nes_terminate_start_timer(nesqp);
3264 nes_terminate_send_fin(nesdev, nesqp, aeqe);
3265}
3266
3267/* Timeout routine in case terminate fails to complete */
3268static void nes_terminate_timeout(unsigned long context)
3269{
3270 struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context;
3271
3272 nes_terminate_done(nesqp, 1);
3273}
3274
3275/* Set a timer in case hw cannot complete the terminate sequence */
3276static void nes_terminate_start_timer(struct nes_qp *nesqp)
3277{
3278 init_timer(&nesqp->terminate_timer);
3279 nesqp->terminate_timer.function = nes_terminate_timeout;
3280 nesqp->terminate_timer.expires = jiffies + HZ;
3281 nesqp->terminate_timer.data = (unsigned long)nesqp;
3282 add_timer(&nesqp->terminate_timer);
3283}
3284
2906/** 3285/**
2907 * nes_process_iwarp_aeqe 3286 * nes_process_iwarp_aeqe
2908 */ 3287 */
@@ -2910,30 +3289,27 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
2910 struct nes_hw_aeqe *aeqe) 3289 struct nes_hw_aeqe *aeqe)
2911{ 3290{
2912 u64 context; 3291 u64 context;
2913 u64 aeqe_context = 0;
2914 unsigned long flags; 3292 unsigned long flags;
2915 struct nes_qp *nesqp; 3293 struct nes_qp *nesqp;
2916 struct nes_hw_cq *hw_cq; 3294 struct nes_hw_cq *hw_cq;
2917 struct nes_cq *nescq; 3295 struct nes_cq *nescq;
2918 int resource_allocated; 3296 int resource_allocated;
2919 /* struct iw_cm_id *cm_id; */
2920 struct nes_adapter *nesadapter = nesdev->nesadapter; 3297 struct nes_adapter *nesadapter = nesdev->nesadapter;
2921 struct ib_event ibevent;
2922 /* struct iw_cm_event cm_event; */
2923 u32 aeq_info; 3298 u32 aeq_info;
2924 u32 next_iwarp_state = 0; 3299 u32 next_iwarp_state = 0;
2925 u16 async_event_id; 3300 u16 async_event_id;
2926 u8 tcp_state; 3301 u8 tcp_state;
2927 u8 iwarp_state; 3302 u8 iwarp_state;
3303 int must_disconn = 1;
3304 int must_terminate = 0;
3305 struct ib_event ibevent;
2928 3306
2929 nes_debug(NES_DBG_AEQ, "\n"); 3307 nes_debug(NES_DBG_AEQ, "\n");
2930 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]); 3308 aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
2931 if ((NES_AEQE_INBOUND_RDMA&aeq_info) || (!(NES_AEQE_QP&aeq_info))) { 3309 if ((NES_AEQE_INBOUND_RDMA & aeq_info) || (!(NES_AEQE_QP & aeq_info))) {
2932 context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]); 3310 context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
2933 context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32; 3311 context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
2934 } else { 3312 } else {
2935 aeqe_context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
2936 aeqe_context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
2937 context = (unsigned long)nesadapter->qp_table[le32_to_cpu( 3313 context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
2938 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN]; 3314 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];
2939 BUG_ON(!context); 3315 BUG_ON(!context);
@@ -2950,7 +3326,11 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
2950 3326
2951 switch (async_event_id) { 3327 switch (async_event_id) {
2952 case NES_AEQE_AEID_LLP_FIN_RECEIVED: 3328 case NES_AEQE_AEID_LLP_FIN_RECEIVED:
2953 nesqp = *((struct nes_qp **)&context); 3329 nesqp = (struct nes_qp *)(unsigned long)context;
3330
3331 if (nesqp->term_flags)
3332 return; /* Ignore it, wait for close complete */
3333
2954 if (atomic_inc_return(&nesqp->close_timer_started) == 1) { 3334 if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
2955 nesqp->cm_id->add_ref(nesqp->cm_id); 3335 nesqp->cm_id->add_ref(nesqp->cm_id);
2956 schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp, 3336 schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,
@@ -2961,18 +3341,24 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
2961 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), 3341 nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
2962 async_event_id, nesqp->last_aeq, tcp_state); 3342 async_event_id, nesqp->last_aeq, tcp_state);
2963 } 3343 }
3344
2964 if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) || 3345 if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
2965 (nesqp->ibqp_state != IB_QPS_RTS)) { 3346 (nesqp->ibqp_state != IB_QPS_RTS)) {
2966 /* FIN Received but tcp state or IB state moved on, 3347 /* FIN Received but tcp state or IB state moved on,
2967 should expect a close complete */ 3348 should expect a close complete */
2968 return; 3349 return;
2969 } 3350 }
3351
2970 case NES_AEQE_AEID_LLP_CLOSE_COMPLETE: 3352 case NES_AEQE_AEID_LLP_CLOSE_COMPLETE:
3353 nesqp = (struct nes_qp *)(unsigned long)context;
3354 if (nesqp->term_flags) {
3355 nes_terminate_done(nesqp, 0);
3356 return;
3357 }
3358
2971 case NES_AEQE_AEID_LLP_CONNECTION_RESET: 3359 case NES_AEQE_AEID_LLP_CONNECTION_RESET:
2972 case NES_AEQE_AEID_TERMINATE_SENT:
2973 case NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE:
2974 case NES_AEQE_AEID_RESET_SENT: 3360 case NES_AEQE_AEID_RESET_SENT:
2975 nesqp = *((struct nes_qp **)&context); 3361 nesqp = (struct nes_qp *)(unsigned long)context;
2976 if (async_event_id == NES_AEQE_AEID_RESET_SENT) { 3362 if (async_event_id == NES_AEQE_AEID_RESET_SENT) {
2977 tcp_state = NES_AEQE_TCP_STATE_CLOSED; 3363 tcp_state = NES_AEQE_TCP_STATE_CLOSED;
2978 } 3364 }
@@ -2984,12 +3370,7 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
2984 if ((tcp_state == NES_AEQE_TCP_STATE_CLOSED) || 3370 if ((tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
2985 (tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) { 3371 (tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) {
2986 nesqp->hte_added = 0; 3372 nesqp->hte_added = 0;
2987 spin_unlock_irqrestore(&nesqp->lock, flags); 3373 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE;
2988 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u to remove hte\n",
2989 nesqp->hwqp.qp_id);
2990 nes_hw_modify_qp(nesdev, nesqp,
2991 NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE, 0);
2992 spin_lock_irqsave(&nesqp->lock, flags);
2993 } 3374 }
2994 3375
2995 if ((nesqp->ibqp_state == IB_QPS_RTS) && 3376 if ((nesqp->ibqp_state == IB_QPS_RTS) &&
@@ -3001,151 +3382,106 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
3001 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING; 3382 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
3002 break; 3383 break;
3003 case NES_AEQE_IWARP_STATE_TERMINATE: 3384 case NES_AEQE_IWARP_STATE_TERMINATE:
3004 next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE; 3385 must_disconn = 0; /* terminate path takes care of disconn */
3005 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_TERMINATE; 3386 if (nesqp->term_flags == 0)
3006 if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) { 3387 must_terminate = 1;
3007 next_iwarp_state |= 0x02000000;
3008 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3009 }
3010 break; 3388 break;
3011 default:
3012 next_iwarp_state = 0;
3013 }
3014 spin_unlock_irqrestore(&nesqp->lock, flags);
3015 if (next_iwarp_state) {
3016 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
3017 " also added another reference\n",
3018 nesqp->hwqp.qp_id, next_iwarp_state);
3019 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
3020 } 3389 }
3021 nes_cm_disconn(nesqp);
3022 } else { 3390 } else {
3023 if (async_event_id == NES_AEQE_AEID_LLP_FIN_RECEIVED) { 3391 if (async_event_id == NES_AEQE_AEID_LLP_FIN_RECEIVED) {
3024 /* FIN Received but ib state not RTS, 3392 /* FIN Received but ib state not RTS,
3025 close complete will be on its way */ 3393 close complete will be on its way */
3026 spin_unlock_irqrestore(&nesqp->lock, flags); 3394 must_disconn = 0;
3027 return;
3028 }
3029 spin_unlock_irqrestore(&nesqp->lock, flags);
3030 if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {
3031 next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000;
3032 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3033 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
3034 " also added another reference\n",
3035 nesqp->hwqp.qp_id, next_iwarp_state);
3036 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
3037 } 3395 }
3038 nes_cm_disconn(nesqp);
3039 } 3396 }
3040 break;
3041 case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED:
3042 nesqp = *((struct nes_qp **)&context);
3043 spin_lock_irqsave(&nesqp->lock, flags);
3044 nesqp->hw_iwarp_state = iwarp_state;
3045 nesqp->hw_tcp_state = tcp_state;
3046 nesqp->last_aeq = async_event_id;
3047 spin_unlock_irqrestore(&nesqp->lock, flags); 3397 spin_unlock_irqrestore(&nesqp->lock, flags);
3048 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TERMINATE_RECEIVED" 3398
3049 " event on QP%u \n Q2 Data:\n", 3399 if (must_terminate)
3050 nesqp->hwqp.qp_id); 3400 nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
3051 if (nesqp->ibqp.event_handler) { 3401 else if (must_disconn) {
3052 ibevent.device = nesqp->ibqp.device; 3402 if (next_iwarp_state) {
3053 ibevent.element.qp = &nesqp->ibqp; 3403 nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X\n",
3054 ibevent.event = IB_EVENT_QP_FATAL; 3404 nesqp->hwqp.qp_id, next_iwarp_state);
3055 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); 3405 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);
3056 } 3406 }
3057 if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
3058 ((nesqp->ibqp_state == IB_QPS_RTS)&&
3059 (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
3060 nes_cm_disconn(nesqp); 3407 nes_cm_disconn(nesqp);
3061 } else {
3062 nesqp->in_disconnect = 0;
3063 wake_up(&nesqp->kick_waitq);
3064 } 3408 }
3065 break; 3409 break;
3066 case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES: 3410
3067 nesqp = *((struct nes_qp **)&context); 3411 case NES_AEQE_AEID_TERMINATE_SENT:
3068 spin_lock_irqsave(&nesqp->lock, flags); 3412 nesqp = (struct nes_qp *)(unsigned long)context;
3069 nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR; 3413 nes_terminate_send_fin(nesdev, nesqp, aeqe);
3070 nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
3071 nesqp->last_aeq = async_event_id;
3072 if (nesqp->cm_id) {
3073 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES"
3074 " event on QP%u, remote IP = 0x%08X \n",
3075 nesqp->hwqp.qp_id,
3076 ntohl(nesqp->cm_id->remote_addr.sin_addr.s_addr));
3077 } else {
3078 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES"
3079 " event on QP%u \n",
3080 nesqp->hwqp.qp_id);
3081 }
3082 spin_unlock_irqrestore(&nesqp->lock, flags);
3083 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_RESET;
3084 nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
3085 if (nesqp->ibqp.event_handler) {
3086 ibevent.device = nesqp->ibqp.device;
3087 ibevent.element.qp = &nesqp->ibqp;
3088 ibevent.event = IB_EVENT_QP_FATAL;
3089 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3090 }
3091 break; 3414 break;
3092 case NES_AEQE_AEID_AMP_BAD_STAG_INDEX: 3415
3093 if (NES_AEQE_INBOUND_RDMA&aeq_info) { 3416 case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED:
3094 nesqp = nesadapter->qp_table[le32_to_cpu( 3417 nesqp = (struct nes_qp *)(unsigned long)context;
3095 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN]; 3418 nes_terminate_received(nesdev, nesqp, aeqe);
3096 } else {
3097 /* TODO: get the actual WQE and mask off wqe index */
3098 context &= ~((u64)511);
3099 nesqp = *((struct nes_qp **)&context);
3100 }
3101 spin_lock_irqsave(&nesqp->lock, flags);
3102 nesqp->hw_iwarp_state = iwarp_state;
3103 nesqp->hw_tcp_state = tcp_state;
3104 nesqp->last_aeq = async_event_id;
3105 spin_unlock_irqrestore(&nesqp->lock, flags);
3106 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_BAD_STAG_INDEX event on QP%u\n",
3107 nesqp->hwqp.qp_id);
3108 if (nesqp->ibqp.event_handler) {
3109 ibevent.device = nesqp->ibqp.device;
3110 ibevent.element.qp = &nesqp->ibqp;
3111 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3112 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3113 }
3114 break; 3419 break;
3420
3421 case NES_AEQE_AEID_AMP_BAD_STAG_KEY:
3422 case NES_AEQE_AEID_AMP_BAD_STAG_INDEX:
3115 case NES_AEQE_AEID_AMP_UNALLOCATED_STAG: 3423 case NES_AEQE_AEID_AMP_UNALLOCATED_STAG:
3116 nesqp = *((struct nes_qp **)&context); 3424 case NES_AEQE_AEID_AMP_INVALID_STAG:
3117 spin_lock_irqsave(&nesqp->lock, flags); 3425 case NES_AEQE_AEID_AMP_RIGHTS_VIOLATION:
3118 nesqp->hw_iwarp_state = iwarp_state; 3426 case NES_AEQE_AEID_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS:
3119 nesqp->hw_tcp_state = tcp_state;
3120 nesqp->last_aeq = async_event_id;
3121 spin_unlock_irqrestore(&nesqp->lock, flags);
3122 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_UNALLOCATED_STAG event on QP%u\n",
3123 nesqp->hwqp.qp_id);
3124 if (nesqp->ibqp.event_handler) {
3125 ibevent.device = nesqp->ibqp.device;
3126 ibevent.element.qp = &nesqp->ibqp;
3127 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3128 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3129 }
3130 break;
3131 case NES_AEQE_AEID_PRIV_OPERATION_DENIED: 3427 case NES_AEQE_AEID_PRIV_OPERATION_DENIED:
3132 nesqp = nesadapter->qp_table[le32_to_cpu(aeqe->aeqe_words 3428 case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
3133 [NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN]; 3429 case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
3134 spin_lock_irqsave(&nesqp->lock, flags); 3430 case NES_AEQE_AEID_AMP_TO_WRAP:
3135 nesqp->hw_iwarp_state = iwarp_state; 3431 nesqp = (struct nes_qp *)(unsigned long)context;
3136 nesqp->hw_tcp_state = tcp_state; 3432 nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_ACCESS_ERR);
3137 nesqp->last_aeq = async_event_id; 3433 break;
3138 spin_unlock_irqrestore(&nesqp->lock, flags); 3434
3139 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_PRIV_OPERATION_DENIED event on QP%u," 3435 case NES_AEQE_AEID_LLP_SEGMENT_TOO_LARGE:
3140 " nesqp = %p, AE reported %p\n", 3436 case NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL:
3141 nesqp->hwqp.qp_id, nesqp, *((struct nes_qp **)&context)); 3437 case NES_AEQE_AEID_DDP_UBE_INVALID_MO:
3142 if (nesqp->ibqp.event_handler) { 3438 case NES_AEQE_AEID_DDP_UBE_INVALID_QN:
3143 ibevent.device = nesqp->ibqp.device; 3439 nesqp = (struct nes_qp *)(unsigned long)context;
3144 ibevent.element.qp = &nesqp->ibqp; 3440 if (iwarp_opcode(nesqp, aeq_info) > IWARP_OPCODE_TERM) {
3145 ibevent.event = IB_EVENT_QP_ACCESS_ERR; 3441 aeq_info &= 0xffff0000;
3146 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); 3442 aeq_info |= NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE;
3443 aeqe->aeqe_words[NES_AEQE_MISC_IDX] = cpu_to_le32(aeq_info);
3147 } 3444 }
3445
3446 case NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE:
3447 case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES:
3448 case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
3449 case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
3450 case NES_AEQE_AEID_AMP_BAD_QP:
3451 case NES_AEQE_AEID_LLP_RECEIVED_MARKER_AND_LENGTH_FIELDS_DONT_MATCH:
3452 case NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC:
3453 case NES_AEQE_AEID_DDP_NO_L_BIT:
3454 case NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN:
3455 case NES_AEQE_AEID_DDP_INVALID_MSN_RANGE_IS_NOT_VALID:
3456 case NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION:
3457 case NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION:
3458 case NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE:
3459 case NES_AEQE_AEID_AMP_BAD_PD:
3460 case NES_AEQE_AEID_AMP_FASTREG_SHARED:
3461 case NES_AEQE_AEID_AMP_FASTREG_VALID_STAG:
3462 case NES_AEQE_AEID_AMP_FASTREG_MW_STAG:
3463 case NES_AEQE_AEID_AMP_FASTREG_INVALID_RIGHTS:
3464 case NES_AEQE_AEID_AMP_FASTREG_PBL_TABLE_OVERFLOW:
3465 case NES_AEQE_AEID_AMP_FASTREG_INVALID_LENGTH:
3466 case NES_AEQE_AEID_AMP_INVALIDATE_SHARED:
3467 case NES_AEQE_AEID_AMP_INVALIDATE_MR_WITH_BOUND_WINDOWS:
3468 case NES_AEQE_AEID_AMP_MWBIND_VALID_STAG:
3469 case NES_AEQE_AEID_AMP_MWBIND_OF_MR_STAG:
3470 case NES_AEQE_AEID_AMP_MWBIND_TO_ZERO_BASED_STAG:
3471 case NES_AEQE_AEID_AMP_MWBIND_TO_MW_STAG:
3472 case NES_AEQE_AEID_AMP_MWBIND_INVALID_RIGHTS:
3473 case NES_AEQE_AEID_AMP_MWBIND_INVALID_BOUNDS:
3474 case NES_AEQE_AEID_AMP_MWBIND_TO_INVALID_PARENT:
3475 case NES_AEQE_AEID_AMP_MWBIND_BIND_DISABLED:
3476 case NES_AEQE_AEID_BAD_CLOSE:
3477 case NES_AEQE_AEID_RDMA_READ_WHILE_ORD_ZERO:
3478 case NES_AEQE_AEID_STAG_ZERO_INVALID:
3479 case NES_AEQE_AEID_ROE_INVALID_RDMA_READ_REQUEST:
3480 case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
3481 nesqp = (struct nes_qp *)(unsigned long)context;
3482 nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
3148 break; 3483 break;
3484
3149 case NES_AEQE_AEID_CQ_OPERATION_ERROR: 3485 case NES_AEQE_AEID_CQ_OPERATION_ERROR:
3150 context <<= 1; 3486 context <<= 1;
3151 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n", 3487 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n",
@@ -3167,81 +3503,7 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
3167 } 3503 }
3168 } 3504 }
3169 break; 3505 break;
3170 case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER: 3506
3171 nesqp = nesadapter->qp_table[le32_to_cpu(
3172 aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
3173 spin_lock_irqsave(&nesqp->lock, flags);
3174 nesqp->hw_iwarp_state = iwarp_state;
3175 nesqp->hw_tcp_state = tcp_state;
3176 nesqp->last_aeq = async_event_id;
3177 spin_unlock_irqrestore(&nesqp->lock, flags);
3178 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG"
3179 "_FOR_AVAILABLE_BUFFER event on QP%u\n",
3180 nesqp->hwqp.qp_id);
3181 if (nesqp->ibqp.event_handler) {
3182 ibevent.device = nesqp->ibqp.device;
3183 ibevent.element.qp = &nesqp->ibqp;
3184 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3185 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3186 }
3187 /* tell cm to disconnect, cm will queue work to thread */
3188 nes_cm_disconn(nesqp);
3189 break;
3190 case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
3191 nesqp = *((struct nes_qp **)&context);
3192 spin_lock_irqsave(&nesqp->lock, flags);
3193 nesqp->hw_iwarp_state = iwarp_state;
3194 nesqp->hw_tcp_state = tcp_state;
3195 nesqp->last_aeq = async_event_id;
3196 spin_unlock_irqrestore(&nesqp->lock, flags);
3197 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_INVALID_MSN"
3198 "_NO_BUFFER_AVAILABLE event on QP%u\n",
3199 nesqp->hwqp.qp_id);
3200 if (nesqp->ibqp.event_handler) {
3201 ibevent.device = nesqp->ibqp.device;
3202 ibevent.element.qp = &nesqp->ibqp;
3203 ibevent.event = IB_EVENT_QP_FATAL;
3204 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3205 }
3206 /* tell cm to disconnect, cm will queue work to thread */
3207 nes_cm_disconn(nesqp);
3208 break;
3209 case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
3210 nesqp = *((struct nes_qp **)&context);
3211 spin_lock_irqsave(&nesqp->lock, flags);
3212 nesqp->hw_iwarp_state = iwarp_state;
3213 nesqp->hw_tcp_state = tcp_state;
3214 nesqp->last_aeq = async_event_id;
3215 spin_unlock_irqrestore(&nesqp->lock, flags);
3216 nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR"
3217 " event on QP%u \n Q2 Data:\n",
3218 nesqp->hwqp.qp_id);
3219 if (nesqp->ibqp.event_handler) {
3220 ibevent.device = nesqp->ibqp.device;
3221 ibevent.element.qp = &nesqp->ibqp;
3222 ibevent.event = IB_EVENT_QP_FATAL;
3223 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
3224 }
3225 /* tell cm to disconnect, cm will queue work to thread */
3226 nes_cm_disconn(nesqp);
3227 break;
3228 /* TODO: additional AEs need to be here */
3229 case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
3230 nesqp = *((struct nes_qp **)&context);
3231 spin_lock_irqsave(&nesqp->lock, flags);
3232 nesqp->hw_iwarp_state = iwarp_state;
3233 nesqp->hw_tcp_state = tcp_state;
3234 nesqp->last_aeq = async_event_id;
3235 spin_unlock_irqrestore(&nesqp->lock, flags);
3236 if (nesqp->ibqp.event_handler) {
3237 ibevent.device = nesqp->ibqp.device;
3238 ibevent.element.qp = &nesqp->ibqp;
3239 ibevent.event = IB_EVENT_QP_ACCESS_ERR;
3240 nesqp->ibqp.event_handler(&ibevent,
3241 nesqp->ibqp.qp_context);
3242 }
3243 nes_cm_disconn(nesqp);
3244 break;
3245 default: 3507 default:
3246 nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n", 3508 nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n",
3247 async_event_id); 3509 async_event_id);
@@ -3250,7 +3512,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
3250 3512
3251} 3513}
3252 3514
3253
3254/** 3515/**
3255 * nes_iwarp_ce_handler 3516 * nes_iwarp_ce_handler
3256 */ 3517 */
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index c3654c6383fe..4a0bfcd5a628 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -241,6 +241,7 @@ enum nes_cqp_stag_wqeword_idx {
241}; 241};
242 242
243#define NES_CQP_OP_IWARP_STATE_SHIFT 28 243#define NES_CQP_OP_IWARP_STATE_SHIFT 28
244#define NES_CQP_OP_TERMLEN_SHIFT 28
244 245
245enum nes_cqp_qp_bits { 246enum nes_cqp_qp_bits {
246 NES_CQP_QP_ARP_VALID = (1<<8), 247 NES_CQP_QP_ARP_VALID = (1<<8),
@@ -265,6 +266,8 @@ enum nes_cqp_qp_bits {
265 NES_CQP_QP_IWARP_STATE_TERMINATE = (5<<NES_CQP_OP_IWARP_STATE_SHIFT), 266 NES_CQP_QP_IWARP_STATE_TERMINATE = (5<<NES_CQP_OP_IWARP_STATE_SHIFT),
266 NES_CQP_QP_IWARP_STATE_ERROR = (6<<NES_CQP_OP_IWARP_STATE_SHIFT), 267 NES_CQP_QP_IWARP_STATE_ERROR = (6<<NES_CQP_OP_IWARP_STATE_SHIFT),
267 NES_CQP_QP_IWARP_STATE_MASK = (7<<NES_CQP_OP_IWARP_STATE_SHIFT), 268 NES_CQP_QP_IWARP_STATE_MASK = (7<<NES_CQP_OP_IWARP_STATE_SHIFT),
269 NES_CQP_QP_TERM_DONT_SEND_FIN = (1<<24),
270 NES_CQP_QP_TERM_DONT_SEND_TERM_MSG = (1<<25),
268 NES_CQP_QP_RESET = (1<<31), 271 NES_CQP_QP_RESET = (1<<31),
269}; 272};
270 273
@@ -633,11 +636,14 @@ enum nes_aeqe_bits {
633 NES_AEQE_INBOUND_RDMA = (1<<19), 636 NES_AEQE_INBOUND_RDMA = (1<<19),
634 NES_AEQE_IWARP_STATE_MASK = (7<<20), 637 NES_AEQE_IWARP_STATE_MASK = (7<<20),
635 NES_AEQE_TCP_STATE_MASK = (0xf<<24), 638 NES_AEQE_TCP_STATE_MASK = (0xf<<24),
639 NES_AEQE_Q2_DATA_WRITTEN = (0x3<<28),
636 NES_AEQE_VALID = (1<<31), 640 NES_AEQE_VALID = (1<<31),
637}; 641};
638 642
639#define NES_AEQE_IWARP_STATE_SHIFT 20 643#define NES_AEQE_IWARP_STATE_SHIFT 20
640#define NES_AEQE_TCP_STATE_SHIFT 24 644#define NES_AEQE_TCP_STATE_SHIFT 24
645#define NES_AEQE_Q2_DATA_ETHERNET (1<<28)
646#define NES_AEQE_Q2_DATA_MPA (1<<29)
641 647
642enum nes_aeqe_iwarp_state { 648enum nes_aeqe_iwarp_state {
643 NES_AEQE_IWARP_STATE_NON_EXISTANT = 0, 649 NES_AEQE_IWARP_STATE_NON_EXISTANT = 0,
@@ -1119,6 +1125,7 @@ struct nes_adapter {
1119 u8 netdev_max; /* from host nic address count in EEPROM */ 1125 u8 netdev_max; /* from host nic address count in EEPROM */
1120 u8 port_count; 1126 u8 port_count;
1121 u8 virtwq; 1127 u8 virtwq;
1128 u8 send_term_ok;
1122 u8 et_use_adaptive_rx_coalesce; 1129 u8 et_use_adaptive_rx_coalesce;
1123 u8 adapter_fcn_count; 1130 u8 adapter_fcn_count;
1124 u8 pft_mcast_map[NES_PFT_SIZE]; 1131 u8 pft_mcast_map[NES_PFT_SIZE];
@@ -1217,6 +1224,90 @@ struct nes_ib_device {
1217 u32 num_pd; 1224 u32 num_pd;
1218}; 1225};
1219 1226
1227enum nes_hdrct_flags {
1228 DDP_LEN_FLAG = 0x80,
1229 DDP_HDR_FLAG = 0x40,
1230 RDMA_HDR_FLAG = 0x20
1231};
1232
1233enum nes_term_layers {
1234 LAYER_RDMA = 0,
1235 LAYER_DDP = 1,
1236 LAYER_MPA = 2
1237};
1238
1239enum nes_term_error_types {
1240 RDMAP_CATASTROPHIC = 0,
1241 RDMAP_REMOTE_PROT = 1,
1242 RDMAP_REMOTE_OP = 2,
1243 DDP_CATASTROPHIC = 0,
1244 DDP_TAGGED_BUFFER = 1,
1245 DDP_UNTAGGED_BUFFER = 2,
1246 DDP_LLP = 3
1247};
1248
1249enum nes_term_rdma_errors {
1250 RDMAP_INV_STAG = 0x00,
1251 RDMAP_INV_BOUNDS = 0x01,
1252 RDMAP_ACCESS = 0x02,
1253 RDMAP_UNASSOC_STAG = 0x03,
1254 RDMAP_TO_WRAP = 0x04,
1255 RDMAP_INV_RDMAP_VER = 0x05,
1256 RDMAP_UNEXPECTED_OP = 0x06,
1257 RDMAP_CATASTROPHIC_LOCAL = 0x07,
1258 RDMAP_CATASTROPHIC_GLOBAL = 0x08,
1259 RDMAP_CANT_INV_STAG = 0x09,
1260 RDMAP_UNSPECIFIED = 0xff
1261};
1262
1263enum nes_term_ddp_errors {
1264 DDP_CATASTROPHIC_LOCAL = 0x00,
1265 DDP_TAGGED_INV_STAG = 0x00,
1266 DDP_TAGGED_BOUNDS = 0x01,
1267 DDP_TAGGED_UNASSOC_STAG = 0x02,
1268 DDP_TAGGED_TO_WRAP = 0x03,
1269 DDP_TAGGED_INV_DDP_VER = 0x04,
1270 DDP_UNTAGGED_INV_QN = 0x01,
1271 DDP_UNTAGGED_INV_MSN_NO_BUF = 0x02,
1272 DDP_UNTAGGED_INV_MSN_RANGE = 0x03,
1273 DDP_UNTAGGED_INV_MO = 0x04,
1274 DDP_UNTAGGED_INV_TOO_LONG = 0x05,
1275 DDP_UNTAGGED_INV_DDP_VER = 0x06
1276};
1277
1278enum nes_term_mpa_errors {
1279 MPA_CLOSED = 0x01,
1280 MPA_CRC = 0x02,
1281 MPA_MARKER = 0x03,
1282 MPA_REQ_RSP = 0x04,
1283};
1284
1285struct nes_terminate_hdr {
1286 u8 layer_etype;
1287 u8 error_code;
1288 u8 hdrct;
1289 u8 rsvd;
1290};
1291
1292/* Used to determine how to fill in terminate error codes */
1293#define IWARP_OPCODE_WRITE 0
1294#define IWARP_OPCODE_READREQ 1
1295#define IWARP_OPCODE_READRSP 2
1296#define IWARP_OPCODE_SEND 3
1297#define IWARP_OPCODE_SEND_INV 4
1298#define IWARP_OPCODE_SEND_SE 5
1299#define IWARP_OPCODE_SEND_SE_INV 6
1300#define IWARP_OPCODE_TERM 7
1301
1302/* These values are used only during terminate processing */
1303#define TERM_DDP_LEN_TAGGED 14
1304#define TERM_DDP_LEN_UNTAGGED 18
1305#define TERM_RDMA_LEN 28
1306#define RDMA_OPCODE_MASK 0x0f
1307#define RDMA_READ_REQ_OPCODE 1
1308#define BAD_FRAME_OFFSET 64
1309#define CQE_MAJOR_DRV 0x8000
1310
1220#define nes_vlan_rx vlan_hwaccel_receive_skb 1311#define nes_vlan_rx vlan_hwaccel_receive_skb
1221#define nes_netif_rx netif_receive_skb 1312#define nes_netif_rx netif_receive_skb
1222 1313
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index b34072b04377..9687c397ce1a 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -183,6 +183,9 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada
183 } else if (((major_ver == 2) && (minor_ver > 21)) || ((major_ver > 2) && (major_ver != 255))) { 183 } else if (((major_ver == 2) && (minor_ver > 21)) || ((major_ver > 2) && (major_ver != 255))) {
184 nesadapter->virtwq = 1; 184 nesadapter->virtwq = 1;
185 } 185 }
186 if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3))
187 nesadapter->send_term_ok = 1;
188
186 nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) + 189 nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) +
187 (u32)((u8)eeprom_data); 190 (u32)((u8)eeprom_data);
188 191
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index c6b5873416eb..36666ac2f546 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -2923,7 +2923,7 @@ static int nes_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
2923 * nes_hw_modify_qp 2923 * nes_hw_modify_qp
2924 */ 2924 */
2925int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp, 2925int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp,
2926 u32 next_iwarp_state, u32 wait_completion) 2926 u32 next_iwarp_state, u32 termlen, u32 wait_completion)
2927{ 2927{
2928 struct nes_hw_cqp_wqe *cqp_wqe; 2928 struct nes_hw_cqp_wqe *cqp_wqe;
2929 /* struct iw_cm_id *cm_id = nesqp->cm_id; */ 2929 /* struct iw_cm_id *cm_id = nesqp->cm_id; */
@@ -2955,6 +2955,13 @@ int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp,
2955 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id); 2955 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
2956 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, (u64)nesqp->nesqp_context_pbase); 2956 set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, (u64)nesqp->nesqp_context_pbase);
2957 2957
2958 /* If sending a terminate message, fill in the length (in words) */
2959 if (((next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) == NES_CQP_QP_IWARP_STATE_TERMINATE) &&
2960 !(next_iwarp_state & NES_CQP_QP_TERM_DONT_SEND_TERM_MSG)) {
2961 termlen = ((termlen + 3) >> 2) << NES_CQP_OP_TERMLEN_SHIFT;
2962 set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_NEW_MSS_IDX, termlen);
2963 }
2964
2958 atomic_set(&cqp_request->refcount, 2); 2965 atomic_set(&cqp_request->refcount, 2);
2959 nes_post_cqp_request(nesdev, cqp_request); 2966 nes_post_cqp_request(nesdev, cqp_request);
2960 2967
@@ -3125,6 +3132,9 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
3125 } 3132 }
3126 nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n", 3133 nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n",
3127 nesqp->hwqp.qp_id); 3134 nesqp->hwqp.qp_id);
3135 if (nesqp->term_flags)
3136 del_timer(&nesqp->terminate_timer);
3137
3128 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR; 3138 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;
3129 /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */ 3139 /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */
3130 if (nesqp->hte_added) { 3140 if (nesqp->hte_added) {
@@ -3202,7 +3212,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
3202 3212
3203 if (issue_modify_qp) { 3213 if (issue_modify_qp) {
3204 nes_debug(NES_DBG_MOD_QP, "call nes_hw_modify_qp\n"); 3214 nes_debug(NES_DBG_MOD_QP, "call nes_hw_modify_qp\n");
3205 ret = nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 1); 3215 ret = nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 1);
3206 if (ret) 3216 if (ret)
3207 nes_debug(NES_DBG_MOD_QP, "nes_hw_modify_qp (next_iwarp_state = 0x%08X)" 3217 nes_debug(NES_DBG_MOD_QP, "nes_hw_modify_qp (next_iwarp_state = 0x%08X)"
3208 " failed for QP%u.\n", 3218 " failed for QP%u.\n",
@@ -3367,6 +3377,12 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
3367 head = nesqp->hwqp.sq_head; 3377 head = nesqp->hwqp.sq_head;
3368 3378
3369 while (ib_wr) { 3379 while (ib_wr) {
3380 /* Check for QP error */
3381 if (nesqp->term_flags) {
3382 err = -EINVAL;
3383 break;
3384 }
3385
3370 /* Check for SQ overflow */ 3386 /* Check for SQ overflow */
3371 if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) { 3387 if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {
3372 err = -EINVAL; 3388 err = -EINVAL;
@@ -3523,6 +3539,12 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr,
3523 head = nesqp->hwqp.rq_head; 3539 head = nesqp->hwqp.rq_head;
3524 3540
3525 while (ib_wr) { 3541 while (ib_wr) {
3542 /* Check for QP error */
3543 if (nesqp->term_flags) {
3544 err = -EINVAL;
3545 break;
3546 }
3547
3526 if (ib_wr->num_sge > nesdev->nesadapter->max_sge) { 3548 if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
3527 err = -EINVAL; 3549 err = -EINVAL;
3528 break; 3550 break;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index 7df34fea2888..d92b1ef4653b 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -40,6 +40,10 @@ struct nes_device;
40#define NES_MAX_USER_DB_REGIONS 4096 40#define NES_MAX_USER_DB_REGIONS 4096
41#define NES_MAX_USER_WQ_REGIONS 4096 41#define NES_MAX_USER_WQ_REGIONS 4096
42 42
43#define NES_TERM_SENT 0x01
44#define NES_TERM_RCVD 0x02
45#define NES_TERM_DONE 0x04
46
43struct nes_ucontext { 47struct nes_ucontext {
44 struct ib_ucontext ibucontext; 48 struct ib_ucontext ibucontext;
45 struct nes_device *nesdev; 49 struct nes_device *nesdev;
@@ -159,6 +163,8 @@ struct nes_qp {
159 void *pbl_vbase; 163 void *pbl_vbase;
160 dma_addr_t pbl_pbase; 164 dma_addr_t pbl_pbase;
161 struct page *page; 165 struct page *page;
166 struct timer_list terminate_timer;
167 enum ib_event_type terminate_eventtype;
162 wait_queue_head_t kick_waitq; 168 wait_queue_head_t kick_waitq;
163 u16 in_disconnect; 169 u16 in_disconnect;
164 u16 private_data_len; 170 u16 private_data_len;
@@ -169,6 +175,7 @@ struct nes_qp {
169 u8 hw_iwarp_state; 175 u8 hw_iwarp_state;
170 u8 flush_issued; 176 u8 flush_issued;
171 u8 hw_tcp_state; 177 u8 hw_tcp_state;
178 u8 term_flags;
172 u8 destroyed; 179 u8 destroyed;
173}; 180};
174#endif /* NES_VERBS_H */ 181#endif /* NES_VERBS_H */