RDMA/cxgb4: Fix vlan support
[cascardo/linux.git] / drivers / infiniband / hw / cxgb4 / cm.c
index 185452a..28114e6 100644 (file)
@@ -47,6 +47,8 @@
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
 
+#include <rdma/ib_addr.h>
+
 #include "iw_cxgb4.h"
 
 static char *states[] = {
@@ -341,10 +343,7 @@ static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp)
 
 static struct net_device *get_real_dev(struct net_device *egress_dev)
 {
-       struct net_device *phys_dev = egress_dev;
-       if (egress_dev->priv_flags & IFF_802_1Q_VLAN)
-               phys_dev = vlan_dev_real_dev(egress_dev);
-       return phys_dev;
+       return rdma_vlan_dev_real_dev(egress_dev) ? : egress_dev;
 }
 
 static int our_interface(struct c4iw_dev *dev, struct net_device *egress_dev)
@@ -587,6 +586,10 @@ static int send_connect(struct c4iw_ep *ep)
                opt2 |= SACK_EN(1);
        if (wscale && enable_tcp_window_scaling)
                opt2 |= WND_SCALE_EN(1);
+       if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+               opt2 |= T5_OPT_2_VALID;
+               opt2 |= V_CONG_CNTRL(CONG_ALG_TAHOE);
+       }
        t4_set_arp_err_handler(skb, NULL, act_open_req_arp_failure);
 
        if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
@@ -996,7 +999,7 @@ static void close_complete_upcall(struct c4iw_ep *ep, int status)
 static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
 {
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
-       state_set(&ep->com, ABORTING);
+       __state_set(&ep->com, ABORTING);
        set_bit(ABORT_CONN, &ep->com.history);
        return send_abort(ep, skb, gfp);
 }
@@ -1154,7 +1157,7 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
        return credits;
 }
 
-static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
+static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 {
        struct mpa_message *mpa;
        struct mpa_v2_conn_params *mpa_v2_params;
@@ -1164,6 +1167,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
        struct c4iw_qp_attributes attrs;
        enum c4iw_qp_attr_mask mask;
        int err;
+       int disconnect = 0;
 
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 
@@ -1173,7 +1177,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
         * will abort the connection.
         */
        if (stop_ep_timer(ep))
-               return;
+               return 0;
 
        /*
         * If we get more than the supported amount of private data
@@ -1195,7 +1199,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
         * if we don't even have the mpa message, then bail.
         */
        if (ep->mpa_pkt_len < sizeof(*mpa))
-               return;
+               return 0;
        mpa = (struct mpa_message *) ep->mpa_pkt;
 
        /* Validate MPA header. */
@@ -1235,7 +1239,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
         * We'll continue process when more data arrives.
         */
        if (ep->mpa_pkt_len < (sizeof(*mpa) + plen))
-               return;
+               return 0;
 
        if (mpa->flags & MPA_REJECT) {
                err = -ECONNREFUSED;
@@ -1337,9 +1341,11 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
                attrs.layer_etype = LAYER_MPA | DDP_LLP;
                attrs.ecode = MPA_NOMATCH_RTR;
                attrs.next_state = C4IW_QP_STATE_TERMINATE;
+               attrs.send_term = 1;
                err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
-                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
                err = -ENOMEM;
+               disconnect = 1;
                goto out;
        }
 
@@ -1355,9 +1361,11 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
                attrs.layer_etype = LAYER_MPA | DDP_LLP;
                attrs.ecode = MPA_INSUFF_IRD;
                attrs.next_state = C4IW_QP_STATE_TERMINATE;
+               attrs.send_term = 1;
                err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
-                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
                err = -ENOMEM;
+               disconnect = 1;
                goto out;
        }
        goto out;
@@ -1366,7 +1374,7 @@ err:
        send_abort(ep, skb, GFP_KERNEL);
 out:
        connect_reply_upcall(ep, err);
-       return;
+       return disconnect;
 }
 
 static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
@@ -1524,6 +1532,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
        unsigned int tid = GET_TID(hdr);
        struct tid_info *t = dev->rdev.lldi.tids;
        __u8 status = hdr->status;
+       int disconnect = 0;
 
        ep = lookup_tid(t, tid);
        if (!ep)
@@ -1539,7 +1548,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
        switch (ep->com.state) {
        case MPA_REQ_SENT:
                ep->rcv_seq += dlen;
-               process_mpa_reply(ep, skb);
+               disconnect = process_mpa_reply(ep, skb);
                break;
        case MPA_REQ_WAIT:
                ep->rcv_seq += dlen;
@@ -1555,13 +1564,16 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
                               ep->com.state, ep->hwtid, status);
                attrs.next_state = C4IW_QP_STATE_TERMINATE;
                c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
-                              C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+                              C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+               disconnect = 1;
                break;
        }
        default:
                break;
        }
        mutex_unlock(&ep->com.mutex);
+       if (disconnect)
+               c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
        return 0;
 }
 
@@ -1733,16 +1745,16 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
                if (!ep->l2t)
                        goto out;
                ep->mtu = dst_mtu(dst);
-               ep->tx_chan = cxgb4_port_chan(n->dev);
-               ep->smac_idx = (cxgb4_port_viid(n->dev) & 0x7F) << 1;
+               ep->tx_chan = cxgb4_port_chan(pdev);
+               ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
                step = cdev->rdev.lldi.ntxq /
                        cdev->rdev.lldi.nchan;
-               ep->txq_idx = cxgb4_port_idx(n->dev) * step;
-               ep->ctrlq_idx = cxgb4_port_idx(n->dev);
+               ep->txq_idx = cxgb4_port_idx(pdev) * step;
+               ep->ctrlq_idx = cxgb4_port_idx(pdev);
                step = cdev->rdev.lldi.nrxq /
                        cdev->rdev.lldi.nchan;
                ep->rss_qid = cdev->rdev.lldi.rxq_ids[
-                       cxgb4_port_idx(n->dev) * step];
+                       cxgb4_port_idx(pdev) * step];
 
                if (clear_mpa_v1) {
                        ep->retry_with_mpa_v1 = 0;
@@ -2009,6 +2021,10 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
                if (tcph->ece && tcph->cwr)
                        opt2 |= CCTRL_ECN(1);
        }
+       if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+               opt2 |= T5_OPT_2_VALID;
+               opt2 |= V_CONG_CNTRL(CONG_ALG_TAHOE);
+       }
 
        rpl = cplhdr(skb);
        INIT_TP_WR(rpl, ep->hwtid);
@@ -3482,9 +3498,9 @@ static void process_timeout(struct c4iw_ep *ep)
                        __func__, ep, ep->hwtid, ep->com.state);
                abort = 0;
        }
-       mutex_unlock(&ep->com.mutex);
        if (abort)
                abort_connection(ep, NULL, GFP_KERNEL);
+       mutex_unlock(&ep->com.mutex);
        c4iw_put_ep(&ep->com);
 }