Add support for a new command in netlink to dump to user the state of the FRMR pools on the devices. Expose each pool with its key and the usage statistics for it.
Unified · Split
| @@ -37,11 +37,13 @@ · 36 unmodified lines | |||
| 37 | #include <net/netlink.h> | 37 | #include <net/netlink.h> |
| 38 | #include <rdma/rdma_cm.h> | 38 | #include <rdma/rdma_cm.h> |
| 39 | #include <rdma/rdma_netlink.h> | 39 | #include <rdma/rdma_netlink.h> |
| 40 | #include <rdma/frmr_pools.h> | ||
| 40 | 41 | ||
| 41 | #include "core_priv.h" | 42 | #include "core_priv.h" |
| 42 | #include "cma_priv.h" | 43 | #include "cma_priv.h" |
| 43 | #include "restrack.h" | 44 | #include "restrack.h" |
| 44 | #include "uverbs.h" | 45 | #include "uverbs.h" |
| 46 | #include "frmr_pools.h" | ||
| 45 | 47 | ||
| 46 | /* | 48 | /* |
| 47 | * This determines whether a non-privileged user is allowed to specify a | 49 | * This determines whether a non-privileged user is allowed to specify a |
| @@ -172,6 +174,16 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = { · 124 unmodified lines | |||
| 172 | [RDMA_NLDEV_ATTR_NAME_ASSIGN_TYPE] = { .type = NLA_U8 }, | 174 | [RDMA_NLDEV_ATTR_NAME_ASSIGN_TYPE] = { .type = NLA_U8 }, |
| 173 | [RDMA_NLDEV_ATTR_EVENT_TYPE] = { .type = NLA_U8 }, | 175 | [RDMA_NLDEV_ATTR_EVENT_TYPE] = { .type = NLA_U8 }, |
| 174 | [RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED] = { .type = NLA_U8 }, | 176 | [RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED] = { .type = NLA_U8 }, |
| 177 | [RDMA_NLDEV_ATTR_FRMR_POOLS] = { .type = NLA_NESTED }, | ||
| 178 | [RDMA_NLDEV_ATTR_FRMR_POOL_ENTRY] = { .type = NLA_NESTED }, | ||
| 179 | [RDMA_NLDEV_ATTR_FRMR_POOL_KEY] = { .type = NLA_NESTED }, | ||
| 180 | [RDMA_NLDEV_ATTR_FRMR_POOL_KEY_ATS] = { .type = NLA_U8 }, | ||
| 181 | [RDMA_NLDEV_ATTR_FRMR_POOL_KEY_ACCESS_FLAGS] = { .type = NLA_U32 }, | ||
| 182 | [RDMA_NLDEV_ATTR_FRMR_POOL_KEY_VENDOR_KEY] = { .type = NLA_U64 }, | ||
| 183 | [RDMA_NLDEV_ATTR_FRMR_POOL_KEY_NUM_DMA_BLOCKS] = { .type = NLA_U64 }, | ||
| 184 | [RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES] = { .type = NLA_U32 }, | ||
| 185 | [RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE] = { .type = NLA_U64 }, | ||
| 186 | [RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE] = { .type = NLA_U64 }, | ||
| 175 | }; | 187 | }; |
| 176 | 188 | ||
| 177 | static int put_driver_name_print_type(struct sk_buff *msg, const char *name, | 189 | static int put_driver_name_print_type(struct sk_buff *msg, const char *name, |
| @@ -2637,6 +2649,156 @@ static int nldev_deldev(struct sk_buff *skb, struct nlmsghdr *nlh, · 2459 unmodified lines | |||
| 2637 | return ib_del_sub_device_and_put(device); | 2649 | return ib_del_sub_device_and_put(device); |
| 2638 | } | 2650 | } |
| 2639 | 2651 | ||
| 2652 | static int fill_frmr_pool_key(struct sk_buff *msg, struct ib_frmr_key *key) | ||
| 2653 | { | ||
| 2654 | struct nlattr *key_attr; | ||
| 2655 | |||
| 2656 | key_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_FRMR_POOL_KEY); | ||
| 2657 | if (!key_attr) | ||
| 2658 | return -EMSGSIZE; | ||
| 2659 | |||
| 2660 | if (nla_put_u8(msg, RDMA_NLDEV_ATTR_FRMR_POOL_KEY_ATS, key->ats)) | ||
| 2661 | goto err; | ||
| 2662 | if (nla_put_u32(msg, RDMA_NLDEV_ATTR_FRMR_POOL_KEY_ACCESS_FLAGS, | ||
| 2663 | key->access_flags)) | ||
| 2664 | goto err; | ||
| 2665 | if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_FRMR_POOL_KEY_VENDOR_KEY, | ||
| 2666 | key->vendor_key, RDMA_NLDEV_ATTR_PAD)) | ||
| 2667 | goto err; | ||
| 2668 | if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_FRMR_POOL_KEY_NUM_DMA_BLOCKS, | ||
| 2669 | key->num_dma_blocks, RDMA_NLDEV_ATTR_PAD)) | ||
| 2670 | goto err; | ||
| 2671 | |||
| 2672 | nla_nest_end(msg, key_attr); | ||
| 2673 | return 0; | ||
| 2674 | |||
| 2675 | err: | ||
| 2676 | return -EMSGSIZE; | ||
| 2677 | } | ||
| 2678 | |||
| 2679 | static int fill_frmr_pool_entry(struct sk_buff *msg, struct ib_frmr_pool *pool) | ||
| 2680 | { | ||
| 2681 | if (fill_frmr_pool_key(msg, &pool->key)) | ||
| 2682 | return -EMSGSIZE; | ||
| 2683 | |||
| 2684 | spin_lock(&pool->lock); | ||
| 2685 | if (nla_put_u32(msg, RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES, | ||
| 2686 | pool->queue.ci + pool->inactive_queue.ci)) | ||
| 2687 | goto err_unlock; | ||
| 2688 | if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE, | ||
| 2689 | pool->max_in_use, RDMA_NLDEV_ATTR_PAD)) | ||
| 2690 | goto err_unlock; | ||
| 2691 | if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE, | ||
| 2692 | pool->in_use, RDMA_NLDEV_ATTR_PAD)) | ||
| 2693 | goto err_unlock; | ||
| 2694 | spin_unlock(&pool->lock); | ||
| 2695 | |||
| 2696 | return 0; | ||
| 2697 | |||
| 2698 | err_unlock: | ||
| 2699 | spin_unlock(&pool->lock); | ||
| 2700 | return -EMSGSIZE; | ||
| 2701 | } | ||
| 2702 | |||
| 2703 | static int nldev_frmr_pools_get_dumpit(struct sk_buff *skb, | ||
| 2704 | struct netlink_callback *cb) | ||
| 2705 | { | ||
| 2706 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX]; | ||
| 2707 | struct ib_frmr_pools *pools; | ||
| 2708 | int err, ret = 0, idx = 0; | ||
| 2709 | struct ib_frmr_pool *pool; | ||
| 2710 | struct nlattr *table_attr; | ||
| 2711 | struct nlattr *entry_attr; | ||
| 2712 | struct ib_device *device; | ||
| 2713 | int start = cb->args[0]; | ||
| 2714 | struct rb_node *node; | ||
| 2715 | struct nlmsghdr *nlh; | ||
| 2716 | bool filled = false; | ||
| 2717 | |||
| 2718 | err = __nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, | ||
| 2719 | nldev_policy, NL_VALIDATE_LIBERAL, NULL); | ||
| 2720 | if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX]) | ||
| 2721 | return -EINVAL; | ||
| 2722 | |||
| 2723 | device = ib_device_get_by_index( | ||
| 2724 | sock_net(skb->sk), nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX])); | ||
| 2725 | if (!device) | ||
| 2726 | return -EINVAL; | ||
| 2727 | |||
| 2728 | pools = device->frmr_pools; | ||
| 2729 | if (!pools) { | ||
| 2730 | ib_device_put(device); | ||
| 2731 | return 0; | ||
| 2732 | } | ||
| 2733 | |||
| 2734 | nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, | ||
| 2735 | RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, | ||
| 2736 | RDMA_NLDEV_CMD_FRMR_POOLS_GET), | ||
| 2737 | 0, NLM_F_MULTI); | ||
| 2738 | |||
| 2739 | if (!nlh || fill_nldev_handle(skb, device)) { | ||
| 2740 | ret = -EMSGSIZE; | ||
| 2741 | goto err; | ||
| 2742 | } | ||
| 2743 | |||
| 2744 | table_attr = nla_nest_start_noflag(skb, RDMA_NLDEV_ATTR_FRMR_POOLS); | ||
| 2745 | if (!table_attr) { | ||
| 2746 | ret = -EMSGSIZE; | ||
| 2747 | goto err; | ||
| 2748 | } | ||
| 2749 | |||
| 2750 | read_lock(&pools->rb_lock); | ||
| 2751 | for (node = rb_first(&pools->rb_root); node; node = rb_next(node)) { | ||
| 2752 | pool = rb_entry(node, struct ib_frmr_pool, node); | ||
| 2753 | if (pool->key.kernel_vendor_key) | ||
| 2754 | continue; | ||
| 2755 | |||
| 2756 | if (idx < start) { | ||
| 2757 | idx++; | ||
| 2758 | continue; | ||
| 2759 | } | ||
| 2760 | |||
| 2761 | filled = true; | ||
| 2762 | |||
| 2763 | entry_attr = nla_nest_start_noflag( | ||
| 2764 | skb, RDMA_NLDEV_ATTR_FRMR_POOL_ENTRY); | ||
| 2765 | if (!entry_attr) { | ||
| 2766 | ret = -EMSGSIZE; | ||
| 2767 | goto end_msg; | ||
| 2768 | } | ||
| 2769 | |||
| 2770 | if (fill_frmr_pool_entry(skb, pool)) { | ||
| 2771 | nla_nest_cancel(skb, entry_attr); | ||
| 2772 | ret = -EMSGSIZE; | ||
| 2773 | goto end_msg; | ||
| 2774 | } | ||
| 2775 | |||
| 2776 | nla_nest_end(skb, entry_attr); | ||
| 2777 | idx++; | ||
| 2778 | } | ||
| 2779 | end_msg: | ||
| 2780 | read_unlock(&pools->rb_lock); | ||
| 2781 | |||
| 2782 | nla_nest_end(skb, table_attr); | ||
| 2783 | nlmsg_end(skb, nlh); | ||
| 2784 | cb->args[0] = idx; | ||
| 2785 | |||
| 2786 | /* | ||
| 2787 | * No more entries to fill, cancel the message and | ||
| 2788 | * return 0 to mark end of dumpit. | ||
| 2789 | */ | ||
| 2790 | if (!filled) | ||
| 2791 | goto err; | ||
| 2792 | |||
| 2793 | ib_device_put(device); | ||
| 2794 | return skb->len; | ||
| 2795 | |||
| 2796 | err: | ||
| 2797 | nlmsg_cancel(skb, nlh); | ||
| 2798 | ib_device_put(device); | ||
| 2799 | return ret; | ||
| 2800 | } | ||
| 2801 | |||
| 2640 | static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { | 2802 | static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { |
| 2641 | [RDMA_NLDEV_CMD_GET] = { | 2803 | [RDMA_NLDEV_CMD_GET] = { |
| 2642 | .doit = nldev_get_doit, | 2804 | .doit = nldev_get_doit, |
| @@ -2743,6 +2905,9 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { · 100 unmodified lines | |||
| 2743 | .doit = nldev_deldev, | 2905 | .doit = nldev_deldev, |
| 2744 | .flags = RDMA_NL_ADMIN_PERM, | 2906 | .flags = RDMA_NL_ADMIN_PERM, |
| 2745 | }, | 2907 | }, |
| 2908 | [RDMA_NLDEV_CMD_FRMR_POOLS_GET] = { | ||
| 2909 | .dump = nldev_frmr_pools_get_dumpit, | ||
| 2910 | }, | ||
| 2746 | }; | 2911 | }; |
| 2747 | 2912 | ||
| 2748 | static int fill_mon_netdev_rename(struct sk_buff *msg, | 2913 | static int fill_mon_netdev_rename(struct sk_buff *msg, |
| @@ -308,6 +308,8 @@ enum rdma_nldev_command { · 307 unmodified lines | |||
| 308 | 308 | ||
| 309 | RDMA_NLDEV_CMD_MONITOR, | 309 | RDMA_NLDEV_CMD_MONITOR, |
| 310 | 310 | ||
| 311 | RDMA_NLDEV_CMD_FRMR_POOLS_GET, /* can dump */ | ||
| 312 | |||
| 311 | RDMA_NLDEV_NUM_OPS | 313 | RDMA_NLDEV_NUM_OPS |
| 312 | }; | 314 | }; |
| 313 | 315 | ||
| @@ -582,6 +584,21 @@ enum rdma_nldev_attr { · 268 unmodified lines | |||
| 582 | RDMA_NLDEV_SYS_ATTR_MONITOR_MODE, /* u8 */ | 584 | RDMA_NLDEV_SYS_ATTR_MONITOR_MODE, /* u8 */ |
| 583 | 585 | ||
| 584 | RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED, /* u8 */ | 586 | RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED, /* u8 */ |
| 587 | |||
| 588 | /* | ||
| 589 | * FRMR Pools attributes | ||
| 590 | */ | ||
| 591 | RDMA_NLDEV_ATTR_FRMR_POOLS, /* nested table */ | ||
| 592 | RDMA_NLDEV_ATTR_FRMR_POOL_ENTRY, /* nested table */ | ||
| 593 | RDMA_NLDEV_ATTR_FRMR_POOL_KEY, /* nested table */ | ||
| 594 | RDMA_NLDEV_ATTR_FRMR_POOL_KEY_ATS, /* u8 */ | ||
| 595 | RDMA_NLDEV_ATTR_FRMR_POOL_KEY_ACCESS_FLAGS, /* u32 */ | ||
| 596 | RDMA_NLDEV_ATTR_FRMR_POOL_KEY_VENDOR_KEY, /* u64 */ | ||
| 597 | RDMA_NLDEV_ATTR_FRMR_POOL_KEY_NUM_DMA_BLOCKS, /* u64 */ | ||
| 598 | RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES, /* u32 */ | ||
| 599 | RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE, /* u64 */ | ||
| 600 | RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE, /* u64 */ | ||
| 601 | |||
| 585 | /* | 602 | /* |
| 586 | * Always the end | 603 | * Always the end |
| 587 | */ | 604 | */ |