]>
Commit | Line | Data |
---|---|---|
40df8263 LR |
1 | /* |
2 | * dev.c RDMA tool | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
6 | * as published by the Free Software Foundation; either version | |
7 | * 2 of the License, or (at your option) any later version. | |
8 | * | |
9 | * Authors: Leon Romanovsky <leonro@mellanox.com> | |
10 | */ | |
11 | ||
12 | #include "rdma.h" | |
13 | ||
14 | static int dev_help(struct rd *rd) | |
15 | { | |
16 | pr_out("Usage: %s dev show [DEV]\n", rd->filename); | |
17 | return 0; | |
18 | } | |
19 | ||
20 | static const char *dev_caps_to_str(uint32_t idx) | |
21 | { | |
22 | #define RDMA_DEV_FLAGS(x) \ | |
23 | x(RESIZE_MAX_WR, 0) \ | |
24 | x(BAD_PKEY_CNTR, 1) \ | |
25 | x(BAD_QKEY_CNTR, 2) \ | |
26 | x(RAW_MULTI, 3) \ | |
27 | x(AUTO_PATH_MIG, 4) \ | |
28 | x(CHANGE_PHY_PORT, 5) \ | |
29 | x(UD_AV_PORT_ENFORCE_PORT_ENFORCE, 6) \ | |
30 | x(CURR_QP_STATE_MOD, 7) \ | |
31 | x(SHUTDOWN_PORT, 8) \ | |
32 | x(INIT_TYPE, 9) \ | |
33 | x(PORT_ACTIVE_EVENT, 10) \ | |
34 | x(SYS_IMAGE_GUID, 11) \ | |
35 | x(RC_RNR_NAK_GEN, 12) \ | |
36 | x(SRQ_RESIZE, 13) \ | |
37 | x(N_NOTIFY_CQ, 14) \ | |
38 | x(LOCAL_DMA_LKEY, 15) \ | |
39 | x(MEM_WINDOW, 17) \ | |
40 | x(UD_IP_CSUM, 18) \ | |
41 | x(UD_TSO, 19) \ | |
42 | x(XRC, 20) \ | |
43 | x(MEM_MGT_EXTENSIONS, 21) \ | |
44 | x(BLOCK_MULTICAST_LOOPBACK, 22) \ | |
45 | x(MEM_WINDOW_TYPE_2A, 23) \ | |
46 | x(MEM_WINDOW_TYPE_2B, 24) \ | |
47 | x(RC_IP_CSUM, 25) \ | |
48 | x(RAW_IP_CSUM, 26) \ | |
49 | x(CROSS_CHANNEL, 27) \ | |
50 | x(MANAGED_FLOW_STEERING, 29) \ | |
51 | x(SIGNATURE_HANDOVER, 30) \ | |
52 | x(ON_DEMAND_PAGING, 31) \ | |
53 | x(SG_GAPS_REG, 32) \ | |
54 | x(VIRTUAL_FUNCTION, 33) \ | |
55 | x(RAW_SCATTER_FCS, 34) \ | |
56 | x(RDMA_NETDEV_OPA_VNIC, 35) | |
57 | ||
58 | enum { RDMA_DEV_FLAGS(RDMA_BITMAP_ENUM) }; | |
59 | ||
60 | static const char * const | |
61 | rdma_dev_names[] = { RDMA_DEV_FLAGS(RDMA_BITMAP_NAMES) }; | |
62 | #undef RDMA_DEV_FLAGS | |
63 | ||
64 | if (idx < ARRAY_SIZE(rdma_dev_names) && rdma_dev_names[idx]) | |
65 | return rdma_dev_names[idx]; | |
66 | return "UNKNOWN"; | |
67 | } | |
68 | ||
69 | static void dev_print_caps(struct nlattr **tb) | |
70 | { | |
71 | uint64_t caps; | |
72 | uint32_t idx; | |
73 | ||
74 | if (!tb[RDMA_NLDEV_ATTR_CAP_FLAGS]) | |
75 | return; | |
76 | ||
77 | caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]); | |
78 | ||
79 | pr_out("\n caps: <"); | |
80 | for (idx = 0; caps; idx++) { | |
81 | if (caps & 0x1) { | |
82 | pr_out("%s", dev_caps_to_str(idx)); | |
83 | if (caps >> 0x1) | |
84 | pr_out(", "); | |
85 | } | |
86 | caps >>= 0x1; | |
87 | } | |
88 | ||
89 | pr_out(">"); | |
90 | } | |
91 | ||
92 | static void dev_print_fw(struct nlattr **tb) | |
93 | { | |
94 | if (!tb[RDMA_NLDEV_ATTR_FW_VERSION]) | |
95 | return; | |
96 | ||
97 | pr_out("fw %s ", | |
98 | mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION])); | |
99 | } | |
100 | ||
101 | static void dev_print_node_guid(struct nlattr **tb) | |
102 | { | |
103 | uint64_t node_guid; | |
104 | ||
105 | if (!tb[RDMA_NLDEV_ATTR_NODE_GUID]) | |
106 | return; | |
107 | ||
108 | node_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_NODE_GUID]); | |
109 | rd_print_u64("node_guid", node_guid); | |
110 | } | |
111 | ||
112 | static void dev_print_sys_image_guid(struct nlattr **tb) | |
113 | { | |
114 | uint64_t sys_image_guid; | |
115 | ||
116 | if (!tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID]) | |
117 | return; | |
118 | ||
119 | sys_image_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID]); | |
120 | rd_print_u64("sys_image_guid", sys_image_guid); | |
121 | } | |
122 | ||
123 | static const char *node_type_to_str(uint8_t node_type) | |
124 | { | |
125 | static const char * const node_type_str[] = { "unknown", "ca", | |
126 | "switch", "router", | |
127 | "rnic", "usnic", | |
128 | "usnic_dp" }; | |
129 | if (node_type < ARRAY_SIZE(node_type_str)) | |
130 | return node_type_str[node_type]; | |
131 | return "unknown"; | |
132 | } | |
133 | ||
134 | static void dev_print_node_type(struct nlattr **tb) | |
135 | { | |
136 | uint8_t node_type; | |
137 | ||
138 | if (!tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE]) | |
139 | return; | |
140 | ||
141 | node_type = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE]); | |
142 | pr_out("node_type %s ", node_type_to_str(node_type)); | |
143 | } | |
144 | ||
145 | static int dev_parse_cb(const struct nlmsghdr *nlh, void *data) | |
146 | { | |
147 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; | |
148 | struct rd *rd = data; | |
149 | ||
150 | mnl_attr_parse(nlh, 0, rd_attr_cb, tb); | |
151 | if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME]) | |
152 | return MNL_CB_ERROR; | |
153 | ||
154 | pr_out("%u: %s: ", | |
155 | mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]), | |
156 | mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME])); | |
157 | dev_print_node_type(tb); | |
158 | dev_print_fw(tb); | |
159 | dev_print_node_guid(tb); | |
160 | dev_print_sys_image_guid(tb); | |
161 | if (rd->show_details) | |
162 | dev_print_caps(tb); | |
163 | ||
164 | pr_out("\n"); | |
165 | return MNL_CB_OK; | |
166 | } | |
167 | ||
168 | static int dev_no_args(struct rd *rd) | |
169 | { | |
170 | uint32_t seq; | |
171 | int ret; | |
172 | ||
173 | rd_prepare_msg(rd, RDMA_NLDEV_CMD_GET, | |
174 | &seq, (NLM_F_REQUEST | NLM_F_ACK)); | |
175 | mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx); | |
176 | ret = rd_send_msg(rd); | |
177 | if (ret) | |
178 | return ret; | |
179 | ||
180 | return rd_recv_msg(rd, dev_parse_cb, rd, seq); | |
181 | } | |
182 | ||
183 | static int dev_one_show(struct rd *rd) | |
184 | { | |
185 | const struct rd_cmd cmds[] = { | |
186 | { NULL, dev_no_args}, | |
187 | { 0 } | |
188 | }; | |
189 | ||
190 | return rd_exec_cmd(rd, cmds, "parameter"); | |
191 | } | |
192 | ||
193 | static int dev_show(struct rd *rd) | |
194 | { | |
195 | struct dev_map *dev_map; | |
196 | int ret = 0; | |
197 | ||
198 | if (rd_no_arg(rd)) { | |
199 | list_for_each_entry(dev_map, &rd->dev_map_list, list) { | |
200 | rd->dev_idx = dev_map->idx; | |
201 | ret = dev_one_show(rd); | |
202 | if (ret) | |
203 | return ret; | |
204 | } | |
205 | ||
206 | } else { | |
207 | dev_map = dev_map_lookup(rd, false); | |
208 | if (!dev_map) { | |
209 | pr_err("Wrong device name\n"); | |
210 | return -ENOENT; | |
211 | } | |
212 | rd_arg_inc(rd); | |
213 | rd->dev_idx = dev_map->idx; | |
214 | ret = dev_one_show(rd); | |
215 | } | |
216 | return ret; | |
217 | } | |
218 | ||
219 | int cmd_dev(struct rd *rd) | |
220 | { | |
221 | const struct rd_cmd cmds[] = { | |
222 | { NULL, dev_show }, | |
223 | { "show", dev_show }, | |
224 | { "list", dev_show }, | |
225 | { "help", dev_help }, | |
226 | { 0 } | |
227 | }; | |
228 | ||
229 | return rd_exec_cmd(rd, cmds, "dev command"); | |
230 | } |