Commit 793dad94 authored by Vipul Pandya's avatar Vipul Pandya Committed by Roland Dreier

RDMA/cxgb4: Fix bug for active and passive LE hash collision path

Retries active opens for INUSE errors.

Logs any active ofld_connect_wr error replies.

Sends ofld_connect_wr on same ctrlq. It needs to go  on the same control txq as
regular CPL active/passive messages.

Retries on active open replies with EADDRINUSE.

Uses active open fw wr only if active filter region is set.

Adds stat for ofld_connect_wr failures.

This patch also adds debugfs file to show endpoints.
Signed-off-by: default avatarVipul Pandya <vipul@chelsio.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 1cab775c
This diff is collapsed.
...@@ -280,6 +280,10 @@ static int stats_show(struct seq_file *seq, void *v) ...@@ -280,6 +280,10 @@ static int stats_show(struct seq_file *seq, void *v)
db_state_str[dev->db_state], db_state_str[dev->db_state],
dev->rdev.stats.db_state_transitions); dev->rdev.stats.db_state_transitions);
seq_printf(seq, "TCAM_FULL: %10llu\n", dev->rdev.stats.tcam_full); seq_printf(seq, "TCAM_FULL: %10llu\n", dev->rdev.stats.tcam_full);
seq_printf(seq, "ACT_OFLD_CONN_FAILS: %10llu\n",
dev->rdev.stats.act_ofld_conn_fails);
seq_printf(seq, "PAS_OFLD_CONN_FAILS: %10llu\n",
dev->rdev.stats.pas_ofld_conn_fails);
return 0; return 0;
} }
...@@ -310,6 +314,9 @@ static ssize_t stats_clear(struct file *file, const char __user *buf, ...@@ -310,6 +314,9 @@ static ssize_t stats_clear(struct file *file, const char __user *buf,
dev->rdev.stats.db_empty = 0; dev->rdev.stats.db_empty = 0;
dev->rdev.stats.db_drop = 0; dev->rdev.stats.db_drop = 0;
dev->rdev.stats.db_state_transitions = 0; dev->rdev.stats.db_state_transitions = 0;
dev->rdev.stats.tcam_full = 0;
dev->rdev.stats.act_ofld_conn_fails = 0;
dev->rdev.stats.pas_ofld_conn_fails = 0;
mutex_unlock(&dev->rdev.stats.lock); mutex_unlock(&dev->rdev.stats.lock);
return count; return count;
} }
...@@ -323,6 +330,113 @@ static const struct file_operations stats_debugfs_fops = { ...@@ -323,6 +330,113 @@ static const struct file_operations stats_debugfs_fops = {
.write = stats_clear, .write = stats_clear,
}; };
static int dump_ep(int id, void *p, void *data)
{
struct c4iw_ep *ep = p;
struct c4iw_debugfs_data *epd = data;
int space;
int cc;
space = epd->bufsize - epd->pos - 1;
if (space == 0)
return 1;
cc = snprintf(epd->buf + epd->pos, space,
"ep %p cm_id %p qp %p state %d flags 0x%lx history 0x%lx "
"hwtid %d atid %d %pI4:%d <-> %pI4:%d\n",
ep, ep->com.cm_id, ep->com.qp, (int)ep->com.state,
ep->com.flags, ep->com.history, ep->hwtid, ep->atid,
&ep->com.local_addr.sin_addr.s_addr,
ntohs(ep->com.local_addr.sin_port),
&ep->com.remote_addr.sin_addr.s_addr,
ntohs(ep->com.remote_addr.sin_port));
if (cc < space)
epd->pos += cc;
return 0;
}
static int dump_listen_ep(int id, void *p, void *data)
{
struct c4iw_listen_ep *ep = p;
struct c4iw_debugfs_data *epd = data;
int space;
int cc;
space = epd->bufsize - epd->pos - 1;
if (space == 0)
return 1;
cc = snprintf(epd->buf + epd->pos, space,
"ep %p cm_id %p state %d flags 0x%lx stid %d backlog %d "
"%pI4:%d\n", ep, ep->com.cm_id, (int)ep->com.state,
ep->com.flags, ep->stid, ep->backlog,
&ep->com.local_addr.sin_addr.s_addr,
ntohs(ep->com.local_addr.sin_port));
if (cc < space)
epd->pos += cc;
return 0;
}
static int ep_release(struct inode *inode, struct file *file)
{
struct c4iw_debugfs_data *epd = file->private_data;
if (!epd) {
pr_info("%s null qpd?\n", __func__);
return 0;
}
vfree(epd->buf);
kfree(epd);
return 0;
}
static int ep_open(struct inode *inode, struct file *file)
{
struct c4iw_debugfs_data *epd;
int ret = 0;
int count = 1;
epd = kmalloc(sizeof(*epd), GFP_KERNEL);
if (!epd) {
ret = -ENOMEM;
goto out;
}
epd->devp = inode->i_private;
epd->pos = 0;
spin_lock_irq(&epd->devp->lock);
idr_for_each(&epd->devp->hwtid_idr, count_idrs, &count);
idr_for_each(&epd->devp->atid_idr, count_idrs, &count);
idr_for_each(&epd->devp->stid_idr, count_idrs, &count);
spin_unlock_irq(&epd->devp->lock);
epd->bufsize = count * 160;
epd->buf = vmalloc(epd->bufsize);
if (!epd->buf) {
ret = -ENOMEM;
goto err1;
}
spin_lock_irq(&epd->devp->lock);
idr_for_each(&epd->devp->hwtid_idr, dump_ep, epd);
idr_for_each(&epd->devp->atid_idr, dump_ep, epd);
idr_for_each(&epd->devp->stid_idr, dump_listen_ep, epd);
spin_unlock_irq(&epd->devp->lock);
file->private_data = epd;
goto out;
err1:
kfree(epd);
out:
return ret;
}
static const struct file_operations ep_debugfs_fops = {
.owner = THIS_MODULE,
.open = ep_open,
.release = ep_release,
.read = debugfs_read,
};
static int setup_debugfs(struct c4iw_dev *devp) static int setup_debugfs(struct c4iw_dev *devp)
{ {
struct dentry *de; struct dentry *de;
...@@ -345,6 +459,11 @@ static int setup_debugfs(struct c4iw_dev *devp) ...@@ -345,6 +459,11 @@ static int setup_debugfs(struct c4iw_dev *devp)
if (de && de->d_inode) if (de && de->d_inode)
de->d_inode->i_size = 4096; de->d_inode->i_size = 4096;
de = debugfs_create_file("eps", S_IWUSR, devp->debugfs_root,
(void *)devp, &ep_debugfs_fops);
if (de && de->d_inode)
de->d_inode->i_size = 4096;
return 0; return 0;
} }
...@@ -476,6 +595,9 @@ static void c4iw_dealloc(struct uld_ctx *ctx) ...@@ -476,6 +595,9 @@ static void c4iw_dealloc(struct uld_ctx *ctx)
idr_destroy(&ctx->dev->cqidr); idr_destroy(&ctx->dev->cqidr);
idr_destroy(&ctx->dev->qpidr); idr_destroy(&ctx->dev->qpidr);
idr_destroy(&ctx->dev->mmidr); idr_destroy(&ctx->dev->mmidr);
idr_destroy(&ctx->dev->hwtid_idr);
idr_destroy(&ctx->dev->stid_idr);
idr_destroy(&ctx->dev->atid_idr);
iounmap(ctx->dev->rdev.oc_mw_kva); iounmap(ctx->dev->rdev.oc_mw_kva);
ib_dealloc_device(&ctx->dev->ibdev); ib_dealloc_device(&ctx->dev->ibdev);
ctx->dev = NULL; ctx->dev = NULL;
...@@ -533,6 +655,9 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) ...@@ -533,6 +655,9 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
idr_init(&devp->cqidr); idr_init(&devp->cqidr);
idr_init(&devp->qpidr); idr_init(&devp->qpidr);
idr_init(&devp->mmidr); idr_init(&devp->mmidr);
idr_init(&devp->hwtid_idr);
idr_init(&devp->stid_idr);
idr_init(&devp->atid_idr);
spin_lock_init(&devp->lock); spin_lock_init(&devp->lock);
mutex_init(&devp->rdev.stats.lock); mutex_init(&devp->rdev.stats.lock);
mutex_init(&devp->db_mutex); mutex_init(&devp->db_mutex);
......
...@@ -131,6 +131,8 @@ struct c4iw_stats { ...@@ -131,6 +131,8 @@ struct c4iw_stats {
u64 db_drop; u64 db_drop;
u64 db_state_transitions; u64 db_state_transitions;
u64 tcam_full; u64 tcam_full;
u64 act_ofld_conn_fails;
u64 pas_ofld_conn_fails;
}; };
struct c4iw_rdev { struct c4iw_rdev {
...@@ -224,6 +226,9 @@ struct c4iw_dev { ...@@ -224,6 +226,9 @@ struct c4iw_dev {
struct dentry *debugfs_root; struct dentry *debugfs_root;
enum db_state db_state; enum db_state db_state;
int qpcnt; int qpcnt;
struct idr hwtid_idr;
struct idr atid_idr;
struct idr stid_idr;
}; };
static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev) static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
...@@ -713,6 +718,31 @@ enum c4iw_ep_flags { ...@@ -713,6 +718,31 @@ enum c4iw_ep_flags {
CLOSE_SENT = 3, CLOSE_SENT = 3,
}; };
enum c4iw_ep_history {
ACT_OPEN_REQ = 0,
ACT_OFLD_CONN = 1,
ACT_OPEN_RPL = 2,
ACT_ESTAB = 3,
PASS_ACCEPT_REQ = 4,
PASS_ESTAB = 5,
ABORT_UPCALL = 6,
ESTAB_UPCALL = 7,
CLOSE_UPCALL = 8,
ULP_ACCEPT = 9,
ULP_REJECT = 10,
TIMEDOUT = 11,
PEER_ABORT = 12,
PEER_CLOSE = 13,
CONNREQ_UPCALL = 14,
ABORT_CONN = 15,
DISCONN_UPCALL = 16,
EP_DISC_CLOSE = 17,
EP_DISC_ABORT = 18,
CONN_RPL_UPCALL = 19,
ACT_RETRY_NOMEM = 20,
ACT_RETRY_INUSE = 21
};
struct c4iw_ep_common { struct c4iw_ep_common {
struct iw_cm_id *cm_id; struct iw_cm_id *cm_id;
struct c4iw_qp *qp; struct c4iw_qp *qp;
...@@ -724,6 +754,7 @@ struct c4iw_ep_common { ...@@ -724,6 +754,7 @@ struct c4iw_ep_common {
struct sockaddr_in remote_addr; struct sockaddr_in remote_addr;
struct c4iw_wr_wait wr_wait; struct c4iw_wr_wait wr_wait;
unsigned long flags; unsigned long flags;
unsigned long history;
}; };
struct c4iw_listen_ep { struct c4iw_listen_ep {
...@@ -761,6 +792,7 @@ struct c4iw_ep { ...@@ -761,6 +792,7 @@ struct c4iw_ep {
u8 tos; u8 tos;
u8 retry_with_mpa_v1; u8 retry_with_mpa_v1;
u8 tried_with_mpa_v1; u8 tried_with_mpa_v1;
unsigned int retry_count;
}; };
static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id) static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id)
......
...@@ -530,6 +530,7 @@ struct adapter { ...@@ -530,6 +530,7 @@ struct adapter {
struct net_device *port[MAX_NPORTS]; struct net_device *port[MAX_NPORTS];
u8 chan_map[NCHAN]; /* channel -> port map */ u8 chan_map[NCHAN]; /* channel -> port map */
u32 filter_mode;
unsigned int l2t_start; unsigned int l2t_start;
unsigned int l2t_end; unsigned int l2t_end;
struct l2t_data *l2t; struct l2t_data *l2t;
......
...@@ -2670,7 +2670,8 @@ static int tid_init(struct tid_info *t) ...@@ -2670,7 +2670,8 @@ static int tid_init(struct tid_info *t)
* Returns <0 on error and one of the %NET_XMIT_* values on success. * Returns <0 on error and one of the %NET_XMIT_* values on success.
*/ */
int cxgb4_create_server(const struct net_device *dev, unsigned int stid, int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
__be32 sip, __be16 sport, unsigned int queue) __be32 sip, __be16 sport, __be16 vlan,
unsigned int queue)
{ {
unsigned int chan; unsigned int chan;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -3043,7 +3044,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld) ...@@ -3043,7 +3044,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET( lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >> t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
(adap->fn * 4)); (adap->fn * 4));
lli.filt_mode = tp_vlan_pri_map; lli.filt_mode = adap->filter_mode;
/* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */ /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
for (i = 0; i < NCHAN; i++) for (i = 0; i < NCHAN; i++)
lli.tx_modq[i] = i; lli.tx_modq[i] = i;
...@@ -3307,7 +3308,8 @@ static int delete_filter(struct adapter *adapter, unsigned int fidx) ...@@ -3307,7 +3308,8 @@ static int delete_filter(struct adapter *adapter, unsigned int fidx)
} }
int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
__be32 sip, __be16 sport, unsigned int queue) __be32 sip, __be16 sport, __be16 vlan,
unsigned int queue, unsigned char port, unsigned char mask)
{ {
int ret; int ret;
struct filter_entry *f; struct filter_entry *f;
...@@ -3339,11 +3341,16 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, ...@@ -3339,11 +3341,16 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
f->fs.val.lport = cpu_to_be16(sport); f->fs.val.lport = cpu_to_be16(sport);
f->fs.mask.lport = ~0; f->fs.mask.lport = ~0;
val = (u8 *)&sip; val = (u8 *)&sip;
if ((val[0] | val[1] | val[2] | val[3]) != 0) if ((val[0] | val[1] | val[2] | val[3]) != 0) {
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
f->fs.val.lip[i] = val[i]; f->fs.val.lip[i] = val[i];
f->fs.mask.lip[i] = ~0; f->fs.mask.lip[i] = ~0;
} }
if (adap->filter_mode & F_PORT) {
f->fs.val.iport = port;
f->fs.mask.iport = mask;
}
}
f->fs.dirsteer = 1; f->fs.dirsteer = 1;
f->fs.iq = queue; f->fs.iq = queue;
...@@ -4450,6 +4457,10 @@ static int adap_init0(struct adapter *adap) ...@@ -4450,6 +4457,10 @@ static int adap_init0(struct adapter *adap)
for (j = 0; j < NCHAN; j++) for (j = 0; j < NCHAN; j++)
adap->params.tp.tx_modq[j] = j; adap->params.tp.tx_modq[j] = j;
t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
&adap->filter_mode, 1,
TP_VLAN_PRI_MAP);
adap->flags |= FW_OK; adap->flags |= FW_OK;
return 0; return 0;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/inetdevice.h>
#include <linux/atomic.h> #include <linux/atomic.h>
/* CPL message priority levels */ /* CPL message priority levels */
...@@ -151,9 +152,12 @@ void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); ...@@ -151,9 +152,12 @@ void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid);
struct in6_addr; struct in6_addr;
int cxgb4_create_server(const struct net_device *dev, unsigned int stid, int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
__be32 sip, __be16 sport, unsigned int queue); __be32 sip, __be16 sport, __be16 vlan,
unsigned int queue);
int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
__be32 sip, __be16 sport, unsigned int queue); __be32 sip, __be16 sport, __be16 vlan,
unsigned int queue,
unsigned char port, unsigned char mask);
int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid, int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
unsigned int queue, bool ipv6); unsigned int queue, bool ipv6);
static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue) static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
......
...@@ -1098,5 +1098,7 @@ ...@@ -1098,5 +1098,7 @@
#define A_TP_TX_SCHED_PCMD 0x25 #define A_TP_TX_SCHED_PCMD 0x25
#define S_PORT 1 #define S_PORT 1
#define V_PORT(x) ((x) << S_PORT)
#define F_PORT V_PORT(1U)
#endif /* __T4_REGS_H */ #endif /* __T4_REGS_H */
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