diff options
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_provider.c')
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_provider.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index daa54db00aa9..28199e42b36f 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
@@ -574,6 +574,74 @@ static int mthca_dereg_mr(struct ib_mr *mr) | |||
574 | return 0; | 574 | return 0; |
575 | } | 575 | } |
576 | 576 | ||
577 | static struct ib_fmr *mthca_alloc_fmr(struct ib_pd *pd, int mr_access_flags, | ||
578 | struct ib_fmr_attr *fmr_attr) | ||
579 | { | ||
580 | struct mthca_fmr *fmr; | ||
581 | int err; | ||
582 | |||
583 | fmr = kmalloc(sizeof *fmr, GFP_KERNEL); | ||
584 | if (!fmr) | ||
585 | return ERR_PTR(-ENOMEM); | ||
586 | |||
587 | memcpy(&fmr->attr, fmr_attr, sizeof *fmr_attr); | ||
588 | err = mthca_fmr_alloc(to_mdev(pd->device), to_mpd(pd)->pd_num, | ||
589 | convert_access(mr_access_flags), fmr); | ||
590 | |||
591 | if (err) { | ||
592 | kfree(fmr); | ||
593 | return ERR_PTR(err); | ||
594 | } | ||
595 | |||
596 | return &fmr->ibmr; | ||
597 | } | ||
598 | |||
599 | static int mthca_dealloc_fmr(struct ib_fmr *fmr) | ||
600 | { | ||
601 | struct mthca_fmr *mfmr = to_mfmr(fmr); | ||
602 | int err; | ||
603 | |||
604 | err = mthca_free_fmr(to_mdev(fmr->device), mfmr); | ||
605 | if (err) | ||
606 | return err; | ||
607 | |||
608 | kfree(mfmr); | ||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static int mthca_unmap_fmr(struct list_head *fmr_list) | ||
613 | { | ||
614 | struct ib_fmr *fmr; | ||
615 | int err; | ||
616 | u8 status; | ||
617 | struct mthca_dev *mdev = NULL; | ||
618 | |||
619 | list_for_each_entry(fmr, fmr_list, list) { | ||
620 | if (mdev && to_mdev(fmr->device) != mdev) | ||
621 | return -EINVAL; | ||
622 | mdev = to_mdev(fmr->device); | ||
623 | } | ||
624 | |||
625 | if (!mdev) | ||
626 | return 0; | ||
627 | |||
628 | if (mdev->hca_type == ARBEL_NATIVE) { | ||
629 | list_for_each_entry(fmr, fmr_list, list) | ||
630 | mthca_arbel_fmr_unmap(mdev, to_mfmr(fmr)); | ||
631 | |||
632 | wmb(); | ||
633 | } else | ||
634 | list_for_each_entry(fmr, fmr_list, list) | ||
635 | mthca_tavor_fmr_unmap(mdev, to_mfmr(fmr)); | ||
636 | |||
637 | err = mthca_SYNC_TPT(mdev, &status); | ||
638 | if (err) | ||
639 | return err; | ||
640 | if (status) | ||
641 | return -EINVAL; | ||
642 | return 0; | ||
643 | } | ||
644 | |||
577 | static ssize_t show_rev(struct class_device *cdev, char *buf) | 645 | static ssize_t show_rev(struct class_device *cdev, char *buf) |
578 | { | 646 | { |
579 | struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev); | 647 | struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev); |
@@ -637,6 +705,17 @@ int mthca_register_device(struct mthca_dev *dev) | |||
637 | dev->ib_dev.get_dma_mr = mthca_get_dma_mr; | 705 | dev->ib_dev.get_dma_mr = mthca_get_dma_mr; |
638 | dev->ib_dev.reg_phys_mr = mthca_reg_phys_mr; | 706 | dev->ib_dev.reg_phys_mr = mthca_reg_phys_mr; |
639 | dev->ib_dev.dereg_mr = mthca_dereg_mr; | 707 | dev->ib_dev.dereg_mr = mthca_dereg_mr; |
708 | |||
709 | if (dev->mthca_flags & MTHCA_FLAG_FMR) { | ||
710 | dev->ib_dev.alloc_fmr = mthca_alloc_fmr; | ||
711 | dev->ib_dev.unmap_fmr = mthca_unmap_fmr; | ||
712 | dev->ib_dev.dealloc_fmr = mthca_dealloc_fmr; | ||
713 | if (dev->hca_type == ARBEL_NATIVE) | ||
714 | dev->ib_dev.map_phys_fmr = mthca_arbel_map_phys_fmr; | ||
715 | else | ||
716 | dev->ib_dev.map_phys_fmr = mthca_tavor_map_phys_fmr; | ||
717 | } | ||
718 | |||
640 | dev->ib_dev.attach_mcast = mthca_multicast_attach; | 719 | dev->ib_dev.attach_mcast = mthca_multicast_attach; |
641 | dev->ib_dev.detach_mcast = mthca_multicast_detach; | 720 | dev->ib_dev.detach_mcast = mthca_multicast_detach; |
642 | dev->ib_dev.process_mad = mthca_process_mad; | 721 | dev->ib_dev.process_mad = mthca_process_mad; |