spin_lock_init(&rdi->n_pds_lock);
        rdi->n_pds_allocated = 0;
 
+       if (rdi->dparms.nports) {
+               rdi->ports = kcalloc(rdi->dparms.nports,
+                                    sizeof(struct rvt_ibport **),
+                                    GFP_KERNEL);
+               if (!rdi->ports) {
+                       rvt_pr_err(rdi, "Could not allocate port mem.\n");
+                       ret = -ENOMEM;
+                       goto bail_mr;
+               }
+       } else {
+               rvt_pr_warn(rdi, "Driver says it has no ports.\n");
+       }
+
        /* We are now good to announce we exist */
        ret =  ib_register_device(&rdi->ibdev, rdi->driver_f.port_callback);
        if (ret) {
        rvt_mr_exit(rdi);
 }
 EXPORT_SYMBOL(rvt_unregister_device);
+
+/*
+ * Keep track of a list of ports. No need to have a detach port.
+ * They persist until the driver goes away.
+ */
+void rvt_attach_port(struct rvt_dev_info *rdi, struct rvt_ibport *port,
+                    int portnum)
+{
+       rdi->ports[portnum] = port;
+}
+EXPORT_SYMBOL(rvt_attach_port);
 
  * rdmavt layer.
  */
 
+#include <linux/spinlock.h>
+#include <linux/list.h>
 #include "ib_verbs.h"
 
 #define RVT_MULTICAST_LID_BASE 0xC000
 
 /* End QP section */
 
+struct rvt_ibport {
+       struct rvt_qp __rcu *qp[2];
+       struct ib_mad_agent *send_agent;        /* agent for SMI (traps) */
+       struct rb_root mcast_tree;
+       spinlock_t lock;                /* protect changes in this struct */
+
+       /* non-zero when timer is set */
+       unsigned long mkey_lease_timeout;
+       unsigned long trap_timeout;
+       __be64 gid_prefix;      /* in network order */
+       __be64 mkey;
+       u64 tid;
+       u32 port_cap_flags;
+       u32 pma_sample_start;
+       u32 pma_sample_interval;
+       __be16 pma_counter_select[5];
+       u16 pma_tag;
+       u16 mkey_lease_period;
+       u16 sm_lid;
+       u8 sm_sl;
+       u8 mkeyprot;
+       u8 subnet_timeout;
+       u8 vl_high_limit;
+
+       /*
+        * Driver is expected to keep these up to date. These
+        * counters are informational only and not required to be
+        * completely accurate.
+        */
+       u64 n_rc_resends;
+       u64 n_seq_naks;
+       u64 n_rdma_seq;
+       u64 n_rnr_naks;
+       u64 n_other_naks;
+       u64 n_loop_pkts;
+       u64 n_pkt_drops;
+       u64 n_vl15_dropped;
+       u64 n_rc_timeouts;
+       u64 n_dmawait;
+       u64 n_unaligned;
+       u64 n_rc_dupreq;
+       u64 n_rc_seqnak;
+       u16 pkey_violations;
+       u16 qkey_violations;
+       u16 mkey_violations;
+
+       /* Hot-path per CPU counters to avoid cacheline trading to update */
+       u64 z_rc_acks;
+       u64 z_rc_qacks;
+       u64 z_rc_delayed_comp;
+       u64 __percpu *rc_acks;
+       u64 __percpu *rc_qacks;
+       u64 __percpu *rc_delayed_comp;
+
+       void *priv; /* driver private data */
+
+       /* TODO: Move sm_ah and smi_ah into here as well*/
+};
+
 /*
  * Things that are driver specific, module parameters in hfi1 and qib
  */
         * For instance special module parameters. Goes here.
         */
        unsigned int lkey_table_size;
+       int nports;
 };
 
 /*
        spinlock_t n_ahs_lock; /* Protect ah allocated count */
 
        int flags;
+       struct rvt_ibport **ports;
 };
 
 static inline struct rvt_pd *ibpd_to_rvtpd(struct ib_pd *ibpd)
 int rvt_register_device(struct rvt_dev_info *rvd);
 void rvt_unregister_device(struct rvt_dev_info *rvd);
 int rvt_check_ah(struct ib_device *ibdev, struct ib_ah_attr *ah_attr);
+void rvt_attach_port(struct rvt_dev_info *rdi, struct rvt_ibport *port,
+                    int portnum);
 int rvt_rkey_ok(struct rvt_qp *qp, struct rvt_sge *sge,
                u32 len, u64 vaddr, u32 rkey, int acc);
 int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd,
                struct rvt_sge *isge, struct ib_sge *sge, int acc);
-
 #endif          /* DEF_RDMA_VT_H */