These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / infiniband / hw / cxgb4 / cm.c
index 3ad8dc7..c9cffce 100644 (file)
@@ -50,6 +50,7 @@
 #include <rdma/ib_addr.h>
 
 #include "iw_cxgb4.h"
+#include "clip_tbl.h"
 
 static char *states[] = {
        "idle",
@@ -115,11 +116,11 @@ module_param(ep_timeout_secs, int, 0644);
 MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout "
                                   "in seconds (default=60)");
 
-static int mpa_rev = 1;
+static int mpa_rev = 2;
 module_param(mpa_rev, int, 0644);
 MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, "
                "1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft"
-               " compliant (default=1)");
+               " compliant (default=2)");
 
 static int markers_enabled;
 module_param(markers_enabled, int, 0644);
@@ -298,6 +299,16 @@ void _c4iw_free_ep(struct kref *kref)
        if (test_bit(QP_REFERENCED, &ep->com.flags))
                deref_qp(ep);
        if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) {
+               if (ep->com.remote_addr.ss_family == AF_INET6) {
+                       struct sockaddr_in6 *sin6 =
+                                       (struct sockaddr_in6 *)
+                                       &ep->com.mapped_local_addr;
+
+                       cxgb4_clip_release(
+                                       ep->com.dev->rdev.lldi.ports[0],
+                                       (const u32 *)&sin6->sin6_addr.s6_addr,
+                                       1);
+               }
                remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid);
                cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
                dst_release(ep->dst);
@@ -442,6 +453,12 @@ static void act_open_req_arp_failure(void *handle, struct sk_buff *skb)
        kfree_skb(skb);
        connect_reply_upcall(ep, -EHOSTUNREACH);
        state_set(&ep->com, DEAD);
+       if (ep->com.remote_addr.ss_family == AF_INET6) {
+               struct sockaddr_in6 *sin6 =
+                       (struct sockaddr_in6 *)&ep->com.mapped_local_addr;
+               cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0],
+                                  (const u32 *)&sin6->sin6_addr.s6_addr, 1);
+       }
        remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
        cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
        dst_release(ep->dst);
@@ -615,22 +632,18 @@ static void best_mtu(const unsigned short *mtus, unsigned short mtu,
 
 static int send_connect(struct c4iw_ep *ep)
 {
-       struct cpl_act_open_req *req;
-       struct cpl_t5_act_open_req *t5_req;
-       struct cpl_act_open_req6 *req6;
-       struct cpl_t5_act_open_req6 *t5_req6;
+       struct cpl_act_open_req *req = NULL;
+       struct cpl_t5_act_open_req *t5req = NULL;
+       struct cpl_t6_act_open_req *t6req = NULL;
+       struct cpl_act_open_req6 *req6 = NULL;
+       struct cpl_t5_act_open_req6 *t5req6 = NULL;
+       struct cpl_t6_act_open_req6 *t6req6 = NULL;
        struct sk_buff *skb;
        u64 opt0;
        u32 opt2;
        unsigned int mtu_idx;
        int wscale;
-       int wrlen;
-       int sizev4 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ?
-                               sizeof(struct cpl_act_open_req) :
-                               sizeof(struct cpl_t5_act_open_req);
-       int sizev6 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ?
-                               sizeof(struct cpl_act_open_req6) :
-                               sizeof(struct cpl_t5_act_open_req6);
+       int win, sizev4, sizev6, wrlen;
        struct sockaddr_in *la = (struct sockaddr_in *)
                                 &ep->com.mapped_local_addr;
        struct sockaddr_in *ra = (struct sockaddr_in *)
@@ -639,7 +652,28 @@ static int send_connect(struct c4iw_ep *ep)
                                   &ep->com.mapped_local_addr;
        struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)
                                   &ep->com.mapped_remote_addr;
-       int win;
+       int ret;
+       enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;
+       u32 isn = (prandom_u32() & ~7UL) - 1;
+
+       switch (CHELSIO_CHIP_VERSION(adapter_type)) {
+       case CHELSIO_T4:
+               sizev4 = sizeof(struct cpl_act_open_req);
+               sizev6 = sizeof(struct cpl_act_open_req6);
+               break;
+       case CHELSIO_T5:
+               sizev4 = sizeof(struct cpl_t5_act_open_req);
+               sizev6 = sizeof(struct cpl_t5_act_open_req6);
+               break;
+       case CHELSIO_T6:
+               sizev4 = sizeof(struct cpl_t6_act_open_req);
+               sizev6 = sizeof(struct cpl_t6_act_open_req6);
+               break;
+       default:
+               pr_err("T%d Chip is not supported\n",
+                      CHELSIO_CHIP_VERSION(adapter_type));
+               return -EINVAL;
+       }
 
        wrlen = (ep->com.remote_addr.ss_family == AF_INET) ?
                        roundup(sizev4, 16) :
@@ -688,109 +722,128 @@ static int send_connect(struct c4iw_ep *ep)
                opt2 |= SACK_EN_F;
        if (wscale && enable_tcp_window_scaling)
                opt2 |= WND_SCALE_EN_F;
-       if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+       if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) {
+               if (peer2peer)
+                       isn += 4;
+
                opt2 |= T5_OPT_2_VALID_F;
                opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE);
                opt2 |= T5_ISS_F;
        }
+
+       if (ep->com.remote_addr.ss_family == AF_INET6)
+               cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0],
+                              (const u32 *)&la6->sin6_addr.s6_addr, 1);
+
        t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure);
 
-       if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
-               if (ep->com.remote_addr.ss_family == AF_INET) {
-                       req = (struct cpl_act_open_req *) skb_put(skb, wrlen);
+       if (ep->com.remote_addr.ss_family == AF_INET) {
+               switch (CHELSIO_CHIP_VERSION(adapter_type)) {
+               case CHELSIO_T4:
+                       req = (struct cpl_act_open_req *)skb_put(skb, wrlen);
                        INIT_TP_WR(req, 0);
-                       OPCODE_TID(req) = cpu_to_be32(
-                                       MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
-                                       ((ep->rss_qid << 14) | ep->atid)));
-                       req->local_port = la->sin_port;
-                       req->peer_port = ra->sin_port;
-                       req->local_ip = la->sin_addr.s_addr;
-                       req->peer_ip = ra->sin_addr.s_addr;
-                       req->opt0 = cpu_to_be64(opt0);
+                       break;
+               case CHELSIO_T5:
+                       t5req = (struct cpl_t5_act_open_req *)skb_put(skb,
+                                       wrlen);
+                       INIT_TP_WR(t5req, 0);
+                       req = (struct cpl_act_open_req *)t5req;
+                       break;
+               case CHELSIO_T6:
+                       t6req = (struct cpl_t6_act_open_req *)skb_put(skb,
+                                       wrlen);
+                       INIT_TP_WR(t6req, 0);
+                       req = (struct cpl_act_open_req *)t6req;
+                       t5req = (struct cpl_t5_act_open_req *)t6req;
+                       break;
+               default:
+                       pr_err("T%d Chip is not supported\n",
+                              CHELSIO_CHIP_VERSION(adapter_type));
+                       ret = -EINVAL;
+                       goto clip_release;
+               }
+
+               OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+                                       ((ep->rss_qid<<14) | ep->atid)));
+               req->local_port = la->sin_port;
+               req->peer_port = ra->sin_port;
+               req->local_ip = la->sin_addr.s_addr;
+               req->peer_ip = ra->sin_addr.s_addr;
+               req->opt0 = cpu_to_be64(opt0);
+
+               if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
                        req->params = cpu_to_be32(cxgb4_select_ntuple(
                                                ep->com.dev->rdev.lldi.ports[0],
                                                ep->l2t));
                        req->opt2 = cpu_to_be32(opt2);
                } else {
+                       t5req->params = cpu_to_be64(FILTER_TUPLE_V(
+                                               cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t)));
+                       t5req->rsvd = cpu_to_be32(isn);
+                       PDBG("%s snd_isn %u\n", __func__, t5req->rsvd);
+                       t5req->opt2 = cpu_to_be32(opt2);
+               }
+       } else {
+               switch (CHELSIO_CHIP_VERSION(adapter_type)) {
+               case CHELSIO_T4:
                        req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen);
-
                        INIT_TP_WR(req6, 0);
-                       OPCODE_TID(req6) = cpu_to_be32(
-                                          MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
-                                          ((ep->rss_qid<<14)|ep->atid)));
-                       req6->local_port = la6->sin6_port;
-                       req6->peer_port = ra6->sin6_port;
-                       req6->local_ip_hi = *((__be64 *)
-                                               (la6->sin6_addr.s6_addr));
-                       req6->local_ip_lo = *((__be64 *)
-                                               (la6->sin6_addr.s6_addr + 8));
-                       req6->peer_ip_hi = *((__be64 *)
-                                               (ra6->sin6_addr.s6_addr));
-                       req6->peer_ip_lo = *((__be64 *)
-                                               (ra6->sin6_addr.s6_addr + 8));
-                       req6->opt0 = cpu_to_be64(opt0);
+                       break;
+               case CHELSIO_T5:
+                       t5req6 = (struct cpl_t5_act_open_req6 *)skb_put(skb,
+                                       wrlen);
+                       INIT_TP_WR(t5req6, 0);
+                       req6 = (struct cpl_act_open_req6 *)t5req6;
+                       break;
+               case CHELSIO_T6:
+                       t6req6 = (struct cpl_t6_act_open_req6 *)skb_put(skb,
+                                       wrlen);
+                       INIT_TP_WR(t6req6, 0);
+                       req6 = (struct cpl_act_open_req6 *)t6req6;
+                       t5req6 = (struct cpl_t5_act_open_req6 *)t6req6;
+                       break;
+               default:
+                       pr_err("T%d Chip is not supported\n",
+                              CHELSIO_CHIP_VERSION(adapter_type));
+                       ret = -EINVAL;
+                       goto clip_release;
+               }
+
+               OPCODE_TID(req6) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+                                       ((ep->rss_qid<<14)|ep->atid)));
+               req6->local_port = la6->sin6_port;
+               req6->peer_port = ra6->sin6_port;
+               req6->local_ip_hi = *((__be64 *)(la6->sin6_addr.s6_addr));
+               req6->local_ip_lo = *((__be64 *)(la6->sin6_addr.s6_addr + 8));
+               req6->peer_ip_hi = *((__be64 *)(ra6->sin6_addr.s6_addr));
+               req6->peer_ip_lo = *((__be64 *)(ra6->sin6_addr.s6_addr + 8));
+               req6->opt0 = cpu_to_be64(opt0);
+
+               if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
                        req6->params = cpu_to_be32(cxgb4_select_ntuple(
                                                ep->com.dev->rdev.lldi.ports[0],
                                                ep->l2t));
                        req6->opt2 = cpu_to_be32(opt2);
-               }
-       } else {
-               u32 isn = (prandom_u32() & ~7UL) - 1;
-
-               if (peer2peer)
-                       isn += 4;
-
-               if (ep->com.remote_addr.ss_family == AF_INET) {
-                       t5_req = (struct cpl_t5_act_open_req *)
-                                skb_put(skb, wrlen);
-                       INIT_TP_WR(t5_req, 0);
-                       OPCODE_TID(t5_req) = cpu_to_be32(
-                                       MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
-                                       ((ep->rss_qid << 14) | ep->atid)));
-                       t5_req->local_port = la->sin_port;
-                       t5_req->peer_port = ra->sin_port;
-                       t5_req->local_ip = la->sin_addr.s_addr;
-                       t5_req->peer_ip = ra->sin_addr.s_addr;
-                       t5_req->opt0 = cpu_to_be64(opt0);
-                       t5_req->params = cpu_to_be64(FILTER_TUPLE_V(
-                                                    cxgb4_select_ntuple(
-                                            ep->com.dev->rdev.lldi.ports[0],
-                                            ep->l2t)));
-                       t5_req->rsvd = cpu_to_be32(isn);
-                       PDBG("%s snd_isn %u\n", __func__,
-                            be32_to_cpu(t5_req->rsvd));
-                       t5_req->opt2 = cpu_to_be32(opt2);
                } else {
-                       t5_req6 = (struct cpl_t5_act_open_req6 *)
-                                 skb_put(skb, wrlen);
-                       INIT_TP_WR(t5_req6, 0);
-                       OPCODE_TID(t5_req6) = cpu_to_be32(
-                                             MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
-                                             ((ep->rss_qid<<14)|ep->atid)));
-                       t5_req6->local_port = la6->sin6_port;
-                       t5_req6->peer_port = ra6->sin6_port;
-                       t5_req6->local_ip_hi = *((__be64 *)
-                                               (la6->sin6_addr.s6_addr));
-                       t5_req6->local_ip_lo = *((__be64 *)
-                                               (la6->sin6_addr.s6_addr + 8));
-                       t5_req6->peer_ip_hi = *((__be64 *)
-                                               (ra6->sin6_addr.s6_addr));
-                       t5_req6->peer_ip_lo = *((__be64 *)
-                                               (ra6->sin6_addr.s6_addr + 8));
-                       t5_req6->opt0 = cpu_to_be64(opt0);
-                       t5_req6->params = cpu_to_be64(FILTER_TUPLE_V(
-                                                       cxgb4_select_ntuple(
+                       t5req6->params = cpu_to_be64(FILTER_TUPLE_V(
+                                               cxgb4_select_ntuple(
                                                ep->com.dev->rdev.lldi.ports[0],
                                                ep->l2t)));
-                       t5_req6->rsvd = cpu_to_be32(isn);
-                       PDBG("%s snd_isn %u\n", __func__,
-                            be32_to_cpu(t5_req6->rsvd));
-                       t5_req6->opt2 = cpu_to_be32(opt2);
+                       t5req6->rsvd = cpu_to_be32(isn);
+                       PDBG("%s snd_isn %u\n", __func__, t5req6->rsvd);
+                       t5req6->opt2 = cpu_to_be32(opt2);
                }
        }
 
        set_bit(ACT_OPEN_REQ, &ep->com.history);
-       return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+       ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+clip_release:
+       if (ret && ep->com.remote_addr.ss_family == AF_INET6)
+               cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0],
+                                  (const u32 *)&la6->sin6_addr.s6_addr, 1);
+       return ret;
 }
 
 static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
@@ -1169,6 +1222,8 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
        if ((status == 0) || (status == -ECONNREFUSED)) {
                if (!ep->tried_with_mpa_v1) {
                        /* this means MPA_v2 is used */
+                       event.ord = ep->ird;
+                       event.ird = ep->ord;
                        event.private_data_len = ep->plen -
                                sizeof(struct mpa_v2_conn_params);
                        event.private_data = ep->mpa_pkt +
@@ -1176,6 +1231,8 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
                                sizeof(struct mpa_v2_conn_params);
                } else {
                        /* this means MPA_v1 is used */
+                       event.ord = cur_max_read_depth(ep->com.dev);
+                       event.ird = cur_max_read_depth(ep->com.dev);
                        event.private_data_len = ep->plen;
                        event.private_data = ep->mpa_pkt +
                                sizeof(struct mpa_message);
@@ -1238,8 +1295,8 @@ static void established_upcall(struct c4iw_ep *ep)
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
        memset(&event, 0, sizeof(event));
        event.event = IW_CM_EVENT_ESTABLISHED;
-       event.ird = ep->ird;
-       event.ord = ep->ord;
+       event.ird = ep->ord;
+       event.ord = ep->ird;
        if (ep->com.cm_id) {
                PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
                ep->com.cm_id->event_handler(ep->com.cm_id, &event);
@@ -1871,7 +1928,7 @@ static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi)
 
 static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
                     struct dst_entry *dst, struct c4iw_dev *cdev,
-                    bool clear_mpa_v1)
+                    bool clear_mpa_v1, enum chip_type adapter_type)
 {
        struct neighbour *n;
        int err, step;
@@ -1906,7 +1963,8 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
                        goto out;
                ep->mtu = pdev->mtu;
                ep->tx_chan = cxgb4_port_chan(pdev);
-               ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+               ep->smac_idx = cxgb4_tp_smt_idx(adapter_type,
+                                               cxgb4_port_viid(pdev));
                step = cdev->rdev.lldi.ntxq /
                        cdev->rdev.lldi.nchan;
                ep->txq_idx = cxgb4_port_idx(pdev) * step;
@@ -1925,7 +1983,8 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
                        goto out;
                ep->mtu = dst_mtu(dst);
                ep->tx_chan = cxgb4_port_chan(pdev);
-               ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+               ep->smac_idx = cxgb4_tp_smt_idx(adapter_type,
+                                               cxgb4_port_viid(pdev));
                step = cdev->rdev.lldi.ntxq /
                        cdev->rdev.lldi.nchan;
                ep->txq_idx = cxgb4_port_idx(pdev) * step;
@@ -1998,7 +2057,8 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
                err = -EHOSTUNREACH;
                goto fail3;
        }
-       err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false);
+       err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false,
+                       ep->com.dev->rdev.lldi.adapter_type);
        if (err) {
                pr_err("%s - cannot alloc l2e.\n", __func__);
                goto fail4;
@@ -2091,6 +2151,15 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        case CPL_ERR_CONN_EXIST:
                if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) {
                        set_bit(ACT_RETRY_INUSE, &ep->com.history);
+                       if (ep->com.remote_addr.ss_family == AF_INET6) {
+                               struct sockaddr_in6 *sin6 =
+                                               (struct sockaddr_in6 *)
+                                               &ep->com.mapped_local_addr;
+                               cxgb4_clip_release(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               (const u32 *)
+                                               &sin6->sin6_addr.s6_addr, 1);
+                       }
                        remove_handle(ep->com.dev, &ep->com.dev->atid_idr,
                                        atid);
                        cxgb4_free_atid(t, atid);
@@ -2118,6 +2187,12 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        connect_reply_upcall(ep, status2errno(status));
        state_set(&ep->com, DEAD);
 
+       if (ep->com.remote_addr.ss_family == AF_INET6) {
+               struct sockaddr_in6 *sin6 =
+                       (struct sockaddr_in6 *)&ep->com.mapped_local_addr;
+               cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0],
+                                  (const u32 *)&sin6->sin6_addr.s6_addr, 1);
+       }
        if (status && act_open_has_tid(status))
                cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl));
 
@@ -2171,13 +2246,14 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
        int wscale;
        struct cpl_t5_pass_accept_rpl *rpl5 = NULL;
        int win;
+       enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;
 
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
        BUG_ON(skb_cloned(skb));
 
        skb_get(skb);
        rpl = cplhdr(skb);
-       if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+       if (!is_t4(adapter_type)) {
                skb_trim(skb, roundup(sizeof(*rpl5), 16));
                rpl5 = (void *)rpl;
                INIT_TP_WR(rpl5, ep->hwtid);
@@ -2224,12 +2300,16 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
                const struct tcphdr *tcph;
                u32 hlen = ntohl(req->hdr_len);
 
-               tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) +
-                       IP_HDR_LEN_G(hlen);
+               if (CHELSIO_CHIP_VERSION(adapter_type) <= CHELSIO_T5)
+                       tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) +
+                               IP_HDR_LEN_G(hlen);
+               else
+                       tcph = (const void *)(req + 1) +
+                               T6_ETH_HDR_LEN_G(hlen) + T6_IP_HDR_LEN_G(hlen);
                if (tcph->ece && tcph->cwr)
                        opt2 |= CCTRL_ECN_V(1);
        }
-       if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+       if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) {
                u32 isn = (prandom_u32() & ~7UL) - 1;
                opt2 |= T5_OPT_2_VALID_F;
                opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE);
@@ -2260,12 +2340,16 @@ static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb)
        return;
 }
 
-static void get_4tuple(struct cpl_pass_accept_req *req, int *iptype,
-                      __u8 *local_ip, __u8 *peer_ip,
+static void get_4tuple(struct cpl_pass_accept_req *req, enum chip_type type,
+                      int *iptype, __u8 *local_ip, __u8 *peer_ip,
                       __be16 *local_port, __be16 *peer_port)
 {
-       int eth_len = ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len));
-       int ip_len = IP_HDR_LEN_G(be32_to_cpu(req->hdr_len));
+       int eth_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ?
+                     ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len)) :
+                     T6_ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len));
+       int ip_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ?
+                    IP_HDR_LEN_G(be32_to_cpu(req->hdr_len)) :
+                    T6_IP_HDR_LEN_G(be32_to_cpu(req->hdr_len));
        struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len);
        struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len);
        struct tcphdr *tcp = (struct tcphdr *)
@@ -2302,6 +2386,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
        struct dst_entry *dst;
        __u8 local_ip[16], peer_ip[16];
        __be16 local_port, peer_port;
+       struct sockaddr_in6 *sin6;
        int err;
        u16 peer_mss = ntohs(req->tcpopt.mss);
        int iptype;
@@ -2319,7 +2404,8 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                goto reject;
        }
 
-       get_4tuple(req, &iptype, local_ip, peer_ip, &local_port, &peer_port);
+       get_4tuple(req, parent_ep->com.dev->rdev.lldi.adapter_type, &iptype,
+                  local_ip, peer_ip, &local_port, &peer_port);
 
        /* Find output route */
        if (iptype == 4)  {
@@ -2354,7 +2440,8 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                goto reject;
        }
 
-       err = import_ep(child_ep, iptype, peer_ip, dst, dev, false);
+       err = import_ep(child_ep, iptype, peer_ip, dst, dev, false,
+                       parent_ep->com.dev->rdev.lldi.adapter_type);
        if (err) {
                printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
                       __func__);
@@ -2400,9 +2487,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                sin->sin_port = peer_port;
                sin->sin_addr.s_addr = *(__be32 *)peer_ip;
        } else {
-               struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)
-                       &child_ep->com.mapped_local_addr;
-
+               sin6 = (struct sockaddr_in6 *)&child_ep->com.mapped_local_addr;
                sin6->sin6_family = PF_INET6;
                sin6->sin6_port = local_port;
                memcpy(sin6->sin6_addr.s6_addr, local_ip, 16);
@@ -2436,6 +2521,11 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
        insert_handle(dev, &dev->hwtid_idr, child_ep, child_ep->hwtid);
        accept_cr(child_ep, skb, req);
        set_bit(PASS_ACCEPT_REQ, &child_ep->com.history);
+       if (iptype == 6) {
+               sin6 = (struct sockaddr_in6 *)&child_ep->com.mapped_local_addr;
+               cxgb4_clip_get(child_ep->com.dev->rdev.lldi.ports[0],
+                              (const u32 *)&sin6->sin6_addr.s6_addr, 1);
+       }
        goto out;
 reject:
        reject_cr(dev, hwtid, skb);
@@ -2672,6 +2762,15 @@ out:
        if (release)
                release_ep_resources(ep);
        else if (ep->retry_with_mpa_v1) {
+               if (ep->com.remote_addr.ss_family == AF_INET6) {
+                       struct sockaddr_in6 *sin6 =
+                                       (struct sockaddr_in6 *)
+                                       &ep->com.mapped_local_addr;
+                       cxgb4_clip_release(
+                                       ep->com.dev->rdev.lldi.ports[0],
+                                       (const u32 *)&sin6->sin6_addr.s6_addr,
+                                       1);
+               }
                remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid);
                cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
                dst_release(ep->dst);
@@ -2874,7 +2973,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        } else {
                if (peer2peer &&
                    (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) &&
-                   (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ord == 0)
+                   (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ird == 0)
                        ep->ird = 1;
        }
 
@@ -2976,7 +3075,7 @@ static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id)
        struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->local_addr;
        struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->remote_addr;
 
-       if (get_lladdr(dev->rdev.lldi.ports[0], &addr, IFA_F_TENTATIVE)) {
+       if (!get_lladdr(dev->rdev.lldi.ports[0], &addr, IFA_F_TENTATIVE)) {
                memcpy(la6->sin6_addr.s6_addr, &addr, 16);
                memcpy(ra6->sin6_addr.s6_addr, &addr, 16);
                return 0;
@@ -3134,7 +3233,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
                goto fail2;
        }
 
-       err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true);
+       err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true,
+                       ep->com.dev->rdev.lldi.adapter_type);
        if (err) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                goto fail3;
@@ -3186,6 +3286,9 @@ static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep)
                pr_err("cxgb4_create_server6/filter failed err %d stid %d laddr %pI6 lport %d\n",
                       err, ep->stid,
                       sin6->sin6_addr.s6_addr, ntohs(sin6->sin6_port));
+       else
+               cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0],
+                              (const u32 *)&sin6->sin6_addr.s6_addr, 1);
        return err;
 }
 
@@ -3202,6 +3305,10 @@ static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep)
                                sin->sin_addr.s_addr, sin->sin_port, 0,
                                ep->com.dev->rdev.lldi.rxq_ids[0], 0, 0);
                        if (err == -EBUSY) {
+                               if (c4iw_fatal_error(&ep->com.dev->rdev)) {
+                                       err = -EIO;
+                                       break;
+                               }
                                set_current_state(TASK_UNINTERRUPTIBLE);
                                schedule_timeout(usecs_to_jiffies(100));
                        }
@@ -3334,6 +3441,7 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id)
                        ep->com.dev->rdev.lldi.ports[0], ep->stid,
                        ep->com.dev->rdev.lldi.rxq_ids[0], 0);
        } else {
+               struct sockaddr_in6 *sin6;
                c4iw_init_wr_wait(&ep->com.wr_wait);
                err = cxgb4_remove_server(
                                ep->com.dev->rdev.lldi.ports[0], ep->stid,
@@ -3342,6 +3450,9 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id)
                        goto done;
                err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait,
                                          0, 0, __func__);
+               sin6 = (struct sockaddr_in6 *)&ep->com.mapped_local_addr;
+               cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0],
+                                  (const u32 *)&sin6->sin6_addr.s6_addr, 1);
        }
        remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid);
        cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid,
@@ -3461,6 +3572,12 @@ static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb,
        mutex_unlock(&dev->rdev.stats.lock);
        connect_reply_upcall(ep, status2errno(req->retval));
        state_set(&ep->com, DEAD);
+       if (ep->com.remote_addr.ss_family == AF_INET6) {
+               struct sockaddr_in6 *sin6 =
+                       (struct sockaddr_in6 *)&ep->com.mapped_local_addr;
+               cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0],
+                                  (const u32 *)&sin6->sin6_addr.s6_addr, 1);
+       }
        remove_handle(dev, &dev->atid_idr, atid);
        cxgb4_free_atid(dev->rdev.lldi.tids, atid);
        dst_release(ep->dst);
@@ -3525,20 +3642,23 @@ static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
 
 static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
 {
-       u32 l2info;
-       u16 vlantag, len, hdr_len, eth_hdr_len;
+       __be32 l2info;
+       __be16 hdr_len, vlantag, len;
+       u16 eth_hdr_len;
+       int tcp_hdr_len, ip_hdr_len;
        u8 intf;
        struct cpl_rx_pkt *cpl = cplhdr(skb);
        struct cpl_pass_accept_req *req;
        struct tcp_options_received tmp_opt;
        struct c4iw_dev *dev;
+       enum chip_type type;
 
        dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *)));
        /* Store values from cpl_rx_pkt in temporary location. */
-       vlantag = (__force u16) cpl->vlan;
-       len = (__force u16) cpl->len;
-       l2info  = (__force u32) cpl->l2info;
-       hdr_len = (__force u16) cpl->hdr_len;
+       vlantag = cpl->vlan;
+       len = cpl->len;
+       l2info  = cpl->l2info;
+       hdr_len = cpl->hdr_len;
        intf = cpl->iff;
 
        __skb_pull(skb, sizeof(*req) + sizeof(struct rss_header));
@@ -3555,20 +3675,28 @@ static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
        memset(req, 0, sizeof(*req));
        req->l2info = cpu_to_be16(SYN_INTF_V(intf) |
                         SYN_MAC_IDX_V(RX_MACIDX_G(
-                        (__force int) htonl(l2info))) |
+                        be32_to_cpu(l2info))) |
                         SYN_XACT_MATCH_F);
-       eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ?
-                           RX_ETHHDR_LEN_G((__force int)htonl(l2info)) :
-                           RX_T5_ETHHDR_LEN_G((__force int)htonl(l2info));
-       req->hdr_len = cpu_to_be32(SYN_RX_CHAN_V(RX_CHAN_G(
-                                       (__force int) htonl(l2info))) |
-                                  TCP_HDR_LEN_V(RX_TCPHDR_LEN_G(
-                                       (__force int) htons(hdr_len))) |
-                                  IP_HDR_LEN_V(RX_IPHDR_LEN_G(
-                                       (__force int) htons(hdr_len))) |
-                                  ETH_HDR_LEN_V(RX_ETHHDR_LEN_G(eth_hdr_len)));
-       req->vlan = (__force __be16) vlantag;
-       req->len = (__force __be16) len;
+       type = dev->rdev.lldi.adapter_type;
+       tcp_hdr_len = RX_TCPHDR_LEN_G(be16_to_cpu(hdr_len));
+       ip_hdr_len = RX_IPHDR_LEN_G(be16_to_cpu(hdr_len));
+       req->hdr_len =
+               cpu_to_be32(SYN_RX_CHAN_V(RX_CHAN_G(be32_to_cpu(l2info))));
+       if (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) {
+               eth_hdr_len = is_t4(type) ?
+                               RX_ETHHDR_LEN_G(be32_to_cpu(l2info)) :
+                               RX_T5_ETHHDR_LEN_G(be32_to_cpu(l2info));
+               req->hdr_len |= cpu_to_be32(TCP_HDR_LEN_V(tcp_hdr_len) |
+                                           IP_HDR_LEN_V(ip_hdr_len) |
+                                           ETH_HDR_LEN_V(eth_hdr_len));
+       } else { /* T6 and later */
+               eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(l2info));
+               req->hdr_len |= cpu_to_be32(T6_TCP_HDR_LEN_V(tcp_hdr_len) |
+                                           T6_IP_HDR_LEN_V(ip_hdr_len) |
+                                           T6_ETH_HDR_LEN_V(eth_hdr_len));
+       }
+       req->vlan = vlantag;
+       req->len = len;
        req->tos_stid = cpu_to_be32(PASS_OPEN_TID_V(stid) |
                                    PASS_OPEN_TOS_V(tos));
        req->tcpopt.mss = htons(tmp_opt.mss_clamp);
@@ -3687,9 +3815,22 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
                goto reject;
        }
 
-       eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ?
-                           RX_ETHHDR_LEN_G(htonl(cpl->l2info)) :
-                           RX_T5_ETHHDR_LEN_G(htonl(cpl->l2info));
+       switch (CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)) {
+       case CHELSIO_T4:
+               eth_hdr_len = RX_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info));
+               break;
+       case CHELSIO_T5:
+               eth_hdr_len = RX_T5_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info));
+               break;
+       case CHELSIO_T6:
+               eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info));
+               break;
+       default:
+               pr_err("T%d Chip is not supported\n",
+                      CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type));
+               goto reject;
+       }
+
        if (eth_hdr_len == ETH_HLEN) {
                eh = (struct ethhdr *)(req + 1);
                iph = (struct iphdr *)(eh + 1);