Commit ffebedb7 authored by Roland Dreier's avatar Roland Dreier

Merge branches 'amso1100', 'bkl', 'cma', 'cxgb3', 'cxgb4', 'ipoib', 'iser',...

Merge branches 'amso1100', 'bkl', 'cma', 'cxgb3', 'cxgb4', 'ipoib', 'iser', 'masked-atomics', 'misc', 'mthca' and 'nes' into for-next
......@@ -1719,6 +1719,20 @@ W: http://www.openfabrics.org
S: Supported
F: drivers/infiniband/hw/cxgb3/
CXGB4 ETHERNET DRIVER (CXGB4)
M: Dimitris Michailidis <dm@chelsio.com>
L: netdev@vger.kernel.org
W: http://www.chelsio.com
S: Supported
F: drivers/net/cxgb4/
CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
M: Steve Wise <swise@chelsio.com>
L: linux-rdma@vger.kernel.org
W: http://www.openfabrics.org
S: Supported
F: drivers/infiniband/hw/cxgb4/
CYBERPRO FB DRIVER
M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
......
......@@ -46,6 +46,7 @@ source "drivers/infiniband/hw/ipath/Kconfig"
source "drivers/infiniband/hw/ehca/Kconfig"
source "drivers/infiniband/hw/amso1100/Kconfig"
source "drivers/infiniband/hw/cxgb3/Kconfig"
source "drivers/infiniband/hw/cxgb4/Kconfig"
source "drivers/infiniband/hw/mlx4/Kconfig"
source "drivers/infiniband/hw/nes/Kconfig"
......
......@@ -4,6 +4,7 @@ obj-$(CONFIG_INFINIBAND_IPATH) += hw/ipath/
obj-$(CONFIG_INFINIBAND_EHCA) += hw/ehca/
obj-$(CONFIG_INFINIBAND_AMSO1100) += hw/amso1100/
obj-$(CONFIG_INFINIBAND_CXGB3) += hw/cxgb3/
obj-$(CONFIG_INFINIBAND_CXGB4) += hw/cxgb4/
obj-$(CONFIG_MLX4_INFINIBAND) += hw/mlx4/
obj-$(CONFIG_INFINIBAND_NES) += hw/nes/
obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/
......
......@@ -79,7 +79,6 @@ static DEFINE_IDR(sdp_ps);
static DEFINE_IDR(tcp_ps);
static DEFINE_IDR(udp_ps);
static DEFINE_IDR(ipoib_ps);
static int next_port;
struct cma_device {
struct list_head list;
......@@ -1677,13 +1676,13 @@ int rdma_set_ib_paths(struct rdma_cm_id *id,
if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_RESOLVED))
return -EINVAL;
id->route.path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL);
id->route.path_rec = kmemdup(path_rec, sizeof *path_rec * num_paths,
GFP_KERNEL);
if (!id->route.path_rec) {
ret = -ENOMEM;
goto err;
}
memcpy(id->route.path_rec, path_rec, sizeof *path_rec * num_paths);
id->route.num_paths = num_paths;
return 0;
err:
......@@ -1970,47 +1969,33 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv)
{
struct rdma_bind_list *bind_list;
int port, ret, low, high;
bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
if (!bind_list)
return -ENOMEM;
retry:
/* FIXME: add proper port randomization per like inet_csk_get_port */
do {
ret = idr_get_new_above(ps, bind_list, next_port, &port);
} while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
if (ret)
goto err1;
static unsigned int last_used_port;
int low, high, remaining;
unsigned int rover;
inet_get_local_port_range(&low, &high);
if (port > high) {
if (next_port != low) {
idr_remove(ps, port);
next_port = low;
goto retry;
}
ret = -EADDRNOTAVAIL;
goto err2;
remaining = (high - low) + 1;
rover = net_random() % remaining + low;
retry:
if (last_used_port != rover &&
!idr_find(ps, (unsigned short) rover)) {
int ret = cma_alloc_port(ps, id_priv, rover);
/*
* Remember previously used port number in order to avoid
* re-using same port immediately after it is closed.
*/
if (!ret)
last_used_port = rover;
if (ret != -EADDRNOTAVAIL)
return ret;
}
if (port == high)
next_port = low;
else
next_port = port + 1;
bind_list->ps = ps;
bind_list->port = (unsigned short) port;
cma_bind_port(bind_list, id_priv);
return 0;
err2:
idr_remove(ps, port);
err1:
kfree(bind_list);
return ret;
if (--remaining) {
rover++;
if ((rover < low) || (rover > high))
rover = low;
goto retry;
}
return -EADDRNOTAVAIL;
}
static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
......@@ -2995,12 +2980,7 @@ static void cma_remove_one(struct ib_device *device)
static int __init cma_init(void)
{
int ret, low, high, remaining;
get_random_bytes(&next_port, sizeof next_port);
inet_get_local_port_range(&low, &high);
remaining = (high - low) + 1;
next_port = ((unsigned int) next_port % remaining) + low;
int ret;
cma_wq = create_singlethread_workqueue("rdma_cm");
if (!cma_wq)
......
......@@ -291,13 +291,11 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
}
if (mad_reg_req) {
reg_req = kmalloc(sizeof *reg_req, GFP_KERNEL);
reg_req = kmemdup(mad_reg_req, sizeof *reg_req, GFP_KERNEL);
if (!reg_req) {
ret = ERR_PTR(-ENOMEM);
goto error3;
}
/* Make a copy of the MAD registration request */
memcpy(reg_req, mad_reg_req, sizeof *reg_req);
}
/* Now, fill in the various structures */
......
......@@ -1181,7 +1181,7 @@ static int ib_ucm_open(struct inode *inode, struct file *filp)
file->filp = filp;
file->device = container_of(inode->i_cdev, struct ib_ucm_device, cdev);
return 0;
return nonseekable_open(inode, filp);
}
static int ib_ucm_close(struct inode *inode, struct file *filp)
......@@ -1229,6 +1229,7 @@ static const struct file_operations ucm_fops = {
.release = ib_ucm_close,
.write = ib_ucm_write,
.poll = ib_ucm_poll,
.llseek = no_llseek,
};
static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
......
......@@ -1220,7 +1220,8 @@ static int ucma_open(struct inode *inode, struct file *filp)
filp->private_data = file;
file->filp = filp;
return 0;
return nonseekable_open(inode, filp);
}
static int ucma_close(struct inode *inode, struct file *filp)
......@@ -1250,6 +1251,7 @@ static const struct file_operations ucma_fops = {
.release = ucma_close,
.write = ucma_write,
.poll = ucma_poll,
.llseek = no_llseek,
};
static struct miscdevice ucma_misc = {
......
......@@ -781,7 +781,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
{
struct ib_umad_port *port;
struct ib_umad_file *file;
int ret = 0;
int ret;
port = container_of(inode->i_cdev, struct ib_umad_port, cdev);
if (port)
......@@ -814,6 +814,8 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
list_add_tail(&file->port_list, &port->file_list);
ret = nonseekable_open(inode, filp);
out:
mutex_unlock(&port->file_mutex);
return ret;
......@@ -866,7 +868,8 @@ static const struct file_operations umad_fops = {
.compat_ioctl = ib_umad_compat_ioctl,
#endif
.open = ib_umad_open,
.release = ib_umad_close
.release = ib_umad_close,
.llseek = no_llseek,
};
static int ib_umad_sm_open(struct inode *inode, struct file *filp)
......@@ -903,7 +906,7 @@ static int ib_umad_sm_open(struct inode *inode, struct file *filp)
filp->private_data = port;
return 0;
return nonseekable_open(inode, filp);
fail:
kref_put(&port->umad_dev->ref, ib_umad_release_dev);
......@@ -933,7 +936,8 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp)
static const struct file_operations umad_sm_fops = {
.owner = THIS_MODULE,
.open = ib_umad_sm_open,
.release = ib_umad_sm_close
.release = ib_umad_sm_close,
.llseek = no_llseek,
};
static struct ib_client umad_client = {
......
......@@ -369,7 +369,8 @@ static const struct file_operations uverbs_event_fops = {
.read = ib_uverbs_event_read,
.poll = ib_uverbs_event_poll,
.release = ib_uverbs_event_close,
.fasync = ib_uverbs_event_fasync
.fasync = ib_uverbs_event_fasync,
.llseek = no_llseek,
};
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
......@@ -623,7 +624,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
filp->private_data = file;
return 0;
return nonseekable_open(inode, filp);
err_module:
module_put(dev->ib_dev->owner);
......@@ -651,7 +652,8 @@ static const struct file_operations uverbs_fops = {
.owner = THIS_MODULE,
.write = ib_uverbs_write,
.open = ib_uverbs_open,
.release = ib_uverbs_close
.release = ib_uverbs_close,
.llseek = no_llseek,
};
static const struct file_operations uverbs_mmap_fops = {
......@@ -659,7 +661,8 @@ static const struct file_operations uverbs_mmap_fops = {
.write = ib_uverbs_write,
.mmap = ib_uverbs_mmap,
.open = ib_uverbs_open,
.release = ib_uverbs_close
.release = ib_uverbs_close,
.llseek = no_llseek,
};
static struct ib_client uverbs_client = {
......
......@@ -174,7 +174,7 @@ int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq, int kernel)
kfree(cq->sw_queue);
return -ENOMEM;
}
pci_unmap_addr_set(cq, mapping, cq->dma_addr);
dma_unmap_addr_set(cq, mapping, cq->dma_addr);
memset(cq->queue, 0, size);
setup.id = cq->cqid;
setup.base_addr = (u64) (cq->dma_addr);
......@@ -297,7 +297,7 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,
goto err4;
memset(wq->queue, 0, depth * sizeof(union t3_wr));
pci_unmap_addr_set(wq, mapping, wq->dma_addr);
dma_unmap_addr_set(wq, mapping, wq->dma_addr);
wq->doorbell = (void __iomem *)rdev_p->rnic_info.kdb_addr;
if (!kernel_domain)
wq->udb = (u64)rdev_p->rnic_info.udbell_physbase +
......@@ -325,7 +325,7 @@ int cxio_destroy_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),
(1UL << (cq->size_log2))
* sizeof(struct t3_cqe), cq->queue,
pci_unmap_addr(cq, mapping));
dma_unmap_addr(cq, mapping));
cxio_hal_put_cqid(rdev_p->rscp, cq->cqid);
return err;
}
......@@ -336,7 +336,7 @@ int cxio_destroy_qp(struct cxio_rdev *rdev_p, struct t3_wq *wq,
dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),
(1UL << (wq->size_log2))
* sizeof(union t3_wr), wq->queue,
pci_unmap_addr(wq, mapping));
dma_unmap_addr(wq, mapping));
kfree(wq->sq);
cxio_hal_rqtpool_free(rdev_p, wq->rq_addr, (1UL << wq->rq_size_log2));
kfree(wq->rq);
......@@ -537,7 +537,7 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
err = -ENOMEM;
goto err;
}
pci_unmap_addr_set(&rdev_p->ctrl_qp, mapping,
dma_unmap_addr_set(&rdev_p->ctrl_qp, mapping,
rdev_p->ctrl_qp.dma_addr);
rdev_p->ctrl_qp.doorbell = (void __iomem *)rdev_p->rnic_info.kdb_addr;
memset(rdev_p->ctrl_qp.workq, 0,
......@@ -583,7 +583,7 @@ static int cxio_hal_destroy_ctrl_qp(struct cxio_rdev *rdev_p)
dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),
(1UL << T3_CTRL_QP_SIZE_LOG2)
* sizeof(union t3_wr), rdev_p->ctrl_qp.workq,
pci_unmap_addr(&rdev_p->ctrl_qp, mapping));
dma_unmap_addr(&rdev_p->ctrl_qp, mapping));
return cxio_hal_clear_qp_ctx(rdev_p, T3_CTRL_QP_ID);
}
......
......@@ -71,7 +71,7 @@ struct cxio_hal_ctrl_qp {
wait_queue_head_t waitq;/* wait for RspQ/CQE msg */
union t3_wr *workq; /* the work request queue */
dma_addr_t dma_addr; /* pci bus address of the workq */
DECLARE_PCI_UNMAP_ADDR(mapping)
DEFINE_DMA_UNMAP_ADDR(mapping);
void __iomem *doorbell;
};
......
......@@ -691,7 +691,7 @@ struct t3_swrq {
struct t3_wq {
union t3_wr *queue; /* DMA accessable memory */
dma_addr_t dma_addr; /* DMA address for HW */
DECLARE_PCI_UNMAP_ADDR(mapping) /* unmap kruft */
DEFINE_DMA_UNMAP_ADDR(mapping); /* unmap kruft */
u32 error; /* 1 once we go to ERROR */
u32 qpid;
u32 wptr; /* idx to next available WR slot */
......@@ -718,7 +718,7 @@ struct t3_cq {
u32 wptr;
u32 size_log2;
dma_addr_t dma_addr;
DECLARE_PCI_UNMAP_ADDR(mapping)
DEFINE_DMA_UNMAP_ADDR(mapping);
struct t3_cqe *queue;
struct t3_cqe *sw_queue;
u32 sw_rptr;
......
......@@ -47,8 +47,6 @@ MODULE_DESCRIPTION("Chelsio T3 RDMA Driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRV_VERSION);
cxgb3_cpl_handler_func t3c_handlers[NUM_CPL_CMDS];
static void open_rnic_dev(struct t3cdev *);
static void close_rnic_dev(struct t3cdev *);
static void iwch_event_handler(struct t3cdev *, u32, u32);
......
......@@ -102,12 +102,9 @@ static unsigned int cong_flavor = 1;
module_param(cong_flavor, uint, 0644);
MODULE_PARM_DESC(cong_flavor, "TCP Congestion control flavor (default=1)");
static void process_work(struct work_struct *work);
static struct workqueue_struct *workq;
static DECLARE_WORK(skb_work, process_work);
static struct sk_buff_head rxq;
static cxgb3_cpl_handler_func work_handlers[NUM_CPL_CMDS];
static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp);
static void ep_timeout(unsigned long arg);
......@@ -151,7 +148,7 @@ int iwch_l2t_send(struct t3cdev *tdev, struct sk_buff *skb, struct l2t_entry *l2
return -EIO;
}
error = l2t_send(tdev, skb, l2e);
if (error)
if (error < 0)
kfree_skb(skb);
return error;
}
......@@ -167,7 +164,7 @@ int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb)
return -EIO;
}
error = cxgb3_ofld_send(tdev, skb);
if (error)
if (error < 0)
kfree_skb(skb);
return error;
}
......@@ -302,27 +299,6 @@ static void release_ep_resources(struct iwch_ep *ep)
put_ep(&ep->com);
}
static void process_work(struct work_struct *work)
{
struct sk_buff *skb = NULL;
void *ep;
struct t3cdev *tdev;
int ret;
while ((skb = skb_dequeue(&rxq))) {
ep = *((void **) (skb->cb));
tdev = *((struct t3cdev **) (skb->cb + sizeof(void *)));
ret = work_handlers[G_OPCODE(ntohl((__force __be32)skb->csum))](tdev, skb, ep);
if (ret & CPL_RET_BUF_DONE)
kfree_skb(skb);
/*
* ep was referenced in sched(), and is freed here.
*/
put_ep((struct iwch_ep_common *)ep);
}
}
static int status2errno(int status)
{
switch (status) {
......@@ -2157,7 +2133,49 @@ int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
/*
* All the CM events are handled on a work queue to have a safe context.
* These are the real handlers that are called from the work queue.
*/
static const cxgb3_cpl_handler_func work_handlers[NUM_CPL_CMDS] = {
[CPL_ACT_ESTABLISH] = act_establish,
[CPL_ACT_OPEN_RPL] = act_open_rpl,
[CPL_RX_DATA] = rx_data,
[CPL_TX_DMA_ACK] = tx_ack,
[CPL_ABORT_RPL_RSS] = abort_rpl,
[CPL_ABORT_RPL] = abort_rpl,
[CPL_PASS_OPEN_RPL] = pass_open_rpl,
[CPL_CLOSE_LISTSRV_RPL] = close_listsrv_rpl,
[CPL_PASS_ACCEPT_REQ] = pass_accept_req,
[CPL_PASS_ESTABLISH] = pass_establish,
[CPL_PEER_CLOSE] = peer_close,
[CPL_ABORT_REQ_RSS] = peer_abort,
[CPL_CLOSE_CON_RPL] = close_con_rpl,
[CPL_RDMA_TERMINATE] = terminate,
[CPL_RDMA_EC_STATUS] = ec_status,
};
static void process_work(struct work_struct *work)
{
struct sk_buff *skb = NULL;
void *ep;
struct t3cdev *tdev;
int ret;
while ((skb = skb_dequeue(&rxq))) {
ep = *((void **) (skb->cb));
tdev = *((struct t3cdev **) (skb->cb + sizeof(void *)));
ret = work_handlers[G_OPCODE(ntohl((__force __be32)skb->csum))](tdev, skb, ep);
if (ret & CPL_RET_BUF_DONE)
kfree_skb(skb);
/*
* ep was referenced in sched(), and is freed here.
*/
put_ep((struct iwch_ep_common *)ep);
}
}
static DECLARE_WORK(skb_work, process_work);
static int sched(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
{
struct iwch_ep_common *epc = ctx;
......@@ -2189,6 +2207,29 @@ static int set_tcb_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
return CPL_RET_BUF_DONE;
}
/*
* All upcalls from the T3 Core go to sched() to schedule the
* processing on a work queue.
*/
cxgb3_cpl_handler_func t3c_handlers[NUM_CPL_CMDS] = {
[CPL_ACT_ESTABLISH] = sched,
[CPL_ACT_OPEN_RPL] = sched,
[CPL_RX_DATA] = sched,
[CPL_TX_DMA_ACK] = sched,
[CPL_ABORT_RPL_RSS] = sched,
[CPL_ABORT_RPL] = sched,
[CPL_PASS_OPEN_RPL] = sched,
[CPL_CLOSE_LISTSRV_RPL] = sched,
[CPL_PASS_ACCEPT_REQ] = sched,
[CPL_PASS_ESTABLISH] = sched,
[CPL_PEER_CLOSE] = sched,
[CPL_CLOSE_CON_RPL] = sched,
[CPL_ABORT_REQ_RSS] = sched,
[CPL_RDMA_TERMINATE] = sched,
[CPL_RDMA_EC_STATUS] = sched,
[CPL_SET_TCB_RPL] = set_tcb_rpl,
};
int __init iwch_cm_init(void)
{
skb_queue_head_init(&rxq);
......@@ -2197,46 +2238,6 @@ int __init iwch_cm_init(void)
if (!workq)
return -ENOMEM;
/*
* All upcalls from the T3 Core go to sched() to
* schedule the processing on a work queue.
*/
t3c_handlers[CPL_ACT_ESTABLISH] = sched;
t3c_handlers[CPL_ACT_OPEN_RPL] = sched;
t3c_handlers[CPL_RX_DATA] = sched;
t3c_handlers[CPL_TX_DMA_ACK] = sched;
t3c_handlers[CPL_ABORT_RPL_RSS] = sched;
t3c_handlers[CPL_ABORT_RPL] = sched;
t3c_handlers[CPL_PASS_OPEN_RPL] = sched;
t3c_handlers[CPL_CLOSE_LISTSRV_RPL] = sched;
t3c_handlers[CPL_PASS_ACCEPT_REQ] = sched;
t3c_handlers[CPL_PASS_ESTABLISH] = sched;
t3c_handlers[CPL_PEER_CLOSE] = sched;
t3c_handlers[CPL_CLOSE_CON_RPL] = sched;
t3c_handlers[CPL_ABORT_REQ_RSS] = sched;
t3c_handlers[CPL_RDMA_TERMINATE] = sched;
t3c_handlers[CPL_RDMA_EC_STATUS] = sched;
t3c_handlers[CPL_SET_TCB_RPL] = set_tcb_rpl;
/*
* These are the real handlers that are called from a
* work queue.
*/
work_handlers[CPL_ACT_ESTABLISH] = act_establish;
work_handlers[CPL_ACT_OPEN_RPL] = act_open_rpl;
work_handlers[CPL_RX_DATA] = rx_data;
work_handlers[CPL_TX_DMA_ACK] = tx_ack;
work_handlers[CPL_ABORT_RPL_RSS] = abort_rpl;
work_handlers[CPL_ABORT_RPL] = abort_rpl;
work_handlers[CPL_PASS_OPEN_RPL] = pass_open_rpl;
work_handlers[CPL_CLOSE_LISTSRV_RPL] = close_listsrv_rpl;
work_handlers[CPL_PASS_ACCEPT_REQ] = pass_accept_req;
work_handlers[CPL_PASS_ESTABLISH] = pass_establish;
work_handlers[CPL_PEER_CLOSE] = peer_close;
work_handlers[CPL_ABORT_REQ_RSS] = peer_abort;
work_handlers[CPL_CLOSE_CON_RPL] = close_con_rpl;
work_handlers[CPL_RDMA_TERMINATE] = terminate;
work_handlers[CPL_RDMA_EC_STATUS] = ec_status;
return 0;
}
......
config INFINIBAND_CXGB4
tristate "Chelsio T4 RDMA Driver"
depends on CHELSIO_T4 && INET
select GENERIC_ALLOCATOR
---help---
This is an iWARP/RDMA driver for the Chelsio T4 1GbE and
10GbE adapters.
For general information about Chelsio and our products, visit
our website at <http://www.chelsio.com>.
For customer support, please visit our customer support page at
<http://www.chelsio.com/support.htm>.
Please send feedback to <linux-bugs@chelsio.com>.
To compile this driver as a module, choose M here: the module
will be called iw_cxgb4.
EXTRA_CFLAGS += -Idrivers/net/cxgb4
obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
iw_cxgb4-y := device.o cm.o provider.o mem.o cq.o qp.o resource.o ev.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2009-2010 Chelsio, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/slab.h>
#include <linux/mman.h>
#include <net/sock.h>
#include "iw_cxgb4.h"
static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
struct c4iw_qp *qhp,
struct t4_cqe *err_cqe,
enum ib_event_type ib_event)
{
struct ib_event event;
struct c4iw_qp_attributes attrs;
if ((qhp->attr.state == C4IW_QP_STATE_ERROR) ||
(qhp->attr.state == C4IW_QP_STATE_TERMINATE)) {
PDBG("%s AE received after RTS - "
"qp state %d qpid 0x%x status 0x%x\n", __func__,
qhp->attr.state, qhp->wq.sq.qid, CQE_STATUS(err_cqe));
return;
}
printk(KERN_ERR MOD "AE qpid 0x%x opcode %d status 0x%x "
"type %d wrid.hi 0x%x wrid.lo 0x%x\n",
CQE_QPID(err_cqe), CQE_OPCODE(err_cqe),
CQE_STATUS(err_cqe), CQE_TYPE(err_cqe),
CQE_WRID_HI(err_cqe), CQE_WRID_LOW(err_cqe));
if (qhp->attr.state == C4IW_QP_STATE_RTS) {
attrs.next_state = C4IW_QP_STATE_TERMINATE;
c4iw_modify_qp(qhp->rhp, qhp, C4IW_QP_ATTR_NEXT_STATE,
&attrs, 1);
}
event.event = ib_event;
event.device = chp->ibcq.device;
if (ib_event == IB_EVENT_CQ_ERR)
event.element.cq = &chp->ibcq;
else
event.element.qp = &qhp->ibqp;
if (qhp->ibqp.event_handler)
(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
}
void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
{
struct c4iw_cq *chp;
struct c4iw_qp *qhp;
u32 cqid;
spin_lock(&dev->lock);
qhp = get_qhp(dev, CQE_QPID(err_cqe));
if (!qhp) {
printk(KERN_ERR MOD "BAD AE qpid 0x%x opcode %d "
"status 0x%x type %d wrid.hi 0x%x wrid.lo 0x%x\n",
CQE_QPID(err_cqe),
CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe),
CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe),
CQE_WRID_LOW(err_cqe));
spin_unlock(&dev->lock);
goto out;
}
if (SQ_TYPE(err_cqe))
cqid = qhp->attr.scq;
else
cqid = qhp->attr.rcq;
chp = get_chp(dev, cqid);
if (!chp) {
printk(KERN_ERR MOD "BAD AE cqid 0x%x qpid 0x%x opcode %d "
"status 0x%x type %d wrid.hi 0x%x wrid.lo 0x%x\n",
cqid, CQE_QPID(err_cqe),
CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe),
CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe),
CQE_WRID_LOW(err_cqe));
spin_unlock(&dev->lock);
goto out;
}
c4iw_qp_add_ref(&qhp->ibqp);
atomic_inc(&chp->refcnt);
spin_unlock(&dev->lock);
/* Bad incoming write */
if (RQ_TYPE(err_cqe) &&
(CQE_OPCODE(err_cqe) == FW_RI_RDMA_WRITE)) {
post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_REQ_ERR);
goto done;
}
switch (CQE_STATUS(err_cqe)) {
/* Completion Events */
case T4_ERR_SUCCESS:
printk(KERN_ERR MOD "AE with status 0!\n");
break;
case T4_ERR_STAG:
case T4_ERR_PDID:
case T4_ERR_QPID:
case T4_ERR_ACCESS:
case T4_ERR_WRAP:
case T4_ERR_BOUND:
case T4_ERR_INVALIDATE_SHARED_MR:
case T4_ERR_INVALIDATE_MR_WITH_MW_BOUND:
post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_ACCESS_ERR);
break;
/* Device Fatal Errors */
case T4_ERR_ECC:
case T4_ERR_ECC_PSTAG:
case T4_ERR_INTERNAL_ERR:
post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_DEVICE_FATAL);
break;
/* QP Fatal Errors */
case T4_ERR_OUT_OF_RQE:
case T4_ERR_PBL_ADDR_BOUND:
case T4_ERR_CRC:
case T4_ERR_MARKER:
case T4_ERR_PDU_LEN_ERR:
case T4_ERR_DDP_VERSION:
case T4_ERR_RDMA_VERSION:
case T4_ERR_OPCODE:
case T4_ERR_DDP_QUEUE_NUM:
case T4_ERR_MSN:
case T4_ERR_TBIT:
case T4_ERR_MO:
case T4_ERR_MSN_GAP:
case T4_ERR_MSN_RANGE:
case T4_ERR_RQE_ADDR_BOUND:
case T4_ERR_IRD_OVERFLOW:
post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_FATAL);
break;
default:
printk(KERN_ERR MOD "Unknown T4 status 0x%x QPID 0x%x\n",
CQE_STATUS(err_cqe), qhp->wq.sq.qid);
post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_FATAL);
break;
}
done:
if (atomic_dec_and_test(&chp->refcnt))
wake_up(&chp->wait);
c4iw_qp_rem_ref(&qhp->ibqp);
out:
return;
}
int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
{
struct c4iw_cq *chp;
chp = get_chp(dev, qid);
if (chp)
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
else
PDBG("%s unknown cqid 0x%x\n", __func__, qid);
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2009-2010 Chelsio, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __C4IW_USER_H__
#define __C4IW_USER_H__
#define C4IW_UVERBS_ABI_VERSION 1
/*
* Make sure that all structs defined in this file remain laid out so
* that they pack the same way on 32-bit and 64-bit architectures (to
* avoid incompatibility between 32-bit userspace and 64-bit kernels).
* In particular do not use pointer types -- pass pointers in __u64
* instead.
*/
struct c4iw_create_cq_resp {
__u64 key;
__u64 gts_key;
__u64 memsize;
__u32 cqid;
__u32 size;
__u32 qid_mask;
};
struct c4iw_create_qp_resp {
__u64 sq_key;
__u64 rq_key;
__u64 sq_db_gts_key;
__u64 rq_db_gts_key;
__u64 sq_memsize;
__u64 rq_memsize;
__u32 sqid;
__u32 rqid;
__u32 sq_size;
__u32 rq_size;
__u32 qid_mask;
};
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment