diff options
Diffstat (limited to 'drivers/infiniband/hw/cxgb4/provider.c')
| -rw-r--r-- | drivers/infiniband/hw/cxgb4/provider.c | 50 | 
1 files changed, 46 insertions, 4 deletions
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c index 7e94c9a656a..b1d305338de 100644 --- a/drivers/infiniband/hw/cxgb4/provider.c +++ b/drivers/infiniband/hw/cxgb4/provider.c @@ -106,15 +106,57 @@ static struct ib_ucontext *c4iw_alloc_ucontext(struct ib_device *ibdev,  {  	struct c4iw_ucontext *context;  	struct c4iw_dev *rhp = to_c4iw_dev(ibdev); +	static int warned; +	struct c4iw_alloc_ucontext_resp uresp; +	int ret = 0; +	struct c4iw_mm_entry *mm = NULL;  	PDBG("%s ibdev %p\n", __func__, ibdev);  	context = kzalloc(sizeof(*context), GFP_KERNEL); -	if (!context) -		return ERR_PTR(-ENOMEM); +	if (!context) { +		ret = -ENOMEM; +		goto err; +	} +  	c4iw_init_dev_ucontext(&rhp->rdev, &context->uctx);  	INIT_LIST_HEAD(&context->mmaps);  	spin_lock_init(&context->mmap_lock); + +	if (udata->outlen < sizeof(uresp) - sizeof(uresp.reserved)) { +		if (!warned++) +			pr_err(MOD "Warning - downlevel libcxgb4 (non-fatal), device status page disabled."); +		rhp->rdev.flags |= T4_STATUS_PAGE_DISABLED; +	} else { +		mm = kmalloc(sizeof(*mm), GFP_KERNEL); +		if (!mm) { +			ret = -ENOMEM; +			goto err_free; +		} + +		uresp.status_page_size = PAGE_SIZE; + +		spin_lock(&context->mmap_lock); +		uresp.status_page_key = context->key; +		context->key += PAGE_SIZE; +		spin_unlock(&context->mmap_lock); + +		ret = ib_copy_to_udata(udata, &uresp, +				       sizeof(uresp) - sizeof(uresp.reserved)); +		if (ret) +			goto err_mm; + +		mm->key = uresp.status_page_key; +		mm->addr = virt_to_phys(rhp->rdev.status_page); +		mm->len = PAGE_SIZE; +		insert_mmap(context, mm); +	}  	return &context->ibucontext; +err_mm: +	kfree(mm); +err_free: +	kfree(context); +err: +	return ERR_PTR(ret);  }  static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) @@ -287,7 +329,7 @@ static int c4iw_query_device(struct ib_device *ibdev,  	props->max_mr = c4iw_num_stags(&dev->rdev);  	props->max_pd = T4_MAX_NUM_PD;  	props->local_ca_ack_delay = 0; -	props->max_fast_reg_page_list_len = T4_MAX_FR_DEPTH; +	props->max_fast_reg_page_list_len = t4_max_fr_depth(use_dsgl);  	return 0;  } @@ -458,7 +500,7 @@ int c4iw_register_device(struct c4iw_dev *dev)  	dev->ibdev.node_type = RDMA_NODE_RNIC;  	memcpy(dev->ibdev.node_desc, C4IW_NODE_DESC, sizeof(C4IW_NODE_DESC));  	dev->ibdev.phys_port_cnt = dev->rdev.lldi.nports; -	dev->ibdev.num_comp_vectors = 1; +	dev->ibdev.num_comp_vectors =  dev->rdev.lldi.nciq;  	dev->ibdev.dma_device = &(dev->rdev.lldi.pdev->dev);  	dev->ibdev.query_device = c4iw_query_device;  	dev->ibdev.query_port = c4iw_query_port;  | 
