diff options
| -rw-r--r-- | drivers/infiniband/hw/mlx4/mad.c | 684 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 80 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 34 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cmd.c | 3 | ||||
| -rw-r--r-- | include/linux/mlx4/device.h | 3 | ||||
| -rw-r--r-- | include/linux/mlx4/driver.h | 2 |
6 files changed, 798 insertions, 8 deletions
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 9c2ae7efd00..e98849338a9 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c | |||
| @@ -44,6 +44,35 @@ enum { | |||
| 44 | MLX4_IB_VENDOR_CLASS2 = 0xa | 44 | MLX4_IB_VENDOR_CLASS2 = 0xa |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | #define MLX4_TUN_SEND_WRID_SHIFT 34 | ||
| 48 | #define MLX4_TUN_QPN_SHIFT 32 | ||
| 49 | #define MLX4_TUN_WRID_RECV (((u64) 1) << MLX4_TUN_SEND_WRID_SHIFT) | ||
| 50 | #define MLX4_TUN_SET_WRID_QPN(a) (((u64) ((a) & 0x3)) << MLX4_TUN_QPN_SHIFT) | ||
| 51 | |||
| 52 | #define MLX4_TUN_IS_RECV(a) (((a) >> MLX4_TUN_SEND_WRID_SHIFT) & 0x1) | ||
| 53 | #define MLX4_TUN_WRID_QPN(a) (((a) >> MLX4_TUN_QPN_SHIFT) & 0x3) | ||
| 54 | |||
| 55 | struct mlx4_mad_rcv_buf { | ||
| 56 | struct ib_grh grh; | ||
| 57 | u8 payload[256]; | ||
| 58 | } __packed; | ||
| 59 | |||
| 60 | struct mlx4_mad_snd_buf { | ||
| 61 | u8 payload[256]; | ||
| 62 | } __packed; | ||
| 63 | |||
| 64 | struct mlx4_tunnel_mad { | ||
| 65 | struct ib_grh grh; | ||
| 66 | struct mlx4_ib_tunnel_header hdr; | ||
| 67 | struct ib_mad mad; | ||
| 68 | } __packed; | ||
| 69 | |||
| 70 | struct mlx4_rcv_tunnel_mad { | ||
| 71 | struct mlx4_rcv_tunnel_hdr hdr; | ||
| 72 | struct ib_grh grh; | ||
| 73 | struct ib_mad mad; | ||
| 74 | } __packed; | ||
| 75 | |||
| 47 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, | 76 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, |
| 48 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 77 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, |
| 49 | void *in_mad, void *response_mad) | 78 | void *in_mad, void *response_mad) |
| @@ -516,3 +545,658 @@ void mlx4_ib_dispatch_event(struct mlx4_ib_dev *dev, u8 port_num, | |||
| 516 | 545 | ||
| 517 | ib_dispatch_event(&event); | 546 | ib_dispatch_event(&event); |
| 518 | } | 547 | } |
| 548 | |||
| 549 | static void mlx4_ib_tunnel_comp_handler(struct ib_cq *cq, void *arg) | ||
| 550 | { | ||
| 551 | unsigned long flags; | ||
| 552 | struct mlx4_ib_demux_pv_ctx *ctx = cq->cq_context; | ||
| 553 | struct mlx4_ib_dev *dev = to_mdev(ctx->ib_dev); | ||
| 554 | spin_lock_irqsave(&dev->sriov.going_down_lock, flags); | ||
| 555 | if (!dev->sriov.is_going_down && ctx->state == DEMUX_PV_STATE_ACTIVE) | ||
| 556 | queue_work(ctx->wq, &ctx->work); | ||
| 557 | spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags); | ||
| 558 | } | ||
| 559 | |||
| 560 | static int mlx4_ib_post_pv_qp_buf(struct mlx4_ib_demux_pv_ctx *ctx, | ||
| 561 | struct mlx4_ib_demux_pv_qp *tun_qp, | ||
| 562 | int index) | ||
| 563 | { | ||
| 564 | struct ib_sge sg_list; | ||
| 565 | struct ib_recv_wr recv_wr, *bad_recv_wr; | ||
| 566 | int size; | ||
| 567 | |||
| 568 | size = (tun_qp->qp->qp_type == IB_QPT_UD) ? | ||
| 569 | sizeof (struct mlx4_tunnel_mad) : sizeof (struct mlx4_mad_rcv_buf); | ||
| 570 | |||
| 571 | sg_list.addr = tun_qp->ring[index].map; | ||
| 572 | sg_list.length = size; | ||
| 573 | sg_list.lkey = ctx->mr->lkey; | ||
| 574 | |||
| 575 | recv_wr.next = NULL; | ||
| 576 | recv_wr.sg_list = &sg_list; | ||
| 577 | recv_wr.num_sge = 1; | ||
| 578 | recv_wr.wr_id = (u64) index | MLX4_TUN_WRID_RECV | | ||
| 579 | MLX4_TUN_SET_WRID_QPN(tun_qp->proxy_qpt); | ||
| 580 | ib_dma_sync_single_for_device(ctx->ib_dev, tun_qp->ring[index].map, | ||
| 581 | size, DMA_FROM_DEVICE); | ||
| 582 | return ib_post_recv(tun_qp->qp, &recv_wr, &bad_recv_wr); | ||
| 583 | } | ||
| 584 | |||
| 585 | static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx, | ||
| 586 | enum ib_qp_type qp_type, int is_tun) | ||
| 587 | { | ||
| 588 | int i; | ||
| 589 | struct mlx4_ib_demux_pv_qp *tun_qp; | ||
| 590 | int rx_buf_size, tx_buf_size; | ||
| 591 | |||
| 592 | if (qp_type > IB_QPT_GSI) | ||
| 593 | return -EINVAL; | ||
| 594 | |||
| 595 | tun_qp = &ctx->qp[qp_type]; | ||
| 596 | |||
| 597 | tun_qp->ring = kzalloc(sizeof (struct mlx4_ib_buf) * MLX4_NUM_TUNNEL_BUFS, | ||
| 598 | GFP_KERNEL); | ||
| 599 | if (!tun_qp->ring) | ||
| 600 | return -ENOMEM; | ||
| 601 | |||
| 602 | tun_qp->tx_ring = kcalloc(MLX4_NUM_TUNNEL_BUFS, | ||
| 603 | sizeof (struct mlx4_ib_tun_tx_buf), | ||
| 604 | GFP_KERNEL); | ||
| 605 | if (!tun_qp->tx_ring) { | ||
| 606 | kfree(tun_qp->ring); | ||
| 607 | tun_qp->ring = NULL; | ||
| 608 | return -ENOMEM; | ||
| 609 | } | ||
| 610 | |||
| 611 | if (is_tun) { | ||
| 612 | rx_buf_size = sizeof (struct mlx4_tunnel_mad); | ||
| 613 | tx_buf_size = sizeof (struct mlx4_rcv_tunnel_mad); | ||
| 614 | } else { | ||
| 615 | rx_buf_size = sizeof (struct mlx4_mad_rcv_buf); | ||
| 616 | tx_buf_size = sizeof (struct mlx4_mad_snd_buf); | ||
| 617 | } | ||
| 618 | |||
| 619 | for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) { | ||
| 620 | tun_qp->ring[i].addr = kmalloc(rx_buf_size, GFP_KERNEL); | ||
| 621 | if (!tun_qp->ring[i].addr) | ||
| 622 | goto err; | ||
| 623 | tun_qp->ring[i].map = ib_dma_map_single(ctx->ib_dev, | ||
| 624 | tun_qp->ring[i].addr, | ||
| 625 | rx_buf_size, | ||
| 626 | DMA_FROM_DEVICE); | ||
| 627 | } | ||
| 628 | |||
| 629 | for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) { | ||
| 630 | tun_qp->tx_ring[i].buf.addr = | ||
| 631 | kmalloc(tx_buf_size, GFP_KERNEL); | ||
| 632 | if (!tun_qp->tx_ring[i].buf.addr) | ||
| 633 | goto tx_err; | ||
| 634 | tun_qp->tx_ring[i].buf.map = | ||
| 635 | ib_dma_map_single(ctx->ib_dev, | ||
| 636 | tun_qp->tx_ring[i].buf.addr, | ||
| 637 | tx_buf_size, | ||
| 638 | DMA_TO_DEVICE); | ||
| 639 | tun_qp->tx_ring[i].ah = NULL; | ||
| 640 | } | ||
| 641 | spin_lock_init(&tun_qp->tx_lock); | ||
| 642 | tun_qp->tx_ix_head = 0; | ||
| 643 | tun_qp->tx_ix_tail = 0; | ||
| 644 | tun_qp->proxy_qpt = qp_type; | ||
| 645 | |||
| 646 | return 0; | ||
| 647 | |||
| 648 | tx_err: | ||
| 649 | while (i > 0) { | ||
| 650 | --i; | ||
| 651 | ib_dma_unmap_single(ctx->ib_dev, tun_qp->tx_ring[i].buf.map, | ||
| 652 | tx_buf_size, DMA_TO_DEVICE); | ||
| 653 | kfree(tun_qp->tx_ring[i].buf.addr); | ||
| 654 | } | ||
| 655 | kfree(tun_qp->tx_ring); | ||
| 656 | tun_qp->tx_ring = NULL; | ||
| 657 | i = MLX4_NUM_TUNNEL_BUFS; | ||
| 658 | err: | ||
| 659 | while (i > 0) { | ||
| 660 | --i; | ||
| 661 | ib_dma_unmap_single(ctx->ib_dev, tun_qp->ring[i].map, | ||
| 662 | rx_buf_size, DMA_FROM_DEVICE); | ||
| 663 | kfree(tun_qp->ring[i].addr); | ||
| 664 | } | ||
| 665 | kfree(tun_qp->ring); | ||
| 666 | tun_qp->ring = NULL; | ||
| 667 | return -ENOMEM; | ||
| 668 | } | ||
| 669 | |||
| 670 | static void mlx4_ib_free_pv_qp_bufs(struct mlx4_ib_demux_pv_ctx *ctx, | ||
| 671 | enum ib_qp_type qp_type, int is_tun) | ||
| 672 | { | ||
| 673 | int i; | ||
| 674 | struct mlx4_ib_demux_pv_qp *tun_qp; | ||
| 675 | int rx_buf_size, tx_buf_size; | ||
| 676 | |||
| 677 | if (qp_type > IB_QPT_GSI) | ||
| 678 | return; | ||
| 679 | |||
| 680 | tun_qp = &ctx->qp[qp_type]; | ||
| 681 | if (is_tun) { | ||
| 682 | rx_buf_size = sizeof (struct mlx4_tunnel_mad); | ||
| 683 | tx_buf_size = sizeof (struct mlx4_rcv_tunnel_mad); | ||
| 684 | } else { | ||
| 685 | rx_buf_size = sizeof (struct mlx4_mad_rcv_buf); | ||
| 686 | tx_buf_size = sizeof (struct mlx4_mad_snd_buf); | ||
| 687 | } | ||
| 688 | |||
| 689 | |||
| 690 | for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) { | ||
| 691 | ib_dma_unmap_single(ctx->ib_dev, tun_qp->ring[i].map, | ||
| 692 | rx_buf_size, DMA_FROM_DEVICE); | ||
| 693 | kfree(tun_qp->ring[i].addr); | ||
| 694 | } | ||
| 695 | |||
| 696 | for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) { | ||
| 697 | ib_dma_unmap_single(ctx->ib_dev, tun_qp->tx_ring[i].buf.map, | ||
| 698 | tx_buf_size, DMA_TO_DEVICE); | ||
| 699 | kfree(tun_qp->tx_ring[i].buf.addr); | ||
| 700 | if (tun_qp->tx_ring[i].ah) | ||
| 701 | ib_destroy_ah(tun_qp->tx_ring[i].ah); | ||
| 702 | } | ||
| 703 | kfree(tun_qp->tx_ring); | ||
| 704 | kfree(tun_qp->ring); | ||
| 705 | } | ||
| 706 | |||
| 707 | static void mlx4_ib_tunnel_comp_worker(struct work_struct *work) | ||
| 708 | { | ||
