diff options
author | David S. Miller <davem@davemloft.net> | 2014-03-14 22:44:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-14 22:44:19 -0400 |
commit | 1c79a5a8f4faec88f9f4632d0ef9b0365bff8e28 (patch) | |
tree | b7552ee535f565d5a83039ed976a442c7f869402 | |
parent | 57a7744e09867ebcfa0ccf1d6d529caa7728d552 (diff) | |
parent | 05eb23893c2cf9502a9cec0c32e7f1d1ed2895c8 (diff) |
Merge branch 'cxgb4-next'
Hariprasad Shenai says:
====================
Doorbell drop Avoidance Bug fix for iw_cxgb4
This patch series provides fixes for Chelsio T4/T5 adapters
related to DB Drop avoidance and other small fix related to keepalive on
iw-cxgb4.
The patches series is created against David Miller's 'net-next' tree.
And includes patches on cxgb4 and iw_cxgb4 driver.
We would like to request this patch series to get merged via David Miller's
'net-next' tree.
We have included all the maintainers of respective drivers. Kindly review the
change and let us know in case of any review comments.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/infiniband/hw/cxgb4/cm.c | 24 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/device.c | 177 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 9 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/provider.c | 43 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/qp.c | 140 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/t4.h | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/user.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 87 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/sge.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | 1 |
11 files changed, 299 insertions, 202 deletions
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index d286bdebe2ab..7e98a58aacfd 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c | |||
@@ -1647,6 +1647,15 @@ static inline int act_open_has_tid(int status) | |||
1647 | status != CPL_ERR_ARP_MISS; | 1647 | status != CPL_ERR_ARP_MISS; |
1648 | } | 1648 | } |
1649 | 1649 | ||
1650 | /* Returns whether a CPL status conveys negative advice. | ||
1651 | */ | ||
1652 | static int is_neg_adv(unsigned int status) | ||
1653 | { | ||
1654 | return status == CPL_ERR_RTX_NEG_ADVICE || | ||
1655 | status == CPL_ERR_PERSIST_NEG_ADVICE || | ||
1656 | status == CPL_ERR_KEEPALV_NEG_ADVICE; | ||
1657 | } | ||
1658 | |||
1650 | #define ACT_OPEN_RETRY_COUNT 2 | 1659 | #define ACT_OPEN_RETRY_COUNT 2 |
1651 | 1660 | ||
1652 | static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, | 1661 | static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, |
@@ -1835,7 +1844,7 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
1835 | PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid, | 1844 | PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid, |
1836 | status, status2errno(status)); | 1845 | status, status2errno(status)); |
1837 | 1846 | ||
1838 | if (status == CPL_ERR_RTX_NEG_ADVICE) { | 1847 | if (is_neg_adv(status)) { |
1839 | printk(KERN_WARNING MOD "Connection problems for atid %u\n", | 1848 | printk(KERN_WARNING MOD "Connection problems for atid %u\n", |
1840 | atid); | 1849 | atid); |
1841 | return 0; | 1850 | return 0; |
@@ -2265,15 +2274,6 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) | |||
2265 | return 0; | 2274 | return 0; |
2266 | } | 2275 | } |
2267 | 2276 | ||
2268 | /* | ||
2269 | * Returns whether an ABORT_REQ_RSS message is a negative advice. | ||
2270 | */ | ||
2271 | static int is_neg_adv_abort(unsigned int status) | ||
2272 | { | ||
2273 | return status == CPL_ERR_RTX_NEG_ADVICE || | ||
2274 | status == CPL_ERR_PERSIST_NEG_ADVICE; | ||
2275 | } | ||
2276 | |||
2277 | static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) | 2277 | static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) |
2278 | { | 2278 | { |
2279 | struct cpl_abort_req_rss *req = cplhdr(skb); | 2279 | struct cpl_abort_req_rss *req = cplhdr(skb); |
@@ -2287,7 +2287,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) | |||
2287 | unsigned int tid = GET_TID(req); | 2287 | unsigned int tid = GET_TID(req); |
2288 | 2288 | ||
2289 | ep = lookup_tid(t, tid); | 2289 | ep = lookup_tid(t, tid); |
2290 | if (is_neg_adv_abort(req->status)) { | 2290 | if (is_neg_adv(req->status)) { |
2291 | PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep, | 2291 | PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep, |
2292 | ep->hwtid); | 2292 | ep->hwtid); |
2293 | return 0; | 2293 | return 0; |
@@ -3570,7 +3570,7 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) | |||
3570 | kfree_skb(skb); | 3570 | kfree_skb(skb); |
3571 | return 0; | 3571 | return 0; |
3572 | } | 3572 | } |
3573 | if (is_neg_adv_abort(req->status)) { | 3573 | if (is_neg_adv(req->status)) { |
3574 | PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep, | 3574 | PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep, |
3575 | ep->hwtid); | 3575 | ep->hwtid); |
3576 | kfree_skb(skb); | 3576 | kfree_skb(skb); |
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index 4a033853312e..ba7335fd4ebf 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c | |||
@@ -64,6 +64,10 @@ struct uld_ctx { | |||
64 | static LIST_HEAD(uld_ctx_list); | 64 | static LIST_HEAD(uld_ctx_list); |
65 | static DEFINE_MUTEX(dev_mutex); | 65 | static DEFINE_MUTEX(dev_mutex); |
66 | 66 | ||
67 | #define DB_FC_RESUME_SIZE 64 | ||
68 | #define DB_FC_RESUME_DELAY 1 | ||
69 | #define DB_FC_DRAIN_THRESH 0 | ||
70 | |||
67 | static struct dentry *c4iw_debugfs_root; | 71 | static struct dentry *c4iw_debugfs_root; |
68 | 72 | ||
69 | struct c4iw_debugfs_data { | 73 | struct c4iw_debugfs_data { |
@@ -282,7 +286,7 @@ static const struct file_operations stag_debugfs_fops = { | |||
282 | .llseek = default_llseek, | 286 | .llseek = default_llseek, |
283 | }; | 287 | }; |
284 | 288 | ||
285 | static char *db_state_str[] = {"NORMAL", "FLOW_CONTROL", "RECOVERY"}; | 289 | static char *db_state_str[] = {"NORMAL", "FLOW_CONTROL", "RECOVERY", "STOPPED"}; |
286 | 290 | ||
287 | static int stats_show(struct seq_file *seq, void *v) | 291 | static int stats_show(struct seq_file *seq, void *v) |
288 | { | 292 | { |
@@ -311,9 +315,10 @@ static int stats_show(struct seq_file *seq, void *v) | |||
311 | seq_printf(seq, " DB FULL: %10llu\n", dev->rdev.stats.db_full); | 315 | seq_printf(seq, " DB FULL: %10llu\n", dev->rdev.stats.db_full); |
312 | seq_printf(seq, " DB EMPTY: %10llu\n", dev->rdev.stats.db_empty); | 316 | seq_printf(seq, " DB EMPTY: %10llu\n", dev->rdev.stats.db_empty); |
313 | seq_printf(seq, " DB DROP: %10llu\n", dev->rdev.stats.db_drop); | 317 | seq_printf(seq, " DB DROP: %10llu\n", dev->rdev.stats.db_drop); |
314 | seq_printf(seq, " DB State: %s Transitions %llu\n", | 318 | seq_printf(seq, " DB State: %s Transitions %llu FC Interruptions %llu\n", |
315 | db_state_str[dev->db_state], | 319 | db_state_str[dev->db_state], |
316 | dev->rdev.stats.db_state_transitions); | 320 | dev->rdev.stats.db_state_transitions, |
321 | dev->rdev.stats.db_fc_interruptions); | ||
317 | seq_printf(seq, "TCAM_FULL: %10llu\n", dev->rdev.stats.tcam_full); | 322 | seq_printf(seq, "TCAM_FULL: %10llu\n", dev->rdev.stats.tcam_full); |
318 | seq_printf(seq, "ACT_OFLD_CONN_FAILS: %10llu\n", | 323 | seq_printf(seq, "ACT_OFLD_CONN_FAILS: %10llu\n", |
319 | dev->rdev.stats.act_ofld_conn_fails); | 324 | dev->rdev.stats.act_ofld_conn_fails); |
@@ -643,6 +648,12 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev) | |||
643 | printk(KERN_ERR MOD "error %d initializing ocqp pool\n", err); | 648 | printk(KERN_ERR MOD "error %d initializing ocqp pool\n", err); |
644 | goto err4; | 649 | goto err4; |
645 | } | 650 | } |
651 | rdev->status_page = (struct t4_dev_status_page *) | ||
652 | __get_free_page(GFP_KERNEL); | ||
653 | if (!rdev->status_page) { | ||
654 | pr_err(MOD "error allocating status page\n"); | ||
655 | goto err4; | ||
656 | } | ||
646 | return 0; | 657 | return 0; |
647 | err4: | 658 | err4: |
648 | c4iw_rqtpool_destroy(rdev); | 659 | c4iw_rqtpool_destroy(rdev); |
@@ -656,6 +667,7 @@ err1: | |||
656 | 667 | ||
657 | static void c4iw_rdev_close(struct c4iw_rdev *rdev) | 668 | static void c4iw_rdev_close(struct c4iw_rdev *rdev) |
658 | { | 669 | { |
670 | free_page((unsigned long)rdev->status_page); | ||
659 | c4iw_pblpool_destroy(rdev); | 671 | c4iw_pblpool_destroy(rdev); |
660 | c4iw_rqtpool_destroy(rdev); | 672 | c4iw_rqtpool_destroy(rdev); |
661 | c4iw_destroy_resource(&rdev->resource); | 673 | c4iw_destroy_resource(&rdev->resource); |
@@ -703,18 +715,6 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) | |||
703 | pr_info("%s: On-Chip Queues not supported on this device.\n", | 715 | pr_info("%s: On-Chip Queues not supported on this device.\n", |
704 | pci_name(infop->pdev)); | 716 | pci_name(infop->pdev)); |
705 | 717 | ||
706 | if (!is_t4(infop->adapter_type)) { | ||
707 | if (!allow_db_fc_on_t5) { | ||
708 | db_fc_threshold = 100000; | ||
709 | pr_info("DB Flow Control Disabled.\n"); | ||
710 | } | ||
711 | |||
712 | if (!allow_db_coalescing_on_t5) { | ||
713 | db_coalescing_threshold = -1; | ||
714 | pr_info("DB Coalescing Disabled.\n"); | ||
715 | } | ||
716 | } | ||
717 | |||
718 | devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp)); | 718 | devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp)); |
719 | if (!devp) { | 719 | if (!devp) { |
720 | printk(KERN_ERR MOD "Cannot allocate ib device\n"); | 720 | printk(KERN_ERR MOD "Cannot allocate ib device\n"); |
@@ -749,6 +749,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) | |||
749 | spin_lock_init(&devp->lock); | 749 | spin_lock_init(&devp->lock); |
750 | mutex_init(&devp->rdev.stats.lock); | 750 | mutex_init(&devp->rdev.stats.lock); |
751 | mutex_init(&devp->db_mutex); | 751 | mutex_init(&devp->db_mutex); |
752 | INIT_LIST_HEAD(&devp->db_fc_list); | ||
752 | 753 | ||
753 | if (c4iw_debugfs_root) { | 754 | if (c4iw_debugfs_root) { |
754 | devp->debugfs_root = debugfs_create_dir( | 755 | devp->debugfs_root = debugfs_create_dir( |
@@ -977,13 +978,16 @@ static int disable_qp_db(int id, void *p, void *data) | |||
977 | 978 | ||
978 | static void stop_queues(struct uld_ctx *ctx) | 979 | static void stop_queues(struct uld_ctx *ctx) |
979 | { | 980 | { |
980 | spin_lock_irq(&ctx->dev->lock); | 981 | unsigned long flags; |
981 | if (ctx->dev->db_state == NORMAL) { | 982 | |
982 | ctx->dev->rdev.stats.db_state_transitions++; | 983 | spin_lock_irqsave(&ctx->dev->lock, flags); |
983 | ctx->dev->db_state = FLOW_CONTROL; | 984 | ctx->dev->rdev.stats.db_state_transitions++; |
985 | ctx->dev->db_state = STOPPED; | ||
986 | if (ctx->dev->rdev.flags & T4_STATUS_PAGE_DISABLED) | ||
984 | idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL); | 987 | idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL); |
985 | } | 988 | else |
986 | spin_unlock_irq(&ctx->dev->lock); | 989 | ctx->dev->rdev.status_page->db_off = 1; |
990 | spin_unlock_irqrestore(&ctx->dev->lock, flags); | ||
987 | } | 991 | } |
988 | 992 | ||
989 | static int enable_qp_db(int id, void *p, void *data) | 993 | static int enable_qp_db(int id, void *p, void *data) |
@@ -994,15 +998,70 @@ static int enable_qp_db(int id, void *p, void *data) | |||
994 | return 0; | 998 | return 0; |
995 | } | 999 | } |
996 | 1000 | ||
1001 | static void resume_rc_qp(struct c4iw_qp *qp) | ||
1002 | { | ||
1003 | spin_lock(&qp->lock); | ||
1004 | t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc); | ||
1005 | qp->wq.sq.wq_pidx_inc = 0; | ||
1006 | t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc); | ||
1007 | qp->wq.rq.wq_pidx_inc = 0; | ||
1008 | spin_unlock(&qp->lock); | ||
1009 | } | ||
1010 | |||
1011 | static void resume_a_chunk(struct uld_ctx *ctx) | ||
1012 | { | ||
1013 | int i; | ||
1014 | struct c4iw_qp *qp; | ||
1015 | |||
1016 | for (i = 0; i < DB_FC_RESUME_SIZE; i++) { | ||
1017 | qp = list_first_entry(&ctx->dev->db_fc_list, struct c4iw_qp, | ||
1018 | db_fc_entry); | ||
1019 | list_del_init(&qp->db_fc_entry); | ||
1020 | resume_rc_qp(qp); | ||
1021 | if (list_empty(&ctx->dev->db_fc_list)) | ||
1022 | break; | ||
1023 | } | ||
1024 | } | ||
1025 | |||
997 | static void resume_queues(struct uld_ctx *ctx) | 1026 | static void resume_queues(struct uld_ctx *ctx) |
998 | { | 1027 | { |
999 | spin_lock_irq(&ctx->dev->lock); | 1028 | spin_lock_irq(&ctx->dev->lock); |
1000 | if (ctx->dev->qpcnt <= db_fc_threshold && | 1029 | if (ctx->dev->db_state != STOPPED) |
1001 | ctx->dev->db_state == FLOW_CONTROL) { | 1030 | goto out; |
1002 | ctx->dev->db_state = NORMAL; | 1031 | ctx->dev->db_state = FLOW_CONTROL; |
1003 | ctx->dev->rdev.stats.db_state_transitions++; | 1032 | while (1) { |
1004 | idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL); | 1033 | if (list_empty(&ctx->dev->db_fc_list)) { |
1034 | WARN_ON(ctx->dev->db_state != FLOW_CONTROL); | ||
1035 | ctx->dev->db_state = NORMAL; | ||
1036 | ctx->dev->rdev.stats.db_state_transitions++; | ||
1037 | if (ctx->dev->rdev.flags & T4_STATUS_PAGE_DISABLED) { | ||
1038 | idr_for_each(&ctx->dev->qpidr, enable_qp_db, | ||
1039 | NULL); | ||
1040 | } else { | ||
1041 | ctx->dev->rdev.status_page->db_off = 0; | ||
1042 | } | ||
1043 | break; | ||
1044 | } else { | ||
1045 | if (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1) | ||
1046 | < (ctx->dev->rdev.lldi.dbfifo_int_thresh << | ||
1047 | DB_FC_DRAIN_THRESH)) { | ||
1048 | resume_a_chunk(ctx); | ||
1049 | } | ||
1050 | if (!list_empty(&ctx->dev->db_fc_list)) { | ||
1051 | spin_unlock_irq(&ctx->dev->lock); | ||
1052 | if (DB_FC_RESUME_DELAY) { | ||
1053 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1054 | schedule_timeout(DB_FC_RESUME_DELAY); | ||
1055 | } | ||
1056 | spin_lock_irq(&ctx->dev->lock); | ||
1057 | if (ctx->dev->db_state != FLOW_CONTROL) | ||
1058 | break; | ||
1059 | } | ||
1060 | } | ||
1005 | } | 1061 | } |
1062 | out: | ||
1063 | if (ctx->dev->db_state != NORMAL) | ||
1064 | ctx->dev->rdev.stats.db_fc_interruptions++; | ||
1006 | spin_unlock_irq(&ctx->dev->lock); | 1065 | spin_unlock_irq(&ctx->dev->lock); |
1007 | } | 1066 | } |
1008 | 1067 | ||
@@ -1028,12 +1087,12 @@ static int count_qps(int id, void *p, void *data) | |||
1028 | return 0; | 1087 | return 0; |
1029 | } | 1088 | } |
1030 | 1089 | ||
1031 | static void deref_qps(struct qp_list qp_list) | 1090 | static void deref_qps(struct qp_list *qp_list) |
1032 | { | 1091 | { |
1033 | int idx; | 1092 | int idx; |
1034 | 1093 | ||
1035 | for (idx = 0; idx < qp_list.idx; idx++) | 1094 | for (idx = 0; idx < qp_list->idx; idx++) |
1036 | c4iw_qp_rem_ref(&qp_list.qps[idx]->ibqp); | 1095 | c4iw_qp_rem_ref(&qp_list->qps[idx]->ibqp); |
1037 | } | 1096 | } |
1038 | 1097 | ||
1039 | static void recover_lost_dbs(struct uld_ctx *ctx, struct qp_list *qp_list) | 1098 | static void recover_lost_dbs(struct uld_ctx *ctx, struct qp_list *qp_list) |
@@ -1044,17 +1103,22 @@ static void recover_lost_dbs(struct uld_ctx *ctx, struct qp_list *qp_list) | |||
1044 | for (idx = 0; idx < qp_list->idx; idx++) { | 1103 | for (idx = 0; idx < qp_list->idx; idx++) { |
1045 | struct c4iw_qp *qp = qp_list->qps[idx]; | 1104 | struct c4iw_qp *qp = qp_list->qps[idx]; |
1046 | 1105 | ||
1106 | spin_lock_irq(&qp->rhp->lock); | ||
1107 | spin_lock(&qp->lock); | ||
1047 | ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0], | 1108 | ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0], |
1048 | qp->wq.sq.qid, | 1109 | qp->wq.sq.qid, |
1049 | t4_sq_host_wq_pidx(&qp->wq), | 1110 | t4_sq_host_wq_pidx(&qp->wq), |
1050 | t4_sq_wq_size(&qp->wq)); | 1111 | t4_sq_wq_size(&qp->wq)); |
1051 | if (ret) { | 1112 | if (ret) { |
1052 | printk(KERN_ERR MOD "%s: Fatal error - " | 1113 | pr_err(KERN_ERR MOD "%s: Fatal error - " |
1053 | "DB overflow recovery failed - " | 1114 | "DB overflow recovery failed - " |
1054 | "error syncing SQ qid %u\n", | 1115 | "error syncing SQ qid %u\n", |
1055 | pci_name(ctx->lldi.pdev), qp->wq.sq.qid); | 1116 | pci_name(ctx->lldi.pdev), qp->wq.sq.qid); |
1117 | spin_unlock(&qp->lock); | ||
1118 | spin_unlock_irq(&qp->rhp->lock); | ||
1056 | return; | 1119 | return; |
1057 | } | 1120 | } |
1121 | qp->wq.sq.wq_pidx_inc = 0; | ||
1058 | 1122 | ||
1059 | ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0], | 1123 | ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0], |
1060 | qp->wq.rq.qid, | 1124 | qp->wq.rq.qid, |
@@ -1062,12 +1126,17 @@ static void recover_lost_dbs(struct uld_ctx *ctx, struct qp_list *qp_list) | |||
1062 | t4_rq_wq_size(&qp->wq)); | 1126 | t4_rq_wq_size(&qp->wq)); |
1063 | 1127 | ||
1064 | if (ret) { | 1128 | if (ret) { |
1065 | printk(KERN_ERR MOD "%s: Fatal error - " | 1129 | pr_err(KERN_ERR MOD "%s: Fatal error - " |
1066 | "DB overflow recovery failed - " | 1130 | "DB overflow recovery failed - " |
1067 | "error syncing RQ qid %u\n", | 1131 | "error syncing RQ qid %u\n", |
1068 | pci_name(ctx->lldi.pdev), qp->wq.rq.qid); | 1132 | pci_name(ctx->lldi.pdev), qp->wq.rq.qid); |
1133 | spin_unlock(&qp->lock); | ||
1134 | spin_unlock_irq(&qp->rhp->lock); | ||
1069 | return; | 1135 | return; |
1070 | } | 1136 | } |
1137 | qp->wq.rq.wq_pidx_inc = 0; | ||
1138 | spin_unlock(&qp->lock); | ||
1139 | spin_unlock_irq(&qp->rhp->lock); | ||
1071 | 1140 | ||
1072 | /* Wait for the dbfifo to drain */ | 1141 | /* Wait for the dbfifo to drain */ |
1073 | while (cxgb4_dbfifo_count(qp->rhp->rdev.lldi.ports[0], 1) > 0) { | 1142 | while (cxgb4_dbfifo_count(qp->rhp->rdev.lldi.ports[0], 1) > 0) { |
@@ -1083,36 +1152,22 @@ static void recover_queues(struct uld_ctx *ctx) | |||
1083 | struct qp_list qp_list; | 1152 | struct qp_list qp_list; |
1084 | int ret; | 1153 | int ret; |
1085 | 1154 | ||
1086 | /* lock out kernel db ringers */ | ||
1087 | mutex_lock(&ctx->dev->db_mutex); | ||
1088 | |||
1089 | /* put all queues in to recovery mode */ | ||
1090 | spin_lock_irq(&ctx->dev->lock); | ||
1091 | ctx->dev->db_state = RECOVERY; | ||
1092 | ctx->dev->rdev.stats.db_state_transitions++; | ||
1093 | idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL); | ||
1094 | spin_unlock_irq(&ctx->dev->lock); | ||
1095 | |||
1096 | /* slow everybody down */ | 1155 | /* slow everybody down */ |
1097 | set_current_state(TASK_UNINTERRUPTIBLE); | 1156 | set_current_state(TASK_UNINTERRUPTIBLE); |
1098 | schedule_timeout(usecs_to_jiffies(1000)); | 1157 | schedule_timeout(usecs_to_jiffies(1000)); |
1099 | 1158 | ||
1100 | /* Wait for the dbfifo to completely drain. */ | ||
1101 | while (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1) > 0) { | ||
1102 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1103 | schedule_timeout(usecs_to_jiffies(10)); | ||
1104 | } | ||
1105 | |||
1106 | /* flush the SGE contexts */ | 1159 | /* flush the SGE contexts */ |
1107 | ret = cxgb4_flush_eq_cache(ctx->dev->rdev.lldi.ports[0]); | 1160 | ret = cxgb4_flush_eq_cache(ctx->dev->rdev.lldi.ports[0]); |
1108 | if (ret) { | 1161 | if (ret) { |
1109 | printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n", | 1162 | printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n", |
1110 | pci_name(ctx->lldi.pdev)); | 1163 | pci_name(ctx->lldi.pdev)); |
1111 | goto out; | 1164 | return; |
1112 | } | 1165 | } |
1113 | 1166 | ||
1114 | /* Count active queues so we can build a list of queues to recover */ | 1167 | /* Count active queues so we can build a list of queues to recover */ |
1115 | spin_lock_irq(&ctx->dev->lock); | 1168 | spin_lock_irq(&ctx->dev->lock); |
1169 | WARN_ON(ctx->dev->db_state != STOPPED); | ||
1170 | ctx->dev->db_state = RECOVERY; | ||
1116 | idr_for_each(&ctx->dev->qpidr, count_qps, &count); | 1171 | idr_for_each(&ctx->dev->qpidr, count_qps, &count); |
1117 | 1172 | ||
1118 | qp_list.qps = kzalloc(count * sizeof *qp_list.qps, GFP_ATOMIC); | 1173 | qp_list.qps = kzalloc(count * sizeof *qp_list.qps, GFP_ATOMIC); |
@@ -1120,7 +1175,7 @@ static void recover_queues(struct uld_ctx *ctx) | |||
1120 | printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n", | 1175 | printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n", |
1121 | pci_name(ctx->lldi.pdev)); | 1176 | pci_name(ctx->lldi.pdev)); |
1122 | spin_unlock_irq(&ctx->dev->lock); | 1177 | spin_unlock_irq(&ctx->dev->lock); |
1123 | goto out; | 1178 | return; |
1124 | } | 1179 | } |
1125 | qp_list.idx = 0; | 1180 | qp_list.idx = 0; |
1126 | 1181 | ||
@@ -1133,29 +1188,13 @@ static void recover_queues(struct uld_ctx *ctx) | |||
1133 | recover_lost_dbs(ctx, &qp_list); | 1188 | recover_lost_dbs(ctx, &qp_list); |
1134 | 1189 | ||
1135 | /* we're almost done! deref the qps and clean up */ | 1190 | /* we're almost done! deref the qps and clean up */ |
1136 | deref_qps(qp_list); | 1191 | deref_qps(&qp_list); |
1137 | kfree(qp_list.qps); | 1192 | kfree(qp_list.qps); |
1138 | 1193 | ||
1139 | /* Wait for the dbfifo to completely drain again */ | ||
1140 | while (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1) > 0) { | ||
1141 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1142 | schedule_timeout(usecs_to_jiffies(10)); | ||
1143 | } | ||
1144 | |||
1145 | /* resume the queues */ | ||
1146 | spin_lock_irq(&ctx->dev->lock); | 1194 | spin_lock_irq(&ctx->dev->lock); |
1147 | if (ctx->dev->qpcnt > db_fc_threshold) | 1195 | WARN_ON(ctx->dev->db_state != RECOVERY); |
1148 | ctx->dev->db_state = FLOW_CONTROL; | 1196 | ctx->dev->db_state = STOPPED; |
1149 | else { | ||
1150 | ctx->dev->db_state = NORMAL; | ||
1151 | idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL); | ||
1152 | } | ||
1153 | ctx->dev->rdev.stats.db_state_transitions++; | ||
1154 | spin_unlock_irq(&ctx->dev->lock); | 1197 | spin_unlock_irq(&ctx->dev->lock); |
1155 | |||
1156 | out: | ||
1157 | /* start up kernel db ringers again */ | ||
1158 | mutex_unlock(&ctx->dev->db_mutex); | ||
1159 | } | 1198 | } |
1160 | 1199 | ||
1161 | static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...) | 1200 | static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...) |
@@ -1165,9 +1204,7 @@ static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...) | |||
1165 | switch (control) { | 1204 | switch (control) { |
1166 | case CXGB4_CONTROL_DB_FULL: | 1205 | case CXGB4_CONTROL_DB_FULL: |
1167 | stop_queues(ctx); | 1206 | stop_queues(ctx); |
1168 | mutex_lock(&ctx->dev->rdev.stats.lock); | ||
1169 | ctx->dev->rdev.stats.db_full++; | 1207 | ctx->dev->rdev.stats.db_full++; |
1170 | mutex_unlock(&ctx->dev->rdev.stats.lock); | ||
1171 | break; | 1208 | break; |
1172 | case CXGB4_CONTROL_DB_EMPTY: | 1209 | case CXGB4_CONTROL_DB_EMPTY: |
1173 | resume_queues(ctx); | 1210 | resume_queues(ctx); |
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 23eaeabab93b..eb18f9be35e4 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | |||
@@ -109,6 +109,7 @@ struct c4iw_dev_ucontext { | |||
109 | 109 | ||
110 | enum c4iw_rdev_flags { | 110 | enum c4iw_rdev_flags { |
111 | T4_FATAL_ERROR = (1<<0), | 111 | T4_FATAL_ERROR = (1<<0), |
112 | T4_STATUS_PAGE_DISABLED = (1<<1), | ||
112 | }; | 113 | }; |
113 | 114 | ||
114 | struct c4iw_stat { | 115 | struct c4iw_stat { |
@@ -130,6 +131,7 @@ struct c4iw_stats { | |||
130 | u64 db_empty; | 131 | u64 db_empty; |
131 | u64 db_drop; | 132 | u64 db_drop; |
132 | u64 db_state_transitions; | 133 | u64 db_state_transitions; |
134 | u64 db_fc_interruptions; | ||
133 | u64 tcam_full; | 135 | u64 tcam_full; |
134 | u64 act_ofld_conn_fails; | 136 | u64 act_ofld_conn_fails; |
135 | u64 pas_ofld_conn_fails; | 137 | u64 pas_ofld_conn_fails; |
@@ -150,6 +152,7 @@ struct c4iw_rdev { | |||
150 | unsigned long oc_mw_pa; | 152 | unsigned long oc_mw_pa; |
151 | void __iomem *oc_mw_kva; | 153 | void __iomem *oc_mw_kva; |
152 | struct c4iw_stats stats; | 154 | struct c4iw_stats stats; |
155 | struct t4_dev_status_page *status_page; | ||
153 | }; | 156 | }; |
154 | 157 | ||
155 | static inline int c4iw_fatal_error(struct c4iw_rdev *rdev) | 158 | static inline int c4iw_fatal_error(struct c4iw_rdev *rdev) |
@@ -211,7 +214,8 @@ static inline int c4iw_wait_for_reply(struct c4iw_rdev *rdev, | |||
211 | enum db_state { | 214 | enum db_state { |
212 | NORMAL = 0, | 215 | NORMAL = 0, |
213 | FLOW_CONTROL = 1, | 216 | FLOW_CONTROL = 1, |
214 | RECOVERY = 2 | 217 | RECOVERY = 2, |
218 | STOPPED = 3 | ||
215 | }; | 219 | }; |
216 | 220 | ||
217 | struct c4iw_dev { | 221 | struct c4iw_dev { |
@@ -225,10 +229,10 @@ struct c4iw_dev { | |||
225 | struct mutex db_mutex; | 229 | struct mutex db_mutex; |
226 | struct dentry *debugfs_root; | 230 | struct dentry *debugfs_root; |
227 | enum db_state db_state; | 231 | enum db_state db_state; |
228 | int qpcnt; | ||
229 | struct idr hwtid_idr; | 232 | struct idr hwtid_idr; |
230 | struct idr atid_idr; | 233 | struct idr atid_idr; |
231 | struct idr stid_idr; | 234 | struct idr stid_idr; |
235 | struct list_head db_fc_list; | ||
232 | }; | 236 | }; |
233 | 237 | ||
234 | static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev) | 238 | static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev) |
@@ -432,6 +436,7 @@ struct c4iw_qp_attributes { | |||
432 | 436 | ||
433 | struct c4iw_qp { | 437 | struct c4iw_qp { |
434 | struct ib_qp ibqp; | 438 | struct ib_qp ibqp; |
439 | struct list_head db_fc_entry; | ||
435 | struct c4iw_dev *rhp; | 440 | struct c4iw_dev *rhp; |
436 | struct c4iw_ep *ep; | 441 | struct c4iw_ep *ep; |
437 | struct c4iw_qp_attributes attr; | 442 | struct c4iw_qp_attributes attr; |
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c index 7e94c9a656a1..e36d2a27c431 100644 --- a/drivers/infiniband/hw/cxgb4/provider.c +++ b/drivers/infiniband/hw/cxgb4/provider.c | |||
@@ -106,15 +106,54 @@ static struct ib_ucontext *c4iw_alloc_ucontext(struct ib_device *ibdev, | |||
106 | { | 106 | { |
107 | struct c4iw_ucontext *context; | 107 | struct c4iw_ucontext *context; |
108 | struct c4iw_dev *rhp = to_c4iw_dev(ibdev); | 108 | struct c4iw_dev *rhp = to_c4iw_dev(ibdev); |
109 | static int warned; | ||
110 | struct c4iw_alloc_ucontext_resp uresp; | ||
111 | int ret = 0; | ||
112 | struct c4iw_mm_entry *mm = NULL; | ||
109 | 113 | ||
110 | PDBG("%s ibdev %p\n", __func__, ibdev); | 114 | PDBG("%s ibdev %p\n", __func__, ibdev); |
111 | context = kzalloc(sizeof(*context), GFP_KERNEL); | 115 | context = kzalloc(sizeof(*context), GFP_KERNEL); |
112 | if (!context) | 116 | if (!context) { |
113 | return ERR_PTR(-ENOMEM); | 117 | ret = -ENOMEM; |
118 | goto err; | ||
119 | } | ||
120 | |||
114 | c4iw_init_dev_ucontext(&rhp->rdev, &context->uctx); | 121 | c4iw_init_dev_ucontext(&rhp->rdev, &context->uctx); |
115 | INIT_LIST_HEAD(&context->mmaps); | 122 | INIT_LIST_HEAD(&context->mmaps); |
116 | spin_lock_init(&context->mmap_lock); | 123 | spin_lock_init(&context->mmap_lock); |
124 | |||
125 | if (udata->outlen < sizeof(uresp)) { | ||
126 | if (!warned++) | ||
127 | pr_err(MOD "Warning - downlevel libcxgb4 (non-fatal), device status page disabled."); | ||
128 | rhp->rdev.flags |= T4_STATUS_PAGE_DISABLED; | ||
129 | } else { | ||
130 | mm = kmalloc(sizeof(*mm), GFP_KERNEL); | ||
131 | if (!mm) | ||
132 | goto err_free; | ||
133 | |||
134 | uresp.status_page_size = PAGE_SIZE; | ||
135 | |||
136 | spin_lock(&context->mmap_lock); | ||
137 | uresp.status_page_key = context->key; | ||
138 | context->key += PAGE_SIZE; | ||
139 | spin_unlock(&context->mmap_lock); | ||
140 | |||
141 | ret = ib_copy_to_udata(udata, &uresp, sizeof(uresp)); | ||
142 | if (ret) | ||
143 | goto err_mm; | ||
144 | |||
145 | mm->key = uresp.status_page_key; | ||
146 | mm->addr = virt_to_phys(rhp->rdev.status_page); | ||
147 | mm->len = PAGE_SIZE; | ||
148 | insert_mmap(context, mm); | ||
149 | } | ||
117 | return &context->ibucontext; | 150 | return &context->ibucontext; |
151 | err_mm: | ||
152 | kfree(mm); | ||
153 | err_free: | ||
154 | kfree(context); | ||
155 | err: | ||
156 | return ERR_PTR(ret); | ||
118 | } | 157 | } |
119 | 158 | ||
120 | static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) | 159 | static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) |
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 582936708e6e..3b62eb556a47 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c | |||
@@ -638,6 +638,46 @@ void c4iw_qp_rem_ref(struct ib_qp *qp) | |||
638 | wake_up(&(to_c4iw_qp(qp)->wait)); | 638 | wake_up(&(to_c4iw_qp(qp)->wait)); |
639 | } | 639 | } |
640 | 640 | ||
641 | static void add_to_fc_list(struct list_head *head, struct list_head *entry) | ||
642 | { | ||
643 | if (list_empty(entry)) | ||
644 | list_add_tail(entry, head); | ||
645 | } | ||
646 | |||
647 | static int ring_kernel_sq_db(struct c4iw_qp *qhp, u16 inc) | ||
648 | { | ||
649 | unsigned long flags; | ||
650 | |||
651 | spin_lock_irqsave(&qhp->rhp->lock, flags); | ||
652 | spin_lock(&qhp->lock); | ||
653 | if (qhp->rhp->db_state == NORMAL) { | ||
654 | t4_ring_sq_db(&qhp->wq, inc); | ||
655 | } else { | ||
656 | add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry); | ||
657 | qhp->wq.sq.wq_pidx_inc += inc; | ||
658 | } | ||
659 | spin_unlock(&qhp->lock); | ||
660 | spin_unlock_irqrestore(&qhp->rhp->lock, flags); | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static int ring_kernel_rq_db(struct c4iw_qp *qhp, u16 inc) | ||
665 | { | ||
666 | unsigned long flags; | ||
667 | |||
668 | spin_lock_irqsave(&qhp->rhp->lock, flags); | ||
669 | spin_lock(&qhp->lock); | ||
670 | if (qhp->rhp->db_state == NORMAL) { | ||
671 | t4_ring_rq_db(&qhp->wq, inc); | ||
672 | } else { | ||
673 | add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry); | ||
674 | qhp->wq.rq.wq_pidx_inc += inc; | ||
675 | } | ||
676 | spin_unlock(&qhp->lock); | ||
677 | spin_unlock_irqrestore(&qhp->rhp->lock, flags); | ||
678 | return 0; | ||
679 | } | ||
680 | |||
641 | int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | 681 | int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, |
642 | struct ib_send_wr **bad_wr) | 682 | struct ib_send_wr **bad_wr) |
643 | { | 683 | { |
@@ -750,9 +790,13 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
750 | t4_sq_produce(&qhp->wq, len16); | 790 | t4_sq_produce(&qhp->wq, len16); |
751 | idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE); | 791 | idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE); |
752 | } | 792 | } |
753 | if (t4_wq_db_enabled(&qhp->wq)) | 793 | if (!qhp->rhp->rdev.status_page->db_off) { |
754 | t4_ring_sq_db(&qhp->wq, idx); | 794 | t4_ring_sq_db(&qhp->wq, idx); |
755 | spin_unlock_irqrestore(&qhp->lock, flag); | 795 | spin_unlock_irqrestore(&qhp->lock, flag); |
796 | } else { | ||
797 | spin_unlock_irqrestore(&qhp->lock, flag); | ||
798 | ring_kernel_sq_db(qhp, idx); | ||
799 | } | ||
756 | return err; | 800 | return err; |
757 | } | 801 | } |
758 | 802 | ||
@@ -812,9 +856,13 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, | |||
812 | wr = wr->next; | 856 | wr = wr->next; |
813 | num_wrs--; | 857 | num_wrs--; |
814 | } | 858 | } |
815 | if (t4_wq_db_enabled(&qhp->wq)) | 859 | if (!qhp->rhp->rdev.status_page->db_off) { |
816 | t4_ring_rq_db(&qhp->wq, idx); | 860 | t4_ring_rq_db(&qhp->wq, idx); |
817 | spin_unlock_irqrestore(&qhp->lock, flag); | 861 | spin_unlock_irqrestore(&qhp->lock, flag); |
862 | } else { | ||
863 | spin_unlock_irqrestore(&qhp->lock, flag); | ||
864 | ring_kernel_rq_db(qhp, idx); | ||
865 | } | ||
818 | return err; | 866 | return err; |
819 | } | 867 | } |
820 | 868 | ||
@@ -1200,35 +1248,6 @@ out: | |||
1200 | return ret; | 1248 | return ret; |
1201 | } | 1249 | } |
1202 | 1250 | ||
1203 | /* | ||
1204 | * Called by the library when the qp has user dbs disabled due to | ||
1205 | * a DB_FULL condition. This function will single-thread all user | ||
1206 | * DB rings to avoid overflowing the hw db-fifo. | ||
1207 | */ | ||
1208 | static int ring_kernel_db(struct c4iw_qp *qhp, u32 qid, u16 inc) | ||
1209 | { | ||
1210 | int delay = db_delay_usecs; | ||
1211 | |||
1212 | mutex_lock(&qhp->rhp->db_mutex); | ||
1213 | do { | ||
1214 | |||
1215 | /* | ||
1216 | * The interrupt threshold is dbfifo_int_thresh << 6. So | ||
1217 | * make sure we don't cross that and generate an interrupt. | ||
1218 | */ | ||
1219 | if (cxgb4_dbfifo_count(qhp->rhp->rdev.lldi.ports[0], 1) < | ||
1220 | (qhp->rhp->rdev.lldi.dbfifo_int_thresh << 5)) { | ||
1221 | writel(QID(qid) | PIDX(inc), qhp->wq.db); | ||
1222 | break; | ||
1223 | } | ||
1224 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1225 | schedule_timeout(usecs_to_jiffies(delay)); | ||
1226 | delay = min(delay << 1, 2000); | ||
1227 | } while (1); | ||
1228 | mutex_unlock(&qhp->rhp->db_mutex); | ||
1229 | return 0; | ||
1230 | } | ||
1231 | |||
1232 | int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, | 1251 | int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, |
1233 | enum c4iw_qp_attr_mask mask, | 1252 | enum c4iw_qp_attr_mask mask, |
1234 | struct c4iw_qp_attributes *attrs, | 1253 | struct c4iw_qp_attributes *attrs, |
@@ -1278,11 +1297,11 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, | |||
1278 | } | 1297 | } |
1279 | 1298 | ||
1280 | if (mask & C4IW_QP_ATTR_SQ_DB) { | 1299 | if (mask & C4IW_QP_ATTR_SQ_DB) { |
1281 | ret = ring_kernel_db(qhp, qhp->wq.sq.qid, attrs->sq_db_inc); | 1300 | ret = ring_kernel_sq_db(qhp, attrs->sq_db_inc); |
1282 | goto out; | 1301 | goto out; |
1283 | } | 1302 | } |
1284 | if (mask & C4IW_QP_ATTR_RQ_DB) { | 1303 | if (mask & C4IW_QP_ATTR_RQ_DB) { |
1285 | ret = ring_kernel_db(qhp, qhp->wq.rq.qid, attrs->rq_db_inc); | 1304 | ret = ring_kernel_rq_db(qhp, attrs->rq_db_inc); |
1286 | goto out; | 1305 | goto out; |
1287 | } | 1306 | } |
1288 | 1307 | ||
@@ -1465,14 +1484,6 @@ out: | |||
1465 | return ret; | 1484 | return ret; |
1466 | } | 1485 | } |
1467 | 1486 | ||
1468 | static int enable_qp_db(int id, void *p, void *data) | ||
1469 | { | ||
1470 | struct c4iw_qp *qp = p; | ||
1471 | |||
1472 | t4_enable_wq_db(&qp->wq); | ||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | int c4iw_destroy_qp(struct ib_qp *ib_qp) | 1487 | int c4iw_destroy_qp(struct ib_qp *ib_qp) |
1477 | { | 1488 | { |
1478 | struct c4iw_dev *rhp; | 1489 | struct c4iw_dev *rhp; |
@@ -1490,22 +1501,15 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp) | |||
1490 | c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0); | 1501 | c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0); |
1491 | wait_event(qhp->wait, !qhp->ep); | 1502 | wait_event(qhp->wait, !qhp->ep); |
1492 | 1503 | ||
1493 | spin_lock_irq(&rhp->lock); | 1504 | remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid); |
1494 | remove_handle_nolock(rhp, &rhp->qpidr, qhp->wq.sq.qid); | ||
1495 | rhp->qpcnt--; | ||
1496 | BUG_ON(rhp->qpcnt < 0); | ||
1497 | if (rhp->qpcnt <= db_fc_threshold && rhp->db_state == FLOW_CONTROL) { | ||
1498 | rhp->rdev.stats.db_state_transitions++; | ||
1499 | rhp->db_state = NORMAL; | ||
1500 | idr_for_each(&rhp->qpidr, enable_qp_db, NULL); | ||
1501 | } | ||
1502 | if (db_coalescing_threshold >= 0) | ||
1503 | if (rhp->qpcnt <= db_coalescing_threshold) | ||
1504 | cxgb4_enable_db_coalescing(rhp->rdev.lldi.ports[0]); | ||
1505 | spin_unlock_irq(&rhp->lock); | ||
1506 | atomic_dec(&qhp->refcnt); | 1505 | atomic_dec(&qhp->refcnt); |
1507 | wait_event(qhp->wait, !atomic_read(&qhp->refcnt)); | 1506 | wait_event(qhp->wait, !atomic_read(&qhp->refcnt)); |
1508 | 1507 | ||
1508 | spin_lock_irq(&rhp->lock); | ||
1509 | if (!list_empty(&qhp->db_fc_entry)) | ||
1510 | list_del_init(&qhp->db_fc_entry); | ||
1511 | spin_unlock_irq(&rhp->lock); | ||
1512 | |||
1509 | ucontext = ib_qp->uobject ? | 1513 | ucontext = ib_qp->uobject ? |
1510 | to_c4iw_ucontext(ib_qp->uobject->context) : NULL; | 1514 | to_c4iw_ucontext(ib_qp->uobject->context) : NULL; |
1511 | destroy_qp(&rhp->rdev, &qhp->wq, | 1515 | destroy_qp(&rhp->rdev, &qhp->wq, |
@@ -1516,14 +1520,6 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp) | |||
1516 | return 0; | 1520 | return 0; |
1517 | } | 1521 | } |
1518 | 1522 | ||
1519 | static int disable_qp_db(int id, void *p, void *data) | ||
1520 | { | ||
1521 | struct c4iw_qp *qp = p; | ||
1522 | |||
1523 | t4_disable_wq_db(&qp->wq); | ||
1524 | return 0; | ||
1525 | } | ||
1526 | |||
1527 | struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, | 1523 | struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, |
1528 | struct ib_udata *udata) | 1524 | struct ib_udata *udata) |
1529 | { | 1525 | { |
@@ -1610,20 +1606,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, | |||
1610 | init_waitqueue_head(&qhp->wait); | 1606 | init_waitqueue_head(&qhp->wait); |
1611 | atomic_set(&qhp->refcnt, 1); | 1607 | atomic_set(&qhp->refcnt, 1); |
1612 | 1608 | ||
1613 | spin_lock_irq(&rhp->lock); | 1609 | ret = insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid); |
1614 | if (rhp->db_state != NORMAL) | ||
1615 | t4_disable_wq_db(&qhp->wq); | ||
1616 | rhp->qpcnt++; | ||
1617 | if (rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) { | ||
1618 | rhp->rdev.stats.db_state_transitions++; | ||
1619 | rhp->db_state = FLOW_CONTROL; | ||
1620 | idr_for_each(&rhp->qpidr, disable_qp_db, NULL); | ||
1621 | } | ||
1622 | if (db_coalescing_threshold >= 0) | ||
1623 | if (rhp->qpcnt > db_coalescing_threshold) | ||
1624 | cxgb4_disable_db_coalescing(rhp->rdev.lldi.ports[0]); | ||
1625 | ret = insert_handle_nolock(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid); | ||
1626 | spin_unlock_irq(&rhp->lock); | ||
1627 | if (ret) | 1610 | if (ret) |
1628 | goto err2; | 1611 | goto err2; |
1629 | 1612 | ||
@@ -1709,6 +1692,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, | |||
1709 | } | 1692 | } |
1710 | qhp->ibqp.qp_num = qhp->wq.sq.qid; | 1693 | qhp->ibqp.qp_num = qhp->wq.sq.qid; |
1711 | init_timer(&(qhp->timer)); | 1694 | init_timer(&(qhp->timer)); |
1695 | INIT_LIST_HEAD(&qhp->db_fc_entry); | ||
1712 | PDBG("%s qhp %p sq_num_entries %d, rq_num_entries %d qpid 0x%0x\n", | 1696 | PDBG("%s qhp %p sq_num_entries %d, rq_num_entries %d qpid 0x%0x\n", |
1713 | __func__, qhp, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries, | 1697 | __func__, qhp, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries, |
1714 | qhp->wq.sq.qid); | 1698 | qhp->wq.sq.qid); |
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index e73ace739183..eeca8b1e6376 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h | |||
@@ -300,6 +300,7 @@ struct t4_sq { | |||
300 | u16 cidx; | 300 | u16 cidx; |
301 | u16 pidx; | 301 | u16 pidx; |
302 | u16 wq_pidx; | 302 | u16 wq_pidx; |
303 | u16 wq_pidx_inc; | ||
303 | u16 flags; | 304 | u16 flags; |
304 | short flush_cidx; | 305 | short flush_cidx; |
305 | }; | 306 | }; |
@@ -324,6 +325,7 @@ struct t4_rq { | |||
324 | u16 cidx; | 325 | u16 cidx; |
325 | u16 pidx; | 326 | u16 pidx; |
326 | u16 wq_pidx; | 327 | u16 wq_pidx; |
328 | u16 wq_pidx_inc; | ||
327 | }; | 329 | }; |
328 | 330 | ||
329 | struct t4_wq { | 331 | struct t4_wq { |
@@ -609,3 +611,7 @@ static inline void t4_set_cq_in_error(struct t4_cq *cq) | |||
609 | ((struct t4_status_page *)&cq->queue[cq->size])->qp_err = 1; | 611 | ((struct t4_status_page *)&cq->queue[cq->size])->qp_err = 1; |
610 | } | 612 | } |
611 | #endif | 613 | #endif |
614 | |||
615 | struct t4_dev_status_page { | ||
616 | u8 db_off; | ||
617 | }; | ||
diff --git a/drivers/infiniband/hw/cxgb4/user.h b/drivers/infiniband/hw/cxgb4/user.h index 32b754c35ab7..11ccd276e5d9 100644 --- a/drivers/infiniband/hw/cxgb4/user.h +++ b/drivers/infiniband/hw/cxgb4/user.h | |||
@@ -70,4 +70,9 @@ struct c4iw_create_qp_resp { | |||
70 | __u32 qid_mask; | 70 | __u32 qid_mask; |
71 | __u32 flags; | 71 | __u32 flags; |
72 | }; | 72 | }; |
73 | |||
74 | struct c4iw_alloc_ucontext_resp { | ||
75 | __u64 status_page_key; | ||
76 | __u32 status_page_size; | ||
77 | }; | ||
73 | #endif | 78 | #endif |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 50abe1d61287..32db37709263 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | |||
@@ -500,6 +500,7 @@ struct sge_txq { | |||
500 | spinlock_t db_lock; | 500 | spinlock_t db_lock; |
501 | int db_disabled; | 501 | int db_disabled; |
502 | unsigned short db_pidx; | 502 | unsigned short db_pidx; |
503 | unsigned short db_pidx_inc; | ||
503 | u64 udb; | 504 | u64 udb; |
504 | }; | 505 | }; |
505 | 506 | ||
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 0ac53dd84c61..cc04d090354c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | |||
@@ -3578,14 +3578,25 @@ static void drain_db_fifo(struct adapter *adap, int usecs) | |||
3578 | 3578 | ||
3579 | static void disable_txq_db(struct sge_txq *q) | 3579 | static void disable_txq_db(struct sge_txq *q) |
3580 | { | 3580 | { |
3581 | spin_lock_irq(&q->db_lock); | 3581 | unsigned long flags; |
3582 | |||
3583 | spin_lock_irqsave(&q->db_lock, flags); | ||
3582 | q->db_disabled = 1; | 3584 | q->db_disabled = 1; |
3583 | spin_unlock_irq(&q->db_lock); | 3585 | spin_unlock_irqrestore(&q->db_lock, flags); |
3584 | } | 3586 | } |
3585 | 3587 | ||
3586 | static void enable_txq_db(struct sge_txq *q) | 3588 | static void enable_txq_db(struct adapter *adap, struct sge_txq *q) |
3587 | { | 3589 | { |
3588 | spin_lock_irq(&q->db_lock); | 3590 | spin_lock_irq(&q->db_lock); |
3591 | if (q->db_pidx_inc) { | ||
3592 | /* Make sure that all writes to the TX descriptors | ||
3593 | * are committed before we tell HW about them. | ||
3594 | */ | ||
3595 | wmb(); | ||
3596 | t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), | ||
3597 | QID(q->cntxt_id) | PIDX(q->db_pidx_inc)); | ||
3598 | q->db_pidx_inc = 0; | ||
3599 | } | ||
3589 | q->db_disabled = 0; | 3600 | q->db_disabled = 0; |
3590 | spin_unlock_irq(&q->db_lock); | 3601 | spin_unlock_irq(&q->db_lock); |
3591 | } | 3602 | } |
@@ -3607,11 +3618,32 @@ static void enable_dbs(struct adapter *adap) | |||
3607 | int i; | 3618 | int i; |
3608 | 3619 | ||
3609 | for_each_ethrxq(&adap->sge, i) | 3620 | for_each_ethrxq(&adap->sge, i) |
3610 | enable_txq_db(&adap->sge.ethtxq[i].q); | 3621 | enable_txq_db(adap, &adap->sge.ethtxq[i].q); |
3611 | for_each_ofldrxq(&adap->sge, i) | 3622 | for_each_ofldrxq(&adap->sge, i) |
3612 | enable_txq_db(&adap->sge.ofldtxq[i].q); | 3623 | enable_txq_db(adap, &adap->sge.ofldtxq[i].q); |
3613 | for_each_port(adap, i) | 3624 | for_each_port(adap, i) |
3614 | enable_txq_db(&adap->sge.ctrlq[i].q); | 3625 | enable_txq_db(adap, &adap->sge.ctrlq[i].q); |
3626 | } | ||
3627 | |||
3628 | static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd) | ||
3629 | { | ||
3630 | if (adap->uld_handle[CXGB4_ULD_RDMA]) | ||
3631 | ulds[CXGB4_ULD_RDMA].control(adap->uld_handle[CXGB4_ULD_RDMA], | ||
3632 | cmd); | ||
3633 | } | ||
3634 | |||
3635 | static void process_db_full(struct work_struct *work) | ||
3636 | { | ||
3637 | struct adapter *adap; | ||
3638 | |||
3639 | adap = container_of(work, struct adapter, db_full_task); | ||
3640 | |||
3641 | drain_db_fifo(adap, dbfifo_drain_delay); | ||
3642 | enable_dbs(adap); | ||
3643 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY); | ||
3644 | t4_set_reg_field(adap, SGE_INT_ENABLE3, | ||
3645 | DBFIFO_HP_INT | DBFIFO_LP_INT, | ||
3646 | DBFIFO_HP_INT | DBFIFO_LP_INT); | ||
3615 | } | 3647 | } |
3616 | 3648 | ||
3617 | static void sync_txq_pidx(struct adapter *adap, struct sge_txq *q) | 3649 | static void sync_txq_pidx(struct adapter *adap, struct sge_txq *q) |
@@ -3619,7 +3651,7 @@ static void sync_txq_pidx(struct adapter *adap, struct sge_txq *q) | |||
3619 | u16 hw_pidx, hw_cidx; | 3651 | u16 hw_pidx, hw_cidx; |
3620 | int ret; | 3652 | int ret; |
3621 | 3653 | ||
3622 | spin_lock_bh(&q->db_lock); | 3654 | spin_lock_irq(&q->db_lock); |
3623 | ret = read_eq_indices(adap, (u16)q->cntxt_id, &hw_pidx, &hw_cidx); | 3655 | ret = read_eq_indices(adap, (u16)q->cntxt_id, &hw_pidx, &hw_cidx); |
3624 | if (ret) | 3656 | if (ret) |
3625 | goto out; | 3657 | goto out; |
@@ -3636,7 +3668,8 @@ static void sync_txq_pidx(struct adapter *adap, struct sge_txq *q) | |||
3636 | } | 3668 | } |
3637 | out: | 3669 | out: |
3638 | q->db_disabled = 0; | 3670 | q->db_disabled = 0; |
3639 | spin_unlock_bh(&q->db_lock); | 3671 | q->db_pidx_inc = 0; |
3672 | spin_unlock_irq(&q->db_lock); | ||
3640 | if (ret) | 3673 | if (ret) |
3641 | CH_WARN(adap, "DB drop recovery failed.\n"); | 3674 | CH_WARN(adap, "DB drop recovery failed.\n"); |
3642 | } | 3675 | } |
@@ -3652,29 +3685,6 @@ static void recover_all_queues(struct adapter *adap) | |||
3652 | sync_txq_pidx(adap, &adap->sge.ctrlq[i].q); | 3685 | sync_txq_pidx(adap, &adap->sge.ctrlq[i].q); |
3653 | } | 3686 | } |
3654 | 3687 | ||
3655 | static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd) | ||
3656 | { | ||
3657 | mutex_lock(&uld_mutex); | ||
3658 | if (adap->uld_handle[CXGB4_ULD_RDMA]) | ||
3659 | ulds[CXGB4_ULD_RDMA].control(adap->uld_handle[CXGB4_ULD_RDMA], | ||
3660 | cmd); | ||
3661 | mutex_unlock(&uld_mutex); | ||
3662 | } | ||
3663 | |||
3664 | static void process_db_full(struct work_struct *work) | ||
3665 | { | ||
3666 | struct adapter *adap; | ||
3667 | |||
3668 | adap = container_of(work, struct adapter, db_full_task); | ||
3669 | |||
3670 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL); | ||
3671 | drain_db_fifo(adap, dbfifo_drain_delay); | ||
3672 | t4_set_reg_field(adap, SGE_INT_ENABLE3, | ||
3673 | DBFIFO_HP_INT | DBFIFO_LP_INT, | ||
3674 | DBFIFO_HP_INT | DBFIFO_LP_INT); | ||
3675 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY); | ||
3676 | } | ||
3677 | |||
3678 | static void process_db_drop(struct work_struct *work) | 3688 | static void process_db_drop(struct work_struct *work) |
3679 | { | 3689 | { |
3680 | struct adapter *adap; | 3690 | struct adapter *adap; |
@@ -3682,11 +3692,13 @@ static void process_db_drop(struct work_struct *work) | |||
3682 | adap = container_of(work, struct adapter, db_drop_task); | 3692 | adap = container_of(work, struct adapter, db_drop_task); |
3683 | 3693 | ||
3684 | if (is_t4(adap->params.chip)) { | 3694 | if (is_t4(adap->params.chip)) { |
3685 | disable_dbs(adap); | 3695 | drain_db_fifo(adap, dbfifo_drain_delay); |
3686 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP); | 3696 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP); |
3687 | drain_db_fifo(adap, 1); | 3697 | drain_db_fifo(adap, dbfifo_drain_delay); |
3688 | recover_all_queues(adap); | 3698 | recover_all_queues(adap); |
3699 | drain_db_fifo(adap, dbfifo_drain_delay); | ||
3689 | enable_dbs(adap); | 3700 | enable_dbs(adap); |
3701 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY); | ||
3690 | } else { | 3702 | } else { |
3691 | u32 dropped_db = t4_read_reg(adap, 0x010ac); | 3703 | u32 dropped_db = t4_read_reg(adap, 0x010ac); |
3692 | u16 qid = (dropped_db >> 15) & 0x1ffff; | 3704 | u16 qid = (dropped_db >> 15) & 0x1ffff; |
@@ -3727,6 +3739,8 @@ static void process_db_drop(struct work_struct *work) | |||
3727 | void t4_db_full(struct adapter *adap) | 3739 | void t4_db_full(struct adapter *adap) |
3728 | { | 3740 | { |
3729 | if (is_t4(adap->params.chip)) { | 3741 | if (is_t4(adap->params.chip)) { |
3742 | disable_dbs(adap); | ||
3743 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL); | ||
3730 | t4_set_reg_field(adap, SGE_INT_ENABLE3, | 3744 | t4_set_reg_field(adap, SGE_INT_ENABLE3, |
3731 | DBFIFO_HP_INT | DBFIFO_LP_INT, 0); | 3745 | DBFIFO_HP_INT | DBFIFO_LP_INT, 0); |
3732 | queue_work(workq, &adap->db_full_task); | 3746 | queue_work(workq, &adap->db_full_task); |
@@ -3735,8 +3749,11 @@ void t4_db_full(struct adapter *adap) | |||
3735 | 3749 | ||
3736 | void t4_db_dropped(struct adapter *adap) | 3750 | void t4_db_dropped(struct adapter *adap) |
3737 | { | 3751 | { |
3738 | if (is_t4(adap->params.chip)) | 3752 | if (is_t4(adap->params.chip)) { |
3739 | queue_work(workq, &adap->db_drop_task); | 3753 | disable_dbs(adap); |
3754 | notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL); | ||
3755 | } | ||
3756 | queue_work(workq, &adap->db_drop_task); | ||
3740 | } | 3757 | } |
3741 | 3758 | ||
3742 | static void uld_attach(struct adapter *adap, unsigned int uld) | 3759 | static void uld_attach(struct adapter *adap, unsigned int uld) |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 46429f9d0592..d4db382ff8c7 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c | |||
@@ -860,9 +860,10 @@ static void cxgb_pio_copy(u64 __iomem *dst, u64 *src) | |||
860 | static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n) | 860 | static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n) |
861 | { | 861 | { |
862 | unsigned int *wr, index; | 862 | unsigned int *wr, index; |
863 | unsigned long flags; | ||
863 | 864 | ||
864 | wmb(); /* write descriptors before telling HW */ | 865 | wmb(); /* write descriptors before telling HW */ |
865 | spin_lock(&q->db_lock); | 866 | spin_lock_irqsave(&q->db_lock, flags); |
866 | if (!q->db_disabled) { | 867 | if (!q->db_disabled) { |
867 | if (is_t4(adap->params.chip)) { | 868 | if (is_t4(adap->params.chip)) { |
868 | t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), | 869 | t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), |
@@ -878,9 +879,10 @@ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n) | |||
878 | writel(n, adap->bar2 + q->udb + 8); | 879 | writel(n, adap->bar2 + q->udb + 8); |
879 | wmb(); | 880 | wmb(); |
880 | } | 881 | } |
881 | } | 882 | } else |
883 | q->db_pidx_inc += n; | ||
882 | q->db_pidx = q->pidx; | 884 | q->db_pidx = q->pidx; |
883 | spin_unlock(&q->db_lock); | 885 | spin_unlock_irqrestore(&q->db_lock, flags); |
884 | } | 886 | } |
885 | 887 | ||
886 | /** | 888 | /** |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h index cd6874b571ee..f2738c710789 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | |||
@@ -116,6 +116,7 @@ enum CPL_error { | |||
116 | CPL_ERR_KEEPALIVE_TIMEDOUT = 34, | 116 | CPL_ERR_KEEPALIVE_TIMEDOUT = 34, |
117 | CPL_ERR_RTX_NEG_ADVICE = 35, | 117 | CPL_ERR_RTX_NEG_ADVICE = 35, |
118 | CPL_ERR_PERSIST_NEG_ADVICE = 36, | 118 | CPL_ERR_PERSIST_NEG_ADVICE = 36, |
119 | CPL_ERR_KEEPALV_NEG_ADVICE = 37, | ||
119 | CPL_ERR_ABORT_FAILED = 42, | 120 | CPL_ERR_ABORT_FAILED = 42, |
120 | CPL_ERR_IWARP_FLM = 50, | 121 | CPL_ERR_IWARP_FLM = 50, |
121 | }; | 122 | }; |