mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-08-18 02:22:47 -07:00
Merge tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
Pull infiniband updates from Roland Dreier:
"Main batch of InfiniBand/RDMA changes for 3.15:
- The biggest change is core API extensions and mlx5 low-level driver
support for handling DIF/DIX-style protection information, and the
addition of PI support to the iSER initiator. Target support will
be arriving shortly through the SCSI target tree.
- A nice simplification to the "umem" memory pinning library now that
we have chained sg lists. Kudos to Yishai Hadas for realizing our
code didn't have to be so crazy.
- Another nice simplification to the sg wrappers used by qib, ipath
and ehca to handle their mapping of memory to adapter.
- The usual batch of fixes to bugs found by static checkers etc.
from intrepid people like Dan Carpenter and Yann Droneaud.
- A large batch of cxgb4, ocrdma, qib driver updates"
* tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (102 commits)
RDMA/ocrdma: Unregister inet notifier when unloading ocrdma
RDMA/ocrdma: Fix warnings about pointer <-> integer casts
RDMA/ocrdma: Code clean-up
RDMA/ocrdma: Display FW version
RDMA/ocrdma: Query controller information
RDMA/ocrdma: Support non-embedded mailbox commands
RDMA/ocrdma: Handle CQ overrun error
RDMA/ocrdma: Display proper value for max_mw
RDMA/ocrdma: Use non-zero tag in SRQ posting
RDMA/ocrdma: Memory leak fix in ocrdma_dereg_mr()
RDMA/ocrdma: Increment abi version count
RDMA/ocrdma: Update version string
be2net: Add abi version between be2net and ocrdma
RDMA/ocrdma: ABI versioning between ocrdma and be2net
RDMA/ocrdma: Allow DPP QP creation
RDMA/ocrdma: Read ASIC_ID register to select asic_gen
RDMA/ocrdma: SQ and RQ doorbell offset clean up
RDMA/ocrdma: EQ full catastrophe avoidance
RDMA/cxgb4: Disable DSGL use by default
RDMA/cxgb4: rx_data() needs to hold the ep mutex
...
This commit is contained in:
commit
877f075aac
88 files changed
+4635
-1476
No files matched your search
@@ -349,23 +349,6 @@ static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
|
||||
grh, &av->ah_attr);
|
||||
}
|
||||
|
||||
int ib_update_cm_av(struct ib_cm_id *id, const u8 *smac, const u8 *alt_smac)
|
||||
{
|
||||
struct cm_id_private *cm_id_priv;
|
||||
|
||||
cm_id_priv = container_of(id, struct cm_id_private, id);
|
||||
|
||||
if (smac != NULL)
|
||||
memcpy(cm_id_priv->av.smac, smac, sizeof(cm_id_priv->av.smac));
|
||||
|
||||
if (alt_smac != NULL)
|
||||
memcpy(cm_id_priv->alt_av.smac, alt_smac,
|
||||
sizeof(cm_id_priv->alt_av.smac));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_update_cm_av);
|
||||
|
||||
static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
|
||||
{
|
||||
struct cm_device *cm_dev;
|
||||
|
||||
@@ -1284,15 +1284,6 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
|
||||
struct rdma_id_private *listen_id, *conn_id;
|
||||
struct rdma_cm_event event;
|
||||
int offset, ret;
|
||||
u8 smac[ETH_ALEN];
|
||||
u8 alt_smac[ETH_ALEN];
|
||||
u8 *psmac = smac;
|
||||
u8 *palt_smac = alt_smac;
|
||||
int is_iboe = ((rdma_node_get_transport(cm_id->device->node_type) ==
|
||||
RDMA_TRANSPORT_IB) &&
|
||||
(rdma_port_get_link_layer(cm_id->device,
|
||||
ib_event->param.req_rcvd.port) ==
|
||||
IB_LINK_LAYER_ETHERNET));
|
||||
|
||||
listen_id = cm_id->context;
|
||||
if (!cma_check_req_qp_type(&listen_id->id, ib_event))
|
||||
@@ -1336,28 +1327,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
|
||||
ret = conn_id->id.event_handler(&conn_id->id, &event);
|
||||
if (ret)
|
||||
goto err3;
|
||||
|
||||
if (is_iboe) {
|
||||
if (ib_event->param.req_rcvd.primary_path != NULL)
|
||||
rdma_addr_find_smac_by_sgid(
|
||||
&ib_event->param.req_rcvd.primary_path->sgid,
|
||||
psmac, NULL);
|
||||
else
|
||||
psmac = NULL;
|
||||
if (ib_event->param.req_rcvd.alternate_path != NULL)
|
||||
rdma_addr_find_smac_by_sgid(
|
||||
&ib_event->param.req_rcvd.alternate_path->sgid,
|
||||
palt_smac, NULL);
|
||||
else
|
||||
palt_smac = NULL;
|
||||
}
|
||||
/*
|
||||
* Acquire mutex to prevent user executing rdma_destroy_id()
|
||||
* while we're accessing the cm_id.
|
||||
*/
|
||||
mutex_lock(&lock);
|
||||
if (is_iboe)
|
||||
ib_update_cm_av(cm_id, psmac, palt_smac);
|
||||
if (cma_comp(conn_id, RDMA_CM_CONNECT) &&
|
||||
(conn_id->id.qp_type != IB_QPT_UD))
|
||||
ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
|
||||
|
||||
@@ -1022,12 +1022,21 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
|
||||
mad_send_wr->send_buf.mad,
|
||||
sge[0].length,
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(ib_dma_mapping_error(mad_agent->device, sge[0].addr)))
|
||||
return -ENOMEM;
|
||||
|
||||
mad_send_wr->header_mapping = sge[0].addr;
|
||||
|
||||
sge[1].addr = ib_dma_map_single(mad_agent->device,
|
||||
ib_get_payload(mad_send_wr),
|
||||
sge[1].length,
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(ib_dma_mapping_error(mad_agent->device, sge[1].addr))) {
|
||||
ib_dma_unmap_single(mad_agent->device,
|
||||
mad_send_wr->header_mapping,
|
||||
sge[0].length, DMA_TO_DEVICE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
mad_send_wr->payload_mapping = sge[1].addr;
|
||||
|
||||
spin_lock_irqsave(&qp_info->send_queue.lock, flags);
|
||||
@@ -2590,6 +2599,11 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
|
||||
sizeof *mad_priv -
|
||||
sizeof mad_priv->header,
|
||||
DMA_FROM_DEVICE);
|
||||
if (unlikely(ib_dma_mapping_error(qp_info->port_priv->device,
|
||||
sg_list.addr))) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
mad_priv->header.mapping = sg_list.addr;
|
||||
recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list;
|
||||
mad_priv->header.mad_list.mad_queue = recv_queue;
|
||||
|
||||
@@ -42,29 +42,29 @@
|
||||
|
||||
#include "uverbs.h"
|
||||
|
||||
#define IB_UMEM_MAX_PAGE_CHUNK \
|
||||
((PAGE_SIZE - offsetof(struct ib_umem_chunk, page_list)) / \
|
||||
((void *) &((struct ib_umem_chunk *) 0)->page_list[1] - \
|
||||
(void *) &((struct ib_umem_chunk *) 0)->page_list[0]))
|
||||
|
||||
static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int dirty)
|
||||
{
|
||||
struct ib_umem_chunk *chunk, *tmp;
|
||||
struct scatterlist *sg;
|
||||
struct page *page;
|
||||
int i;
|
||||
|
||||
list_for_each_entry_safe(chunk, tmp, &umem->chunk_list, list) {
|
||||
ib_dma_unmap_sg(dev, chunk->page_list,
|
||||
chunk->nents, DMA_BIDIRECTIONAL);
|
||||
for (i = 0; i < chunk->nents; ++i) {
|
||||
struct page *page = sg_page(&chunk->page_list[i]);
|
||||
if (umem->nmap > 0)
|
||||
ib_dma_unmap_sg(dev, umem->sg_head.sgl,
|
||||
umem->nmap,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
if (umem->writable && dirty)
|
||||
set_page_dirty_lock(page);
|
||||
put_page(page);
|
||||
}
|
||||
for_each_sg(umem->sg_head.sgl, sg, umem->npages, i) {
|
||||
|
||||
kfree(chunk);
|
||||
page = sg_page(sg);
|
||||
if (umem->writable && dirty)
|
||||
set_page_dirty_lock(page);
|
||||
put_page(page);
|
||||
}
|
||||
|
||||
sg_free_table(&umem->sg_head);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,15 +81,15 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
struct ib_umem *umem;
|
||||
struct page **page_list;
|
||||
struct vm_area_struct **vma_list;
|
||||
struct ib_umem_chunk *chunk;
|
||||
unsigned long locked;
|
||||
unsigned long lock_limit;
|
||||
unsigned long cur_base;
|
||||
unsigned long npages;
|
||||
int ret;
|
||||
int off;
|
||||
int i;
|
||||
DEFINE_DMA_ATTRS(attrs);
|
||||
struct scatterlist *sg, *sg_list_start;
|
||||
int need_release = 0;
|
||||
|
||||
if (dmasync)
|
||||
dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
|
||||
@@ -97,7 +97,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
if (!can_do_mlock())
|
||||
return ERR_PTR(-EPERM);
|
||||
|
||||
umem = kmalloc(sizeof *umem, GFP_KERNEL);
|
||||
umem = kzalloc(sizeof *umem, GFP_KERNEL);
|
||||
if (!umem)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@@ -117,8 +117,6 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
/* We assume the memory is from hugetlb until proved otherwise */
|
||||
umem->hugetlb = 1;
|
||||
|
||||
INIT_LIST_HEAD(&umem->chunk_list);
|
||||
|
||||
page_list = (struct page **) __get_free_page(GFP_KERNEL);
|
||||
if (!page_list) {
|
||||
kfree(umem);
|
||||
@@ -147,7 +145,18 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
|
||||
cur_base = addr & PAGE_MASK;
|
||||
|
||||
ret = 0;
|
||||
if (npages == 0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sg_alloc_table(&umem->sg_head, npages, GFP_KERNEL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
need_release = 1;
|
||||
sg_list_start = umem->sg_head.sgl;
|
||||
|
||||
while (npages) {
|
||||
ret = get_user_pages(current, current->mm, cur_base,
|
||||
min_t(unsigned long, npages,
|
||||
@@ -157,54 +166,38 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
umem->npages += ret;
|
||||
cur_base += ret * PAGE_SIZE;
|
||||
npages -= ret;
|
||||
|
||||
off = 0;
|
||||
for_each_sg(sg_list_start, sg, ret, i) {
|
||||
if (vma_list && !is_vm_hugetlb_page(vma_list[i]))
|
||||
umem->hugetlb = 0;
|
||||
|
||||
while (ret) {
|
||||
chunk = kmalloc(sizeof *chunk + sizeof (struct scatterlist) *
|
||||
min_t(int, ret, IB_UMEM_MAX_PAGE_CHUNK),
|
||||
GFP_KERNEL);
|
||||
if (!chunk) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
chunk->nents = min_t(int, ret, IB_UMEM_MAX_PAGE_CHUNK);
|
||||
sg_init_table(chunk->page_list, chunk->nents);
|
||||
for (i = 0; i < chunk->nents; ++i) {
|
||||
if (vma_list &&
|
||||
!is_vm_hugetlb_page(vma_list[i + off]))
|
||||
umem->hugetlb = 0;
|
||||
sg_set_page(&chunk->page_list[i], page_list[i + off], PAGE_SIZE, 0);
|
||||
}
|
||||
|
||||
chunk->nmap = ib_dma_map_sg_attrs(context->device,
|
||||
&chunk->page_list[0],
|
||||
chunk->nents,
|
||||
DMA_BIDIRECTIONAL,
|
||||
&attrs);
|
||||
if (chunk->nmap <= 0) {
|
||||
for (i = 0; i < chunk->nents; ++i)
|
||||
put_page(sg_page(&chunk->page_list[i]));
|
||||
kfree(chunk);
|
||||
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret -= chunk->nents;
|
||||
off += chunk->nents;
|
||||
list_add_tail(&chunk->list, &umem->chunk_list);
|
||||
sg_set_page(sg, page_list[i], PAGE_SIZE, 0);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
/* preparing for next loop */
|
||||
sg_list_start = sg;
|
||||
}
|
||||
|
||||
umem->nmap = ib_dma_map_sg_attrs(context->device,
|
||||
umem->sg_head.sgl,
|
||||
umem->npages,
|
||||
DMA_BIDIRECTIONAL,
|
||||
&attrs);
|
||||
|
||||
if (umem->nmap <= 0) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (ret < 0) {
|
||||
__ib_umem_release(context->device, umem, 0);
|
||||
if (need_release)
|
||||
__ib_umem_release(context->device, umem, 0);
|
||||
kfree(umem);
|
||||
} else
|
||||
current->mm->pinned_vm = locked;
|
||||
@@ -278,17 +271,16 @@ EXPORT_SYMBOL(ib_umem_release);
|
||||
|
||||
int ib_umem_page_count(struct ib_umem *umem)
|
||||
{
|
||||
struct ib_umem_chunk *chunk;
|
||||
int shift;
|
||||
int i;
|
||||
int n;
|
||||
struct scatterlist *sg;
|
||||
|
||||
shift = ilog2(umem->page_size);
|
||||
|
||||
n = 0;
|
||||
list_for_each_entry(chunk, &umem->chunk_list, list)
|
||||
for (i = 0; i < chunk->nmap; ++i)
|
||||
n += sg_dma_len(&chunk->page_list[i]) >> shift;
|
||||
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, i)
|
||||
n += sg_dma_len(sg) >> shift;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -1169,6 +1169,45 @@ int ib_dereg_mr(struct ib_mr *mr)
|
||||
}
|
||||
EXPORT_SYMBOL(ib_dereg_mr);
|
||||
|
||||
struct ib_mr *ib_create_mr(struct ib_pd *pd,
|
||||
struct ib_mr_init_attr *mr_init_attr)
|
||||
{
|
||||
struct ib_mr *mr;
|
||||
|
||||
if (!pd->device->create_mr)
|
||||
return ERR_PTR(-ENOSYS);
|
||||
|
||||
mr = pd->device->create_mr(pd, mr_init_attr);
|
||||
|
||||
if (!IS_ERR(mr)) {
|
||||
mr->device = pd->device;
|
||||
mr->pd = pd;
|
||||
mr->uobject = NULL;
|
||||
atomic_inc(&pd->usecnt);
|
||||
atomic_set(&mr->usecnt, 0);
|
||||
}
|
||||
|
||||
return mr;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_create_mr);
|
||||
|
||||
int ib_destroy_mr(struct ib_mr *mr)
|
||||
{
|
||||
struct ib_pd *pd;
|
||||
int ret;
|
||||
|
||||
if (atomic_read(&mr->usecnt))
|
||||
return -EBUSY;
|
||||
|
||||
pd = mr->pd;
|
||||
ret = mr->device->destroy_mr(mr);
|
||||
if (!ret)
|
||||
atomic_dec(&pd->usecnt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_destroy_mr);
|
||||
|
||||
struct ib_mr *ib_alloc_fast_reg_mr(struct ib_pd *pd, int max_page_list_len)
|
||||
{
|
||||
struct ib_mr *mr;
|
||||
@@ -1398,3 +1437,11 @@ int ib_destroy_flow(struct ib_flow *flow_id)
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_destroy_flow);
|
||||
|
||||
int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
|
||||
struct ib_mr_status *mr_status)
|
||||
{
|
||||
return mr->device->check_mr_status ?
|
||||
mr->device->check_mr_status(mr, check_mask, mr_status) : -ENOSYS;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_check_mr_status);
|
||||
@@ -431,9 +431,9 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
u64 *pages;
|
||||
u64 kva = 0;
|
||||
int shift, n, len;
|
||||
int i, j, k;
|
||||
int i, k, entry;
|
||||
int err = 0;
|
||||
struct ib_umem_chunk *chunk;
|
||||
struct scatterlist *sg;
|
||||
struct c2_pd *c2pd = to_c2pd(pd);
|
||||
struct c2_mr *c2mr;
|
||||
|
||||
@@ -452,10 +452,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
}
|
||||
|
||||
shift = ffs(c2mr->umem->page_size) - 1;
|
||||
|
||||
n = 0;
|
||||
list_for_each_entry(chunk, &c2mr->umem->chunk_list, list)
|
||||
n += chunk->nents;
|
||||
n = c2mr->umem->nmap;
|
||||
|
||||
pages = kmalloc(n * sizeof(u64), GFP_KERNEL);
|
||||
if (!pages) {
|
||||
@@ -464,14 +461,12 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
}
|
||||
|
||||
i = 0;
|
||||
list_for_each_entry(chunk, &c2mr->umem->chunk_list, list) {
|
||||
for (j = 0; j < chunk->nmap; ++j) {
|
||||
len = sg_dma_len(&chunk->page_list[j]) >> shift;
|
||||
for (k = 0; k < len; ++k) {
|
||||
pages[i++] =
|
||||
sg_dma_address(&chunk->page_list[j]) +
|
||||
(c2mr->umem->page_size * k);
|
||||
}
|
||||
for_each_sg(c2mr->umem->sg_head.sgl, sg, c2mr->umem->nmap, entry) {
|
||||
len = sg_dma_len(sg) >> shift;
|
||||
for (k = 0; k < len; ++k) {
|
||||
pages[i++] =
|
||||
sg_dma_address(sg) +
|
||||
(c2mr->umem->page_size * k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -618,14 +618,13 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
{
|
||||
__be64 *pages;
|
||||
int shift, n, len;
|
||||
int i, j, k;
|
||||
int i, k, entry;
|
||||
int err = 0;
|
||||
struct ib_umem_chunk *chunk;
|
||||
struct iwch_dev *rhp;
|
||||
struct iwch_pd *php;
|
||||
struct iwch_mr *mhp;
|
||||
struct iwch_reg_user_mr_resp uresp;
|
||||
|
||||
struct scatterlist *sg;
|
||||
PDBG("%s ib_pd %p\n", __func__, pd);
|
||||
|
||||
php = to_iwch_pd(pd);
|
||||
@@ -645,9 +644,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
|
||||
shift = ffs(mhp->umem->page_size) - 1;
|
||||
|
||||
n = 0;
|
||||
list_for_each_entry(chunk, &mhp->umem->chunk_list, list)
|
||||
n += chunk->nents;
|
||||
n = mhp->umem->nmap;
|
||||
|
||||
err = iwch_alloc_pbl(mhp, n);
|
||||
if (err)
|
||||
@@ -661,12 +658,10 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
|
||||
i = n = 0;
|
||||
|
||||
list_for_each_entry(chunk, &mhp->umem->chunk_list, list)
|
||||
for (j = 0; j < chunk->nmap; ++j) {
|
||||
len = sg_dma_len(&chunk->page_list[j]) >> shift;
|
||||
for_each_sg(mhp->umem->sg_head.sgl, sg, mhp->umem->nmap, entry) {
|
||||
len = sg_dma_len(sg) >> shift;
|
||||
for (k = 0; k < len; ++k) {
|
||||
pages[i++] = cpu_to_be64(sg_dma_address(
|
||||
&chunk->page_list[j]) +
|
||||
pages[i++] = cpu_to_be64(sg_dma_address(sg) +
|
||||
mhp->umem->page_size * k);
|
||||
if (i == PAGE_SIZE / sizeof *pages) {
|
||||
err = iwch_write_pbl(mhp, pages, i, n);
|
||||
@@ -676,7 +671,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
err = iwch_write_pbl(mhp, pages, i, n);
|
||||
|
||||
@@ -98,9 +98,9 @@ int c4iw_debug;
|
||||
module_param(c4iw_debug, int, 0644);
|
||||
MODULE_PARM_DESC(c4iw_debug, "Enable debug logging (default=0)");
|
||||
|
||||
static int peer2peer;
|
||||
static int peer2peer = 1;
|
||||
module_param(peer2peer, int, 0644);
|
||||
MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=0)");
|
||||
MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=1)");
|
||||
|
||||
static int p2p_type = FW_RI_INIT_P2PTYPE_READ_REQ;
|
||||
module_param(p2p_type, int, 0644);
|
||||
@@ -400,7 +400,8 @@ static struct dst_entry *find_route(struct c4iw_dev *dev, __be32 local_ip,
|
||||
n = dst_neigh_lookup(&rt->dst, &peer_ip);
|
||||
if (!n)
|
||||
return NULL;
|
||||
if (!our_interface(dev, n->dev)) {
|
||||
if (!our_interface(dev, n->dev) &&
|
||||
!(n->dev->flags & IFF_LOOPBACK)) {
|
||||
dst_release(&rt->dst);
|
||||
return NULL;
|
||||
}
|
||||
@@ -759,8 +760,9 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
|
||||
ep->mpa_skb = skb;
|
||||
c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
|
||||
start_ep_timer(ep);
|
||||
state_set(&ep->com, MPA_REQ_SENT);
|
||||
__state_set(&ep->com, MPA_REQ_SENT);
|
||||
ep->mpa_attr.initiator = 1;
|
||||
ep->snd_seq += mpalen;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -840,6 +842,7 @@ static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen)
|
||||
t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
|
||||
BUG_ON(ep->mpa_skb);
|
||||
ep->mpa_skb = skb;
|
||||
ep->snd_seq += mpalen;
|
||||
return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
|
||||
}
|
||||
|
||||
@@ -923,7 +926,8 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
|
||||
skb_get(skb);
|
||||
t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
|
||||
ep->mpa_skb = skb;
|
||||
state_set(&ep->com, MPA_REP_SENT);
|
||||
__state_set(&ep->com, MPA_REP_SENT);
|
||||
ep->snd_seq += mpalen;
|
||||
return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
|
||||
}
|
||||
|
||||
@@ -940,6 +944,7 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
PDBG("%s ep %p tid %u snd_isn %u rcv_isn %u\n", __func__, ep, tid,
|
||||
be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn));
|
||||
|
||||
mutex_lock(&ep->com.mutex);
|
||||
dst_confirm(ep->dst);
|
||||
|
||||
/* setup the hwtid for this connection */
|
||||
@@ -963,17 +968,18 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
send_mpa_req(ep, skb, 1);
|
||||
else
|
||||
send_mpa_req(ep, skb, mpa_rev);
|
||||
|
||||
mutex_unlock(&ep->com.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_complete_upcall(struct c4iw_ep *ep)
|
||||
static void close_complete_upcall(struct c4iw_ep *ep, int status)
|
||||
{
|
||||
struct iw_cm_event event;
|
||||
|
||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.event = IW_CM_EVENT_CLOSE;
|
||||
event.status = status;
|
||||
if (ep->com.cm_id) {
|
||||
PDBG("close complete delivered ep %p cm_id %p tid %u\n",
|
||||
ep, ep->com.cm_id, ep->hwtid);
|
||||
@@ -987,7 +993,6 @@ static void close_complete_upcall(struct c4iw_ep *ep)
|
||||
static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
|
||||
{
|
||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||
close_complete_upcall(ep);
|
||||
state_set(&ep->com, ABORTING);
|
||||
set_bit(ABORT_CONN, &ep->com.history);
|
||||
return send_abort(ep, skb, gfp);
|
||||
@@ -1066,9 +1071,10 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
|
||||
}
|
||||
}
|
||||
|
||||
static void connect_request_upcall(struct c4iw_ep *ep)
|
||||
static int connect_request_upcall(struct c4iw_ep *ep)
|
||||
{
|
||||
struct iw_cm_event event;
|
||||
int ret;
|
||||
|
||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||
memset(&event, 0, sizeof(event));
|
||||
@@ -1093,15 +1099,14 @@ static void connect_request_upcall(struct c4iw_ep *ep)
|
||||
event.private_data_len = ep->plen;
|
||||
event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
|
||||
}
|
||||
if (state_read(&ep->parent_ep->com) != DEAD) {
|
||||
c4iw_get_ep(&ep->com);
|
||||
ep->parent_ep->com.cm_id->event_handler(
|
||||
ep->parent_ep->com.cm_id,
|
||||
&event);
|
||||
}
|
||||
c4iw_get_ep(&ep->com);
|
||||
ret = ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id,
|
||||
&event);
|
||||
if (ret)
|
||||
c4iw_put_ep(&ep->com);
|
||||
set_bit(CONNREQ_UPCALL, &ep->com.history);
|
||||
c4iw_put_ep(&ep->parent_ep->com);
|
||||
ep->parent_ep = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void established_upcall(struct c4iw_ep *ep)
|
||||
@@ -1165,7 +1170,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
|
||||
* the connection.
|
||||
*/
|
||||
stop_ep_timer(ep);
|
||||
if (state_read(&ep->com) != MPA_REQ_SENT)
|
||||
if (ep->com.state != MPA_REQ_SENT)
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -1240,7 +1245,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
|
||||
* start reply message including private data. And
|
||||
* the MPA header is valid.
|
||||
*/
|
||||
state_set(&ep->com, FPDU_MODE);
|
||||
__state_set(&ep->com, FPDU_MODE);
|
||||
ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
|
||||
ep->mpa_attr.recv_marker_enabled = markers_enabled;
|
||||
ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
|
||||
@@ -1355,7 +1360,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
|
||||
}
|
||||
goto out;
|
||||
err:
|
||||
state_set(&ep->com, ABORTING);
|
||||
__state_set(&ep->com, ABORTING);
|
||||
send_abort(ep, skb, GFP_KERNEL);
|
||||
out:
|
||||
connect_reply_upcall(ep, err);
|
||||
@@ -1370,7 +1375,7 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
|
||||
|
||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||
|
||||
if (state_read(&ep->com) != MPA_REQ_WAIT)
|
||||
if (ep->com.state != MPA_REQ_WAIT)
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -1400,7 +1405,6 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
|
||||
return;
|
||||
|
||||
PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
|
||||
stop_ep_timer(ep);
|
||||
mpa = (struct mpa_message *) ep->mpa_pkt;
|
||||
|
||||
/*
|
||||
@@ -1492,10 +1496,18 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
|
||||
ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
|
||||
ep->mpa_attr.p2p_type);
|
||||
|
||||
state_set(&ep->com, MPA_REQ_RCVD);
|
||||
__state_set(&ep->com, MPA_REQ_RCVD);
|
||||
stop_ep_timer(ep);
|
||||
|
||||
/* drive upcall */
|
||||
connect_request_upcall(ep);
|
||||
mutex_lock(&ep->parent_ep->com.mutex);
|
||||
if (ep->parent_ep->com.state != DEAD) {
|
||||
if (connect_request_upcall(ep))
|
||||
abort_connection(ep, skb, GFP_KERNEL);
|
||||
} else {
|
||||
abort_connection(ep, skb, GFP_KERNEL);
|
||||
}
|
||||
mutex_unlock(&ep->parent_ep->com.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1509,14 +1521,17 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
__u8 status = hdr->status;
|
||||
|
||||
ep = lookup_tid(t, tid);
|
||||
if (!ep)
|
||||
return 0;
|
||||
PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen);
|
||||
skb_pull(skb, sizeof(*hdr));
|
||||
skb_trim(skb, dlen);
|
||||
mutex_lock(&ep->com.mutex);
|
||||
|
||||
/* update RX credits */
|
||||
update_rx_credits(ep, dlen);
|
||||
|
||||
switch (state_read(&ep->com)) {
|
||||
switch (ep->com.state) {
|
||||
case MPA_REQ_SENT:
|
||||
ep->rcv_seq += dlen;
|
||||
process_mpa_reply(ep, skb);
|
||||
@@ -1532,7 +1547,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
pr_err("%s Unexpected streaming data." \
|
||||
" qpid %u ep %p state %d tid %u status %d\n",
|
||||
__func__, ep->com.qp->wq.sq.qid, ep,
|
||||
state_read(&ep->com), ep->hwtid, status);
|
||||
ep->com.state, ep->hwtid, status);
|
||||
attrs.next_state = C4IW_QP_STATE_TERMINATE;
|
||||
c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
|
||||
C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
|
||||
@@ -1541,6 +1556,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&ep->com.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2255,7 +2271,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
|
||||
C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
|
||||
}
|
||||
close_complete_upcall(ep);
|
||||
close_complete_upcall(ep, 0);
|
||||
__state_set(&ep->com, DEAD);
|
||||
release = 1;
|
||||
disconnect = 0;
|
||||
@@ -2425,7 +2441,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
C4IW_QP_ATTR_NEXT_STATE,
|
||||
&attrs, 1);
|
||||
}
|
||||
close_complete_upcall(ep);
|
||||
close_complete_upcall(ep, 0);
|
||||
__state_set(&ep->com, DEAD);
|
||||
release = 1;
|
||||
break;
|
||||
@@ -2500,22 +2516,28 @@ static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
|
||||
int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
int disconnect = 0;
|
||||
struct c4iw_ep *ep = to_ep(cm_id);
|
||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||
|
||||
if (state_read(&ep->com) == DEAD) {
|
||||
mutex_lock(&ep->com.mutex);
|
||||
if (ep->com.state == DEAD) {
|
||||
mutex_unlock(&ep->com.mutex);
|
||||
c4iw_put_ep(&ep->com);
|
||||
return -ECONNRESET;
|
||||
}
|
||||
set_bit(ULP_REJECT, &ep->com.history);
|
||||
BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
|
||||
BUG_ON(ep->com.state != MPA_REQ_RCVD);
|
||||
if (mpa_rev == 0)
|
||||
abort_connection(ep, NULL, GFP_KERNEL);
|
||||
else {
|
||||
err = send_mpa_reject(ep, pdata, pdata_len);
|
||||
err = c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
|
||||
disconnect = 1;
|
||||
}
|
||||
mutex_unlock(&ep->com.mutex);
|
||||
if (disconnect)
|
||||
err = c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
|
||||
c4iw_put_ep(&ep->com);
|
||||
return 0;
|
||||
}
|
||||
@@ -2530,12 +2552,14 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
|
||||
struct c4iw_qp *qp = get_qhp(h, conn_param->qpn);
|
||||
|
||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||
if (state_read(&ep->com) == DEAD) {
|
||||
|
||||
mutex_lock(&ep->com.mutex);
|
||||
if (ep->com.state == DEAD) {
|
||||
err = -ECONNRESET;
|
||||
goto err;
|
||||
}
|
||||
|
||||
BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
|
||||
BUG_ON(ep->com.state != MPA_REQ_RCVD);
|
||||
BUG_ON(!qp);
|
||||
|
||||
set_bit(ULP_ACCEPT, &ep->com.history);
|
||||
@@ -2604,14 +2628,16 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
|
||||
if (err)
|
||||
goto err1;
|
||||
|
||||
state_set(&ep->com, FPDU_MODE);
|
||||
__state_set(&ep->com, FPDU_MODE);
|
||||
established_upcall(ep);
|
||||
mutex_unlock(&ep->com.mutex);
|
||||
c4iw_put_ep(&ep->com);
|
||||
return 0;
|
||||
err1:
|
||||
ep->com.cm_id = NULL;
|
||||
cm_id->rem_ref(cm_id);
|
||||
err:
|
||||
mutex_unlock(&ep->com.mutex);
|
||||
c4iw_put_ep(&ep->com);
|
||||
return err;
|
||||
}
|
||||
@@ -2980,7 +3006,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
|
||||
rdev = &ep->com.dev->rdev;
|
||||
if (c4iw_fatal_error(rdev)) {
|
||||
fatal = 1;
|
||||
close_complete_upcall(ep);
|
||||
close_complete_upcall(ep, -EIO);
|
||||
ep->com.state = DEAD;
|
||||
}
|
||||
switch (ep->com.state) {
|
||||
@@ -3022,7 +3048,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
|
||||
if (close) {
|
||||
if (abrupt) {
|
||||
set_bit(EP_DISC_ABORT, &ep->com.history);
|
||||
close_complete_upcall(ep);
|
||||
close_complete_upcall(ep, -ECONNRESET);
|
||||
ret = send_abort(ep, NULL, gfp);
|
||||
} else {
|
||||
set_bit(EP_DISC_CLOSE, &ep->com.history);
|
||||
@@ -3203,6 +3229,7 @@ static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb,
|
||||
struct sk_buff *req_skb;
|
||||
struct fw_ofld_connection_wr *req;
|
||||
struct cpl_pass_accept_req *cpl = cplhdr(skb);
|
||||
int ret;
|
||||
|
||||
req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL);
|
||||
req = (struct fw_ofld_connection_wr *)__skb_put(req_skb, sizeof(*req));
|
||||
@@ -3239,7 +3266,13 @@ static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb,
|
||||
req->cookie = (unsigned long)skb;
|
||||
|
||||
set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id);
|
||||
cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb);
|
||||
ret = cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb);
|
||||
if (ret < 0) {
|
||||
pr_err("%s - cxgb4_ofld_send error %d - dropping\n", __func__,
|
||||
ret);
|
||||
kfree_skb(skb);
|
||||
kfree_skb(req_skb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3346,13 +3379,13 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
pi = (struct port_info *)netdev_priv(pdev);
|
||||
tx_chan = cxgb4_port_chan(pdev);
|
||||
}
|
||||
neigh_release(neigh);
|
||||
if (!e) {
|
||||
pr_err("%s - failed to allocate l2t entry!\n",
|
||||
__func__);
|
||||
goto free_dst;
|
||||
}
|
||||
|
||||
neigh_release(neigh);
|
||||
step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
|
||||
rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step];
|
||||
window = (__force u16) htons((__force u16)tcph->window);
|
||||
@@ -3427,6 +3460,7 @@ static void process_timeout(struct c4iw_ep *ep)
|
||||
&attrs, 1);
|
||||
}
|
||||
__state_set(&ep->com, ABORTING);
|
||||
close_complete_upcall(ep, -ETIMEDOUT);
|
||||
break;
|
||||
default:
|
||||
WARN(1, "%s unexpected state ep %p tid %u state %u\n",
|
||||
|
||||
@@ -365,8 +365,14 @@ void c4iw_flush_hw_cq(struct c4iw_cq *chp)
|
||||
|
||||
if (CQE_OPCODE(hw_cqe) == FW_RI_READ_RESP) {
|
||||
|
||||
/*
|
||||
* drop peer2peer RTR reads.
|
||||
/* If we have reached here because of async
|
||||
* event or other error, and have egress error
|
||||
* then drop
|
||||
*/
|
||||
if (CQE_TYPE(hw_cqe) == 1)
|
||||
goto next_cqe;
|
||||
|
||||
/* drop peer2peer RTR reads.
|
||||
*/
|
||||
if (CQE_WRID_STAG(hw_cqe) == 1)
|
||||
goto next_cqe;
|
||||
@@ -511,8 +517,18 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
|
||||
*/
|
||||
if (RQ_TYPE(hw_cqe) && (CQE_OPCODE(hw_cqe) == FW_RI_READ_RESP)) {
|
||||
|
||||
/*
|
||||
* If this is an unsolicited read response, then the read
|
||||
/* If we have reached here because of async
|
||||
* event or other error, and have egress error
|
||||
* then drop
|
||||
*/
|
||||
if (CQE_TYPE(hw_cqe) == 1) {
|
||||
if (CQE_STATUS(hw_cqe))
|
||||
t4_set_wq_in_error(wq);
|
||||
ret = -EAGAIN;
|
||||
goto skip_cqe;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
@@ -603,7 +619,7 @@ proc_cqe:
|
||||
*/
|
||||
if (SQ_TYPE(hw_cqe)) {
|
||||
int idx = CQE_WRID_SQ_IDX(hw_cqe);
|
||||
BUG_ON(idx > wq->sq.size);
|
||||
BUG_ON(idx >= wq->sq.size);
|
||||
|
||||
/*
|
||||
* Account for any unsignaled completions completed by
|
||||
@@ -617,7 +633,7 @@ proc_cqe:
|
||||
wq->sq.in_use -= wq->sq.size + idx - wq->sq.cidx;
|
||||
else
|
||||
wq->sq.in_use -= idx - wq->sq.cidx;
|
||||
BUG_ON(wq->sq.in_use < 0 && wq->sq.in_use < wq->sq.size);
|
||||
BUG_ON(wq->sq.in_use <= 0 && wq->sq.in_use >= wq->sq.size);
|
||||
|
||||
wq->sq.cidx = (uint16_t)idx;
|
||||
PDBG("%s completing sq idx %u\n", __func__, wq->sq.cidx);
|
||||
@@ -881,7 +897,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
|
||||
/*
|
||||
* Make actual HW queue 2x to avoid cdix_inc overflows.
|
||||
*/
|
||||
hwentries = entries * 2;
|
||||
hwentries = min(entries * 2, T4_MAX_IQ_SIZE);
|
||||
|
||||
/*
|
||||
* Make HW queue at least 64 entries so GTS updates aren't too
|
||||
@@ -930,6 +946,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
|
||||
if (!mm2)
|
||||
goto err4;
|
||||
|
||||
memset(&uresp, 0, sizeof(uresp));
|
||||
uresp.qid_mask = rhp->rdev.cqmask;
|
||||
uresp.cqid = chp->cq.cqid;
|
||||
uresp.size = chp->cq.size;
|
||||
|
||||
@@ -898,11 +898,13 @@ static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
|
||||
}
|
||||
|
||||
opcode = *(u8 *)rsp;
|
||||
if (c4iw_handlers[opcode])
|
||||
if (c4iw_handlers[opcode]) {
|
||||
c4iw_handlers[opcode](dev, skb);
|
||||
else
|
||||
} else {
|
||||
pr_info("%s no handler opcode 0x%x...\n", __func__,
|
||||
opcode);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
nomem:
|
||||
|
||||
@@ -373,6 +373,7 @@ struct c4iw_fr_page_list {
|
||||
DEFINE_DMA_UNMAP_ADDR(mapping);
|
||||
dma_addr_t dma_addr;
|
||||
struct c4iw_dev *dev;
|
||||
int pll_len;
|
||||
};
|
||||
|
||||
static inline struct c4iw_fr_page_list *to_c4iw_fr_page_list(
|
||||
@@ -446,6 +447,7 @@ struct c4iw_qp {
|
||||
atomic_t refcnt;
|
||||
wait_queue_head_t wait;
|
||||
struct timer_list timer;
|
||||
int sq_sig_all;
|
||||
};
|
||||
|
||||
static inline struct c4iw_qp *to_c4iw_qp(struct ib_qp *ibqp)
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
|
||||
#include "iw_cxgb4.h"
|
||||
|
||||
int use_dsgl = 1;
|
||||
int use_dsgl = 0;
|
||||
module_param(use_dsgl, int, 0644);
|
||||
MODULE_PARM_DESC(use_dsgl, "Use DSGL for PBL/FastReg (default=1)");
|
||||
MODULE_PARM_DESC(use_dsgl, "Use DSGL for PBL/FastReg (default=0)");
|
||||
|
||||
#define T4_ULPTX_MIN_IO 32
|
||||
#define C4IW_MAX_INLINE_SIZE 96
|
||||
@@ -678,9 +678,9 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
{
|
||||
__be64 *pages;
|
||||
int shift, n, len;
|
||||
int i, j, k;
|
||||
int i, k, entry;
|
||||
int err = 0;
|
||||
struct ib_umem_chunk *chunk;
|
||||
struct scatterlist *sg;
|
||||
struct c4iw_dev *rhp;
|
||||
struct c4iw_pd *php;
|
||||
struct c4iw_mr *mhp;
|
||||
@@ -710,10 +710,7 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
|
||||
shift = ffs(mhp->umem->page_size) - 1;
|
||||
|
||||
n = 0;
|
||||
list_for_each_entry(chunk, &mhp->umem->chunk_list, list)
|
||||
n += chunk->nents;
|
||||
|
||||
n = mhp->umem->nmap;
|
||||
err = alloc_pbl(mhp, n);
|
||||
if (err)
|
||||
goto err;
|
||||
@@ -726,24 +723,22 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
|
||||
i = n = 0;
|
||||
|
||||
list_for_each_entry(chunk, &mhp->umem->chunk_list, list)
|
||||
for (j = 0; j < chunk->nmap; ++j) {
|
||||
len = sg_dma_len(&chunk->page_list[j]) >> shift;
|
||||
for (k = 0; k < len; ++k) {
|
||||
pages[i++] = cpu_to_be64(sg_dma_address(
|
||||
&chunk->page_list[j]) +
|
||||
mhp->umem->page_size * k);
|
||||
if (i == PAGE_SIZE / sizeof *pages) {
|
||||
err = write_pbl(&mhp->rhp->rdev,
|
||||
pages,
|
||||
mhp->attr.pbl_addr + (n << 3), i);
|
||||
if (err)
|
||||
goto pbl_done;
|
||||
n += i;
|
||||
i = 0;
|
||||
}
|
||||
for_each_sg(mhp->umem->sg_head.sgl, sg, mhp->umem->nmap, entry) {
|
||||
len = sg_dma_len(sg) >> shift;
|
||||
for (k = 0; k < len; ++k) {
|
||||
pages[i++] = cpu_to_be64(sg_dma_address(sg) +
|
||||
mhp->umem->page_size * k);
|
||||
if (i == PAGE_SIZE / sizeof *pages) {
|
||||
err = write_pbl(&mhp->rhp->rdev,
|
||||
pages,
|
||||
mhp->attr.pbl_addr + (n << 3), i);
|
||||
if (err)
|
||||
goto pbl_done;
|
||||
n += i;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
err = write_pbl(&mhp->rhp->rdev, pages,
|
||||
@@ -903,7 +898,11 @@ struct ib_fast_reg_page_list *c4iw_alloc_fastreg_pbl(struct ib_device *device,
|
||||
dma_unmap_addr_set(c4pl, mapping, dma_addr);
|
||||
c4pl->dma_addr = dma_addr;
|
||||
c4pl->dev = dev;
|
||||
c4pl->ibpl.max_page_list_len = pll_len;
|
||||
c4pl->pll_len = pll_len;
|
||||
|
||||
PDBG("%s c4pl %p pll_len %u page_list %p dma_addr %pad\n",
|
||||
__func__, c4pl, c4pl->pll_len, c4pl->ibpl.page_list,
|
||||
&c4pl->dma_addr);
|
||||
|
||||
return &c4pl->ibpl;
|
||||
}
|
||||
@@ -912,8 +911,12 @@ void c4iw_free_fastreg_pbl(struct ib_fast_reg_page_list *ibpl)
|
||||
{
|
||||
struct c4iw_fr_page_list *c4pl = to_c4iw_fr_page_list(ibpl);
|
||||
|
||||
PDBG("%s c4pl %p pll_len %u page_list %p dma_addr %pad\n",
|
||||
__func__, c4pl, c4pl->pll_len, c4pl->ibpl.page_list,
|
||||
&c4pl->dma_addr);
|
||||
|
||||
dma_free_coherent(&c4pl->dev->rdev.lldi.pdev->dev,
|
||||
c4pl->ibpl.max_page_list_len,
|
||||
c4pl->pll_len,
|
||||
c4pl->ibpl.page_list, dma_unmap_addr(c4pl, mapping));
|
||||
kfree(c4pl);
|
||||
}
|
||||
|
||||
@@ -715,7 +715,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
fw_flags = 0;
|
||||
if (wr->send_flags & IB_SEND_SOLICITED)
|
||||
fw_flags |= FW_RI_SOLICITED_EVENT_FLAG;
|
||||
if (wr->send_flags & IB_SEND_SIGNALED)
|
||||
if (wr->send_flags & IB_SEND_SIGNALED || qhp->sq_sig_all)
|
||||
fw_flags |= FW_RI_COMPLETION_FLAG;
|
||||
swsqe = &qhp->wq.sq.sw_sq[qhp->wq.sq.pidx];
|
||||
switch (wr->opcode) {
|
||||
@@ -776,7 +776,8 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
}
|
||||
swsqe->idx = qhp->wq.sq.pidx;
|
||||
swsqe->complete = 0;
|
||||
swsqe->signaled = (wr->send_flags & IB_SEND_SIGNALED);
|
||||
swsqe->signaled = (wr->send_flags & IB_SEND_SIGNALED) ||
|
||||
qhp->sq_sig_all;
|
||||
swsqe->flushed = 0;
|
||||
swsqe->wr_id = wr->wr_id;
|
||||
|
||||
@@ -1529,7 +1530,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
|
||||
struct c4iw_cq *schp;
|
||||
struct c4iw_cq *rchp;
|
||||
struct c4iw_create_qp_resp uresp;
|
||||
int sqsize, rqsize;
|
||||
unsigned int sqsize, rqsize;
|
||||
struct c4iw_ucontext *ucontext;
|
||||
int ret;
|
||||
struct c4iw_mm_entry *mm1, *mm2, *mm3, *mm4, *mm5 = NULL;
|
||||
@@ -1601,6 +1602,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
|
||||
qhp->attr.enable_bind = 1;
|
||||
qhp->attr.max_ord = 1;
|
||||
qhp->attr.max_ird = 1;
|
||||
qhp->sq_sig_all = attrs->sq_sig_type == IB_SIGNAL_ALL_WR;
|
||||
spin_lock_init(&qhp->lock);
|
||||
mutex_init(&qhp->mutex);
|
||||
init_waitqueue_head(&qhp->wait);
|
||||
|
||||
@@ -322,7 +322,7 @@ struct ehca_mr_pginfo {
|
||||
} phy;
|
||||
struct { /* type EHCA_MR_PGI_USER section */
|
||||
struct ib_umem *region;
|
||||
struct ib_umem_chunk *next_chunk;
|
||||
struct scatterlist *next_sg;
|
||||
u64 next_nmap;
|
||||
} usr;
|
||||
struct { /* type EHCA_MR_PGI_FMR section */
|
||||
|
||||
@@ -283,6 +283,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
|
||||
(my_cq->galpas.user.fw_handle & (PAGE_SIZE - 1));
|
||||
if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
|
||||
ehca_err(device, "Copy to udata failed.");
|
||||
cq = ERR_PTR(-EFAULT);
|
||||
goto create_cq_exit4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,10 +400,7 @@ reg_user_mr_fallback:
|
||||
pginfo.num_hwpages = num_hwpages;
|
||||
pginfo.u.usr.region = e_mr->umem;
|
||||
pginfo.next_hwpage = e_mr->umem->offset / hwpage_size;
|
||||
pginfo.u.usr.next_chunk = list_prepare_entry(pginfo.u.usr.next_chunk,
|
||||
(&e_mr->umem->chunk_list),
|
||||
list);
|
||||
|
||||
pginfo.u.usr.next_sg = pginfo.u.usr.region->sg_head.sgl;
|
||||
ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags,
|
||||
e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
|
||||
&e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
|
||||
@@ -1858,61 +1855,39 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
|
||||
u64 *kpage)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ib_umem_chunk *prev_chunk;
|
||||
struct ib_umem_chunk *chunk;
|
||||
u64 pgaddr;
|
||||
u32 i = 0;
|
||||
u32 j = 0;
|
||||
int hwpages_per_kpage = PAGE_SIZE / pginfo->hwpage_size;
|
||||
struct scatterlist **sg = &pginfo->u.usr.next_sg;
|
||||
|
||||
/* loop over desired chunk entries */
|
||||
chunk = pginfo->u.usr.next_chunk;
|
||||
prev_chunk = pginfo->u.usr.next_chunk;
|
||||
list_for_each_entry_continue(
|
||||
chunk, (&(pginfo->u.usr.region->chunk_list)), list) {
|
||||
for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
|
||||
pgaddr = page_to_pfn(sg_page(&chunk->page_list[i]))
|
||||
<< PAGE_SHIFT ;
|
||||
*kpage = pgaddr + (pginfo->next_hwpage *
|
||||
pginfo->hwpage_size);
|
||||
if ( !(*kpage) ) {
|
||||
ehca_gen_err("pgaddr=%llx "
|
||||
"chunk->page_list[i]=%llx "
|
||||
"i=%x next_hwpage=%llx",
|
||||
pgaddr, (u64)sg_dma_address(
|
||||
&chunk->page_list[i]),
|
||||
i, pginfo->next_hwpage);
|
||||
return -EFAULT;
|
||||
}
|
||||
(pginfo->hwpage_cnt)++;
|
||||
(pginfo->next_hwpage)++;
|
||||
kpage++;
|
||||
if (pginfo->next_hwpage % hwpages_per_kpage == 0) {
|
||||
(pginfo->kpage_cnt)++;
|
||||
(pginfo->u.usr.next_nmap)++;
|
||||
pginfo->next_hwpage = 0;
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
if (j >= number) break;
|
||||
while (*sg != NULL) {
|
||||
pgaddr = page_to_pfn(sg_page(*sg))
|
||||
<< PAGE_SHIFT;
|
||||
*kpage = pgaddr + (pginfo->next_hwpage *
|
||||
pginfo->hwpage_size);
|
||||
if (!(*kpage)) {
|
||||
ehca_gen_err("pgaddr=%llx "
|
||||
"sg_dma_address=%llx "
|
||||
"entry=%llx next_hwpage=%llx",
|
||||
pgaddr, (u64)sg_dma_address(*sg),
|
||||
pginfo->u.usr.next_nmap,
|
||||
pginfo->next_hwpage);
|
||||
return -EFAULT;
|
||||
}
|
||||
if ((pginfo->u.usr.next_nmap >= chunk->nmap) &&
|
||||
(j >= number)) {
|
||||
pginfo->u.usr.next_nmap = 0;
|
||||
prev_chunk = chunk;
|
||||
(pginfo->hwpage_cnt)++;
|
||||
(pginfo->next_hwpage)++;
|
||||
kpage++;
|
||||
if (pginfo->next_hwpage % hwpages_per_kpage == 0) {
|
||||
(pginfo->kpage_cnt)++;
|
||||
(pginfo->u.usr.next_nmap)++;
|
||||
pginfo->next_hwpage = 0;
|
||||
*sg = sg_next(*sg);
|
||||
}
|
||||
j++;
|
||||
if (j >= number)
|
||||
break;
|
||||
} else if (pginfo->u.usr.next_nmap >= chunk->nmap) {
|
||||
pginfo->u.usr.next_nmap = 0;
|
||||
prev_chunk = chunk;
|
||||
} else if (j >= number)
|
||||
break;
|
||||
else
|
||||
prev_chunk = chunk;
|
||||
}
|
||||
pginfo->u.usr.next_chunk =
|
||||
list_prepare_entry(prev_chunk,
|
||||
(&(pginfo->u.usr.region->chunk_list)),
|
||||
list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1920,20 +1895,19 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
|
||||
* check given pages for contiguous layout
|
||||
* last page addr is returned in prev_pgaddr for further check
|
||||
*/
|
||||
static int ehca_check_kpages_per_ate(struct scatterlist *page_list,
|
||||
int start_idx, int end_idx,
|
||||
static int ehca_check_kpages_per_ate(struct scatterlist **sg,
|
||||
int num_pages,
|
||||
u64 *prev_pgaddr)
|
||||
{
|
||||
int t;
|
||||
for (t = start_idx; t <= end_idx; t++) {
|
||||
u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
|
||||
for (; *sg && num_pages > 0; *sg = sg_next(*sg), num_pages--) {
|
||||
u64 pgaddr = page_to_pfn(sg_page(*sg)) << PAGE_SHIFT;
|
||||
if (ehca_debug_level >= 3)
|
||||
ehca_gen_dbg("chunk_page=%llx value=%016llx", pgaddr,
|
||||
*(u64 *)__va(pgaddr));
|
||||
if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
|
||||
ehca_gen_err("uncontiguous page found pgaddr=%llx "
|
||||
"prev_pgaddr=%llx page_list_i=%x",
|
||||
pgaddr, *prev_pgaddr, t);
|
||||
"prev_pgaddr=%llx entries_left_in_hwpage=%x",
|
||||
pgaddr, *prev_pgaddr, num_pages);
|
||||
return -EINVAL;
|
||||
}
|
||||
*prev_pgaddr = pgaddr;
|
||||
@@ -1947,111 +1921,80 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
|
||||
u64 *kpage)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ib_umem_chunk *prev_chunk;
|
||||
struct ib_umem_chunk *chunk;
|
||||
u64 pgaddr, prev_pgaddr;
|
||||
u32 i = 0;
|
||||
u32 j = 0;
|
||||
int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE;
|
||||
int nr_kpages = kpages_per_hwpage;
|
||||
struct scatterlist **sg = &pginfo->u.usr.next_sg;
|
||||
|
||||
/* loop over desired chunk entries */
|
||||
chunk = pginfo->u.usr.next_chunk;
|
||||
prev_chunk = pginfo->u.usr.next_chunk;
|
||||
list_for_each_entry_continue(
|
||||
chunk, (&(pginfo->u.usr.region->chunk_list)), list) {
|
||||
for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
|
||||
if (nr_kpages == kpages_per_hwpage) {
|
||||
pgaddr = ( page_to_pfn(sg_page(&chunk->page_list[i]))
|
||||
<< PAGE_SHIFT );
|
||||
*kpage = pgaddr;
|
||||
if ( !(*kpage) ) {
|
||||
ehca_gen_err("pgaddr=%llx i=%x",
|
||||
pgaddr, i);
|
||||
while (*sg != NULL) {
|
||||
|
||||
if (nr_kpages == kpages_per_hwpage) {
|
||||
pgaddr = (page_to_pfn(sg_page(*sg))
|
||||
<< PAGE_SHIFT);
|
||||
*kpage = pgaddr;
|
||||
if (!(*kpage)) {
|
||||
ehca_gen_err("pgaddr=%llx entry=%llx",
|
||||
pgaddr, pginfo->u.usr.next_nmap);
|
||||
ret = -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* The first page in a hwpage must be aligned;
|
||||
* the first MR page is exempt from this rule.
|
||||
*/
|
||||
if (pgaddr & (pginfo->hwpage_size - 1)) {
|
||||
if (pginfo->hwpage_cnt) {
|
||||
ehca_gen_err(
|
||||
"invalid alignment "
|
||||
"pgaddr=%llx entry=%llx "
|
||||
"mr_pgsize=%llx",
|
||||
pgaddr, pginfo->u.usr.next_nmap,
|
||||
pginfo->hwpage_size);
|
||||
ret = -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* The first page in a hwpage must be aligned;
|
||||
* the first MR page is exempt from this rule.
|
||||
*/
|
||||
if (pgaddr & (pginfo->hwpage_size - 1)) {
|
||||
if (pginfo->hwpage_cnt) {
|
||||
ehca_gen_err(
|
||||
"invalid alignment "
|
||||
"pgaddr=%llx i=%x "
|
||||
"mr_pgsize=%llx",
|
||||
pgaddr, i,
|
||||
pginfo->hwpage_size);
|
||||
ret = -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
/* first MR page */
|
||||
pginfo->kpage_cnt =
|
||||
(pgaddr &
|
||||
(pginfo->hwpage_size - 1)) >>
|
||||
PAGE_SHIFT;
|
||||
nr_kpages -= pginfo->kpage_cnt;
|
||||
*kpage = pgaddr &
|
||||
~(pginfo->hwpage_size - 1);
|
||||
}
|
||||
if (ehca_debug_level >= 3) {
|
||||
u64 val = *(u64 *)__va(pgaddr);
|
||||
ehca_gen_dbg("kpage=%llx chunk_page=%llx "
|
||||
"value=%016llx",
|
||||
*kpage, pgaddr, val);
|
||||
}
|
||||
prev_pgaddr = pgaddr;
|
||||
i++;
|
||||
pginfo->kpage_cnt++;
|
||||
pginfo->u.usr.next_nmap++;
|
||||
nr_kpages--;
|
||||
if (!nr_kpages)
|
||||
goto next_kpage;
|
||||
continue;
|
||||
/* first MR page */
|
||||
pginfo->kpage_cnt =
|
||||
(pgaddr &
|
||||
(pginfo->hwpage_size - 1)) >>
|
||||
PAGE_SHIFT;
|
||||
nr_kpages -= pginfo->kpage_cnt;
|
||||
*kpage = pgaddr &
|
||||
~(pginfo->hwpage_size - 1);
|
||||
}
|
||||
if (i + nr_kpages > chunk->nmap) {
|
||||
ret = ehca_check_kpages_per_ate(
|
||||
chunk->page_list, i,
|
||||
chunk->nmap - 1, &prev_pgaddr);
|
||||
if (ret) return ret;
|
||||
pginfo->kpage_cnt += chunk->nmap - i;
|
||||
pginfo->u.usr.next_nmap += chunk->nmap - i;
|
||||
nr_kpages -= chunk->nmap - i;
|
||||
break;
|
||||
if (ehca_debug_level >= 3) {
|
||||
u64 val = *(u64 *)__va(pgaddr);
|
||||
ehca_gen_dbg("kpage=%llx page=%llx "
|
||||
"value=%016llx",
|
||||
*kpage, pgaddr, val);
|
||||
}
|
||||
|
||||
ret = ehca_check_kpages_per_ate(chunk->page_list, i,
|
||||
i + nr_kpages - 1,
|
||||
&prev_pgaddr);
|
||||
if (ret) return ret;
|
||||
i += nr_kpages;
|
||||
pginfo->kpage_cnt += nr_kpages;
|
||||
pginfo->u.usr.next_nmap += nr_kpages;
|
||||
next_kpage:
|
||||
nr_kpages = kpages_per_hwpage;
|
||||
(pginfo->hwpage_cnt)++;
|
||||
kpage++;
|
||||
j++;
|
||||
if (j >= number) break;
|
||||
prev_pgaddr = pgaddr;
|
||||
*sg = sg_next(*sg);
|
||||
pginfo->kpage_cnt++;
|
||||
pginfo->u.usr.next_nmap++;
|
||||
nr_kpages--;
|
||||
if (!nr_kpages)
|
||||
goto next_kpage;
|
||||
continue;
|
||||
}
|
||||
if ((pginfo->u.usr.next_nmap >= chunk->nmap) &&
|
||||
(j >= number)) {
|
||||
pginfo->u.usr.next_nmap = 0;
|
||||
prev_chunk = chunk;
|
||||
|
||||
ret = ehca_check_kpages_per_ate(sg, nr_kpages,
|
||||
&prev_pgaddr);
|
||||
if (ret)
|
||||
return ret;
|
||||
pginfo->kpage_cnt += nr_kpages;
|
||||
pginfo->u.usr.next_nmap += nr_kpages;
|
||||
|
||||
next_kpage:
|
||||
nr_kpages = kpages_per_hwpage;
|
||||
(pginfo->hwpage_cnt)++;
|
||||
kpage++;
|
||||
j++;
|
||||
if (j >= number)
|
||||
break;
|
||||
} else if (pginfo->u.usr.next_nmap >= chunk->nmap) {
|
||||
pginfo->u.usr.next_nmap = 0;
|
||||
prev_chunk = chunk;
|
||||
} else if (j >= number)
|
||||
break;
|
||||
else
|
||||
prev_chunk = chunk;
|
||||
}
|
||||
pginfo->u.usr.next_chunk =
|
||||
list_prepare_entry(prev_chunk,
|
||||
(&(pginfo->u.usr.region->chunk_list)),
|
||||
list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2591,16 +2534,6 @@ static void ehca_dma_unmap_sg(struct ib_device *dev, struct scatterlist *sg,
|
||||
/* This is only a stub; nothing to be done here */
|
||||
}
|
||||
|
||||
static u64 ehca_dma_address(struct ib_device *dev, struct scatterlist *sg)
|
||||
{
|
||||
return sg->dma_address;
|
||||
}
|
||||
|
||||
static unsigned int ehca_dma_len(struct ib_device *dev, struct scatterlist *sg)
|
||||
{
|
||||
return sg->length;
|
||||
}
|
||||
|
||||
static void ehca_dma_sync_single_for_cpu(struct ib_device *dev, u64 addr,
|
||||
size_t size,
|
||||
enum dma_data_direction dir)
|
||||
@@ -2653,8 +2586,6 @@ struct ib_dma_mapping_ops ehca_dma_mapping_ops = {
|
||||
.unmap_page = ehca_dma_unmap_page,
|
||||
.map_sg = ehca_dma_map_sg,
|
||||
.unmap_sg = ehca_dma_unmap_sg,
|
||||
.dma_address = ehca_dma_address,
|
||||
.dma_len = ehca_dma_len,
|
||||
.sync_single_for_cpu = ehca_dma_sync_single_for_cpu,
|
||||
.sync_single_for_device = ehca_dma_sync_single_for_device,
|
||||
.alloc_coherent = ehca_dma_alloc_coherent,
|
||||
|
||||
@@ -326,7 +326,7 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
u32 __iomem *piobuf;
|
||||
u32 plen, clen, pbufn;
|
||||
u32 plen, pbufn, maxlen_reserve;
|
||||
struct ipath_diag_pkt odp;
|
||||
struct ipath_diag_xpkt dp;
|
||||
u32 *tmpbuf = NULL;
|
||||
@@ -335,51 +335,29 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
|
||||
u64 val;
|
||||
u32 l_state, lt_state; /* LinkState, LinkTrainingState */
|
||||
|
||||
if (count < sizeof(odp)) {
|
||||
ret = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (count == sizeof(dp)) {
|
||||
if (copy_from_user(&dp, data, sizeof(dp))) {
|
||||
ret = -EFAULT;
|
||||
goto bail;
|
||||
}
|
||||
} else if (copy_from_user(&odp, data, sizeof(odp))) {
|
||||
ret = -EFAULT;
|
||||
} else if (count == sizeof(odp)) {
|
||||
if (copy_from_user(&odp, data, sizeof(odp))) {
|
||||
ret = -EFAULT;
|
||||
goto bail;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Due to padding/alignment issues (lessened with new struct)
|
||||
* the old and new structs are the same length. We need to
|
||||
* disambiguate them, which we can do because odp.len has never
|
||||
* been less than the total of LRH+BTH+DETH so far, while
|
||||
* dp.unit (same offset) unit is unlikely to get that high.
|
||||
* Similarly, dp.data, the pointer to user at the same offset
|
||||
* as odp.unit, is almost certainly at least one (512byte)page
|
||||
* "above" NULL. The if-block below can be omitted if compatibility
|
||||
* between a new driver and older diagnostic code is unimportant.
|
||||
* compatibility the other direction (new diags, old driver) is
|
||||
* handled in the diagnostic code, with a warning.
|
||||
*/
|
||||
if (dp.unit >= 20 && dp.data < 512) {
|
||||
/* very probable version mismatch. Fix it up */
|
||||
memcpy(&odp, &dp, sizeof(odp));
|
||||
/* We got a legacy dp, copy elements to dp */
|
||||
dp.unit = odp.unit;
|
||||
dp.data = odp.data;
|
||||
dp.len = odp.len;
|
||||
dp.pbc_wd = 0; /* Indicate we need to compute PBC wd */
|
||||
}
|
||||
|
||||
/* send count must be an exact number of dwords */
|
||||
if (dp.len & 3) {
|
||||
ret = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
clen = dp.len >> 2;
|
||||
plen = dp.len >> 2;
|
||||
|
||||
dd = ipath_lookup(dp.unit);
|
||||
if (!dd || !(dd->ipath_flags & IPATH_PRESENT) ||
|
||||
@@ -422,16 +400,22 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* need total length before first word written */
|
||||
/* +1 word is for the qword padding */
|
||||
/*
|
||||
* need total length before first word written, plus 2 Dwords. One Dword
|
||||
* is for padding so we get the full user data when not aligned on
|
||||
* a word boundary. The other Dword is to make sure we have room for the
|
||||
* ICRC which gets tacked on later.
|
||||
*/
|
||||
maxlen_reserve = 2 * sizeof(u32);
|
||||
if (dp.len > dd->ipath_ibmaxlen - maxlen_reserve) {
|
||||
ipath_dbg("Pkt len 0x%x > ibmaxlen %x\n",
|
||||
dp.len, dd->ipath_ibmaxlen);
|
||||
ret = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
plen = sizeof(u32) + dp.len;
|
||||
|
||||
if ((plen + 4) > dd->ipath_ibmaxlen) {
|
||||
ipath_dbg("Pkt len 0x%x > ibmaxlen %x\n",
|
||||
plen - 4, dd->ipath_ibmaxlen);
|
||||
ret = -EINVAL;
|
||||
goto bail; /* before writing pbc */
|
||||
}
|
||||
tmpbuf = vmalloc(plen);
|
||||
if (!tmpbuf) {
|
||||
dev_info(&dd->pcidev->dev, "Unable to allocate tmp buffer, "
|
||||
@@ -473,11 +457,11 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
|
||||
*/
|
||||
if (dd->ipath_flags & IPATH_PIO_FLUSH_WC) {
|
||||
ipath_flush_wc();
|
||||
__iowrite32_copy(piobuf + 2, tmpbuf, clen - 1);
|
||||
__iowrite32_copy(piobuf + 2, tmpbuf, plen - 1);
|
||||
ipath_flush_wc();
|
||||
__raw_writel(tmpbuf[clen - 1], piobuf + clen + 1);
|
||||
__raw_writel(tmpbuf[plen - 1], piobuf + plen + 1);
|
||||
} else
|
||||
__iowrite32_copy(piobuf + 2, tmpbuf, clen);
|
||||
__iowrite32_copy(piobuf + 2, tmpbuf, plen);
|
||||
|
||||
ipath_flush_wc();
|
||||
|
||||
|
||||
@@ -115,6 +115,10 @@ static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sgl,
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
sg->dma_address = addr + sg->offset;
|
||||
#ifdef CONFIG_NEED_SG_DMA_LENGTH
|
||||
sg->dma_length = sg->length;
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -126,21 +130,6 @@ static void ipath_unmap_sg(struct ib_device *dev,
|
||||
BUG_ON(!valid_dma_direction(direction));
|
||||
}
|
||||
|
||||
static u64 ipath_sg_dma_address(struct ib_device *dev, struct scatterlist *sg)
|
||||
{
|
||||
u64 addr = (u64) page_address(sg_page(sg));
|
||||
|
||||
if (addr)
|
||||
addr += sg->offset;
|
||||
return addr;
|
||||
}
|
||||
|
||||
static unsigned int ipath_sg_dma_len(struct ib_device *dev,
|
||||
struct scatterlist *sg)
|
||||
{
|
||||
return sg->length;
|
||||
}
|
||||
|
||||
static void ipath_sync_single_for_cpu(struct ib_device *dev,
|
||||
u64 addr,
|
||||
size_t size,
|
||||
@@ -176,17 +165,15 @@ static void ipath_dma_free_coherent(struct ib_device *dev, size_t size,
|
||||
}
|
||||
|
||||
struct ib_dma_mapping_ops ipath_dma_mapping_ops = {
|
||||
ipath_mapping_error,
|
||||
ipath_dma_map_single,
|
||||
ipath_dma_unmap_single,
|
||||
ipath_dma_map_page,
|
||||
ipath_dma_unmap_page,
|
||||
ipath_map_sg,
|
||||
ipath_unmap_sg,
|
||||
ipath_sg_dma_address,
|
||||
ipath_sg_dma_len,
|
||||
ipath_sync_single_for_cpu,
|
||||
ipath_sync_single_for_device,
|
||||
ipath_dma_alloc_coherent,
|
||||
ipath_dma_free_coherent
|
||||
.mapping_error = ipath_mapping_error,
|
||||
.map_single = ipath_dma_map_single,
|
||||
.unmap_single = ipath_dma_unmap_single,
|
||||
.map_page = ipath_dma_map_page,
|
||||
.unmap_page = ipath_dma_unmap_page,
|
||||
.map_sg = ipath_map_sg,
|
||||
.unmap_sg = ipath_unmap_sg,
|
||||
.sync_single_for_cpu = ipath_sync_single_for_cpu,
|
||||
.sync_single_for_device = ipath_sync_single_for_device,
|
||||
.alloc_coherent = ipath_dma_alloc_coherent,
|
||||
.free_coherent = ipath_dma_free_coherent
|
||||
};
|
||||
@@ -188,8 +188,8 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
{
|
||||
struct ipath_mr *mr;
|
||||
struct ib_umem *umem;
|
||||
struct ib_umem_chunk *chunk;
|
||||
int n, m, i;
|
||||
int n, m, entry;
|
||||
struct scatterlist *sg;
|
||||
struct ib_mr *ret;
|
||||
|
||||
if (length == 0) {
|
||||
@@ -202,10 +202,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
if (IS_ERR(umem))
|
||||
return (void *) umem;
|
||||
|
||||
n = 0;
|
||||
list_for_each_entry(chunk, &umem->chunk_list, list)
|
||||
n += chunk->nents;
|
||||
|
||||
n = umem->nmap;
|
||||
mr = alloc_mr(n, &to_idev(pd->device)->lk_table);
|
||||
if (!mr) {
|
||||
ret = ERR_PTR(-ENOMEM);
|
||||
@@ -224,22 +221,20 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
|
||||
m = 0;
|
||||
n = 0;
|
||||
list_for_each_entry(chunk, &umem->chunk_list, list) {
|
||||
for (i = 0; i < chunk->nents; i++) {
|
||||
void *vaddr;
|
||||
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
|
||||
void *vaddr;
|
||||
|
||||
vaddr = page_address(sg_page(&chunk->page_list[i]));
|
||||
if (!vaddr) {
|
||||
ret = ERR_PTR(-EINVAL);
|
||||
goto bail;
|
||||
}
|
||||
mr->mr.map[m]->segs[n].vaddr = vaddr;
|
||||
mr->mr.map[m]->segs[n].length = umem->page_size;
|
||||
n++;
|
||||
if (n == IPATH_SEGSZ) {
|
||||
m++;
|
||||
n = 0;
|
||||
}
|
||||
vaddr = page_address(sg_page(sg));
|
||||
if (!vaddr) {
|
||||
ret = ERR_PTR(-EINVAL);
|
||||
goto bail;
|
||||
}
|
||||
mr->mr.map[m]->segs[n].vaddr = vaddr;
|
||||
mr->mr.map[m]->segs[n].length = umem->page_size;
|
||||
n++;
|
||||
if (n == IPATH_SEGSZ) {
|
||||
m++;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
ret = &mr->ibmr;
|
||||
|
||||
@@ -45,7 +45,6 @@ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
|
||||
struct mlx4_db *db)
|
||||
{
|
||||
struct mlx4_ib_user_db_page *page;
|
||||
struct ib_umem_chunk *chunk;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&context->db_page_mutex);
|
||||
@@ -73,8 +72,7 @@ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
|
||||
list_add(&page->list, &context->db_page_list);
|
||||
|
||||
found:
|
||||
chunk = list_entry(page->umem->chunk_list.next, struct ib_umem_chunk, list);
|
||||
db->dma = sg_dma_address(chunk->page_list) + (virt & ~PAGE_MASK);
|
||||
db->dma = sg_dma_address(page->umem->sg_head.sgl) + (virt & ~PAGE_MASK);
|
||||
db->u.user_page = page;
|
||||
++page->refcnt;
|
||||
|
||||
|
||||
Loaded 20 of 88 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user