提交 0c7d3757 编写于 作者: L Linus Torvalds

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

* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband:
  IB/ehca: Remove obsolete prototypes
  IB/ehca: Remove use of do_mmap()
  RDMA/addr: Handle ethernet neighbour updates during route resolution
  IB: Make sure struct ib_user_mad.data is aligned
  IB/srp: Don't wait for response when QP is in error state.
  IB: Return qp pointer as part of ib_wc
  IB: Include <linux/kref.h> explicitly in <rdma/ib_verbs.h>
...@@ -360,8 +360,7 @@ static int netevent_callback(struct notifier_block *self, unsigned long event, ...@@ -360,8 +360,7 @@ static int netevent_callback(struct notifier_block *self, unsigned long event,
if (event == NETEVENT_NEIGH_UPDATE) { if (event == NETEVENT_NEIGH_UPDATE) {
struct neighbour *neigh = ctx; struct neighbour *neigh = ctx;
if (neigh->dev->type == ARPHRD_INFINIBAND && if (neigh->nud_state & NUD_VALID) {
(neigh->nud_state & NUD_VALID)) {
set_timeout(jiffies); set_timeout(jiffies);
} }
} }
......
...@@ -642,7 +642,8 @@ static void snoop_recv(struct ib_mad_qp_info *qp_info, ...@@ -642,7 +642,8 @@ static void snoop_recv(struct ib_mad_qp_info *qp_info,
spin_unlock_irqrestore(&qp_info->snoop_lock, flags); spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
} }
static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num, static void build_smp_wc(struct ib_qp *qp,
u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
struct ib_wc *wc) struct ib_wc *wc)
{ {
memset(wc, 0, sizeof *wc); memset(wc, 0, sizeof *wc);
...@@ -652,7 +653,7 @@ static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num, ...@@ -652,7 +653,7 @@ static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
wc->pkey_index = pkey_index; wc->pkey_index = pkey_index;
wc->byte_len = sizeof(struct ib_mad) + sizeof(struct ib_grh); wc->byte_len = sizeof(struct ib_mad) + sizeof(struct ib_grh);
wc->src_qp = IB_QP0; wc->src_qp = IB_QP0;
wc->qp_num = IB_QP0; wc->qp = qp;
wc->slid = slid; wc->slid = slid;
wc->sl = 0; wc->sl = 0;
wc->dlid_path_bits = 0; wc->dlid_path_bits = 0;
...@@ -713,7 +714,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, ...@@ -713,7 +714,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
goto out; goto out;
} }
build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid), build_smp_wc(mad_agent_priv->agent.qp,
send_wr->wr_id, be16_to_cpu(smp->dr_slid),
send_wr->wr.ud.pkey_index, send_wr->wr.ud.pkey_index,
send_wr->wr.ud.port_num, &mad_wc); send_wr->wr.ud.port_num, &mad_wc);
...@@ -2355,7 +2357,8 @@ static void local_completions(struct work_struct *work) ...@@ -2355,7 +2357,8 @@ static void local_completions(struct work_struct *work)
* Defined behavior is to complete response * Defined behavior is to complete response
* before request * before request
*/ */
build_smp_wc((unsigned long) local->mad_send_wr, build_smp_wc(recv_mad_agent->agent.qp,
(unsigned long) local->mad_send_wr,
be16_to_cpu(IB_LID_PERMISSIVE), be16_to_cpu(IB_LID_PERMISSIVE),
0, recv_mad_agent->agent.port_num, &wc); 0, recv_mad_agent->agent.port_num, &wc);
......
...@@ -933,7 +933,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, ...@@ -933,7 +933,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
resp->wc[i].vendor_err = wc[i].vendor_err; resp->wc[i].vendor_err = wc[i].vendor_err;
resp->wc[i].byte_len = wc[i].byte_len; resp->wc[i].byte_len = wc[i].byte_len;
resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data; resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data;
resp->wc[i].qp_num = wc[i].qp_num; resp->wc[i].qp_num = wc[i].qp->qp_num;
resp->wc[i].src_qp = wc[i].src_qp; resp->wc[i].src_qp = wc[i].src_qp;
resp->wc[i].wc_flags = wc[i].wc_flags; resp->wc[i].wc_flags = wc[i].wc_flags;
resp->wc[i].pkey_index = wc[i].pkey_index; resp->wc[i].pkey_index = wc[i].pkey_index;
......
...@@ -153,7 +153,7 @@ static inline int c2_poll_one(struct c2_dev *c2dev, ...@@ -153,7 +153,7 @@ static inline int c2_poll_one(struct c2_dev *c2dev,
entry->status = c2_cqe_status_to_openib(c2_wr_get_result(ce)); entry->status = c2_cqe_status_to_openib(c2_wr_get_result(ce));
entry->wr_id = ce->hdr.context; entry->wr_id = ce->hdr.context;
entry->qp_num = ce->handle; entry->qp = &qp->ibqp;
entry->wc_flags = 0; entry->wc_flags = 0;
entry->slid = 0; entry->slid = 0;
entry->sl = 0; entry->sl = 0;
......
...@@ -119,13 +119,14 @@ struct ehca_qp { ...@@ -119,13 +119,14 @@ struct ehca_qp {
struct ipz_qp_handle ipz_qp_handle; struct ipz_qp_handle ipz_qp_handle;
struct ehca_pfqp pf; struct ehca_pfqp pf;
struct ib_qp_init_attr init_attr; struct ib_qp_init_attr init_attr;
u64 uspace_squeue;
u64 uspace_rqueue;
u64 uspace_fwh;
struct ehca_cq *send_cq; struct ehca_cq *send_cq;
struct ehca_cq *recv_cq; struct ehca_cq *recv_cq;
unsigned int sqerr_purgeflag; unsigned int sqerr_purgeflag;
struct hlist_node list_entries; struct hlist_node list_entries;
/* mmap counter for resources mapped into user space */
u32 mm_count_squeue;
u32 mm_count_rqueue;
u32 mm_count_galpa;
}; };
/* must be power of 2 */ /* must be power of 2 */
...@@ -142,13 +143,14 @@ struct ehca_cq { ...@@ -142,13 +143,14 @@ struct ehca_cq {
struct ipz_cq_handle ipz_cq_handle; struct ipz_cq_handle ipz_cq_handle;
struct ehca_pfcq pf; struct ehca_pfcq pf;
spinlock_t cb_lock; spinlock_t cb_lock;
u64 uspace_queue;
u64 uspace_fwh;
struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
struct list_head entry; struct list_head entry;
u32 nr_callbacks; u32 nr_callbacks;
spinlock_t task_lock; spinlock_t task_lock;
u32 ownpid; u32 ownpid;
/* mmap counter for resources mapped into user space */
u32 mm_count_queue;
u32 mm_count_galpa;
}; };
enum ehca_mr_flag { enum ehca_mr_flag {
...@@ -248,20 +250,6 @@ struct ehca_ucontext { ...@@ -248,20 +250,6 @@ struct ehca_ucontext {
struct ib_ucontext ib_ucontext; struct ib_ucontext ib_ucontext;
}; };
struct ehca_module *ehca_module_new(void);
int ehca_module_delete(struct ehca_module *me);
int ehca_eq_ctor(struct ehca_eq *eq);
int ehca_eq_dtor(struct ehca_eq *eq);
struct ehca_shca *ehca_shca_new(void);
int ehca_shca_delete(struct ehca_shca *me);
struct ehca_sport *ehca_sport_new(struct ehca_shca *anchor);
int ehca_init_pd_cache(void); int ehca_init_pd_cache(void);
void ehca_cleanup_pd_cache(void); void ehca_cleanup_pd_cache(void);
int ehca_init_cq_cache(void); int ehca_init_cq_cache(void);
...@@ -283,7 +271,6 @@ extern int ehca_port_act_time; ...@@ -283,7 +271,6 @@ extern int ehca_port_act_time;
extern int ehca_use_hp_mr; extern int ehca_use_hp_mr;
struct ipzu_queue_resp { struct ipzu_queue_resp {
u64 queue; /* points to first queue entry */
u32 qe_size; /* queue entry size */ u32 qe_size; /* queue entry size */
u32 act_nr_of_sg; u32 act_nr_of_sg;
u32 queue_length; /* queue length allocated in bytes */ u32 queue_length; /* queue length allocated in bytes */
...@@ -296,7 +283,6 @@ struct ehca_create_cq_resp { ...@@ -296,7 +283,6 @@ struct ehca_create_cq_resp {
u32 cq_number; u32 cq_number;
u32 token; u32 token;
struct ipzu_queue_resp ipz_queue; struct ipzu_queue_resp ipz_queue;
struct h_galpas galpas;
}; };
struct ehca_create_qp_resp { struct ehca_create_qp_resp {
...@@ -309,7 +295,6 @@ struct ehca_create_qp_resp { ...@@ -309,7 +295,6 @@ struct ehca_create_qp_resp {
u32 dummy; /* padding for 8 byte alignment */ u32 dummy; /* padding for 8 byte alignment */
struct ipzu_queue_resp ipz_squeue; struct ipzu_queue_resp ipz_squeue;
struct ipzu_queue_resp ipz_rqueue; struct ipzu_queue_resp ipz_rqueue;
struct h_galpas galpas;
}; };
struct ehca_alloc_cq_parms { struct ehca_alloc_cq_parms {
......
...@@ -267,7 +267,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, ...@@ -267,7 +267,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
if (context) { if (context) {
struct ipz_queue *ipz_queue = &my_cq->ipz_queue; struct ipz_queue *ipz_queue = &my_cq->ipz_queue;
struct ehca_create_cq_resp resp; struct ehca_create_cq_resp resp;
struct vm_area_struct *vma;
memset(&resp, 0, sizeof(resp)); memset(&resp, 0, sizeof(resp));
resp.cq_number = my_cq->cq_number; resp.cq_number = my_cq->cq_number;
resp.token = my_cq->token; resp.token = my_cq->token;
...@@ -276,40 +275,14 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, ...@@ -276,40 +275,14 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
resp.ipz_queue.queue_length = ipz_queue->queue_length; resp.ipz_queue.queue_length = ipz_queue->queue_length;
resp.ipz_queue.pagesize = ipz_queue->pagesize; resp.ipz_queue.pagesize = ipz_queue->pagesize;
resp.ipz_queue.toggle_state = ipz_queue->toggle_state; resp.ipz_queue.toggle_state = ipz_queue->toggle_state;
ret = ehca_mmap_nopage(((u64)(my_cq->token) << 32) | 0x12000000,
ipz_queue->queue_length,
(void**)&resp.ipz_queue.queue,
&vma);
if (ret) {
ehca_err(device, "Could not mmap queue pages");
cq = ERR_PTR(ret);
goto create_cq_exit4;
}
my_cq->uspace_queue = resp.ipz_queue.queue;
resp.galpas = my_cq->galpas;
ret = ehca_mmap_register(my_cq->galpas.user.fw_handle,
(void**)&resp.galpas.kernel.fw_handle,
&vma);
if (ret) {
ehca_err(device, "Could not mmap fw_handle");
cq = ERR_PTR(ret);
goto create_cq_exit5;
}
my_cq->uspace_fwh = (u64)resp.galpas.kernel.fw_handle;
if (ib_copy_to_udata(udata, &resp, sizeof(resp))) { if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
ehca_err(device, "Copy to udata failed."); ehca_err(device, "Copy to udata failed.");
goto create_cq_exit6; goto create_cq_exit4;
} }
} }
return cq; return cq;
create_cq_exit6:
ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE);
create_cq_exit5:
ehca_munmap(my_cq->uspace_queue, my_cq->ipz_queue.queue_length);
create_cq_exit4: create_cq_exit4:
ipz_queue_dtor(&my_cq->ipz_queue); ipz_queue_dtor(&my_cq->ipz_queue);
...@@ -333,7 +306,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, ...@@ -333,7 +306,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
int ehca_destroy_cq(struct ib_cq *cq) int ehca_destroy_cq(struct ib_cq *cq)
{ {
u64 h_ret; u64 h_ret;
int ret;
struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
int cq_num = my_cq->cq_number; int cq_num = my_cq->cq_number;
struct ib_device *device = cq->device; struct ib_device *device = cq->device;
...@@ -343,6 +315,20 @@ int ehca_destroy_cq(struct ib_cq *cq) ...@@ -343,6 +315,20 @@ int ehca_destroy_cq(struct ib_cq *cq)
u32 cur_pid = current->tgid; u32 cur_pid = current->tgid;
unsigned long flags; unsigned long flags;
if (cq->uobject) {
if (my_cq->mm_count_galpa || my_cq->mm_count_queue) {
ehca_err(device, "Resources still referenced in "
"user space cq_num=%x", my_cq->cq_number);
return -EINVAL;
}
if (my_cq->ownpid != cur_pid) {
ehca_err(device, "Invalid caller pid=%x ownpid=%x "
"cq_num=%x",
cur_pid, my_cq->ownpid, my_cq->cq_number);
return -EINVAL;
}
}
spin_lock_irqsave(&ehca_cq_idr_lock, flags); spin_lock_irqsave(&ehca_cq_idr_lock, flags);
while (my_cq->nr_callbacks) { while (my_cq->nr_callbacks) {
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
...@@ -353,25 +339,6 @@ int ehca_destroy_cq(struct ib_cq *cq) ...@@ -353,25 +339,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
idr_remove(&ehca_cq_idr, my_cq->token); idr_remove(&ehca_cq_idr, my_cq->token);
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) {
ehca_err(device, "Invalid caller pid=%x ownpid=%x",
cur_pid, my_cq->ownpid);
return -EINVAL;
}
/* un-mmap if vma alloc */
if (my_cq->uspace_queue ) {
ret = ehca_munmap(my_cq->uspace_queue,
my_cq->ipz_queue.queue_length);
if (ret)
ehca_err(device, "Could not munmap queue ehca_cq=%p "
"cq_num=%x", my_cq, cq_num);
ret = ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE);
if (ret)
ehca_err(device, "Could not munmap fwh ehca_cq=%p "
"cq_num=%x", my_cq, cq_num);
}
h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
if (h_ret == H_R_STATE) { if (h_ret == H_R_STATE) {
/* cq in err: read err data and destroy it forcibly */ /* cq in err: read err data and destroy it forcibly */
...@@ -400,7 +367,7 @@ int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata) ...@@ -400,7 +367,7 @@ int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
u32 cur_pid = current->tgid; u32 cur_pid = current->tgid;
if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) { if (cq->uobject && my_cq->ownpid != cur_pid) {
ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x", ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x",
cur_pid, my_cq->ownpid); cur_pid, my_cq->ownpid);
return -EINVAL; return -EINVAL;
......
...@@ -171,14 +171,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); ...@@ -171,14 +171,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
void ehca_poll_eqs(unsigned long data); void ehca_poll_eqs(unsigned long data);
int ehca_mmap_nopage(u64 foffset,u64 length,void **mapped,
struct vm_area_struct **vma);
int ehca_mmap_register(u64 physical,void **mapped,
struct vm_area_struct **vma);
int ehca_munmap(unsigned long addr, size_t len);
#ifdef CONFIG_PPC_64K_PAGES #ifdef CONFIG_PPC_64K_PAGES
void *ehca_alloc_fw_ctrlblock(gfp_t flags); void *ehca_alloc_fw_ctrlblock(gfp_t flags);
void ehca_free_fw_ctrlblock(void *ptr); void ehca_free_fw_ctrlblock(void *ptr);
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
MODULE_VERSION("SVNEHCA_0019"); MODULE_VERSION("SVNEHCA_0020");
int ehca_open_aqp1 = 0; int ehca_open_aqp1 = 0;
int ehca_debug_level = 0; int ehca_debug_level = 0;
...@@ -288,7 +288,7 @@ int ehca_init_device(struct ehca_shca *shca) ...@@ -288,7 +288,7 @@ int ehca_init_device(struct ehca_shca *shca)
strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX); strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
shca->ib_device.owner = THIS_MODULE; shca->ib_device.owner = THIS_MODULE;
shca->ib_device.uverbs_abi_ver = 5; shca->ib_device.uverbs_abi_ver = 6;
shca->ib_device.uverbs_cmd_mask = shca->ib_device.uverbs_cmd_mask =
(1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
...@@ -790,7 +790,7 @@ int __init ehca_module_init(void) ...@@ -790,7 +790,7 @@ int __init ehca_module_init(void)
int ret; int ret;
printk(KERN_INFO "eHCA Infiniband Device Driver " printk(KERN_INFO "eHCA Infiniband Device Driver "
"(Rel.: SVNEHCA_0019)\n"); "(Rel.: SVNEHCA_0020)\n");
idr_init(&ehca_qp_idr); idr_init(&ehca_qp_idr);
idr_init(&ehca_cq_idr); idr_init(&ehca_cq_idr);
spin_lock_init(&ehca_qp_idr_lock); spin_lock_init(&ehca_qp_idr_lock);
......
...@@ -637,7 +637,6 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, ...@@ -637,7 +637,6 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue; struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue;
struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue; struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue;
struct ehca_create_qp_resp resp; struct ehca_create_qp_resp resp;
struct vm_area_struct * vma;
memset(&resp, 0, sizeof(resp)); memset(&resp, 0, sizeof(resp));
resp.qp_num = my_qp->real_qp_num; resp.qp_num = my_qp->real_qp_num;
...@@ -651,59 +650,21 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, ...@@ -651,59 +650,21 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length; resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length;
resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize; resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize;
resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state; resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state;
ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x22000000,
ipz_rqueue->queue_length,
(void**)&resp.ipz_rqueue.queue,
&vma);
if (ret) {
ehca_err(pd->device, "Could not mmap rqueue pages");
goto create_qp_exit3;
}
my_qp->uspace_rqueue = resp.ipz_rqueue.queue;
/* squeue properties */ /* squeue properties */
resp.ipz_squeue.qe_size = ipz_squeue->qe_size; resp.ipz_squeue.qe_size = ipz_squeue->qe_size;
resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg; resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg;
resp.ipz_squeue.queue_length = ipz_squeue->queue_length; resp.ipz_squeue.queue_length = ipz_squeue->queue_length;
resp.ipz_squeue.pagesize = ipz_squeue->pagesize; resp.ipz_squeue.pagesize = ipz_squeue->pagesize;
resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state; resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state;
ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x23000000,
ipz_squeue->queue_length,
(void**)&resp.ipz_squeue.queue,
&vma);
if (ret) {
ehca_err(pd->device, "Could not mmap squeue pages");
goto create_qp_exit4;
}
my_qp->uspace_squeue = resp.ipz_squeue.queue;
/* fw_handle */
resp.galpas = my_qp->galpas;
ret = ehca_mmap_register(my_qp->galpas.user.fw_handle,
(void**)&resp.galpas.kernel.fw_handle,
&vma);
if (ret) {
ehca_err(pd->device, "Could not mmap fw_handle");
goto create_qp_exit5;
}
my_qp->uspace_fwh = (u64)resp.galpas.kernel.fw_handle;
if (ib_copy_to_udata(udata, &resp, sizeof resp)) { if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
ehca_err(pd->device, "Copy to udata failed"); ehca_err(pd->device, "Copy to udata failed");
ret = -EINVAL; ret = -EINVAL;
goto create_qp_exit6; goto create_qp_exit3;
} }
} }
return &my_qp->ib_qp; return &my_qp->ib_qp;
create_qp_exit6:
ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE);
create_qp_exit5:
ehca_munmap(my_qp->uspace_squeue, my_qp->ipz_squeue.queue_length);
create_qp_exit4:
ehca_munmap(my_qp->uspace_rqueue, my_qp->ipz_rqueue.queue_length);
create_qp_exit3: create_qp_exit3:
ipz_queue_dtor(&my_qp->ipz_rqueue); ipz_queue_dtor(&my_qp->ipz_rqueue);
ipz_queue_dtor(&my_qp->ipz_squeue); ipz_queue_dtor(&my_qp->ipz_squeue);
...@@ -931,7 +892,7 @@ static int internal_modify_qp(struct ib_qp *ibqp, ...@@ -931,7 +892,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
my_qp->qp_type == IB_QPT_SMI) && my_qp->qp_type == IB_QPT_SMI) &&
statetrans == IB_QPST_SQE2RTS) { statetrans == IB_QPST_SQE2RTS) {
/* mark next free wqe if kernel */ /* mark next free wqe if kernel */
if (my_qp->uspace_squeue == 0) { if (!ibqp->uobject) {
struct ehca_wqe *wqe; struct ehca_wqe *wqe;
/* lock send queue */ /* lock send queue */
spin_lock_irqsave(&my_qp->spinlock_s, spl_flags); spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
...@@ -1417,11 +1378,18 @@ int ehca_destroy_qp(struct ib_qp *ibqp) ...@@ -1417,11 +1378,18 @@ int ehca_destroy_qp(struct ib_qp *ibqp)
enum ib_qp_type qp_type; enum ib_qp_type qp_type;
unsigned long flags; unsigned long flags;
if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && if (ibqp->uobject) {
my_pd->ownpid != cur_pid) { if (my_qp->mm_count_galpa ||
ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x", my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
cur_pid, my_pd->ownpid); ehca_err(ibqp->device, "Resources still referenced in "
return -EINVAL; "user space qp_num=%x", ibqp->qp_num);
return -EINVAL;
}
if (my_pd->ownpid != cur_pid) {
ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x",
cur_pid, my_pd->ownpid);
return -EINVAL;
}
} }
if (my_qp->send_cq) { if (my_qp->send_cq) {
...@@ -1439,24 +1407,6 @@ int ehca_destroy_qp(struct ib_qp *ibqp) ...@@ -1439,24 +1407,6 @@ int ehca_destroy_qp(struct ib_qp *ibqp)
idr_remove(&ehca_qp_idr, my_qp->token); idr_remove(&ehca_qp_idr, my_qp->token);
spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
/* un-mmap if vma alloc */
if (my_qp->uspace_rqueue) {
ret = ehca_munmap(my_qp->uspace_rqueue,
my_qp->ipz_rqueue.queue_length);
if (ret)
ehca_err(ibqp->device, "Could not munmap rqueue "
"qp_num=%x", qp_num);
ret = ehca_munmap(my_qp->uspace_squeue,
my_qp->ipz_squeue.queue_length);
if (ret)
ehca_err(ibqp->device, "Could not munmap squeue "
"qp_num=%x", qp_num);
ret = ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE);
if (ret)
ehca_err(ibqp->device, "Could not munmap fwh qp_num=%x",
qp_num);
}
h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
if (h_ret != H_SUCCESS) { if (h_ret != H_SUCCESS) {
ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx " ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx "
......
...@@ -579,7 +579,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc) ...@@ -579,7 +579,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
} else } else
wc->status = IB_WC_SUCCESS; wc->status = IB_WC_SUCCESS;
wc->qp_num = cqe->local_qp_number; wc->qp = NULL;
wc->byte_len = cqe->nr_bytes_transferred; wc->byte_len = cqe->nr_bytes_transferred;
wc->pkey_index = cqe->pkey_index; wc->pkey_index = cqe->pkey_index;
wc->slid = cqe->rlid; wc->slid = cqe->rlid;
......
...@@ -68,105 +68,183 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context) ...@@ -68,105 +68,183 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context)
return 0; return 0;
} }
struct page *ehca_nopage(struct vm_area_struct *vma, static void ehca_mm_open(struct vm_area_struct *vma)
unsigned long address, int *type)
{ {
struct page *mypage = NULL; u32 *count = (u32*)vma->vm_private_data;
u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; if (!count) {
u32 idr_handle = fileoffset >> 32; ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
u32 q_type = (fileoffset >> 28) & 0xF; /* CQ, QP,... */ vma->vm_start, vma->vm_end);
u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ return;
u32 cur_pid = current->tgid; }
unsigned long flags; (*count)++;
struct ehca_cq *cq; if (!(*count))
struct ehca_qp *qp; ehca_gen_err("Use count overflow vm_start=%lx vm_end=%lx",
struct ehca_pd *pd; vma->vm_start, vma->vm_end);
u64 offset; ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
void *vaddr; vma->vm_start, vma->vm_end, *count);
}
switch (q_type) { static void ehca_mm_close(struct vm_area_struct *vma)
case 1: /* CQ */ {
spin_lock_irqsave(&ehca_cq_idr_lock, flags); u32 *count = (u32*)vma->vm_private_data;
cq = idr_find(&ehca_cq_idr, idr_handle); if (!count) {
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
vma->vm_start, vma->vm_end);
return;
}
(*count)--;
ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
vma->vm_start, vma->vm_end, *count);
}
/* make sure this mmap really belongs to the authorized user */ static struct vm_operations_struct vm_ops = {
if (!cq) { .open = ehca_mm_open,
ehca_gen_err("cq is NULL ret=NOPAGE_SIGBUS"); .close = ehca_mm_close,
return NOPAGE_SIGBUS; };
static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas,
u32 *mm_count)
{
int ret;
u64 vsize, physical;
vsize = vma->vm_end - vma->vm_start;
if (vsize != EHCA_PAGESIZE) {
ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start);
return -EINVAL;
}
physical = galpas->user.fw_handle;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
ehca_gen_dbg("vsize=%lx physical=%lx", vsize, physical);
/* VM_IO | VM_RESERVED are set by remap_pfn_range() */
ret = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT,
vsize, vma->vm_page_prot);
if (unlikely(ret)) {
ehca_gen_err("remap_pfn_range() failed ret=%x", ret);
return -ENOMEM;
}
vma->vm_private_data = mm_count;
(*mm_count)++;
vma->vm_ops = &vm_ops;
return 0;
}
static int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue,
u32 *mm_count)
{
int ret;
u64 start, ofs;
struct page *page;
vma->vm_flags |= VM_RESERVED;
start = vma->vm_start;
for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) {
u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs);
page = virt_to_page(virt_addr);
ret = vm_insert_page(vma, start, page);
if (unlikely(ret)) {
ehca_gen_err("vm_insert_page() failed rc=%x", ret);
return ret;
} }
start += PAGE_SIZE;
}
vma->vm_private_data = mm_count;
(*mm_count)++;
vma->vm_ops = &vm_ops;
if (cq->ownpid != cur_pid) { return 0;
}
static int ehca_mmap_cq(struct vm_area_struct *vma, struct ehca_cq *cq,
u32 rsrc_type)
{
int ret;
switch (rsrc_type) {
case 1: /* galpa fw handle */
ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number);
ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa);
if (unlikely(ret)) {
ehca_err(cq->ib_cq.device, ehca_err(cq->ib_cq.device,
"Invalid caller pid=%x ownpid=%x", "ehca_mmap_fw() failed rc=%x cq_num=%x",
cur_pid, cq->ownpid); ret, cq->cq_number);
return NOPAGE_SIGBUS; return ret;
} }
break;
if (rsrc_type == 2) { case 2: /* cq queue_addr */
ehca_dbg(cq->ib_cq.device, "cq=%p cq queuearea", cq); ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number);
offset = address - vma->vm_start; ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue);
vaddr = ipz_qeit_calc(&cq->ipz_queue, offset); if (unlikely(ret)) {
ehca_dbg(cq->ib_cq.device, "offset=%lx vaddr=%p", ehca_err(cq->ib_cq.device,
offset, vaddr); "ehca_mmap_queue() failed rc=%x cq_num=%x",
mypage = virt_to_page(vaddr); ret, cq->cq_number);
return ret;
} }
break; break;
case 2: /* QP */ default:
spin_lock_irqsave(&ehca_qp_idr_lock, flags); ehca_err(cq->ib_cq.device, "bad resource type=%x cq_num=%x",
qp = idr_find(&ehca_qp_idr, idr_handle); rsrc_type, cq->cq_number);
spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); return -EINVAL;
}
/* make sure this mmap really belongs to the authorized user */ return 0;
if (!qp) { }
ehca_gen_err("qp is NULL ret=NOPAGE_SIGBUS");
return NOPAGE_SIGBUS; static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
u32 rsrc_type)
{
int ret;
switch (rsrc_type) {
case 1: /* galpa fw handle */
ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num);
ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa);
if (unlikely(ret)) {
ehca_err(qp->ib_qp.device,
"remap_pfn_range() failed ret=%x qp_num=%x",
ret, qp->ib_qp.qp_num);
return -ENOMEM;
} }
break;
pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd); case 2: /* qp rqueue_addr */
if (pd->ownpid != cur_pid) { ehca_dbg(qp->ib_qp.device, "qp_num=%x rqueue",
qp->ib_qp.qp_num);
ret = ehca_mmap_queue(vma, &qp->ipz_rqueue, &qp->mm_count_rqueue);
if (unlikely(ret)) {
ehca_err(qp->ib_qp.device, ehca_err(qp->ib_qp.device,
"Invalid caller pid=%x ownpid=%x", "ehca_mmap_queue(rq) failed rc=%x qp_num=%x",
cur_pid, pd->ownpid); ret, qp->ib_qp.qp_num);
return NOPAGE_SIGBUS; return ret;
} }
break;
if (rsrc_type == 2) { /* rqueue */ case 3: /* qp squeue_addr */
ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueuearea", qp); ehca_dbg(qp->ib_qp.device, "qp_num=%x squeue",
offset = address - vma->vm_start; qp->ib_qp.qp_num);
vaddr = ipz_qeit_calc(&qp->ipz_rqueue, offset); ret = ehca_mmap_queue(vma, &qp->ipz_squeue, &qp->mm_count_squeue);
ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p", if (unlikely(ret)) {
offset, vaddr); ehca_err(qp->ib_qp.device,
mypage = virt_to_page(vaddr); "ehca_mmap_queue(sq) failed rc=%x qp_num=%x",
} else if (rsrc_type == 3) { /* squeue */ ret, qp->ib_qp.qp_num);
ehca_dbg(qp->ib_qp.device, "qp=%p qp squeuearea", qp); return ret;
offset = address - vma->vm_start;
vaddr = ipz_qeit_calc(&qp->ipz_squeue, offset);
ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p",
offset, vaddr);
mypage = virt_to_page(vaddr);
} }
break; break;
default: default:
ehca_gen_err("bad queue type %x", q_type); ehca_err(qp->ib_qp.device, "bad resource type=%x qp=num=%x",
return NOPAGE_SIGBUS; rsrc_type, qp->ib_qp.qp_num);
} return -EINVAL;
if (!mypage) {
ehca_gen_err("Invalid page adr==NULL ret=NOPAGE_SIGBUS");
return NOPAGE_SIGBUS;
} }
get_page(mypage);
return mypage; return 0;
} }
static struct vm_operations_struct ehcau_vm_ops = {
.nopage = ehca_nopage,
};
int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
{ {
u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT;
...@@ -175,7 +253,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) ...@@ -175,7 +253,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
u32 cur_pid = current->tgid; u32 cur_pid = current->tgid;
u32 ret; u32 ret;
u64 vsize, physical;
unsigned long flags; unsigned long flags;
struct ehca_cq *cq; struct ehca_cq *cq;
struct ehca_qp *qp; struct ehca_qp *qp;
...@@ -201,44 +278,12 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) ...@@ -201,44 +278,12 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context) if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
return -EINVAL; return -EINVAL;
switch (rsrc_type) { ret = ehca_mmap_cq(vma, cq, rsrc_type);
case 1: /* galpa fw handle */ if (unlikely(ret)) {
ehca_dbg(cq->ib_cq.device, "cq=%p cq triggerarea", cq); ehca_err(cq->ib_cq.device,
vma->vm_flags |= VM_RESERVED; "ehca_mmap_cq() failed rc=%x cq_num=%x",
vsize = vma->vm_end - vma->vm_start; ret, cq->cq_number);
if (vsize != EHCA_PAGESIZE) { return ret;
ehca_err(cq->ib_cq.device, "invalid vsize=%lx",
vma->vm_end - vma->vm_start);
return -EINVAL;
}
physical = cq->galpas.user.fw_handle;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_flags |= VM_IO | VM_RESERVED;
ehca_dbg(cq->ib_cq.device,
"vsize=%lx physical=%lx", vsize, physical);
ret = remap_pfn_range(vma, vma->vm_start,
physical >> PAGE_SHIFT, vsize,
vma->vm_page_prot);
if (ret) {
ehca_err(cq->ib_cq.device,
"remap_pfn_range() failed ret=%x",
ret);
return -ENOMEM;
}
break;
case 2: /* cq queue_addr */
ehca_dbg(cq->ib_cq.device, "cq=%p cq q_addr", cq);
vma->vm_flags |= VM_RESERVED;
vma->vm_ops = &ehcau_vm_ops;
break;
default:
ehca_err(cq->ib_cq.device, "bad resource type %x",
rsrc_type);
return -EINVAL;
} }
break; break;
...@@ -262,50 +307,12 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) ...@@ -262,50 +307,12 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context) if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context)
return -EINVAL; return -EINVAL;
switch (rsrc_type) { ret = ehca_mmap_qp(vma, qp, rsrc_type);
case 1: /* galpa fw handle */ if (unlikely(ret)) {
ehca_dbg(qp->ib_qp.device, "qp=%p qp triggerarea", qp); ehca_err(qp->ib_qp.device,
vma->vm_flags |= VM_RESERVED; "ehca_mmap_qp() failed rc=%x qp_num=%x",
vsize = vma->vm_end - vma->vm_start; ret, qp->ib_qp.qp_num);
if (vsize != EHCA_PAGESIZE) { return ret;
ehca_err(qp->ib_qp.device, "invalid vsize=%lx",
vma->vm_end - vma->vm_start);
return -EINVAL;
}
physical = qp->galpas.user.fw_handle;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_flags |= VM_IO | VM_RESERVED;
ehca_dbg(qp->ib_qp.device, "vsize=%lx physical=%lx",
vsize, physical);
ret = remap_pfn_range(vma, vma->vm_start,
physical >> PAGE_SHIFT, vsize,
vma->vm_page_prot);
if (ret) {
ehca_err(qp->ib_qp.device,
"remap_pfn_range() failed ret=%x",
ret);
return -ENOMEM;
}
break;
case 2: /* qp rqueue_addr */
ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueue_addr", qp);
vma->vm_flags |= VM_RESERVED;
vma->vm_ops = &ehcau_vm_ops;
break;
case 3: /* qp squeue_addr */
ehca_dbg(qp->ib_qp.device, "qp=%p qp squeue_addr", qp);
vma->vm_flags |= VM_RESERVED;
vma->vm_ops = &ehcau_vm_ops;
break;
default:
ehca_err(qp->ib_qp.device, "bad resource type %x",
rsrc_type);
return -EINVAL;
} }
break; break;
...@@ -316,77 +323,3 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) ...@@ -316,77 +323,3 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
return 0; return 0;
} }
int ehca_mmap_nopage(u64 foffset, u64 length, void **mapped,
struct vm_area_struct **vma)
{
down_write(&current->mm->mmap_sem);
*mapped = (void*)do_mmap(NULL,0, length, PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
foffset);
up_write(&current->mm->mmap_sem);
if (!(*mapped)) {
ehca_gen_err("couldn't mmap foffset=%lx length=%lx",
foffset, length);
return -EINVAL;
}
*vma = find_vma(current->mm, (u64)*mapped);
if (!(*vma)) {
down_write(&current->mm->mmap_sem);
do_munmap(current->mm, 0, length);
up_write(&current->mm->mmap_sem);
ehca_gen_err("couldn't find vma queue=%p", *mapped);
return -EINVAL;
}
(*vma)->vm_flags |= VM_RESERVED;
(*vma)->vm_ops = &ehcau_vm_ops;
return 0;
}
int ehca_mmap_register(u64 physical, void **mapped,
struct vm_area_struct **vma)
{
int ret;
unsigned long vsize;
/* ehca hw supports only 4k page */
ret = ehca_mmap_nopage(0, EHCA_PAGESIZE, mapped, vma);
if (ret) {
ehca_gen_err("could'nt mmap physical=%lx", physical);
return ret;
}
(*vma)->vm_flags |= VM_RESERVED;
vsize = (*vma)->vm_end - (*vma)->vm_start;
if (vsize != EHCA_PAGESIZE) {
ehca_gen_err("invalid vsize=%lx",
(*vma)->vm_end - (*vma)->vm_start);
return -EINVAL;
}
(*vma)->vm_page_prot = pgprot_noncached((*vma)->vm_page_prot);
(*vma)->vm_flags |= VM_IO | VM_RESERVED;
ret = remap_pfn_range((*vma), (*vma)->vm_start,
physical >> PAGE_SHIFT, vsize,
(*vma)->vm_page_prot);
if (ret) {
ehca_gen_err("remap_pfn_range() failed ret=%x", ret);
return -ENOMEM;
}
return 0;
}
int ehca_munmap(unsigned long addr, size_t len) {
int ret = 0;
struct mm_struct *mm = current->mm;
if (mm) {
down_write(&mm->mmap_sem);
ret = do_munmap(mm, addr, len);
up_write(&mm->mmap_sem);
}
return ret;
}
...@@ -379,7 +379,7 @@ void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) ...@@ -379,7 +379,7 @@ void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
wc.vendor_err = 0; wc.vendor_err = 0;
wc.byte_len = 0; wc.byte_len = 0;
wc.imm_data = 0; wc.imm_data = 0;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = 0; wc.src_qp = 0;
wc.wc_flags = 0; wc.wc_flags = 0;
wc.pkey_index = 0; wc.pkey_index = 0;
......
...@@ -702,7 +702,7 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) ...@@ -702,7 +702,7 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc)
wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
wc->vendor_err = 0; wc->vendor_err = 0;
wc->byte_len = 0; wc->byte_len = 0;
wc->qp_num = qp->ibqp.qp_num; wc->qp = &qp->ibqp;
wc->src_qp = qp->remote_qpn; wc->src_qp = qp->remote_qpn;
wc->pkey_index = 0; wc->pkey_index = 0;
wc->slid = qp->remote_ah_attr.dlid; wc->slid = qp->remote_ah_attr.dlid;
...@@ -836,7 +836,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) ...@@ -836,7 +836,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
wc.vendor_err = 0; wc.vendor_err = 0;
wc.byte_len = wqe->length; wc.byte_len = wqe->length;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = qp->remote_qpn; wc.src_qp = qp->remote_qpn;
wc.pkey_index = 0; wc.pkey_index = 0;
wc.slid = qp->remote_ah_attr.dlid; wc.slid = qp->remote_ah_attr.dlid;
...@@ -951,7 +951,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) ...@@ -951,7 +951,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
wc.vendor_err = 0; wc.vendor_err = 0;
wc.byte_len = 0; wc.byte_len = 0;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = qp->remote_qpn; wc.src_qp = qp->remote_qpn;
wc.pkey_index = 0; wc.pkey_index = 0;
wc.slid = qp->remote_ah_attr.dlid; wc.slid = qp->remote_ah_attr.dlid;
...@@ -1511,7 +1511,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, ...@@ -1511,7 +1511,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
wc.status = IB_WC_SUCCESS; wc.status = IB_WC_SUCCESS;
wc.opcode = IB_WC_RECV; wc.opcode = IB_WC_RECV;
wc.vendor_err = 0; wc.vendor_err = 0;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = qp->remote_qpn; wc.src_qp = qp->remote_qpn;
wc.pkey_index = 0; wc.pkey_index = 0;
wc.slid = qp->remote_ah_attr.dlid; wc.slid = qp->remote_ah_attr.dlid;
......
...@@ -137,7 +137,7 @@ static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe) ...@@ -137,7 +137,7 @@ static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe)
wc.vendor_err = 0; wc.vendor_err = 0;
wc.byte_len = 0; wc.byte_len = 0;
wc.imm_data = 0; wc.imm_data = 0;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = 0; wc.src_qp = 0;
wc.wc_flags = 0; wc.wc_flags = 0;
wc.pkey_index = 0; wc.pkey_index = 0;
...@@ -336,7 +336,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) ...@@ -336,7 +336,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp)
wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
wc.vendor_err = 0; wc.vendor_err = 0;
wc.byte_len = 0; wc.byte_len = 0;
wc.qp_num = sqp->ibqp.qp_num; wc.qp = &sqp->ibqp;
wc.src_qp = sqp->remote_qpn; wc.src_qp = sqp->remote_qpn;
wc.pkey_index = 0; wc.pkey_index = 0;
wc.slid = sqp->remote_ah_attr.dlid; wc.slid = sqp->remote_ah_attr.dlid;
...@@ -426,7 +426,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) ...@@ -426,7 +426,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp)
wc.status = IB_WC_SUCCESS; wc.status = IB_WC_SUCCESS;
wc.vendor_err = 0; wc.vendor_err = 0;
wc.byte_len = wqe->length; wc.byte_len = wqe->length;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = qp->remote_qpn; wc.src_qp = qp->remote_qpn;
/* XXX do we know which pkey matched? Only needed for GSI. */ /* XXX do we know which pkey matched? Only needed for GSI. */
wc.pkey_index = 0; wc.pkey_index = 0;
...@@ -447,7 +447,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) ...@@ -447,7 +447,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp)
wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
wc.vendor_err = 0; wc.vendor_err = 0;
wc.byte_len = wqe->length; wc.byte_len = wqe->length;
wc.qp_num = sqp->ibqp.qp_num; wc.qp = &sqp->ibqp;
wc.src_qp = 0; wc.src_qp = 0;
wc.pkey_index = 0; wc.pkey_index = 0;
wc.slid = 0; wc.slid = 0;
......
...@@ -49,7 +49,7 @@ static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe, ...@@ -49,7 +49,7 @@ static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe,
wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
wc->vendor_err = 0; wc->vendor_err = 0;
wc->byte_len = wqe->length; wc->byte_len = wqe->length;
wc->qp_num = qp->ibqp.qp_num; wc->qp = &qp->ibqp;
wc->src_qp = qp->remote_qpn; wc->src_qp = qp->remote_qpn;
wc->pkey_index = 0; wc->pkey_index = 0;
wc->slid = qp->remote_ah_attr.dlid; wc->slid = qp->remote_ah_attr.dlid;
...@@ -411,7 +411,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, ...@@ -411,7 +411,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
wc.status = IB_WC_SUCCESS; wc.status = IB_WC_SUCCESS;
wc.opcode = IB_WC_RECV; wc.opcode = IB_WC_RECV;
wc.vendor_err = 0; wc.vendor_err = 0;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = qp->remote_qpn; wc.src_qp = qp->remote_qpn;
wc.pkey_index = 0; wc.pkey_index = 0;
wc.slid = qp->remote_ah_attr.dlid; wc.slid = qp->remote_ah_attr.dlid;
......
...@@ -66,7 +66,7 @@ static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe, ...@@ -66,7 +66,7 @@ static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe,
wc.vendor_err = 0; wc.vendor_err = 0;
wc.byte_len = 0; wc.byte_len = 0;
wc.imm_data = 0; wc.imm_data = 0;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = 0; wc.src_qp = 0;
wc.wc_flags = 0; wc.wc_flags = 0;
wc.pkey_index = 0; wc.pkey_index = 0;
...@@ -255,7 +255,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, ...@@ -255,7 +255,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp,
wc->status = IB_WC_SUCCESS; wc->status = IB_WC_SUCCESS;
wc->opcode = IB_WC_RECV; wc->opcode = IB_WC_RECV;
wc->vendor_err = 0; wc->vendor_err = 0;
wc->qp_num = qp->ibqp.qp_num; wc->qp = &qp->ibqp;
wc->src_qp = sqp->ibqp.qp_num; wc->src_qp = sqp->ibqp.qp_num;
/* XXX do we know which pkey matched? Only needed for GSI. */ /* XXX do we know which pkey matched? Only needed for GSI. */
wc->pkey_index = 0; wc->pkey_index = 0;
...@@ -474,7 +474,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) ...@@ -474,7 +474,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr)
wc.vendor_err = 0; wc.vendor_err = 0;
wc.opcode = IB_WC_SEND; wc.opcode = IB_WC_SEND;
wc.byte_len = len; wc.byte_len = len;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = 0; wc.src_qp = 0;
wc.wc_flags = 0; wc.wc_flags = 0;
/* XXX initialize other fields? */ /* XXX initialize other fields? */
...@@ -651,7 +651,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, ...@@ -651,7 +651,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
wc.status = IB_WC_SUCCESS; wc.status = IB_WC_SUCCESS;
wc.opcode = IB_WC_RECV; wc.opcode = IB_WC_RECV;
wc.vendor_err = 0; wc.vendor_err = 0;
wc.qp_num = qp->ibqp.qp_num; wc.qp = &qp->ibqp;
wc.src_qp = src_qp; wc.src_qp = src_qp;
/* XXX do we know which pkey matched? Only needed for GSI. */ /* XXX do we know which pkey matched? Only needed for GSI. */
wc.pkey_index = 0; wc.pkey_index = 0;
......
...@@ -1854,7 +1854,7 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, ...@@ -1854,7 +1854,7 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
memset(inbox + 256, 0, 256); memset(inbox + 256, 0, 256);
MTHCA_PUT(inbox, in_wc->qp_num, MAD_IFC_MY_QPN_OFFSET); MTHCA_PUT(inbox, in_wc->qp->qp_num, MAD_IFC_MY_QPN_OFFSET);
MTHCA_PUT(inbox, in_wc->src_qp, MAD_IFC_RQPN_OFFSET); MTHCA_PUT(inbox, in_wc->src_qp, MAD_IFC_RQPN_OFFSET);
val = in_wc->sl << 4; val = in_wc->sl << 4;
......
...@@ -534,7 +534,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev, ...@@ -534,7 +534,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
} }
} }
entry->qp_num = (*cur_qp)->qpn; entry->qp = &(*cur_qp)->ibqp;
if (is_send) { if (is_send) {
wq = &(*cur_qp)->sq; wq = &(*cur_qp)->sq;
......
...@@ -548,6 +548,7 @@ static int srp_reconnect_target(struct srp_target_port *target) ...@@ -548,6 +548,7 @@ static int srp_reconnect_target(struct srp_target_port *target)
target->tx_head = 0; target->tx_head = 0;
target->tx_tail = 0; target->tx_tail = 0;
target->qp_in_error = 0;
ret = srp_connect_target(target); ret = srp_connect_target(target);
if (ret) if (ret)
goto err; goto err;
...@@ -878,6 +879,7 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr) ...@@ -878,6 +879,7 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr)
printk(KERN_ERR PFX "failed %s status %d\n", printk(KERN_ERR PFX "failed %s status %d\n",
wc.wr_id & SRP_OP_RECV ? "receive" : "send", wc.wr_id & SRP_OP_RECV ? "receive" : "send",
wc.status); wc.status);
target->qp_in_error = 1;
break; break;
} }
...@@ -1337,6 +1339,8 @@ static int srp_abort(struct scsi_cmnd *scmnd) ...@@ -1337,6 +1339,8 @@ static int srp_abort(struct scsi_cmnd *scmnd)
printk(KERN_ERR "SRP abort called\n"); printk(KERN_ERR "SRP abort called\n");
if (target->qp_in_error)
return FAILED;
if (srp_find_req(target, scmnd, &req)) if (srp_find_req(target, scmnd, &req))
return FAILED; return FAILED;
if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK)) if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK))
...@@ -1365,6 +1369,8 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) ...@@ -1365,6 +1369,8 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
printk(KERN_ERR "SRP reset_device called\n"); printk(KERN_ERR "SRP reset_device called\n");
if (target->qp_in_error)
return FAILED;
if (srp_find_req(target, scmnd, &req)) if (srp_find_req(target, scmnd, &req))
return FAILED; return FAILED;
if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET)) if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET))
...@@ -1801,6 +1807,7 @@ static ssize_t srp_create_target(struct class_device *class_dev, ...@@ -1801,6 +1807,7 @@ static ssize_t srp_create_target(struct class_device *class_dev,
goto err_free; goto err_free;
} }
target->qp_in_error = 0;
ret = srp_connect_target(target); ret = srp_connect_target(target);
if (ret) { if (ret) {
printk(KERN_ERR PFX "Connection failed\n"); printk(KERN_ERR PFX "Connection failed\n");
......
...@@ -158,6 +158,7 @@ struct srp_target_port { ...@@ -158,6 +158,7 @@ struct srp_target_port {
struct completion done; struct completion done;
int status; int status;
enum srp_target_state state; enum srp_target_state state;
int qp_in_error;
}; };
struct srp_iu { struct srp_iu {
......
...@@ -98,7 +98,7 @@ struct ib_user_mad_hdr { ...@@ -98,7 +98,7 @@ struct ib_user_mad_hdr {
*/ */
struct ib_user_mad { struct ib_user_mad {
struct ib_user_mad_hdr hdr; struct ib_user_mad_hdr hdr;
__u8 data[0]; __u64 data[0];
}; };
/** /**
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/kref.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
...@@ -419,8 +420,8 @@ struct ib_wc { ...@@ -419,8 +420,8 @@ struct ib_wc {
enum ib_wc_opcode opcode; enum ib_wc_opcode opcode;
u32 vendor_err; u32 vendor_err;
u32 byte_len; u32 byte_len;
struct ib_qp *qp;
__be32 imm_data; __be32 imm_data;
u32 qp_num;
u32 src_qp; u32 src_qp;
int wc_flags; int wc_flags;
u16 pkey_index; u16 pkey_index;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册