include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / infiniband / hw / cxgb3 / iwch_provider.c
index 5f43806..19b1c4a 100644 (file)
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/list.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
+#include <linux/inetdevice.h>
+#include <linux/slab.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -56,6 +59,7 @@
 #include "iwch_provider.h"
 #include "iwch_cm.h"
 #include "iwch_user.h"
+#include "common.h"
 
 static int iwch_modify_port(struct ib_device *ibdev,
                            u8 port, int port_modify_mask,
@@ -184,7 +188,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
        entries = roundup_pow_of_two(entries);
        chp->cq.size_log2 = ilog2(entries);
 
-       if (cxio_create_cq(&rhp->rdev, &chp->cq)) {
+       if (cxio_create_cq(&rhp->rdev, &chp->cq, !ucontext)) {
                kfree(chp);
                return ERR_PTR(-ENOMEM);
        }
@@ -193,7 +197,11 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
        spin_lock_init(&chp->lock);
        atomic_set(&chp->refcnt, 1);
        init_waitqueue_head(&chp->wait);
-       insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
+       if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) {
+               cxio_destroy_cq(&chp->rhp->rdev, &chp->cq);
+               kfree(chp);
+               return ERR_PTR(-ENOMEM);
+       }
 
        if (ucontext) {
                struct iwch_mm_entry *mm;
@@ -747,7 +755,12 @@ static struct ib_mw *iwch_alloc_mw(struct ib_pd *pd)
        mhp->attr.type = TPT_MW;
        mhp->attr.stag = stag;
        mmid = (stag) >> 8;
-       insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+       mhp->ibmw.rkey = stag;
+       if (insert_handle(rhp, &rhp->mmidr, mhp, mmid)) {
+               cxio_deallocate_window(&rhp->rdev, mhp->attr.stag);
+               kfree(mhp);
+               return ERR_PTR(-ENOMEM);
+       }
        PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __func__, mmid, mhp, stag);
        return &(mhp->ibmw);
 }
@@ -775,37 +788,43 @@ static struct ib_mr *iwch_alloc_fast_reg_mr(struct ib_pd *pd, int pbl_depth)
        struct iwch_mr *mhp;
        u32 mmid;
        u32 stag = 0;
-       int ret;
+       int ret = 0;
 
        php = to_iwch_pd(pd);
        rhp = php->rhp;
        mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
        if (!mhp)
-               return ERR_PTR(-ENOMEM);
+               goto err;
 
        mhp->rhp = rhp;
        ret = iwch_alloc_pbl(mhp, pbl_depth);
-       if (ret) {
-               kfree(mhp);
-               return ERR_PTR(ret);
-       }
+       if (ret)
+               goto err1;
        mhp->attr.pbl_size = pbl_depth;
        ret = cxio_allocate_stag(&rhp->rdev, &stag, php->pdid,
                                 mhp->attr.pbl_size, mhp->attr.pbl_addr);
-       if (ret) {
-               iwch_free_pbl(mhp);
-               kfree(mhp);
-               return ERR_PTR(ret);
-       }
+       if (ret)
+               goto err2;
        mhp->attr.pdid = php->pdid;
        mhp->attr.type = TPT_NON_SHARED_MR;
        mhp->attr.stag = stag;
        mhp->attr.state = 1;
        mmid = (stag) >> 8;
        mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
-       insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+       if (insert_handle(rhp, &rhp->mmidr, mhp, mmid))
+               goto err3;
+
        PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __func__, mmid, mhp, stag);
        return &(mhp->ibmr);
+err3:
+       cxio_dereg_mem(&rhp->rdev, stag, mhp->attr.pbl_size,
+                      mhp->attr.pbl_addr);
+err2:
+       iwch_free_pbl(mhp);
+err1:
+       kfree(mhp);
+err:
+       return ERR_PTR(ret);
 }
 
 static struct ib_fast_reg_page_list *iwch_alloc_fastreg_pbl(
@@ -958,7 +977,13 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
        spin_lock_init(&qhp->lock);
        init_waitqueue_head(&qhp->wait);
        atomic_set(&qhp->refcnt, 1);
-       insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.qpid);
+
+       if (insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.qpid)) {
+               cxio_destroy_qp(&rhp->rdev, &qhp->wq,
+                       ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
+               kfree(qhp);
+               return ERR_PTR(-ENOMEM);
+       }
 
        if (udata) {
 
@@ -1005,10 +1030,10 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
        qhp->ibqp.qp_num = qhp->wq.qpid;
        init_timer(&(qhp->timer));
        PDBG("%s sq_num_entries %d, rq_num_entries %d "
-            "qpid 0x%0x qhp %p dma_addr 0x%llx size %d\n",
+            "qpid 0x%0x qhp %p dma_addr 0x%llx size %d rq_addr 0x%x\n",
             __func__, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
             qhp->wq.qpid, qhp, (unsigned long long) qhp->wq.dma_addr,
-            1 << qhp->wq.size_log2);
+            1 << qhp->wq.size_log2, qhp->wq.rq_addr);
        return &qhp->ibqp;
 }
 
@@ -1100,9 +1125,7 @@ static u64 fw_vers_string_to_u64(struct iwch_dev *iwch_dev)
        char *cp, *next;
        unsigned fw_maj, fw_min, fw_mic;
 
-       rtnl_lock();
        lldev->ethtool_ops->get_drvinfo(lldev, &info);
-       rtnl_unlock();
 
        next = info.fw_version + 1;
        cp = strsep(&next, ".");
@@ -1129,6 +1152,7 @@ static int iwch_query_device(struct ib_device *ibdev,
        props->hw_ver = dev->rdev.t3cdev_p->type;
        props->fw_ver = fw_vers_string_to_u64(dev);
        props->device_cap_flags = dev->device_cap_flags;
+       props->page_size_cap = dev->attr.mem_pgsizes_bitmask;
        props->vendor_id = (u32)dev->rdev.rnic_info.pdev->vendor;
        props->vendor_part_id = (u32)dev->rdev.rnic_info.pdev->device;
        props->max_mr_size = dev->attr.max_mr_size;
@@ -1151,14 +1175,42 @@ static int iwch_query_device(struct ib_device *ibdev,
 static int iwch_query_port(struct ib_device *ibdev,
                           u8 port, struct ib_port_attr *props)
 {
+       struct iwch_dev *dev;
+       struct net_device *netdev;
+       struct in_device *inetdev;
+
        PDBG("%s ibdev %p\n", __func__, ibdev);
+
+       dev = to_iwch_dev(ibdev);
+       netdev = dev->rdev.port_info.lldevs[port-1];
+
+       memset(props, 0, sizeof(struct ib_port_attr));
        props->max_mtu = IB_MTU_4096;
-       props->lid = 0;
-       props->lmc = 0;
-       props->sm_lid = 0;
-       props->sm_sl = 0;
-       props->state = IB_PORT_ACTIVE;
-       props->phys_state = 0;
+       if (netdev->mtu >= 4096)
+               props->active_mtu = IB_MTU_4096;
+       else if (netdev->mtu >= 2048)
+               props->active_mtu = IB_MTU_2048;
+       else if (netdev->mtu >= 1024)
+               props->active_mtu = IB_MTU_1024;
+       else if (netdev->mtu >= 512)
+               props->active_mtu = IB_MTU_512;
+       else
+               props->active_mtu = IB_MTU_256;
+
+       if (!netif_carrier_ok(netdev))
+               props->state = IB_PORT_DOWN;
+       else {
+               inetdev = in_dev_get(netdev);
+               if (inetdev) {
+                       if (inetdev->ifa_list)
+                               props->state = IB_PORT_ACTIVE;
+                       else
+                               props->state = IB_PORT_INIT;
+                       in_dev_put(inetdev);
+               } else
+                       props->state = IB_PORT_INIT;
+       }
+
        props->port_cap_flags =
            IB_PORT_CM_SUP |
            IB_PORT_SNMP_TUNNEL_SUP |
@@ -1167,7 +1219,6 @@ static int iwch_query_port(struct ib_device *ibdev,
            IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP;
        props->gid_tbl_len = 1;
        props->pkey_tbl_len = 1;
-       props->qkey_viol_cntr = 0;
        props->active_width = 2;
        props->active_speed = 2;
        props->max_msg_sz = -1;
@@ -1184,28 +1235,6 @@ static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
        return sprintf(buf, "%d\n", iwch_dev->rdev.t3cdev_p->type);
 }
 
-static int fw_supports_fastreg(struct iwch_dev *iwch_dev)
-{
-       struct ethtool_drvinfo info;
-       struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
-       char *cp, *next;
-       unsigned fw_maj, fw_min;
-
-       rtnl_lock();
-       lldev->ethtool_ops->get_drvinfo(lldev, &info);
-       rtnl_unlock();
-
-       next = info.fw_version+1;
-       cp = strsep(&next, ".");
-       sscanf(cp, "%i", &fw_maj);
-       cp = strsep(&next, ".");
-       sscanf(cp, "%i", &fw_min);
-
-       PDBG("%s maj %u min %u\n", __func__, fw_maj, fw_min);
-
-       return fw_maj > 6 || (fw_maj == 6 && fw_min > 0);
-}
-
 static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
@@ -1214,9 +1243,7 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, ch
        struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
 
        PDBG("%s dev 0x%p\n", __func__, dev);
-       rtnl_lock();
        lldev->ethtool_ops->get_drvinfo(lldev, &info);
-       rtnl_unlock();
        return sprintf(buf, "%s\n", info.fw_version);
 }
 
@@ -1229,9 +1256,7 @@ static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
        struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
 
        PDBG("%s dev 0x%p\n", __func__, dev);
-       rtnl_lock();
        lldev->ethtool_ops->get_drvinfo(lldev, &info);
-       rtnl_unlock();
        return sprintf(buf, "%s\n", info.driver);
 }
 
@@ -1245,6 +1270,61 @@ static ssize_t show_board(struct device *dev, struct device_attribute *attr,
                       iwch_dev->rdev.rnic_info.pdev->device);
 }
 
+static int iwch_get_mib(struct ib_device *ibdev,
+                       union rdma_protocol_stats *stats)
+{
+       struct iwch_dev *dev;
+       struct tp_mib_stats m;
+       int ret;
+
+       PDBG("%s ibdev %p\n", __func__, ibdev);
+       dev = to_iwch_dev(ibdev);
+       ret = dev->rdev.t3cdev_p->ctl(dev->rdev.t3cdev_p, RDMA_GET_MIB, &m);
+       if (ret)
+               return -ENOSYS;
+
+       memset(stats, 0, sizeof *stats);
+       stats->iw.ipInReceives = ((u64) m.ipInReceive_hi << 32) +
+                               m.ipInReceive_lo;
+       stats->iw.ipInHdrErrors = ((u64) m.ipInHdrErrors_hi << 32) +
+                                 m.ipInHdrErrors_lo;
+       stats->iw.ipInAddrErrors = ((u64) m.ipInAddrErrors_hi << 32) +
+                                  m.ipInAddrErrors_lo;
+       stats->iw.ipInUnknownProtos = ((u64) m.ipInUnknownProtos_hi << 32) +
+                                     m.ipInUnknownProtos_lo;
+       stats->iw.ipInDiscards = ((u64) m.ipInDiscards_hi << 32) +
+                                m.ipInDiscards_lo;
+       stats->iw.ipInDelivers = ((u64) m.ipInDelivers_hi << 32) +
+                                m.ipInDelivers_lo;
+       stats->iw.ipOutRequests = ((u64) m.ipOutRequests_hi << 32) +
+                                 m.ipOutRequests_lo;
+       stats->iw.ipOutDiscards = ((u64) m.ipOutDiscards_hi << 32) +
+                                 m.ipOutDiscards_lo;
+       stats->iw.ipOutNoRoutes = ((u64) m.ipOutNoRoutes_hi << 32) +
+                                 m.ipOutNoRoutes_lo;
+       stats->iw.ipReasmTimeout = (u64) m.ipReasmTimeout;
+       stats->iw.ipReasmReqds = (u64) m.ipReasmReqds;
+       stats->iw.ipReasmOKs = (u64) m.ipReasmOKs;
+       stats->iw.ipReasmFails = (u64) m.ipReasmFails;
+       stats->iw.tcpActiveOpens = (u64) m.tcpActiveOpens;
+       stats->iw.tcpPassiveOpens = (u64) m.tcpPassiveOpens;
+       stats->iw.tcpAttemptFails = (u64) m.tcpAttemptFails;
+       stats->iw.tcpEstabResets = (u64) m.tcpEstabResets;
+       stats->iw.tcpOutRsts = (u64) m.tcpOutRsts;
+       stats->iw.tcpCurrEstab = (u64) m.tcpCurrEstab;
+       stats->iw.tcpInSegs = ((u64) m.tcpInSegs_hi << 32) +
+                             m.tcpInSegs_lo;
+       stats->iw.tcpOutSegs = ((u64) m.tcpOutSegs_hi << 32) +
+                              m.tcpOutSegs_lo;
+       stats->iw.tcpRetransSegs = ((u64) m.tcpRetransSeg_hi << 32) +
+                                 m.tcpRetransSeg_lo;
+       stats->iw.tcpInErrs = ((u64) m.tcpInErrs_hi << 32) +
+                             m.tcpInErrs_lo;
+       stats->iw.tcpRtoMin = (u64) m.tcpRtoMin;
+       stats->iw.tcpRtoMax = (u64) m.tcpRtoMax;
+       return 0;
+}
+
 static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
 static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
 static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
@@ -1254,7 +1334,7 @@ static struct device_attribute *iwch_class_attributes[] = {
        &dev_attr_hw_rev,
        &dev_attr_fw_ver,
        &dev_attr_hca_type,
-       &dev_attr_board_id
+       &dev_attr_board_id,
 };
 
 int iwch_register_device(struct iwch_dev *dev)
@@ -1267,10 +1347,12 @@ int iwch_register_device(struct iwch_dev *dev)
        memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid));
        memcpy(&dev->ibdev.node_guid, dev->rdev.t3cdev_p->lldev->dev_addr, 6);
        dev->ibdev.owner = THIS_MODULE;
-       dev->device_cap_flags = IB_DEVICE_ZERO_STAG |
-                               IB_DEVICE_MEM_WINDOW;
-       if (fw_supports_fastreg(dev))
-               dev->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
+       dev->device_cap_flags = IB_DEVICE_LOCAL_DMA_LKEY |
+                               IB_DEVICE_MEM_WINDOW |
+                               IB_DEVICE_MEM_MGT_EXTENSIONS;
+
+       /* cxgb3 supports STag 0. */
+       dev->ibdev.local_dma_lkey = 0;
 
        dev->ibdev.uverbs_cmd_mask =
            (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
@@ -1325,15 +1407,13 @@ int iwch_register_device(struct iwch_dev *dev)
        dev->ibdev.alloc_fast_reg_mr = iwch_alloc_fast_reg_mr;
        dev->ibdev.alloc_fast_reg_page_list = iwch_alloc_fastreg_pbl;
        dev->ibdev.free_fast_reg_page_list = iwch_free_fastreg_pbl;
-
        dev->ibdev.attach_mcast = iwch_multicast_attach;
        dev->ibdev.detach_mcast = iwch_multicast_detach;
        dev->ibdev.process_mad = iwch_process_mad;
-
        dev->ibdev.req_notify_cq = iwch_arm_cq;
        dev->ibdev.post_send = iwch_post_send;
        dev->ibdev.post_recv = iwch_post_receive;
-
+       dev->ibdev.get_protocol_stats = iwch_get_mib;
 
        dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
        if (!dev->ibdev.iwcm)
@@ -1363,6 +1443,7 @@ int iwch_register_device(struct iwch_dev *dev)
 bail2:
        ib_unregister_device(&dev->ibdev);
 bail1:
+       kfree(dev->ibdev.iwcm);
        return ret;
 }
 
@@ -1375,5 +1456,6 @@ void iwch_unregister_device(struct iwch_dev *dev)
                device_remove_file(&dev->ibdev.dev,
                                   iwch_class_attributes[i]);
        ib_unregister_device(&dev->ibdev);
+       kfree(dev->ibdev.iwcm);
        return;
 }