Commit f12c0372 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  RDMA/nes: Formatting cleanup
  RDMA/nes: Add support for SFP+ PHY
  RDMA/nes: Use LRO
  IPoIB: Copy child MTU from parent
  IB/mthca: Avoid changing userspace ABI to handle DMA write barrier attribute
  IB/mthca: Avoid recycling old FMR R_Keys too soon
  mlx4_core: Avoid recycling old FMR R_Keys too soon
  IB/ehca: Allocate event queue size depending on max number of CQs and QPs
  IPoIB: Use separate CQ for UD send completions
  IB/iser: Count FMR alignment violations per session
  IB/iser: Move high-volume debug output to higher debug level
  IB/ehca: handle negative return value from ibmebus_request_irq() properly
  RDMA/cxgb3: Support peer-2-peer connection setup
  RDMA/cxgb3: Set the max_mr_size device attribute correctly
  RDMA/cxgb3: Correctly serialize peer abort path
  mlx4_core: Add a way to set the "collapsed" CQ flag
parents eeb85d0b 7495ab68
...@@ -456,7 +456,8 @@ void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count) ...@@ -456,7 +456,8 @@ void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
ptr = cq->sw_rptr; ptr = cq->sw_rptr;
while (!Q_EMPTY(ptr, cq->sw_wptr)) { while (!Q_EMPTY(ptr, cq->sw_wptr)) {
cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2)); cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2));
if ((SQ_TYPE(*cqe) || (CQE_OPCODE(*cqe) == T3_READ_RESP)) && if ((SQ_TYPE(*cqe) ||
((CQE_OPCODE(*cqe) == T3_READ_RESP) && wq->oldest_read)) &&
(CQE_QPID(*cqe) == wq->qpid)) (CQE_QPID(*cqe) == wq->qpid))
(*count)++; (*count)++;
ptr++; ptr++;
...@@ -829,7 +830,8 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr) ...@@ -829,7 +830,8 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
wqe->mpaattrs = attr->mpaattrs; wqe->mpaattrs = attr->mpaattrs;
wqe->qpcaps = attr->qpcaps; wqe->qpcaps = attr->qpcaps;
wqe->ulpdu_size = cpu_to_be16(attr->tcp_emss); wqe->ulpdu_size = cpu_to_be16(attr->tcp_emss);
wqe->flags = cpu_to_be32(attr->flags); wqe->rqe_count = cpu_to_be16(attr->rqe_count);
wqe->flags_rtr_type = cpu_to_be16(attr->flags|V_RTR_TYPE(attr->rtr_type));
wqe->ord = cpu_to_be32(attr->ord); wqe->ord = cpu_to_be32(attr->ord);
wqe->ird = cpu_to_be32(attr->ird); wqe->ird = cpu_to_be32(attr->ird);
wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr); wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr);
...@@ -1134,6 +1136,18 @@ int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe, ...@@ -1134,6 +1136,18 @@ int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
*/ */
if (RQ_TYPE(*hw_cqe) && (CQE_OPCODE(*hw_cqe) == T3_READ_RESP)) { if (RQ_TYPE(*hw_cqe) && (CQE_OPCODE(*hw_cqe) == T3_READ_RESP)) {
/*
* If this is an unsolicited read response, then the read
* was generated by the kernel driver as part of peer-2-peer
* connection setup. So ignore the completion.
*/
if (!wq->oldest_read) {
if (CQE_STATUS(*hw_cqe))
wq->error = 1;
ret = -1;
goto skip_cqe;
}
/* /*
* Don't write to the HWCQ, so create a new read req CQE * Don't write to the HWCQ, so create a new read req CQE
* in local memory. * in local memory.
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#define T3_MAX_PBL_SIZE 256 #define T3_MAX_PBL_SIZE 256
#define T3_MAX_RQ_SIZE 1024 #define T3_MAX_RQ_SIZE 1024
#define T3_MAX_NUM_STAG (1<<15) #define T3_MAX_NUM_STAG (1<<15)
#define T3_MAX_MR_SIZE 0x100000000ULL
#define T3_STAG_UNSET 0xffffffff #define T3_STAG_UNSET 0xffffffff
......
...@@ -278,6 +278,17 @@ enum t3_qp_caps { ...@@ -278,6 +278,17 @@ enum t3_qp_caps {
uP_RI_QP_STAG0_ENABLE = 0x10 uP_RI_QP_STAG0_ENABLE = 0x10
} __attribute__ ((packed)); } __attribute__ ((packed));
enum rdma_init_rtr_types {
RTR_READ = 1,
RTR_WRITE = 2,
RTR_SEND = 3,
};
#define S_RTR_TYPE 2
#define M_RTR_TYPE 0x3
#define V_RTR_TYPE(x) ((x) << S_RTR_TYPE)
#define G_RTR_TYPE(x) ((((x) >> S_RTR_TYPE)) & M_RTR_TYPE)
struct t3_rdma_init_attr { struct t3_rdma_init_attr {
u32 tid; u32 tid;
u32 qpid; u32 qpid;
...@@ -293,7 +304,9 @@ struct t3_rdma_init_attr { ...@@ -293,7 +304,9 @@ struct t3_rdma_init_attr {
u32 ird; u32 ird;
u64 qp_dma_addr; u64 qp_dma_addr;
u32 qp_dma_size; u32 qp_dma_size;
u32 flags; enum rdma_init_rtr_types rtr_type;
u16 flags;
u16 rqe_count;
u32 irs; u32 irs;
}; };
...@@ -309,8 +322,8 @@ struct t3_rdma_init_wr { ...@@ -309,8 +322,8 @@ struct t3_rdma_init_wr {
u8 mpaattrs; /* 5 */ u8 mpaattrs; /* 5 */
u8 qpcaps; u8 qpcaps;
__be16 ulpdu_size; __be16 ulpdu_size;
__be32 flags; /* bits 31-1 - reservered */ __be16 flags_rtr_type;
/* bit 0 - set if RECV posted */ __be16 rqe_count;
__be32 ord; /* 6 */ __be32 ord; /* 6 */
__be32 ird; __be32 ird;
__be64 qp_dma_addr; /* 7 */ __be64 qp_dma_addr; /* 7 */
...@@ -324,7 +337,7 @@ struct t3_genbit { ...@@ -324,7 +337,7 @@ struct t3_genbit {
}; };
enum rdma_init_wr_flags { enum rdma_init_wr_flags {
RECVS_POSTED = (1<<0), MPA_INITIATOR = (1<<0),
PRIV_QP = (1<<1), PRIV_QP = (1<<1),
}; };
......
...@@ -83,6 +83,7 @@ static void rnic_init(struct iwch_dev *rnicp) ...@@ -83,6 +83,7 @@ static void rnic_init(struct iwch_dev *rnicp)
rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE; rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE;
rnicp->attr.max_pds = T3_MAX_NUM_PD - 1; rnicp->attr.max_pds = T3_MAX_NUM_PD - 1;
rnicp->attr.mem_pgsizes_bitmask = 0x7FFF; /* 4KB-128MB */ rnicp->attr.mem_pgsizes_bitmask = 0x7FFF; /* 4KB-128MB */
rnicp->attr.max_mr_size = T3_MAX_MR_SIZE;
rnicp->attr.can_resize_wq = 0; rnicp->attr.can_resize_wq = 0;
rnicp->attr.max_rdma_reads_per_qp = 8; rnicp->attr.max_rdma_reads_per_qp = 8;
rnicp->attr.max_rdma_read_resources = rnicp->attr.max_rdma_read_resources =
......
...@@ -66,6 +66,7 @@ struct iwch_rnic_attributes { ...@@ -66,6 +66,7 @@ struct iwch_rnic_attributes {
* size (4k)^i. Phys block list mode unsupported. * size (4k)^i. Phys block list mode unsupported.
*/ */
u32 mem_pgsizes_bitmask; u32 mem_pgsizes_bitmask;
u64 max_mr_size;
u8 can_resize_wq; u8 can_resize_wq;
/* /*
......
This diff is collapsed.
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#define put_ep(ep) { \ #define put_ep(ep) { \
PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__, \ PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__, \
ep, atomic_read(&((ep)->kref.refcount))); \ ep, atomic_read(&((ep)->kref.refcount))); \
WARN_ON(atomic_read(&((ep)->kref.refcount)) < 1); \
kref_put(&((ep)->kref), __free_ep); \ kref_put(&((ep)->kref), __free_ep); \
} }
...@@ -225,5 +226,6 @@ int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, st ...@@ -225,5 +226,6 @@ int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, st
int __init iwch_cm_init(void); int __init iwch_cm_init(void);
void __exit iwch_cm_term(void); void __exit iwch_cm_term(void);
extern int peer2peer;
#endif /* _IWCH_CM_H_ */ #endif /* _IWCH_CM_H_ */
...@@ -998,7 +998,7 @@ static int iwch_query_device(struct ib_device *ibdev, ...@@ -998,7 +998,7 @@ static int iwch_query_device(struct ib_device *ibdev,
props->device_cap_flags = dev->device_cap_flags; props->device_cap_flags = dev->device_cap_flags;
props->vendor_id = (u32)dev->rdev.rnic_info.pdev->vendor; props->vendor_id = (u32)dev->rdev.rnic_info.pdev->vendor;
props->vendor_part_id = (u32)dev->rdev.rnic_info.pdev->device; props->vendor_part_id = (u32)dev->rdev.rnic_info.pdev->device;
props->max_mr_size = ~0ull; props->max_mr_size = dev->attr.max_mr_size;
props->max_qp = dev->attr.max_qps; props->max_qp = dev->attr.max_qps;
props->max_qp_wr = dev->attr.max_wrs; props->max_qp_wr = dev->attr.max_wrs;
props->max_sge = dev->attr.max_sge_per_wr; props->max_sge = dev->attr.max_sge_per_wr;
......
...@@ -118,6 +118,7 @@ enum IWCH_QP_FLAGS { ...@@ -118,6 +118,7 @@ enum IWCH_QP_FLAGS {
}; };
struct iwch_mpa_attributes { struct iwch_mpa_attributes {
u8 initiator;
u8 recv_marker_enabled; u8 recv_marker_enabled;
u8 xmit_marker_enabled; /* iWARP: enable inbound Read Resp. */ u8 xmit_marker_enabled; /* iWARP: enable inbound Read Resp. */
u8 crc_enabled; u8 crc_enabled;
...@@ -322,6 +323,7 @@ enum iwch_qp_query_flags { ...@@ -322,6 +323,7 @@ enum iwch_qp_query_flags {
IWCH_QP_QUERY_TEST_USERWRITE = 0x32 /* Test special */ IWCH_QP_QUERY_TEST_USERWRITE = 0x32 /* Test special */
}; };
u16 iwch_rqes_posted(struct iwch_qp *qhp);
int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
struct ib_send_wr **bad_wr); struct ib_send_wr **bad_wr);
int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
...@@ -331,6 +333,7 @@ int iwch_bind_mw(struct ib_qp *qp, ...@@ -331,6 +333,7 @@ int iwch_bind_mw(struct ib_qp *qp,
struct ib_mw_bind *mw_bind); struct ib_mw_bind *mw_bind);
int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg); int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg);
int iwch_post_zb_read(struct iwch_qp *qhp);
int iwch_register_device(struct iwch_dev *dev); int iwch_register_device(struct iwch_dev *dev);
void iwch_unregister_device(struct iwch_dev *dev); void iwch_unregister_device(struct iwch_dev *dev);
int iwch_quiesce_qps(struct iwch_cq *chp); int iwch_quiesce_qps(struct iwch_cq *chp);
......
...@@ -586,6 +586,36 @@ static inline void build_term_codes(struct respQ_msg_t *rsp_msg, ...@@ -586,6 +586,36 @@ static inline void build_term_codes(struct respQ_msg_t *rsp_msg,
} }
} }
int iwch_post_zb_read(struct iwch_qp *qhp)
{
union t3_wr *wqe;
struct sk_buff *skb;
u8 flit_cnt = sizeof(struct t3_rdma_read_wr) >> 3;
PDBG("%s enter\n", __func__);
skb = alloc_skb(40, GFP_KERNEL);
if (!skb) {
printk(KERN_ERR "%s cannot send zb_read!!\n", __func__);
return -ENOMEM;
}
wqe = (union t3_wr *)skb_put(skb, sizeof(struct t3_rdma_read_wr));
memset(wqe, 0, sizeof(struct t3_rdma_read_wr));
wqe->read.rdmaop = T3_READ_REQ;
wqe->read.reserved[0] = 0;
wqe->read.reserved[1] = 0;
wqe->read.reserved[2] = 0;
wqe->read.rem_stag = cpu_to_be32(1);
wqe->read.rem_to = cpu_to_be64(1);
wqe->read.local_stag = cpu_to_be32(1);
wqe->read.local_len = cpu_to_be32(0);
wqe->read.local_to = cpu_to_be64(1);
wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_READ));
wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)|
V_FW_RIWR_LEN(flit_cnt));
skb->priority = CPL_PRIORITY_DATA;
return cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb);
}
/* /*
* This posts a TERMINATE with layer=RDMA, type=catastrophic. * This posts a TERMINATE with layer=RDMA, type=catastrophic.
*/ */
...@@ -671,11 +701,18 @@ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag) ...@@ -671,11 +701,18 @@ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
/* /*
* Return non zero if at least one RECV was pre-posted. * Return count of RECV WRs posted
*/ */
static int rqes_posted(struct iwch_qp *qhp) u16 iwch_rqes_posted(struct iwch_qp *qhp)
{ {
return fw_riwrh_opcode((struct fw_riwrh *)qhp->wq.queue) == T3_WR_RCV; union t3_wr *wqe = qhp->wq.queue;
u16 count = 0;
while ((count+1) != 0 && fw_riwrh_opcode((struct fw_riwrh *)wqe) == T3_WR_RCV) {
count++;
wqe++;
}
PDBG("%s qhp %p count %u\n", __func__, qhp, count);
return count;
} }
static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp, static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
...@@ -716,8 +753,17 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp, ...@@ -716,8 +753,17 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
init_attr.ird = qhp->attr.max_ird; init_attr.ird = qhp->attr.max_ird;
init_attr.qp_dma_addr = qhp->wq.dma_addr; init_attr.qp_dma_addr = qhp->wq.dma_addr;
init_attr.qp_dma_size = (1UL << qhp->wq.size_log2); init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0; init_attr.rqe_count = iwch_rqes_posted(qhp);
init_attr.flags = qhp->attr.mpa_attr.initiator ? MPA_INITIATOR : 0;
init_attr.flags |= capable(CAP_NET_BIND_SERVICE) ? PRIV_QP : 0; init_attr.flags |= capable(CAP_NET_BIND_SERVICE) ? PRIV_QP : 0;
if (peer2peer) {
init_attr.rtr_type = RTR_READ;
if (init_attr.ord == 0 && qhp->attr.mpa_attr.initiator)
init_attr.ord = 1;
if (init_attr.ird == 0 && !qhp->attr.mpa_attr.initiator)
init_attr.ird = 1;
} else
init_attr.rtr_type = 0;
init_attr.irs = qhp->ep->rcv_seq; init_attr.irs = qhp->ep->rcv_seq;
PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d " PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
"flags 0x%x qpcaps 0x%x\n", __func__, "flags 0x%x qpcaps 0x%x\n", __func__,
...@@ -832,6 +878,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp, ...@@ -832,6 +878,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
abort=0; abort=0;
disconnect = 1; disconnect = 1;
ep = qhp->ep; ep = qhp->ep;
get_ep(&ep->com);
} }
flush_qp(qhp, &flag); flush_qp(qhp, &flag);
break; break;
...@@ -848,6 +895,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp, ...@@ -848,6 +895,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
abort=1; abort=1;
disconnect = 1; disconnect = 1;
ep = qhp->ep; ep = qhp->ep;
get_ep(&ep->com);
} }
goto err; goto err;
break; break;
...@@ -929,8 +977,10 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp, ...@@ -929,8 +977,10 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
* on the EP. This can be a normal close (RTS->CLOSING) or * on the EP. This can be a normal close (RTS->CLOSING) or
* an abnormal close (RTS/CLOSING->ERROR). * an abnormal close (RTS/CLOSING->ERROR).
*/ */
if (disconnect) if (disconnect) {
iwch_ep_disconnect(ep, abort, GFP_KERNEL); iwch_ep_disconnect(ep, abort, GFP_KERNEL);
put_ep(&ep->com);
}
/* /*
* If free is 1, then we've disassociated the EP from the QP * If free is 1, then we've disassociated the EP from the QP
......
...@@ -66,6 +66,7 @@ struct ehca_av; ...@@ -66,6 +66,7 @@ struct ehca_av;
#include "ehca_irq.h" #include "ehca_irq.h"
#define EHCA_EQE_CACHE_SIZE 20 #define EHCA_EQE_CACHE_SIZE 20
#define EHCA_MAX_NUM_QUEUES 0xffff
struct ehca_eqe_cache_entry { struct ehca_eqe_cache_entry {
struct ehca_eqe *eqe; struct ehca_eqe *eqe;
...@@ -127,6 +128,8 @@ struct ehca_shca { ...@@ -127,6 +128,8 @@ struct ehca_shca {
/* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */ /* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */
u32 hca_cap_mr_pgsize; u32 hca_cap_mr_pgsize;
int max_mtu; int max_mtu;
atomic_t num_cqs;
atomic_t num_qps;
}; };
struct ehca_pd { struct ehca_pd {
...@@ -344,6 +347,8 @@ extern int ehca_use_hp_mr; ...@@ -344,6 +347,8 @@ extern int ehca_use_hp_mr;
extern int ehca_scaling_code; extern int ehca_scaling_code;
extern int ehca_lock_hcalls; extern int ehca_lock_hcalls;
extern int ehca_nr_ports; extern int ehca_nr_ports;
extern int ehca_max_cq;
extern int ehca_max_qp;
struct ipzu_queue_resp { struct ipzu_queue_resp {
u32 qe_size; /* queue entry size */ u32 qe_size; /* queue entry size */
......
...@@ -132,10 +132,19 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, ...@@ -132,10 +132,19 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
if (cqe >= 0xFFFFFFFF - 64 - additional_cqe) if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (!atomic_add_unless(&shca->num_cqs, 1, ehca_max_cq)) {
ehca_err(device, "Unable to create CQ, max number of %i "
"CQs reached.", ehca_max_cq);
ehca_err(device, "To increase the maximum number of CQs "
"use the number_of_cqs module parameter.\n");
return ERR_PTR(-ENOSPC);
}
my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL); my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
if (!my_cq) { if (!my_cq) {
ehca_err(device, "Out of memory for ehca_cq struct device=%p", ehca_err(device, "Out of memory for ehca_cq struct device=%p",
device); device);
atomic_dec(&shca->num_cqs);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
...@@ -305,6 +314,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, ...@@ -305,6 +314,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
create_cq_exit1: create_cq_exit1:
kmem_cache_free(cq_cache, my_cq); kmem_cache_free(cq_cache, my_cq);
atomic_dec(&shca->num_cqs);
return cq; return cq;
} }
...@@ -359,6 +369,7 @@ int ehca_destroy_cq(struct ib_cq *cq) ...@@ -359,6 +369,7 @@ int ehca_destroy_cq(struct ib_cq *cq)
ipz_queue_dtor(NULL, &my_cq->ipz_queue); ipz_queue_dtor(NULL, &my_cq->ipz_queue);
kmem_cache_free(cq_cache, my_cq); kmem_cache_free(cq_cache, my_cq);
atomic_dec(&shca->num_cqs);
return 0; return 0;
} }
......
...@@ -54,7 +54,8 @@ int ehca_create_eq(struct ehca_shca *shca, ...@@ -54,7 +54,8 @@ int ehca_create_eq(struct ehca_shca *shca,
struct ehca_eq *eq, struct ehca_eq *eq,
const enum ehca_eq_type type, const u32 length) const enum ehca_eq_type type, const u32 length)
{ {
u64 ret; int ret;
u64 h_ret;
u32 nr_pages; u32 nr_pages;
u32 i; u32 i;
void *vpage; void *vpage;
...@@ -73,15 +74,15 @@ int ehca_create_eq(struct ehca_shca *shca, ...@@ -73,15 +74,15 @@ int ehca_create_eq(struct ehca_shca *shca,
return -EINVAL; return -EINVAL;
} }
ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle, h_ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
&eq->pf, &eq->pf,
type, type,
length, length,
&eq->ipz_eq_handle, &eq->ipz_eq_handle,
&eq->length, &eq->length,
&nr_pages, &eq->ist); &nr_pages, &eq->ist);
if (ret != H_SUCCESS) { if (h_ret != H_SUCCESS) {
ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq); ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq);
return -EINVAL; return -EINVAL;
} }
...@@ -97,24 +98,22 @@ int ehca_create_eq(struct ehca_shca *shca, ...@@ -97,24 +98,22 @@ int ehca_create_eq(struct ehca_shca *shca,
u64 rpage; u64 rpage;
vpage = ipz_qpageit_get_inc(&eq->ipz_queue); vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
if (!vpage) { if (!vpage)
ret = H_RESOURCE;
goto create_eq_exit2; goto create_eq_exit2;
}
rpage = virt_to_abs(vpage); rpage = virt_to_abs(vpage);
ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle, h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
eq->ipz_eq_handle, eq->ipz_eq_handle,
&eq->pf, &eq->pf,
0, 0, rpage, 1); 0, 0, rpage, 1);
if (i == (nr_pages - 1)) { if (i == (nr_pages - 1)) {
/* last page */ /* last page */
vpage = ipz_qpageit_get_inc(&eq->ipz_queue); vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
if (ret != H_SUCCESS || vpage) if (h_ret != H_SUCCESS || vpage)
goto create_eq_exit2; goto create_eq_exit2;
} else { } else {
if (ret != H_PAGE_REGISTERED || !vpage) if (h_ret != H_PAGE_REGISTERED || !vpage)
goto create_eq_exit2; goto create_eq_exit2;
} }
} }
......
...@@ -68,6 +68,8 @@ int ehca_port_act_time = 30; ...@@ -68,6 +68,8 @@ int ehca_port_act_time = 30;
int ehca_static_rate = -1; int ehca_static_rate = -1;
int ehca_scaling_code = 0; int ehca_scaling_code = 0;
int ehca_lock_hcalls = -1; int ehca_lock_hcalls = -1;
int ehca_max_cq = -1;
int ehca_max_qp = -1;
module_param_named(open_aqp1, ehca_open_aqp1, bool, S_IRUGO); module_param_named(open_aqp1, ehca_open_aqp1, bool, S_IRUGO);
module_param_named(debug_level, ehca_debug_level, int, S_IRUGO); module_param_named(debug_level, ehca_debug_level, int, S_IRUGO);
...@@ -79,6 +81,8 @@ module_param_named(poll_all_eqs, ehca_poll_all_eqs, bool, S_IRUGO); ...@@ -79,6 +81,8 @@ module_param_named(poll_all_eqs, ehca_poll_all_eqs, bool, S_IRUGO);
module_param_named(static_rate, ehca_static_rate, int, S_IRUGO); module_param_named(static_rate, ehca_static_rate, int, S_IRUGO);
module_param_named(scaling_code, ehca_scaling_code, bool, S_IRUGO); module_param_named(scaling_code, ehca_scaling_code, bool, S_IRUGO);
module_param_named(lock_hcalls, ehca_lock_hcalls, bool, S_IRUGO); module_param_named(lock_hcalls, ehca_lock_hcalls, bool, S_IRUGO);
module_param_named(number_of_cqs, ehca_max_cq, int, S_IRUGO);
module_param_named(number_of_qps, ehca_max_qp, int, S_IRUGO);
MODULE_PARM_DESC(open_aqp1, MODULE_PARM_DESC(open_aqp1,
"Open AQP1 on startup (default: no)"); "Open AQP1 on startup (default: no)");
...@@ -104,6 +108,12 @@ MODULE_PARM_DESC(scaling_code, ...@@ -104,6 +108,12 @@ MODULE_PARM_DESC(scaling_code,
MODULE_PARM_DESC(lock_hcalls, MODULE_PARM_DESC(lock_hcalls,
"Serialize all hCalls made by the driver " "Serialize all hCalls made by the driver "
"(default: autodetect)"); "(default: autodetect)");
MODULE_PARM_DESC(number_of_cqs,
"Max number of CQs which can be allocated "
"(default: autodetect)");
MODULE_PARM_DESC(number_of_qps,
"Max number of QPs which can be allocated "
"(default: autodetect)");
DEFINE_RWLOCK(ehca_qp_idr_lock); DEFINE_RWLOCK(ehca_qp_idr_lock);
DEFINE_RWLOCK(ehca_cq_idr_lock); DEFINE_RWLOCK(ehca_cq_idr_lock);
...@@ -355,6 +365,25 @@ static int ehca_sense_attributes(struct ehca_shca *shca) ...@@ -355,6 +365,25 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
if (rblock->memory_page_size_supported & pgsize_map[i]) if (rblock->memory_page_size_supported & pgsize_map[i])
shca->hca_cap_mr_pgsize |= pgsize_map[i + 1]; shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
/* Set maximum number of CQs and QPs to calculate EQ size */
if (ehca_max_qp == -1)
ehca_max_qp = min_t(int, rblock->max_qp, EHCA_MAX_NUM_QUEUES);
else if (ehca_max_qp < 1 || ehca_max_qp > rblock->max_qp) {
ehca_gen_err("Requested number of QPs is out of range (1 - %i) "
"specified by HW", rblock->max_qp);
ret = -EINVAL;
goto sense_attributes1;
}
if (ehca_max_cq == -1)
ehca_max_cq = min_t(int, rblock->max_cq, EHCA_MAX_NUM_QUEUES);
else if (ehca_max_cq < 1 || ehca_max_cq > rblock->max_cq) {
ehca_gen_err("Requested number of CQs is out of range (1 - %i) "
"specified by HW", rblock->max_cq);
ret = -EINVAL;
goto sense_attributes1;
}
/* query max MTU from first port -- it's the same for all ports */ /* query max MTU from first port -- it's the same for all ports */
port = (struct hipz_query_port *)rblock; port = (struct hipz_query_port *)rblock;
h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port); h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
...@@ -684,7 +713,7 @@ static int __devinit ehca_probe(struct of_device *dev, ...@@ -684,7 +713,7 @@ static int __devinit ehca_probe(struct of_device *dev,
struct ehca_shca *shca; struct ehca_shca *shca;
const u64 *handle; const u64 *handle;
struct ib_pd *ibpd; struct ib_pd *ibpd;
int ret, i; int ret, i, eq_size;
handle = of_get_property(dev->node, "ibm,hca-handle", NULL); handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
if (!handle) { if (!handle) {
...@@ -705,6 +734,8 @@ static int __devinit ehca_probe(struct of_device *dev, ...@@ -705,6 +734,8 @@ static int __devinit ehca_probe(struct of_device *dev,
return -ENOMEM; return -ENOMEM;
} }
mutex_init(&shca->modify_mutex); mutex_init(&shca->modify_mutex);
atomic_set(&shca->num_cqs, 0);
atomic_set(&shca->num_qps, 0);
for (i = 0; i < ARRAY_SIZE(shca->sport); i++) for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
spin_lock_init(&shca->sport[i].mod_sqp_lock); spin_lock_init(&shca->sport[i].mod_sqp_lock);
...@@ -724,8 +755,9 @@ static int __devinit ehca_probe(struct of_device *dev, ...@@ -724,8 +755,9 @@ static int __devinit ehca_probe(struct of_device *dev,
goto probe1; goto probe1;
} }
eq_size = 2 * ehca_max_cq + 4 * ehca_max_qp;
/* create event queues */ /* create event queues */
ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048); ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size);
if (ret) { if (ret) {
ehca_err(&shca->ib_device, "Cannot create EQ."); ehca_err(&shca->ib_device, "Cannot create EQ.");
goto probe1; goto probe1;
......
...@@ -421,8 +421,18 @@ static struct ehca_qp *internal_create_qp( ...@@ -421,8 +421,18 @@ static struct ehca_qp *internal_create_qp(
u32 swqe_size = 0, rwqe_size = 0, ib_qp_num; u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
unsigned long flags; unsigned long flags;
if (init_attr->create_flags) if (!atomic_add_unless(&shca->num_qps, 1, ehca_max_qp)) {
ehca_err(pd->device, "Unable to create QP, max number of %i "
"QPs reached.", ehca_max_qp);
ehca_err(pd->device, "To increase the maximum number of QPs "
"use the number_of_qps module parameter.\n");
return ERR_PTR(-ENOSPC);
}
if (init_attr->create_flags) {
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
}
memset(&parms, 0, sizeof(parms)); memset(&parms, 0, sizeof(parms));
qp_type = init_attr->qp_type; qp_type = init_attr->qp_type;
...@@ -431,6 +441,7 @@ static struct ehca_qp *internal_create_qp( ...@@ -431,6 +441,7 @@ static struct ehca_qp *internal_create_qp(
init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) { init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) {
ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed", ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed",
init_attr->sq_sig_type); init_attr->sq_sig_type);
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -455,6 +466,7 @@ static struct ehca_qp *internal_create_qp( ...@@ -455,6 +466,7 @@ static struct ehca_qp *internal_create_qp(
if (is_llqp && has_srq) { if (is_llqp && has_srq) {
ehca_err(pd->device, "LLQPs can't have an SRQ"); ehca_err(pd->device, "LLQPs can't have an SRQ");
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -466,6 +478,7 @@ static struct ehca_qp *internal_create_qp( ...@@ -466,6 +478,7 @@ static struct ehca_qp *internal_create_qp(
ehca_err(pd->device, "no more than three SGEs " ehca_err(pd->device, "no more than three SGEs "
"supported for SRQ pd=%p max_sge=%x", "supported for SRQ pd=%p max_sge=%x",
pd, init_attr->cap.max_recv_sge); pd, init_attr->cap.max_recv_sge);
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
} }
...@@ -477,6 +490,7 @@ static struct ehca_qp *internal_create_qp( ...@@ -477,6 +490,7 @@ static struct ehca_qp *internal_create_qp(
qp_type != IB_QPT_SMI && qp_type != IB_QPT_SMI &&
qp_type != IB_QPT_GSI) { qp_type != IB_QPT_GSI) {
ehca_err(pd->device, "wrong QP Type=%x", qp_type); ehca_err(pd->device, "wrong QP Type=%x", qp_type);
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -490,6 +504,7 @@ static struct ehca_qp *internal_create_qp( ...@@ -490,6 +504,7 @@ static struct ehca_qp *internal_create_qp(
"or max_rq_wr=%x for RC LLQP", "or max_rq_wr=%x for RC LLQP",
init_attr->cap.max_send_wr, init_attr->cap.max_send_wr,
init_attr->cap.max_recv_wr); init_attr->cap.max_recv_wr);
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
break; break;
...@@ -497,6 +512,7 @@ static struct ehca_qp *internal_create_qp( ...@@ -497,6 +512,7 @@ static struct ehca_qp *internal_create_qp(
if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) { if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {
ehca_err(pd->device, "UD LLQP not supported " ehca_err(pd->device, "UD LLQP not supported "
"by this adapter"); "by this adapter");
atomic_dec(&shca->num_qps);
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
} }
if (!(init_attr->cap.max_send_sge <= 5 if (!(init_attr->cap.max_send_sge <= 5
...@@ -508,20 +524,22 @@ static struct ehca_qp *internal_create_qp( ...@@ -508,20 +524,22 @@ static struct ehca_qp *internal_create_qp(
"or max_recv_sge=%x for UD LLQP", "or max_recv_sge=%x for UD LLQP",
init_attr->cap.max_send_sge, init_attr->cap.max_send_sge,
init_attr->cap.max_recv_sge); init_attr->cap.max_recv_sge);
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} else if (init_attr->cap.max_send_wr > 255) { } else if (init_attr->cap.max_send_wr > 255) {
ehca_err(pd->device, ehca_err(pd->device,
"Invalid Number of " "Invalid Number of "
"max_send_wr=%x for UD QP_TYPE=%x", "max_send_wr=%x for UD QP_TYPE=%x",
init_attr->cap.max_send_wr, qp_type); init_attr->cap.max_send_wr, qp_type);
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
break; break;
default: default:
ehca_err(pd->device, "unsupported LL QP Type=%x", ehca_err(pd->device, "unsupported LL QP Type=%x",
qp_type); qp_type);
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
break;
} }
} else { } else {
int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI
...@@ -533,6 +551,7 @@ static struct ehca_qp *internal_create_qp( ...@@ -533,6 +551,7 @@ static struct ehca_qp *internal_create_qp(
"send_sge=%x recv_sge=%x max_sge=%x", "send_sge=%x recv_sge=%x max_sge=%x",
init_attr->cap.max_send_sge, init_attr->cap.max_send_sge,
init_attr->cap.max_recv_sge, max_sge); init_attr->cap.max_recv_sge, max_sge);
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
} }
...@@ -543,6 +562,7 @@ static struct ehca_qp *internal_create_qp( ...@@ -543,6 +562,7 @@ static struct ehca_qp *internal_create_qp(
my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL); my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
if (!my_qp) { if (!my_qp) {
ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd); ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
atomic_dec(&shca->num_qps);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
...@@ -823,6 +843,7 @@ static struct ehca_qp *internal_create_qp( ...@@ -823,6 +843,7 @@ static struct ehca_qp *internal_create_qp(
create_qp_exit0: create_qp_exit0:
kmem_cache_free(qp_cache, my_qp); kmem_cache_free(qp_cache, my_qp);
atomic_dec(&shca->num_qps);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -1948,6 +1969,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, ...@@ -1948,6 +1969,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
if (HAS_SQ(my_qp)) if (HAS_SQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_squeue); ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
kmem_cache_free(qp_cache, my_qp); kmem_cache_free(qp_cache, my_qp);
atomic_dec(&shca->num_qps);
return 0; return 0;
} }
......
...@@ -221,7 +221,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector ...@@ -221,7 +221,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
} }
err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar,
cq->db.dma, &cq->mcq); cq->db.dma, &cq->mcq, 0);
if (err) if (err)
goto err_dbmap; goto err_dbmap;
......
...@@ -818,15 +818,9 @@ int mthca_arbel_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, ...@@ -818,15 +818,9 @@ int mthca_arbel_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
void mthca_tavor_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr) void mthca_tavor_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
{ {
u32 key;
if (!fmr->maps) if (!fmr->maps)
return; return;
key = tavor_key_to_hw_index(fmr->ibmr.lkey);
key &= dev->limits.num_mpts - 1;
fmr->ibmr.lkey = fmr->ibmr.rkey = tavor_hw_index_to_key(key);
fmr->maps = 0; fmr->maps = 0;
writeb(MTHCA_MPT_STATUS_SW, fmr->mem.tavor.mpt); writeb(MTHCA_MPT_STATUS_SW, fmr->mem.tavor.mpt);
...@@ -834,16 +828,9 @@ void mthca_tavor_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr) ...@@ -834,16 +828,9 @@ void mthca_tavor_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr) void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
{ {
u32 key;
if (!fmr->maps) if (!fmr->maps)
return; return;
key = arbel_key_to_hw_index(fmr->ibmr.lkey);
key &= dev->limits.num_mpts - 1;
key = adjust_key(dev, key);
fmr->ibmr.lkey = fmr->ibmr.rkey = arbel_hw_index_to_key(key);
fmr->maps = 0; fmr->maps = 0;
*(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW; *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW;
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include <rdma/ib_smi.h> #include <rdma/ib_smi.h>
#include <rdma/ib_umem.h> #include <rdma/ib_umem.h>
#include <rdma/ib_user_verbs.h> #include <rdma/ib_user_verbs.h>
#include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include "mthca_dev.h" #include "mthca_dev.h"
...@@ -367,6 +369,8 @@ static struct ib_ucontext *mthca_alloc_ucontext(struct ib_device *ibdev, ...@@ -367,6 +369,8 @@ static struct ib_ucontext *mthca_alloc_ucontext(struct ib_device *ibdev,
return ERR_PTR(-EFAULT); return ERR_PTR(-EFAULT);
} }
context->reg_mr_warned = 0;
return &context->ibucontext; return &context->ibucontext;
} }
...@@ -1013,7 +1017,15 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -1013,7 +1017,15 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
int err = 0; int err = 0;
int write_mtt_size; int write_mtt_size;
if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) if (udata->inlen - sizeof (struct ib_uverbs_cmd_hdr) < sizeof ucmd) {
if (!to_mucontext(pd->uobject->context)->reg_mr_warned) {
mthca_warn(dev, "Process '%s' did not pass in MR attrs.\n",
current->comm);
mthca_warn(dev, " Update libmthca to fix this.\n");
}
++to_mucontext(pd->uobject->context)->reg_mr_warned;
ucmd.mr_attrs = 0;
} else if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
return ERR_PTR(-EFAULT); return ERR_PTR(-EFAULT);
mr = kmalloc(sizeof *mr, GFP_KERNEL); mr = kmalloc(sizeof *mr, GFP_KERNEL);
......
...@@ -67,6 +67,7 @@ struct mthca_ucontext { ...@@ -67,6 +67,7 @@ struct mthca_ucontext {
struct ib_ucontext ibucontext; struct ib_ucontext ibucontext;
struct mthca_uar uar; struct mthca_uar uar;
struct mthca_user_db_table *db_tab; struct mthca_user_db_table *db_tab;
int reg_mr_warned;
}; };
struct mthca_mtt; struct mthca_mtt;
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
* Increment this value if any changes that break userspace ABI * Increment this value if any changes that break userspace ABI
* compatibility are made. * compatibility are made.
*/ */
#define MTHCA_UVERBS_ABI_VERSION 2 #define MTHCA_UVERBS_ABI_VERSION 1
/* /*
* Make sure that all structs defined in this file remain laid out so * Make sure that all structs defined in this file remain laid out so
...@@ -62,10 +62,12 @@ struct mthca_alloc_pd_resp { ...@@ -62,10 +62,12 @@ struct mthca_alloc_pd_resp {
}; };
struct mthca_reg_mr { struct mthca_reg_mr {
/*
* Mark the memory region with a DMA attribute that causes
* in-flight DMA to be flushed when the region is written to:
*/
#define MTHCA_MR_DMASYNC 0x1
__u32 mr_attrs; __u32 mr_attrs;
#define MTHCA_MR_DMASYNC 0x1
/* mark the memory region with a DMA attribute that causes
* in-flight DMA to be flushed when the region is written to */
__u32 reserved; __u32 reserved;
}; };
......
...@@ -2,6 +2,7 @@ config INFINIBAND_NES ...@@ -2,6 +2,7 @@ config INFINIBAND_NES
tristate "NetEffect RNIC Driver" tristate "NetEffect RNIC Driver"
depends on PCI && INET && INFINIBAND depends on PCI && INET && INFINIBAND
select LIBCRC32C select LIBCRC32C
select INET_LRO
---help--- ---help---
This is a low-level driver for NetEffect RDMA enabled This is a low-level driver for NetEffect RDMA enabled
Network Interface Cards (RNIC). Network Interface Cards (RNIC).
......
...@@ -91,6 +91,10 @@ unsigned int nes_debug_level = 0; ...@@ -91,6 +91,10 @@ unsigned int nes_debug_level = 0;
module_param_named(debug_level, nes_debug_level, uint, 0644); module_param_named(debug_level, nes_debug_level, uint, 0644);
MODULE_PARM_DESC(debug_level, "Enable debug output level"); MODULE_PARM_DESC(debug_level, "Enable debug output level");
unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR;
module_param(nes_lro_max_aggr, int, NES_LRO_MAX_AGGR);
MODULE_PARM_DESC(nes_mro_max_aggr, " nic LRO MAX packet aggregation");
LIST_HEAD(nes_adapter_list); LIST_HEAD(nes_adapter_list);
static LIST_HEAD(nes_dev_list); static LIST_HEAD(nes_dev_list);
......
...@@ -173,6 +173,7 @@ extern int disable_mpa_crc; ...@@ -173,6 +173,7 @@ extern int disable_mpa_crc;
extern unsigned int send_first; extern unsigned int send_first;
extern unsigned int nes_drv_opt; extern unsigned int nes_drv_opt;
extern unsigned int nes_debug_level; extern unsigned int nes_debug_level;
extern unsigned int nes_lro_max_aggr;
extern struct list_head nes_adapter_list; extern struct list_head nes_adapter_list;
...@@ -535,8 +536,8 @@ int nes_register_ofa_device(struct nes_ib_device *); ...@@ -535,8 +536,8 @@ int nes_register_ofa_device(struct nes_ib_device *);
int nes_read_eeprom_values(struct nes_device *, struct nes_adapter *); int nes_read_eeprom_values(struct nes_device *, struct nes_adapter *);
void nes_write_1G_phy_reg(struct nes_device *, u8, u8, u16); void nes_write_1G_phy_reg(struct nes_device *, u8, u8, u16);
void nes_read_1G_phy_reg(struct nes_device *, u8, u8, u16 *); void nes_read_1G_phy_reg(struct nes_device *, u8, u8, u16 *);
void nes_write_10G_phy_reg(struct nes_device *, u16, u8, u16); void nes_write_10G_phy_reg(struct nes_device *, u16, u8, u16, u16);
void nes_read_10G_phy_reg(struct nes_device *, u16, u8); void nes_read_10G_phy_reg(struct nes_device *, u8, u8, u16);
struct nes_cqp_request *nes_get_cqp_request(struct nes_device *); struct nes_cqp_request *nes_get_cqp_request(struct nes_device *);
void nes_post_cqp_request(struct nes_device *, struct nes_cqp_request *, int); void nes_post_cqp_request(struct nes_device *, struct nes_cqp_request *, int);
int nes_arp_table(struct nes_device *, u32, u8 *, u32); int nes_arp_table(struct nes_device *, u32, u8 *, u32);
......
...@@ -594,7 +594,7 @@ static void nes_cm_timer_tick(unsigned long pass) ...@@ -594,7 +594,7 @@ static void nes_cm_timer_tick(unsigned long pass)
continue; continue;
} }
/* this seems like the correct place, but leave send entry unprotected */ /* this seems like the correct place, but leave send entry unprotected */
// spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); /* spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); */
atomic_inc(&send_entry->skb->users); atomic_inc(&send_entry->skb->users);
cm_packets_retrans++; cm_packets_retrans++;
nes_debug(NES_DBG_CM, "Retransmitting send_entry %p for node %p," nes_debug(NES_DBG_CM, "Retransmitting send_entry %p for node %p,"
...@@ -1335,7 +1335,7 @@ static int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, ...@@ -1335,7 +1335,7 @@ static int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
cm_node->loc_addr, cm_node->loc_port, cm_node->loc_addr, cm_node->loc_port,
cm_node->rem_addr, cm_node->rem_port, cm_node->rem_addr, cm_node->rem_port,
cm_node->state, atomic_read(&cm_node->ref_count)); cm_node->state, atomic_read(&cm_node->ref_count));
// create event /* create event */
cm_node->state = NES_CM_STATE_CLOSED; cm_node->state = NES_CM_STATE_CLOSED;
create_event(cm_node, NES_CM_EVENT_ABORTED); create_event(cm_node, NES_CM_EVENT_ABORTED);
...@@ -1669,7 +1669,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, ...@@ -1669,7 +1669,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
if (!cm_node) if (!cm_node)
return NULL; return NULL;
// set our node side to client (active) side /* set our node side to client (active) side */
cm_node->tcp_cntxt.client = 1; cm_node->tcp_cntxt.client = 1;
cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
...@@ -1694,7 +1694,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, ...@@ -1694,7 +1694,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
loopbackremotenode->mpa_frame_size = mpa_frame_size - loopbackremotenode->mpa_frame_size = mpa_frame_size -
sizeof(struct ietf_mpa_frame); sizeof(struct ietf_mpa_frame);
// we are done handling this state, set node to a TSA state /* we are done handling this state, set node to a TSA state */
cm_node->state = NES_CM_STATE_TSA; cm_node->state = NES_CM_STATE_TSA;
cm_node->tcp_cntxt.rcv_nxt = loopbackremotenode->tcp_cntxt.loc_seq_num; cm_node->tcp_cntxt.rcv_nxt = loopbackremotenode->tcp_cntxt.loc_seq_num;
loopbackremotenode->tcp_cntxt.rcv_nxt = cm_node->tcp_cntxt.loc_seq_num; loopbackremotenode->tcp_cntxt.rcv_nxt = cm_node->tcp_cntxt.loc_seq_num;
......
This diff is collapsed.
...@@ -33,8 +33,12 @@ ...@@ -33,8 +33,12 @@
#ifndef __NES_HW_H #ifndef __NES_HW_H
#define __NES_HW_H #define __NES_HW_H
#define NES_PHY_TYPE_1G 2 #include <linux/inet_lro.h>
#define NES_PHY_TYPE_IRIS 3
#define NES_PHY_TYPE_1G 2
#define NES_PHY_TYPE_IRIS 3
#define NES_PHY_TYPE_ARGUS 4
#define NES_PHY_TYPE_PUMA_1G 5
#define NES_PHY_TYPE_PUMA_10G 6 #define NES_PHY_TYPE_PUMA_10G 6
#define NES_MULTICAST_PF_MAX 8 #define NES_MULTICAST_PF_MAX 8
...@@ -965,7 +969,7 @@ struct nes_arp_entry { ...@@ -965,7 +969,7 @@ struct nes_arp_entry {
#define NES_NIC_CQ_DOWNWARD_TREND 16 #define NES_NIC_CQ_DOWNWARD_TREND 16
struct nes_hw_tune_timer { struct nes_hw_tune_timer {
//u16 cq_count; /* u16 cq_count; */
u16 threshold_low; u16 threshold_low;
u16 threshold_target; u16 threshold_target;
u16 threshold_high; u16 threshold_high;
...@@ -982,8 +986,10 @@ struct nes_hw_tune_timer { ...@@ -982,8 +986,10 @@ struct nes_hw_tune_timer {
#define NES_TIMER_INT_LIMIT 2 #define NES_TIMER_INT_LIMIT 2
#define NES_TIMER_INT_LIMIT_DYNAMIC 10 #define NES_TIMER_INT_LIMIT_DYNAMIC 10
#define NES_TIMER_ENABLE_LIMIT 4 #define NES_TIMER_ENABLE_LIMIT 4
#define NES_MAX_LINK_INTERRUPTS 128 #define NES_MAX_LINK_INTERRUPTS 128
#define NES_MAX_LINK_CHECK 200 #define NES_MAX_LINK_CHECK 200
#define NES_MAX_LRO_DESCRIPTORS 32
#define NES_LRO_MAX_AGGR 64
struct nes_adapter { struct nes_adapter {
u64 fw_ver; u64 fw_ver;
...@@ -1183,6 +1189,9 @@ struct nes_vnic { ...@@ -1183,6 +1189,9 @@ struct nes_vnic {
u8 of_device_registered; u8 of_device_registered;
u8 rdma_enabled; u8 rdma_enabled;
u8 rx_checksum_disabled; u8 rx_checksum_disabled;
u32 lro_max_aggr;
struct net_lro_mgr lro_mgr;
struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
}; };
struct nes_ib_device { struct nes_ib_device {
......
This diff is collapsed.
...@@ -444,15 +444,13 @@ void nes_read_1G_phy_reg(struct nes_device *nesdev, u8 phy_reg, u8 phy_addr, u16 ...@@ -444,15 +444,13 @@ void nes_read_1G_phy_reg(struct nes_device *nesdev, u8 phy_reg, u8 phy_addr, u16
/** /**
* nes_write_10G_phy_reg * nes_write_10G_phy_reg
*/ */
void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg, void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_addr, u8 dev_addr, u16 phy_reg,
u8 phy_addr, u16 data) u16 data)
{ {
u32 dev_addr;
u32 port_addr; u32 port_addr;
u32 u32temp; u32 u32temp;
u32 counter; u32 counter;
dev_addr = 1;
port_addr = phy_addr; port_addr = phy_addr;
/* set address */ /* set address */
...@@ -492,14 +490,12 @@ void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg, ...@@ -492,14 +490,12 @@ void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg,
* This routine only issues the read, the data must be read * This routine only issues the read, the data must be read
* separately. * separately.
*/ */
void nes_read_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg, u8 phy_addr) void nes_read_10G_phy_reg(struct nes_device *nesdev, u8 phy_addr, u8 dev_addr, u16 phy_reg)
{ {
u32 dev_addr;
u32 port_addr; u32 port_addr;
u32 u32temp; u32 u32temp;
u32 counter; u32 counter;
dev_addr = 1;
port_addr = phy_addr; port_addr = phy_addr;
/* set address */ /* set address */
......
...@@ -1266,7 +1266,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, ...@@ -1266,7 +1266,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
sq_size = init_attr->cap.max_send_wr; sq_size = init_attr->cap.max_send_wr;
rq_size = init_attr->cap.max_recv_wr; rq_size = init_attr->cap.max_recv_wr;
// check if the encoded sizes are OK or not... /* check if the encoded sizes are OK or not... */
sq_encoded_size = nes_get_encoded_size(&sq_size); sq_encoded_size = nes_get_encoded_size(&sq_size);
rq_encoded_size = nes_get_encoded_size(&rq_size); rq_encoded_size = nes_get_encoded_size(&rq_size);
......
...@@ -95,6 +95,8 @@ enum { ...@@ -95,6 +95,8 @@ enum {
IPOIB_MCAST_FLAG_SENDONLY = 1, IPOIB_MCAST_FLAG_SENDONLY = 1,
IPOIB_MCAST_FLAG_BUSY = 2, /* joining or already joined */ IPOIB_MCAST_FLAG_BUSY = 2, /* joining or already joined */
IPOIB_MCAST_FLAG_ATTACHED = 3, IPOIB_MCAST_FLAG_ATTACHED = 3,
MAX_SEND_CQE = 16,
}; };
#define IPOIB_OP_RECV (1ul << 31) #define IPOIB_OP_RECV (1ul << 31)
...@@ -285,7 +287,8 @@ struct ipoib_dev_priv { ...@@ -285,7 +287,8 @@ struct ipoib_dev_priv {
u16 pkey_index; u16 pkey_index;
struct ib_pd *pd; struct ib_pd *pd;
struct ib_mr *mr; struct ib_mr *mr;
struct ib_cq *cq; struct ib_cq *recv_cq;
struct ib_cq *send_cq;
struct ib_qp *qp; struct ib_qp *qp;
u32 qkey; u32 qkey;
...@@ -305,6 +308,7 @@ struct ipoib_dev_priv { ...@@ -305,6 +308,7 @@ struct ipoib_dev_priv {
struct ib_sge tx_sge[MAX_SKB_FRAGS + 1]; struct ib_sge tx_sge[MAX_SKB_FRAGS + 1];
struct ib_send_wr tx_wr; struct ib_send_wr tx_wr;
unsigned tx_outstanding; unsigned tx_outstanding;
struct ib_wc send_wc[MAX_SEND_CQE];
struct ib_recv_wr rx_wr; struct ib_recv_wr rx_wr;
struct ib_sge rx_sge[IPOIB_UD_RX_SG]; struct ib_sge rx_sge[IPOIB_UD_RX_SG];
...@@ -662,7 +666,6 @@ static inline int ipoib_register_debugfs(void) { return 0; } ...@@ -662,7 +666,6 @@ static inline int ipoib_register_debugfs(void) { return 0; }
static inline void ipoib_unregister_debugfs(void) { } static inline void ipoib_unregister_debugfs(void) { }
#endif #endif
#define ipoib_printk(level, priv, format, arg...) \ #define ipoib_printk(level, priv, format, arg...) \
printk(level "%s: " format, ((struct ipoib_dev_priv *) priv)->dev->name , ## arg) printk(level "%s: " format, ((struct ipoib_dev_priv *) priv)->dev->name , ## arg)
#define ipoib_warn(priv, format, arg...) \ #define ipoib_warn(priv, format, arg...) \
......
...@@ -249,8 +249,8 @@ static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev, ...@@ -249,8 +249,8 @@ static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_init_attr attr = { struct ib_qp_init_attr attr = {
.event_handler = ipoib_cm_rx_event_handler, .event_handler = ipoib_cm_rx_event_handler,
.send_cq = priv->cq, /* For drain WR */ .send_cq = priv->recv_cq, /* For drain WR */
.recv_cq = priv->cq, .recv_cq = priv->recv_cq,
.srq = priv->cm.srq, .srq = priv->cm.srq,
.cap.max_send_wr = 1, /* For drain WR */ .cap.max_send_wr = 1, /* For drain WR */
.cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */ .cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */
...@@ -951,8 +951,8 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_ ...@@ -951,8 +951,8 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_
{ {
struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_init_attr attr = { struct ib_qp_init_attr attr = {
.send_cq = priv->cq, .send_cq = priv->recv_cq,
.recv_cq = priv->cq, .recv_cq = priv->recv_cq,
.srq = priv->cm.srq, .srq = priv->cm.srq,
.cap.max_send_wr = ipoib_sendq_size, .cap.max_send_wr = ipoib_sendq_size,
.cap.max_send_sge = 1, .cap.max_send_sge = 1,
......
...@@ -71,7 +71,7 @@ static int ipoib_set_coalesce(struct net_device *dev, ...@@ -71,7 +71,7 @@ static int ipoib_set_coalesce(struct net_device *dev,
coal->rx_max_coalesced_frames > 0xffff) coal->rx_max_coalesced_frames > 0xffff)
return -EINVAL; return -EINVAL;
ret = ib_modify_cq(priv->cq, coal->rx_max_coalesced_frames, ret = ib_modify_cq(priv->recv_cq, coal->rx_max_coalesced_frames,
coal->rx_coalesce_usecs); coal->rx_coalesce_usecs);
if (ret && ret != -ENOSYS) { if (ret && ret != -ENOSYS) {
ipoib_warn(priv, "failed modifying CQ (%d)\n", ret); ipoib_warn(priv, "failed modifying CQ (%d)\n", ret);
......
...@@ -364,7 +364,6 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) ...@@ -364,7 +364,6 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_dev_priv *priv = netdev_priv(dev);
unsigned int wr_id = wc->wr_id; unsigned int wr_id = wc->wr_id;
struct ipoib_tx_buf *tx_req; struct ipoib_tx_buf *tx_req;
unsigned long flags;
ipoib_dbg_data(priv, "send completion: id %d, status: %d\n", ipoib_dbg_data(priv, "send completion: id %d, status: %d\n",
wr_id, wc->status); wr_id, wc->status);
...@@ -384,13 +383,11 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) ...@@ -384,13 +383,11 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
dev_kfree_skb_any(tx_req->skb); dev_kfree_skb_any(tx_req->skb);
spin_lock_irqsave(&priv->tx_lock, flags);
++priv->tx_tail; ++priv->tx_tail;
if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) && if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
netif_queue_stopped(dev) && netif_queue_stopped(dev) &&
test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
netif_wake_queue(dev); netif_wake_queue(dev);
spin_unlock_irqrestore(&priv->tx_lock, flags);
if (wc->status != IB_WC_SUCCESS && if (wc->status != IB_WC_SUCCESS &&
wc->status != IB_WC_WR_FLUSH_ERR) wc->status != IB_WC_WR_FLUSH_ERR)
...@@ -399,6 +396,17 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) ...@@ -399,6 +396,17 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
wc->status, wr_id, wc->vendor_err); wc->status, wr_id, wc->vendor_err);
} }
static int poll_tx(struct ipoib_dev_priv *priv)
{
int n, i;
n = ib_poll_cq(priv->send_cq, MAX_SEND_CQE, priv->send_wc);
for (i = 0; i < n; ++i)
ipoib_ib_handle_tx_wc(priv->dev, priv->send_wc + i);
return n == MAX_SEND_CQE;
}
int ipoib_poll(struct napi_struct *napi, int budget) int ipoib_poll(struct napi_struct *napi, int budget)
{ {
struct ipoib_dev_priv *priv = container_of(napi, struct ipoib_dev_priv, napi); struct ipoib_dev_priv *priv = container_of(napi, struct ipoib_dev_priv, napi);
...@@ -414,7 +422,7 @@ int ipoib_poll(struct napi_struct *napi, int budget) ...@@ -414,7 +422,7 @@ int ipoib_poll(struct napi_struct *napi, int budget)
int max = (budget - done); int max = (budget - done);
t = min(IPOIB_NUM_WC, max); t = min(IPOIB_NUM_WC, max);
n = ib_poll_cq(priv->cq, t, priv->ibwc); n = ib_poll_cq(priv->recv_cq, t, priv->ibwc);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
struct ib_wc *wc = priv->ibwc + i; struct ib_wc *wc = priv->ibwc + i;
...@@ -425,12 +433,8 @@ int ipoib_poll(struct napi_struct *napi, int budget) ...@@ -425,12 +433,8 @@ int ipoib_poll(struct napi_struct *napi, int budget)
ipoib_cm_handle_rx_wc(dev, wc); ipoib_cm_handle_rx_wc(dev, wc);
else else
ipoib_ib_handle_rx_wc(dev, wc); ipoib_ib_handle_rx_wc(dev, wc);
} else { } else
if (wc->wr_id & IPOIB_OP_CM) ipoib_cm_handle_tx_wc(priv->dev, wc);
ipoib_cm_handle_tx_wc(dev, wc);
else
ipoib_ib_handle_tx_wc(dev, wc);
}
} }
if (n != t) if (n != t)
...@@ -439,7 +443,7 @@ int ipoib_poll(struct napi_struct *napi, int budget) ...@@ -439,7 +443,7 @@ int ipoib_poll(struct napi_struct *napi, int budget)
if (done < budget) { if (done < budget) {
netif_rx_complete(dev, napi); netif_rx_complete(dev, napi);
if (unlikely(ib_req_notify_cq(priv->cq, if (unlikely(ib_req_notify_cq(priv->recv_cq,
IB_CQ_NEXT_COMP | IB_CQ_NEXT_COMP |
IB_CQ_REPORT_MISSED_EVENTS)) && IB_CQ_REPORT_MISSED_EVENTS)) &&
netif_rx_reschedule(dev, napi)) netif_rx_reschedule(dev, napi))
...@@ -562,12 +566,16 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, ...@@ -562,12 +566,16 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
address->last_send = priv->tx_head; address->last_send = priv->tx_head;
++priv->tx_head; ++priv->tx_head;
skb_orphan(skb);
if (++priv->tx_outstanding == ipoib_sendq_size) { if (++priv->tx_outstanding == ipoib_sendq_size) {
ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n"); ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
netif_stop_queue(dev); netif_stop_queue(dev);
} }
} }
if (unlikely(priv->tx_outstanding > MAX_SEND_CQE))
poll_tx(priv);
} }
static void __ipoib_reap_ah(struct net_device *dev) static void __ipoib_reap_ah(struct net_device *dev)
...@@ -714,7 +722,7 @@ void ipoib_drain_cq(struct net_device *dev) ...@@ -714,7 +722,7 @@ void ipoib_drain_cq(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_dev_priv *priv = netdev_priv(dev);
int i, n; int i, n;
do { do {
n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc); n = ib_poll_cq(priv->recv_cq, IPOIB_NUM_WC, priv->ibwc);
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
/* /*
* Convert any successful completions to flush * Convert any successful completions to flush
...@@ -729,14 +737,13 @@ void ipoib_drain_cq(struct net_device *dev) ...@@ -729,14 +737,13 @@ void ipoib_drain_cq(struct net_device *dev)
ipoib_cm_handle_rx_wc(dev, priv->ibwc + i); ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
else else
ipoib_ib_handle_rx_wc(dev, priv->ibwc + i); ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
} else { } else
if (priv->ibwc[i].wr_id & IPOIB_OP_CM) ipoib_cm_handle_tx_wc(dev, priv->ibwc + i);
ipoib_cm_handle_tx_wc(dev, priv->ibwc + i);
else
ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
}
} }
} while (n == IPOIB_NUM_WC); } while (n == IPOIB_NUM_WC);
while (poll_tx(priv))
; /* nothing */
} }
int ipoib_ib_dev_stop(struct net_device *dev, int flush) int ipoib_ib_dev_stop(struct net_device *dev, int flush)
...@@ -826,7 +833,7 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush) ...@@ -826,7 +833,7 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
msleep(1); msleep(1);
} }
ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP); ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP);
return 0; return 0;
} }
......
...@@ -1298,7 +1298,8 @@ static int __init ipoib_init_module(void) ...@@ -1298,7 +1298,8 @@ static int __init ipoib_init_module(void)
ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size); ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE); ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE); ipoib_sendq_size = max(ipoib_sendq_size, max(2 * MAX_SEND_CQE,
IPOIB_MIN_QUEUE_SIZE));
#ifdef CONFIG_INFINIBAND_IPOIB_CM #ifdef CONFIG_INFINIBAND_IPOIB_CM
ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP); ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP);
#endif #endif
......
...@@ -171,26 +171,33 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) ...@@ -171,26 +171,33 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
goto out_free_pd; goto out_free_pd;
} }
size = ipoib_sendq_size + ipoib_recvq_size + 1; size = ipoib_recvq_size + 1;
ret = ipoib_cm_dev_init(dev); ret = ipoib_cm_dev_init(dev);
if (!ret) { if (!ret) {
size += ipoib_sendq_size;
if (ipoib_cm_has_srq(dev)) if (ipoib_cm_has_srq(dev))
size += ipoib_recvq_size + 1; /* 1 extra for rx_drain_qp */ size += ipoib_recvq_size + 1; /* 1 extra for rx_drain_qp */
else else
size += ipoib_recvq_size * ipoib_max_conn_qp; size += ipoib_recvq_size * ipoib_max_conn_qp;
} }
priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0); priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
if (IS_ERR(priv->cq)) { if (IS_ERR(priv->recv_cq)) {
printk(KERN_WARNING "%s: failed to create CQ\n", ca->name); printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name);
goto out_free_mr; goto out_free_mr;
} }
if (ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP)) priv->send_cq = ib_create_cq(priv->ca, NULL, NULL, dev, ipoib_sendq_size, 0);
goto out_free_cq; if (IS_ERR(priv->send_cq)) {
printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name);
goto out_free_recv_cq;
}
if (ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP))
goto out_free_send_cq;
init_attr.send_cq = priv->cq; init_attr.send_cq = priv->send_cq;
init_attr.recv_cq = priv->cq; init_attr.recv_cq = priv->recv_cq;
if (priv->hca_caps & IB_DEVICE_UD_TSO) if (priv->hca_caps & IB_DEVICE_UD_TSO)
init_attr.create_flags = IB_QP_CREATE_IPOIB_UD_LSO; init_attr.create_flags = IB_QP_CREATE_IPOIB_UD_LSO;
...@@ -201,7 +208,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) ...@@ -201,7 +208,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
priv->qp = ib_create_qp(priv->pd, &init_attr); priv->qp = ib_create_qp(priv->pd, &init_attr);
if (IS_ERR(priv->qp)) { if (IS_ERR(priv->qp)) {
printk(KERN_WARNING "%s: failed to create QP\n", ca->name); printk(KERN_WARNING "%s: failed to create QP\n", ca->name);
goto out_free_cq; goto out_free_send_cq;
} }
priv->dev->dev_addr[1] = (priv->qp->qp_num >> 16) & 0xff; priv->dev->dev_addr[1] = (priv->qp->qp_num >> 16) & 0xff;
...@@ -230,8 +237,11 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) ...@@ -230,8 +237,11 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
return 0; return 0;
out_free_cq: out_free_send_cq:
ib_destroy_cq(priv->cq); ib_destroy_cq(priv->send_cq);
out_free_recv_cq:
ib_destroy_cq(priv->recv_cq);
out_free_mr: out_free_mr:
ib_dereg_mr(priv->mr); ib_dereg_mr(priv->mr);
...@@ -254,8 +264,11 @@ void ipoib_transport_dev_cleanup(struct net_device *dev) ...@@ -254,8 +264,11 @@ void ipoib_transport_dev_cleanup(struct net_device *dev)
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
} }
if (ib_destroy_cq(priv->cq)) if (ib_destroy_cq(priv->send_cq))
ipoib_warn(priv, "ib_cq_destroy failed\n"); ipoib_warn(priv, "ib_cq_destroy (send) failed\n");
if (ib_destroy_cq(priv->recv_cq))
ipoib_warn(priv, "ib_cq_destroy (recv) failed\n");
ipoib_cm_dev_cleanup(dev); ipoib_cm_dev_cleanup(dev);
......
...@@ -90,6 +90,9 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) ...@@ -90,6 +90,9 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
} }
priv->max_ib_mtu = ppriv->max_ib_mtu; priv->max_ib_mtu = ppriv->max_ib_mtu;
/* MTU will be reset when mcast join happens */
priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu);
priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu;
set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags); set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags);
priv->pkey = pkey; priv->pkey = pkey;
......
...@@ -473,13 +473,15 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s ...@@ -473,13 +473,15 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
stats->r2t_pdus = conn->r2t_pdus_cnt; /* always 0 */ stats->r2t_pdus = conn->r2t_pdus_cnt; /* always 0 */
stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
stats->custom_length = 3; stats->custom_length = 4;
strcpy(stats->custom[0].desc, "qp_tx_queue_full"); strcpy(stats->custom[0].desc, "qp_tx_queue_full");
stats->custom[0].value = 0; /* TB iser_conn->qp_tx_queue_full; */ stats->custom[0].value = 0; /* TB iser_conn->qp_tx_queue_full; */
strcpy(stats->custom[1].desc, "fmr_map_not_avail"); strcpy(stats->custom[1].desc, "fmr_map_not_avail");
stats->custom[1].value = 0; /* TB iser_conn->fmr_map_not_avail */; stats->custom[1].value = 0; /* TB iser_conn->fmr_map_not_avail */;
strcpy(stats->custom[2].desc, "eh_abort_cnt"); strcpy(stats->custom[2].desc, "eh_abort_cnt");
stats->custom[2].value = conn->eh_abort_cnt; stats->custom[2].value = conn->eh_abort_cnt;
strcpy(stats->custom[3].desc, "fmr_unalign_cnt");
stats->custom[3].value = conn->fmr_unalign_cnt;
} }
static int static int
......
...@@ -70,6 +70,13 @@ ...@@ -70,6 +70,13 @@
#define DRV_DATE "May 7th, 2006" #define DRV_DATE "May 7th, 2006"
#define iser_dbg(fmt, arg...) \ #define iser_dbg(fmt, arg...) \
do { \
if (iser_debug_level > 1) \
printk(KERN_DEBUG PFX "%s:" fmt,\
__func__ , ## arg); \
} while (0)
#define iser_warn(fmt, arg...) \
do { \ do { \
if (iser_debug_level > 0) \ if (iser_debug_level > 0) \
printk(KERN_DEBUG PFX "%s:" fmt,\ printk(KERN_DEBUG PFX "%s:" fmt,\
......
...@@ -334,8 +334,11 @@ static void iser_data_buf_dump(struct iser_data_buf *data, ...@@ -334,8 +334,11 @@ static void iser_data_buf_dump(struct iser_data_buf *data,
struct scatterlist *sg; struct scatterlist *sg;
int i; int i;
if (iser_debug_level == 0)
return;
for_each_sg(sgl, sg, data->dma_nents, i) for_each_sg(sgl, sg, data->dma_nents, i)
iser_err("sg[%d] dma_addr:0x%lX page:0x%p " iser_warn("sg[%d] dma_addr:0x%lX page:0x%p "
"off:0x%x sz:0x%x dma_len:0x%x\n", "off:0x%x sz:0x%x dma_len:0x%x\n",
i, (unsigned long)ib_sg_dma_address(ibdev, sg), i, (unsigned long)ib_sg_dma_address(ibdev, sg),
sg_page(sg), sg->offset, sg_page(sg), sg->offset,
...@@ -420,6 +423,7 @@ void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask) ...@@ -420,6 +423,7 @@ void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
enum iser_data_dir cmd_dir) enum iser_data_dir cmd_dir)
{ {
struct iscsi_conn *iscsi_conn = iser_ctask->iser_conn->iscsi_conn;
struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn; struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn;
struct iser_device *device = ib_conn->device; struct iser_device *device = ib_conn->device;
struct ib_device *ibdev = device->ib_device; struct ib_device *ibdev = device->ib_device;
...@@ -434,7 +438,8 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, ...@@ -434,7 +438,8 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
aligned_len = iser_data_buf_aligned_len(mem, ibdev); aligned_len = iser_data_buf_aligned_len(mem, ibdev);
if (aligned_len != mem->dma_nents) { if (aligned_len != mem->dma_nents) {
iser_err("rdma alignment violation %d/%d aligned\n", iscsi_conn->fmr_unalign_cnt++;
iser_warn("rdma alignment violation %d/%d aligned\n",
aligned_len, mem->size); aligned_len, mem->size);
iser_data_buf_dump(mem, ibdev); iser_data_buf_dump(mem, ibdev);
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#define DRV_VERSION "1.0-ko" #define DRV_VERSION "1.0-ko"
/* Firmware version */ /* Firmware version */
#define FW_VERSION_MAJOR 5 #define FW_VERSION_MAJOR 6
#define FW_VERSION_MINOR 0 #define FW_VERSION_MINOR 0
#define FW_VERSION_MICRO 0 #define FW_VERSION_MICRO 0
#endif /* __CHELSIO_VERSION_H */ #endif /* __CHELSIO_VERSION_H */
...@@ -188,7 +188,8 @@ int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq, ...@@ -188,7 +188,8 @@ int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
EXPORT_SYMBOL_GPL(mlx4_cq_resize); EXPORT_SYMBOL_GPL(mlx4_cq_resize);
int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq) struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
int collapsed)
{ {
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_cq_table *cq_table = &priv->cq_table; struct mlx4_cq_table *cq_table = &priv->cq_table;
...@@ -224,6 +225,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, ...@@ -224,6 +225,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
cq_context = mailbox->buf; cq_context = mailbox->buf;
memset(cq_context, 0, sizeof *cq_context); memset(cq_context, 0, sizeof *cq_context);
cq_context->flags = cpu_to_be32(!!collapsed << 18);
cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index); cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index);
cq_context->comp_eqn = priv->eq_table.eq[MLX4_EQ_COMP].eqn; cq_context->comp_eqn = priv->eq_table.eq[MLX4_EQ_COMP].eqn;
cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
......
...@@ -607,15 +607,9 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_enable); ...@@ -607,15 +607,9 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_enable);
void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr, void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
u32 *lkey, u32 *rkey) u32 *lkey, u32 *rkey)
{ {
u32 key;
if (!fmr->maps) if (!fmr->maps)
return; return;
key = key_to_hw_index(fmr->mr.key);
key &= dev->caps.num_mpts - 1;
*lkey = *rkey = fmr->mr.key = hw_index_to_key(key);
fmr->maps = 0; fmr->maps = 0;
*(u8 *) fmr->mpt = MLX4_MPT_STATUS_SW; *(u8 *) fmr->mpt = MLX4_MPT_STATUS_SW;
......
...@@ -382,7 +382,8 @@ void mlx4_free_hwq_res(struct mlx4_dev *mdev, struct mlx4_hwq_resources *wqres, ...@@ -382,7 +382,8 @@ void mlx4_free_hwq_res(struct mlx4_dev *mdev, struct mlx4_hwq_resources *wqres,
int size); int size);
int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq); struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
int collapsed);
void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq); void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq);
int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp); int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp);
......
...@@ -225,6 +225,7 @@ struct iscsi_conn { ...@@ -225,6 +225,7 @@ struct iscsi_conn {
/* custom statistics */ /* custom statistics */
uint32_t eh_abort_cnt; uint32_t eh_abort_cnt;
uint32_t fmr_unalign_cnt;
}; };
struct iscsi_pool { struct iscsi_pool {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment