aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c684
-rw-r--r--drivers/infiniband/hw/mlx4/main.c80
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h34
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c3
-rw-r--r--include/linux/mlx4/device.h3
-rw-r--r--include/linux/mlx4/driver.h2
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
55struct mlx4_mad_rcv_buf {
56 struct ib_grh grh;
57 u8 payload[256];
58} __packed;
59
60struct mlx4_mad_snd_buf {
61 u8 payload[256];
62} __packed;
63
64struct mlx4_tunnel_mad {
65 struct ib_grh grh;
66 struct mlx4_ib_tunnel_header hdr;
67 struct ib_mad mad;
68} __packed;
69
70struct mlx4_rcv_tunnel_mad {
71 struct mlx4_rcv_tunnel_hdr hdr;
72 struct ib_grh grh;
73 struct ib_mad mad;
74} __packed;
75
47int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, 76int 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
549static 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
560static 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
585static 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
648tx_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;
658err:
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
670static 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
707static void mlx4_ib_tunnel_comp_worker(struct work_struct *work)
708{