diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-01 14:01:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-01 14:01:54 -0500 |
commit | 4bc2a9bf8cbb63f3bb9797b2bf30b2316bd27a2b (patch) | |
tree | a02a03a4c75e3da0843168456124f60afae49200 | |
parent | 6a1214113090905aca6a492fc8ef10d84c608a69 (diff) | |
parent | b0f43dcca8a1f46e17b26d10f3cb1b297ebfb44e (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
IB/mlx4: Fix MTT leakage in resize CQ
IB/ehca: Fix problem with generated flush work completions
IB/ehca: Change misleading error message on memory hotplug
mlx4_core: Save/restore default port IB capability mask
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_classes.h | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_main.c | 3 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_qp.c | 26 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_reqs.c | 51 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/cq.c | 5 | ||||
-rw-r--r-- | drivers/net/mlx4/main.c | 8 | ||||
-rw-r--r-- | drivers/net/mlx4/mlx4.h | 1 | ||||
-rw-r--r-- | drivers/net/mlx4/port.c | 39 | ||||
-rw-r--r-- | include/linux/mlx4/device.h | 1 |
9 files changed, 107 insertions, 31 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 4df887af66a5..7fc35cf0cddf 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -163,7 +163,8 @@ struct ehca_mod_qp_parm { | |||
163 | /* struct for tracking if cqes have been reported to the application */ | 163 | /* struct for tracking if cqes have been reported to the application */ |
164 | struct ehca_qmap_entry { | 164 | struct ehca_qmap_entry { |
165 | u16 app_wr_id; | 165 | u16 app_wr_id; |
166 | u16 reported; | 166 | u8 reported; |
167 | u8 cqe_req; | ||
167 | }; | 168 | }; |
168 | 169 | ||
169 | struct ehca_queue_map { | 170 | struct ehca_queue_map { |
@@ -171,6 +172,7 @@ struct ehca_queue_map { | |||
171 | unsigned int entries; | 172 | unsigned int entries; |
172 | unsigned int tail; | 173 | unsigned int tail; |
173 | unsigned int left_to_poll; | 174 | unsigned int left_to_poll; |
175 | unsigned int next_wqe_idx; /* Idx to first wqe to be flushed */ | ||
174 | }; | 176 | }; |
175 | 177 | ||
176 | struct ehca_qp { | 178 | struct ehca_qp { |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index bb02a86aa526..bec7e0249358 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -994,8 +994,7 @@ static int ehca_mem_notifier(struct notifier_block *nb, | |||
994 | if (printk_timed_ratelimit(&ehca_dmem_warn_time, | 994 | if (printk_timed_ratelimit(&ehca_dmem_warn_time, |
995 | 30 * 1000)) | 995 | 30 * 1000)) |
996 | ehca_gen_err("DMEM operations are not allowed" | 996 | ehca_gen_err("DMEM operations are not allowed" |
997 | "as long as an ehca adapter is" | 997 | "in conjunction with eHCA"); |
998 | "attached to the LPAR"); | ||
999 | return NOTIFY_BAD; | 998 | return NOTIFY_BAD; |
1000 | } | 999 | } |
1001 | } | 1000 | } |
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 9e05ee2db39b..cadbf0cdd910 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c | |||
@@ -435,9 +435,13 @@ static void reset_queue_map(struct ehca_queue_map *qmap) | |||
435 | { | 435 | { |
436 | int i; | 436 | int i; |
437 | 437 | ||
438 | qmap->tail = 0; | 438 | qmap->tail = qmap->entries - 1; |
439 | for (i = 0; i < qmap->entries; i++) | 439 | qmap->left_to_poll = 0; |
440 | qmap->next_wqe_idx = 0; | ||
441 | for (i = 0; i < qmap->entries; i++) { | ||
440 | qmap->map[i].reported = 1; | 442 | qmap->map[i].reported = 1; |
443 | qmap->map[i].cqe_req = 0; | ||
444 | } | ||
441 | } | 445 | } |
442 | 446 | ||
443 | /* | 447 | /* |
@@ -1121,6 +1125,7 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue, | |||
1121 | void *wqe_v; | 1125 | void *wqe_v; |
1122 | u64 q_ofs; | 1126 | u64 q_ofs; |
1123 | u32 wqe_idx; | 1127 | u32 wqe_idx; |
1128 | unsigned int tail_idx; | ||
1124 | 1129 | ||
1125 | /* convert real to abs address */ | 1130 | /* convert real to abs address */ |
1126 | wqe_p = wqe_p & (~(1UL << 63)); | 1131 | wqe_p = wqe_p & (~(1UL << 63)); |
@@ -1133,12 +1138,17 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue, | |||
1133 | return -EFAULT; | 1138 | return -EFAULT; |
1134 | } | 1139 | } |
1135 | 1140 | ||
1141 | tail_idx = (qmap->tail + 1) % qmap->entries; | ||
1136 | wqe_idx = q_ofs / ipz_queue->qe_size; | 1142 | wqe_idx = q_ofs / ipz_queue->qe_size; |
1137 | if (wqe_idx < qmap->tail) | ||
1138 | qmap->left_to_poll = (qmap->entries - qmap->tail) + wqe_idx; | ||
1139 | else | ||
1140 | qmap->left_to_poll = wqe_idx - qmap->tail; | ||
1141 | 1143 | ||
1144 | /* check all processed wqes, whether a cqe is requested or not */ | ||
1145 | while (tail_idx != wqe_idx) { | ||
1146 | if (qmap->map[tail_idx].cqe_req) | ||
1147 | qmap->left_to_poll++; | ||
1148 | tail_idx = (tail_idx + 1) % qmap->entries; | ||
1149 | } | ||
1150 | /* save index in queue, where we have to start flushing */ | ||
1151 | qmap->next_wqe_idx = wqe_idx; | ||
1142 | return 0; | 1152 | return 0; |
1143 | } | 1153 | } |
1144 | 1154 | ||
@@ -1185,10 +1195,14 @@ static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca) | |||
1185 | } else { | 1195 | } else { |
1186 | spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); | 1196 | spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); |
1187 | my_qp->sq_map.left_to_poll = 0; | 1197 | my_qp->sq_map.left_to_poll = 0; |
1198 | my_qp->sq_map.next_wqe_idx = (my_qp->sq_map.tail + 1) % | ||
1199 | my_qp->sq_map.entries; | ||
1188 | spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); | 1200 | spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); |
1189 | 1201 | ||
1190 | spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); | 1202 | spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); |
1191 | my_qp->rq_map.left_to_poll = 0; | 1203 | my_qp->rq_map.left_to_poll = 0; |
1204 | my_qp->rq_map.next_wqe_idx = (my_qp->rq_map.tail + 1) % | ||
1205 | my_qp->rq_map.entries; | ||
1192 | spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); | 1206 | spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); |
1193 | } | 1207 | } |
1194 | 1208 | ||
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index 64928079eafa..00a648f4316c 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c | |||
@@ -179,6 +179,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp, | |||
179 | 179 | ||
180 | qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id); | 180 | qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id); |
181 | qmap_entry->reported = 0; | 181 | qmap_entry->reported = 0; |
182 | qmap_entry->cqe_req = 0; | ||
182 | 183 | ||
183 | switch (send_wr->opcode) { | 184 | switch (send_wr->opcode) { |
184 | case IB_WR_SEND: | 185 | case IB_WR_SEND: |
@@ -203,8 +204,10 @@ static inline int ehca_write_swqe(struct ehca_qp *qp, | |||
203 | 204 | ||
204 | if ((send_wr->send_flags & IB_SEND_SIGNALED || | 205 | if ((send_wr->send_flags & IB_SEND_SIGNALED || |
205 | qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR) | 206 | qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR) |
206 | && !hidden) | 207 | && !hidden) { |
207 | wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM; | 208 | wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM; |
209 | qmap_entry->cqe_req = 1; | ||
210 | } | ||
208 | 211 | ||
209 | if (send_wr->opcode == IB_WR_SEND_WITH_IMM || | 212 | if (send_wr->opcode == IB_WR_SEND_WITH_IMM || |
210 | send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) { | 213 | send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) { |
@@ -569,6 +572,7 @@ static int internal_post_recv(struct ehca_qp *my_qp, | |||
569 | qmap_entry = &my_qp->rq_map.map[rq_map_idx]; | 572 | qmap_entry = &my_qp->rq_map.map[rq_map_idx]; |
570 | qmap_entry->app_wr_id = get_app_wr_id(cur_recv_wr->wr_id); | 573 | qmap_entry->app_wr_id = get_app_wr_id(cur_recv_wr->wr_id); |
571 | qmap_entry->reported = 0; | 574 | qmap_entry->reported = 0; |
575 | qmap_entry->cqe_req = 1; | ||
572 | 576 | ||
573 | wqe_cnt++; | 577 | wqe_cnt++; |
574 | } /* eof for cur_recv_wr */ | 578 | } /* eof for cur_recv_wr */ |
@@ -706,27 +710,34 @@ repoll: | |||
706 | goto repoll; | 710 | goto repoll; |
707 | wc->qp = &my_qp->ib_qp; | 711 | wc->qp = &my_qp->ib_qp; |
708 | 712 | ||
713 | qmap_tail_idx = get_app_wr_id(cqe->work_request_id); | ||
714 | if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) | ||
715 | /* We got a send completion. */ | ||
716 | qmap = &my_qp->sq_map; | ||
717 | else | ||
718 | /* We got a receive completion. */ | ||
719 | qmap = &my_qp->rq_map; | ||
720 | |||
721 | /* advance the tail pointer */ | ||
722 | qmap->tail = qmap_tail_idx; | ||
723 | |||
709 | if (is_error) { | 724 | if (is_error) { |
710 | /* | 725 | /* |
711 | * set left_to_poll to 0 because in error state, we will not | 726 | * set left_to_poll to 0 because in error state, we will not |
712 | * get any additional CQEs | 727 | * get any additional CQEs |
713 | */ | 728 | */ |
714 | ehca_add_to_err_list(my_qp, 1); | 729 | my_qp->sq_map.next_wqe_idx = (my_qp->sq_map.tail + 1) % |
730 | my_qp->sq_map.entries; | ||
715 | my_qp->sq_map.left_to_poll = 0; | 731 | my_qp->sq_map.left_to_poll = 0; |
732 | ehca_add_to_err_list(my_qp, 1); | ||
716 | 733 | ||
734 | my_qp->rq_map.next_wqe_idx = (my_qp->rq_map.tail + 1) % | ||
735 | my_qp->rq_map.entries; | ||
736 | my_qp->rq_map.left_to_poll = 0; | ||
717 | if (HAS_RQ(my_qp)) | 737 | if (HAS_RQ(my_qp)) |
718 | ehca_add_to_err_list(my_qp, 0); | 738 | ehca_add_to_err_list(my_qp, 0); |
719 | my_qp->rq_map.left_to_poll = 0; | ||
720 | } | 739 | } |
721 | 740 | ||
722 | qmap_tail_idx = get_app_wr_id(cqe->work_request_id); | ||
723 | if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) | ||
724 | /* We got a send completion. */ | ||
725 | qmap = &my_qp->sq_map; | ||
726 | else | ||
727 | /* We got a receive completion. */ | ||
728 | qmap = &my_qp->rq_map; | ||
729 | |||
730 | qmap_entry = &qmap->map[qmap_tail_idx]; | 741 | qmap_entry = &qmap->map[qmap_tail_idx]; |
731 | if (qmap_entry->reported) { | 742 | if (qmap_entry->reported) { |
732 | ehca_warn(cq->device, "Double cqe on qp_num=%#x", | 743 | ehca_warn(cq->device, "Double cqe on qp_num=%#x", |
@@ -738,10 +749,6 @@ repoll: | |||
738 | wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id); | 749 | wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id); |
739 | qmap_entry->reported = 1; | 750 | qmap_entry->reported = 1; |
740 | 751 | ||
741 | /* this is a proper completion, we need to advance the tail pointer */ | ||
742 | if (++qmap->tail == qmap->entries) | ||
743 | qmap->tail = 0; | ||
744 | |||
745 | /* if left_to_poll is decremented to 0, add the QP to the error list */ | 752 | /* if left_to_poll is decremented to 0, add the QP to the error list */ |
746 | if (qmap->left_to_poll > 0) { | 753 | if (qmap->left_to_poll > 0) { |
747 | qmap->left_to_poll--; | 754 | qmap->left_to_poll--; |
@@ -805,13 +812,14 @@ static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq, | |||
805 | else | 812 | else |
806 | qmap = &my_qp->rq_map; | 813 | qmap = &my_qp->rq_map; |
807 | 814 | ||
808 | qmap_entry = &qmap->map[qmap->tail]; | 815 | qmap_entry = &qmap->map[qmap->next_wqe_idx]; |
809 | 816 | ||
810 | while ((nr < num_entries) && (qmap_entry->reported == 0)) { | 817 | while ((nr < num_entries) && (qmap_entry->reported == 0)) { |
811 | /* generate flush CQE */ | 818 | /* generate flush CQE */ |
819 | |||
812 | memset(wc, 0, sizeof(*wc)); | 820 | memset(wc, 0, sizeof(*wc)); |
813 | 821 | ||
814 | offset = qmap->tail * ipz_queue->qe_size; | 822 | offset = qmap->next_wqe_idx * ipz_queue->qe_size; |
815 | wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset); | 823 | wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset); |
816 | if (!wqe) { | 824 | if (!wqe) { |
817 | ehca_err(cq->device, "Invalid wqe offset=%#lx on " | 825 | ehca_err(cq->device, "Invalid wqe offset=%#lx on " |
@@ -850,11 +858,12 @@ static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq, | |||
850 | 858 | ||
851 | wc->qp = &my_qp->ib_qp; | 859 | wc->qp = &my_qp->ib_qp; |
852 | 860 | ||
853 | /* mark as reported and advance tail pointer */ | 861 | /* mark as reported and advance next_wqe pointer */ |
854 | qmap_entry->reported = 1; | 862 | qmap_entry->reported = 1; |
855 | if (++qmap->tail == qmap->entries) | 863 | qmap->next_wqe_idx++; |
856 | qmap->tail = 0; | 864 | if (qmap->next_wqe_idx == qmap->entries) |
857 | qmap_entry = &qmap->map[qmap->tail]; | 865 | qmap->next_wqe_idx = 0; |
866 | qmap_entry = &qmap->map[qmap->next_wqe_idx]; | ||
858 | 867 | ||
859 | wc++; nr++; | 868 | wc++; nr++; |
860 | } | 869 | } |
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index d0866a3636e2..18308494a195 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c | |||
@@ -343,6 +343,7 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) | |||
343 | { | 343 | { |
344 | struct mlx4_ib_dev *dev = to_mdev(ibcq->device); | 344 | struct mlx4_ib_dev *dev = to_mdev(ibcq->device); |
345 | struct mlx4_ib_cq *cq = to_mcq(ibcq); | 345 | struct mlx4_ib_cq *cq = to_mcq(ibcq); |
346 | struct mlx4_mtt mtt; | ||
346 | int outst_cqe; | 347 | int outst_cqe; |
347 | int err; | 348 | int err; |
348 | 349 | ||
@@ -376,10 +377,13 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) | |||
376 | goto out; | 377 | goto out; |
377 | } | 378 | } |
378 | 379 | ||
380 | mtt = cq->buf.mtt; | ||
381 | |||
379 | err = mlx4_cq_resize(dev->dev, &cq->mcq, entries, &cq->resize_buf->buf.mtt); | 382 | err = mlx4_cq_resize(dev->dev, &cq->mcq, entries, &cq->resize_buf->buf.mtt); |
380 | if (err) | 383 | if (err) |
381 | goto err_buf; | 384 | goto err_buf; |
382 | 385 | ||
386 | mlx4_mtt_cleanup(dev->dev, &mtt); | ||
383 | if (ibcq->uobject) { | 387 | if (ibcq->uobject) { |
384 | cq->buf = cq->resize_buf->buf; | 388 | cq->buf = cq->resize_buf->buf; |
385 | cq->ibcq.cqe = cq->resize_buf->cqe; | 389 | cq->ibcq.cqe = cq->resize_buf->cqe; |
@@ -406,6 +410,7 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) | |||
406 | goto out; | 410 | goto out; |
407 | 411 | ||
408 | err_buf: | 412 | err_buf: |
413 | mlx4_mtt_cleanup(dev->dev, &cq->resize_buf->buf.mtt); | ||
409 | if (!ibcq->uobject) | 414 | if (!ibcq->uobject) |
410 | mlx4_ib_free_cq_buf(dev, &cq->resize_buf->buf, | 415 | mlx4_ib_free_cq_buf(dev, &cq->resize_buf->buf, |
411 | cq->resize_buf->cqe); | 416 | cq->resize_buf->cqe); |
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 468921b8f4b6..90a0281d15ea 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c | |||
@@ -753,6 +753,7 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) | |||
753 | struct mlx4_priv *priv = mlx4_priv(dev); | 753 | struct mlx4_priv *priv = mlx4_priv(dev); |
754 | int err; | 754 | int err; |
755 | int port; | 755 | int port; |
756 | __be32 ib_port_default_caps; | ||
756 | 757 | ||
757 | err = mlx4_init_uar_table(dev); | 758 | err = mlx4_init_uar_table(dev); |
758 | if (err) { | 759 | if (err) { |
@@ -852,6 +853,13 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) | |||
852 | } | 853 | } |
853 | 854 | ||
854 | for (port = 1; port <= dev->caps.num_ports; port++) { | 855 | for (port = 1; port <= dev->caps.num_ports; port++) { |
856 | ib_port_default_caps = 0; | ||
857 | err = mlx4_get_port_ib_caps(dev, port, &ib_port_default_caps); | ||
858 | if (err) | ||
859 | mlx4_warn(dev, "failed to get port %d default " | ||
860 | "ib capabilities (%d). Continuing with " | ||
861 | "caps = 0\n", port, err); | ||
862 | dev->caps.ib_port_def_cap[port] = ib_port_default_caps; | ||
855 | err = mlx4_SET_PORT(dev, port); | 863 | err = mlx4_SET_PORT(dev, port); |
856 | if (err) { | 864 | if (err) { |
857 | mlx4_err(dev, "Failed to set port %d, aborting\n", | 865 | mlx4_err(dev, "Failed to set port %d, aborting\n", |
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index 56a2e213fe62..34c909deaff3 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h | |||
@@ -385,5 +385,6 @@ void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); | |||
385 | void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); | 385 | void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); |
386 | 386 | ||
387 | int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port); | 387 | int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port); |
388 | int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps); | ||
388 | 389 | ||
389 | #endif /* MLX4_H */ | 390 | #endif /* MLX4_H */ |
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c index e2fdab42c4ce..0a057e5dc63b 100644 --- a/drivers/net/mlx4/port.c +++ b/drivers/net/mlx4/port.c | |||
@@ -258,6 +258,42 @@ out: | |||
258 | } | 258 | } |
259 | EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); | 259 | EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); |
260 | 260 | ||
261 | int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) | ||
262 | { | ||
263 | struct mlx4_cmd_mailbox *inmailbox, *outmailbox; | ||
264 | u8 *inbuf, *outbuf; | ||
265 | int err; | ||
266 | |||
267 | inmailbox = mlx4_alloc_cmd_mailbox(dev); | ||
268 | if (IS_ERR(inmailbox)) | ||
269 | return PTR_ERR(inmailbox); | ||
270 | |||
271 | outmailbox = mlx4_alloc_cmd_mailbox(dev); | ||
272 | if (IS_ERR(outmailbox)) { | ||
273 | mlx4_free_cmd_mailbox(dev, inmailbox); | ||
274 | return PTR_ERR(outmailbox); | ||
275 | } | ||
276 | |||
277 | inbuf = inmailbox->buf; | ||
278 | outbuf = outmailbox->buf; | ||
279 | memset(inbuf, 0, 256); | ||
280 | memset(outbuf, 0, 256); | ||
281 | inbuf[0] = 1; | ||
282 | inbuf[1] = 1; | ||
283 | inbuf[2] = 1; | ||
284 | inbuf[3] = 1; | ||
285 | *(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015); | ||
286 | *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); | ||
287 | |||
288 | err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, | ||
289 | MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C); | ||
290 | if (!err) | ||
291 | *caps = *(__be32 *) (outbuf + 84); | ||
292 | mlx4_free_cmd_mailbox(dev, inmailbox); | ||
293 | mlx4_free_cmd_mailbox(dev, outmailbox); | ||
294 | return err; | ||
295 | } | ||
296 | |||
261 | int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) | 297 | int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) |
262 | { | 298 | { |
263 | struct mlx4_cmd_mailbox *mailbox; | 299 | struct mlx4_cmd_mailbox *mailbox; |
@@ -273,7 +309,8 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) | |||
273 | ((u8 *) mailbox->buf)[3] = 6; | 309 | ((u8 *) mailbox->buf)[3] = 6; |
274 | ((__be16 *) mailbox->buf)[4] = cpu_to_be16(1 << 15); | 310 | ((__be16 *) mailbox->buf)[4] = cpu_to_be16(1 << 15); |
275 | ((__be16 *) mailbox->buf)[6] = cpu_to_be16(1 << 15); | 311 | ((__be16 *) mailbox->buf)[6] = cpu_to_be16(1 << 15); |
276 | } | 312 | } else |
313 | ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; | ||
277 | err = mlx4_cmd(dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT, | 314 | err = mlx4_cmd(dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT, |
278 | MLX4_CMD_TIME_CLASS_B); | 315 | MLX4_CMD_TIME_CLASS_B); |
279 | 316 | ||
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index bd9977b89490..371086fd946f 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h | |||
@@ -179,6 +179,7 @@ struct mlx4_caps { | |||
179 | int num_ports; | 179 | int num_ports; |
180 | int vl_cap[MLX4_MAX_PORTS + 1]; | 180 | int vl_cap[MLX4_MAX_PORTS + 1]; |
181 | int ib_mtu_cap[MLX4_MAX_PORTS + 1]; | 181 | int ib_mtu_cap[MLX4_MAX_PORTS + 1]; |
182 | __be32 ib_port_def_cap[MLX4_MAX_PORTS + 1]; | ||
182 | u64 def_mac[MLX4_MAX_PORTS + 1]; | 183 | u64 def_mac[MLX4_MAX_PORTS + 1]; |
183 | int eth_mtu_cap[MLX4_MAX_PORTS + 1]; | 184 | int eth_mtu_cap[MLX4_MAX_PORTS + 1]; |
184 | int gid_table_len[MLX4_MAX_PORTS + 1]; | 185 | int gid_table_len[MLX4_MAX_PORTS + 1]; |