Skip to content

Commit 66ad0d2

Browse files
committed
FPGA Image Tools: fpga-describe-local-image outputs the SH version + supporting MBOX HAL changes. Also added rescan option for future use
1 parent 01e344d commit 66ad0d2

File tree

8 files changed

+258
-17
lines changed

8 files changed

+258
-17
lines changed

sdk/management/fpga_image_tools/src/fpga_local_cmd.c

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,56 @@ cli_show_slot_app_pfs(uint32_t afi_slot)
124124
return -1;
125125
}
126126

127+
/**
128+
* Rescan the application PF map info for the given AFI slot.
129+
*
130+
* @param[in] afi_slot the fpga slot
131+
*
132+
* @returns
133+
* 0 on success
134+
* -1 on failure
135+
*/
136+
static int
137+
cli_rescan_slot_app_pfs(uint32_t afi_slot)
138+
{
139+
fail_on_quiet(afi_slot >= FPGA_SLOT_MAX, err, CLI_INTERNAL_ERR_STR);
140+
141+
/** Retrieve and display associated application PFs (if any) */
142+
bool found_app_pf = false;
143+
int ret;
144+
int i;
145+
for (i = F1_APP_PF_START; i <= F1_APP_PF_END; i++) {
146+
struct fpga_pci_resource_map app_map;
147+
148+
/**
149+
* cli_get_app_pf_map will skip the Mbox PF (ret==1).
150+
* We continue up through F1_APP_PF_END (e.g. 15) for future
151+
* compatibilty with any gaps in the PF numbering.
152+
*/
153+
ret = cli_get_app_pf_map(afi_slot, i, &app_map);
154+
if (ret == 0) {
155+
ret = cli_remove_app_pf(afi_slot, app_map.func);
156+
if (ret != 0) {
157+
/** Output an error but continue with the other app PFs */
158+
printf("Error: could not remove application PF device "
159+
PCI_DEV_FMT "\n",
160+
app_map.domain, app_map.bus, app_map.dev,
161+
app_map.func);
162+
}
163+
found_app_pf = true;
164+
}
165+
}
166+
if (found_app_pf) {
167+
ret = cli_pci_rescan();
168+
fail_on_user(ret != 0, err,
169+
"Error: could not rescan for application PF devices");
170+
}
171+
172+
return 0;
173+
err:
174+
return -1;
175+
}
176+
127177
/**
128178
* Attach for CLI processing.
129179
*
@@ -533,6 +583,7 @@ handle_afi_cmd_metrics_rsp(const union afi_cmd *cmd,
533583
(void)cmd;
534584
/** We've already validated the header... */
535585
struct afi_cmd_metrics_rsp *metrics = (void *)rsp->body;
586+
int ret;
536587

537588
uint32_t tmp_len =
538589
sizeof(struct afi_cmd_hdr) + sizeof(struct afi_cmd_metrics_rsp);
@@ -541,7 +592,7 @@ handle_afi_cmd_metrics_rsp(const union afi_cmd *cmd,
541592
len, tmp_len);
542593

543594
if (f1.show_headers) {
544-
printf("Type FpgaImageSlot FpgaImageId StatusName StatusCode\n");
595+
printf("Type FpgaImageSlot FpgaImageId StatusName StatusCode ShVersion\n");
545596
}
546597

547598
char *afi_id = (!metrics->ids.afi_id[0]) ? "none" : metrics->ids.afi_id;
@@ -551,10 +602,22 @@ handle_afi_cmd_metrics_rsp(const union afi_cmd *cmd,
551602
if ((metrics->status < ACMS_END) && acms_tbl[metrics->status]) {
552603
status_name = (void *)acms_tbl[metrics->status];
553604
}
554-
printf(" %-8s %2u\n", status_name, metrics->status);
605+
606+
struct fpga_hal_mbox_versions ver;
607+
ret = fpga_hal_mbox_get_versions(&ver);
608+
fail_on_quiet(ret != 0, err, "fpga_hal_mbox_get_versions failed");
609+
610+
printf(" %-8s %2u 0x%08x\n",
611+
status_name, metrics->status, ver.sh_version);
612+
613+
if (f1.rescan) {
614+
/** Rescan the application PFs for this slot */
615+
ret = cli_rescan_slot_app_pfs(f1.afi_slot);
616+
fail_on_quiet(ret != 0, err, "cli_rescan_slot_app_pfs failed");
617+
}
555618

556619
/** Display the application PFs for this slot */
557-
int ret = cli_show_slot_app_pfs(f1.afi_slot);
620+
ret = cli_show_slot_app_pfs(f1.afi_slot);
558621
fail_on_quiet(ret != 0, err, "cli_show_slot_app_pfs failed");
559622

560623
return 0;

sdk/management/fpga_image_tools/src/fpga_local_cmd.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ struct ec2_fpga_cmd {
120120
bool show_headers;
121121
bool get_hw_metrics;
122122
bool clear_hw_metrics;
123+
bool rescan;
123124
};
124125

125126
extern struct ec2_fpga_cmd f1;
@@ -160,3 +161,26 @@ void cli_pci_free(void);
160161
*/
161162
int cli_get_app_pf_map(uint32_t slot, uint32_t app_pf_num,
162163
struct fpga_pci_resource_map *map);
164+
165+
/**
166+
* Remove the application PF for the given mbox slot.
167+
*
168+
* @param[in] slot the fpga slot
169+
* @param[in] app_pf_num the application PF number to check
170+
*
171+
* @returns
172+
* 0 on success
173+
* -1 on failure
174+
*/
175+
int
176+
cli_remove_app_pf(uint32_t slot, uint32_t app_pf_num);
177+
178+
/**
179+
* PCI rescan.
180+
*
181+
* @returns
182+
* 0 on success
183+
* -1 on failure
184+
*/
185+
int
186+
cli_pci_rescan(void);

sdk/management/fpga_image_tools/src/fpga_local_cmd_parse.c

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ static const char *describe_afi_usage[] = {
8282
" -S, --fpga-image-slot",
8383
" The logical slot number for the FPGA image.",
8484
" Constraints: Positive integer from 0 to the total slots minus 1.",
85+
" -R --rescan",
86+
" Rescan the AFIDEVICE to update the per-AFI PCI VendorId and",
87+
" DeviceId that may be dynamically modified due to a",
88+
" fpga-load-local-image or fpga-clear-local-image command.",
89+
" NOTE: this option removes the AFIDEVICE from the sysfs PCI",
90+
" subsystem and then rescans the PCI subsystem in order for",
91+
" the modified AFI PCI IDs to be refreshed.",
8592
" -?, --help",
8693
" Display this help.",
8794
" -H, --headers",
@@ -224,15 +231,15 @@ parse_args_load_afi(int argc, char *argv[])
224231
static struct option long_options[] = {
225232
{"fpga-image-slot", required_argument, 0, 'S' },
226233
{"fpga-image-id", required_argument, 0, 'I' },
227-
{"request-timeout", required_argument, 0, 'R' },
234+
{"request-timeout", required_argument, 0, 'r' },
228235
{"headers", no_argument, 0, 'H' },
229236
{"help", no_argument, 0, '?' },
230237
{"version", no_argument, 0, 'V' },
231238
{0, 0, 0, 0 },
232239
};
233240

234241
int long_index = 0;
235-
while ((opt = getopt_long(argc, argv, "S:I:R:H?hV",
242+
while ((opt = getopt_long(argc, argv, "S:I:r:H?hV",
236243
long_options, &long_index)) != -1) {
237244
switch (opt) {
238245
case 'S': {
@@ -249,7 +256,7 @@ parse_args_load_afi(int argc, char *argv[])
249256
f1.afi_id[sizeof(f1.afi_id) - 1] = 0;
250257
break;
251258
}
252-
case 'R': {
259+
case 'r': {
253260
uint32_t value32;
254261
string_to_uint(&value32, optarg);
255262
int ret = config_request_timeout(value32);
@@ -295,15 +302,15 @@ parse_args_clear_afi(int argc, char *argv[])
295302

296303
static struct option long_options[] = {
297304
{"fpga-image-slot", required_argument, 0, 'S' },
298-
{"request-timeout", required_argument, 0, 'R' },
305+
{"request-timeout", required_argument, 0, 'r' },
299306
{"headers", no_argument, 0, 'H' },
300307
{"help", no_argument, 0, '?' },
301308
{"version", no_argument, 0, 'V' },
302309
{0, 0, 0, 0 },
303310
};
304311

305312
int long_index = 0;
306-
while ((opt = getopt_long(argc, argv, "S:R:H?hV",
313+
while ((opt = getopt_long(argc, argv, "S:r:H?hV",
307314
long_options, &long_index)) != -1) {
308315
switch (opt) {
309316
case 'S': {
@@ -312,7 +319,7 @@ parse_args_clear_afi(int argc, char *argv[])
312319
FPGA_SLOT_MAX);
313320
break;
314321
}
315-
case 'R': {
322+
case 'r': {
316323
uint32_t value32;
317324
string_to_uint(&value32, optarg);
318325
int ret = config_request_timeout(value32);
@@ -357,15 +364,16 @@ parse_args_describe_afi(int argc, char *argv[])
357364

358365
static struct option long_options[] = {
359366
{"fpga-image-slot", required_argument, 0, 'S' },
360-
{"request-timeout", required_argument, 0, 'R' },
367+
{"request-timeout", required_argument, 0, 'r' },
368+
{"rescan", no_argument, 0, 'R' },
361369
{"headers", no_argument, 0, 'H' },
362370
{"help", no_argument, 0, '?' },
363371
{"version", no_argument, 0, 'V' },
364372
{0, 0, 0, 0 },
365373
};
366374

367375
int long_index = 0;
368-
while ((opt = getopt_long(argc, argv, "S:MCR:H?hV",
376+
while ((opt = getopt_long(argc, argv, "S:r:RH?hV",
369377
long_options, &long_index)) != -1) {
370378
switch (opt) {
371379
case 'S': {
@@ -374,13 +382,17 @@ parse_args_describe_afi(int argc, char *argv[])
374382
"fpga-image-slot must be less than %u", FPGA_SLOT_MAX);
375383
break;
376384
}
377-
case 'R': {
385+
case 'r': {
378386
uint32_t value32;
379387
string_to_uint(&value32, optarg);
380388
int ret = config_request_timeout(value32);
381389
fail_on_quiet(ret != 0, err, "Could not configure the request-timeout");
382390
break;
383391
}
392+
case 'R': {
393+
f1.rescan = true;
394+
break;
395+
}
384396
case 'H': {
385397
f1.show_headers = true;
386398
break;
@@ -418,18 +430,18 @@ parse_args_describe_afi_slots(int argc, char *argv[])
418430
int opt = 0;
419431

420432
static struct option long_options[] = {
421-
{"request-timeout", required_argument, 0, 'R' },
433+
{"request-timeout", required_argument, 0, 'r' },
422434
{"headers", no_argument, 0, 'H' },
423435
{"help", no_argument, 0, '?' },
424436
{"version", no_argument, 0, 'V' },
425437
{0, 0, 0, 0 },
426438
};
427439

428440
int long_index = 0;
429-
while ((opt = getopt_long(argc, argv, "R:H?hV",
441+
while ((opt = getopt_long(argc, argv, "r:H?hV",
430442
long_options, &long_index)) != -1) {
431443
switch (opt) {
432-
case 'R': {
444+
case 'r': {
433445
uint32_t value32;
434446
string_to_uint(&value32, optarg);
435447
int ret = config_request_timeout(value32);

sdk/management/fpga_image_tools/src/fpga_local_cmd_pci_sysfs.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include <assert.h>
2121
#include <limits.h>
22+
#include <fcntl.h>
23+
#include <unistd.h>
2224
#include <sys/types.h>
2325
#include <sys/stat.h>
2426
#include <stdlib.h>
@@ -227,6 +229,112 @@ cli_get_app_pf_map(uint32_t slot, uint32_t app_pf_num,
227229
return -1;
228230
}
229231

232+
/**
233+
* Write a '1' to the given sysfs file.
234+
*
235+
* @param[in] path the sysfs file path
236+
*
237+
* @returns
238+
* 0 on success
239+
* -1 on failure
240+
*/
241+
static int
242+
cli_write_one2file(char *path)
243+
{
244+
int ret = -1;
245+
246+
int fd = open(path, O_WRONLY);
247+
fail_on_quiet(fd == -1, err, "opening %s", path);
248+
249+
char buf[] = { '1', 0 };
250+
ret = -!!write_loop(fd, buf, sizeof(buf));
251+
fail_on_quiet(ret != 0, err_close, "error writing %s", path);
252+
253+
err_close:
254+
close(fd);
255+
err:
256+
return ret;
257+
}
258+
259+
/**
260+
* Remove the application PF for the given mbox slot.
261+
*
262+
* @param[in] slot the fpga slot
263+
* @param[in] app_pf_num the application PF number to check
264+
*
265+
* @returns
266+
* 0 on success
267+
* -1 on failure
268+
*/
269+
int
270+
cli_remove_app_pf(uint32_t slot, uint32_t app_pf_num)
271+
{
272+
fail_on_quiet(slot >= FPGA_SLOT_MAX, err, CLI_INTERNAL_ERR_STR);
273+
fail_on_quiet(app_pf_num > F1_APP_PF_END, err, CLI_INTERNAL_ERR_STR);
274+
275+
/** Setup pointers to the mbox and associated PCI resource maps */
276+
struct fpga_pci_resource_map *mbox_map = &f1.mbox_slot_devs[slot].map;
277+
278+
/** Construct the PCI device directory name using the PCI_DEV_FMT */
279+
char dir_name[NAME_MAX + 1];
280+
int ret = snprintf(dir_name, sizeof(dir_name), PCI_DEV_FMT,
281+
mbox_map->domain, mbox_map->bus, mbox_map->dev, app_pf_num);
282+
283+
fail_on_quiet(ret < 0, err, "Error building the dir_name");
284+
fail_on_quiet((size_t) ret >= sizeof(dir_name), err, "dir_name too long");
285+
286+
/** Setup the path to the device's remove file */
287+
char sysfs_name[NAME_MAX + 1];
288+
ret = snprintf(sysfs_name, sizeof(sysfs_name),
289+
"/sys/bus/pci/devices/%s/remove", dir_name);
290+
291+
fail_on_quiet(ret < 0, err,
292+
"Error building the sysfs path for remove file");
293+
fail_on_quiet((size_t) ret >= sizeof(sysfs_name), err,
294+
"sysfs path too long for remove file");
295+
296+
/** Write a "1" to the device's remove file */
297+
ret = cli_write_one2file(sysfs_name);
298+
fail_on_quiet(ret != 0, err, "cli_write_one2file failed");
299+
300+
/** Check for file existence, should fail */
301+
struct stat file_stat;
302+
ret = stat(sysfs_name, &file_stat);
303+
fail_on_quiet(ret == 0, err, "remove failed for path=%s", sysfs_name);
304+
305+
return 0;
306+
err:
307+
return -1;
308+
}
309+
310+
/**
311+
* PCI rescan.
312+
*
313+
* @returns
314+
* 0 on success
315+
* -1 on failure
316+
*/
317+
int
318+
cli_pci_rescan(void)
319+
{
320+
/** Setup and write '1' to the PCI rescan file */
321+
char sysfs_name[NAME_MAX + 1];
322+
int ret = snprintf(sysfs_name, sizeof(sysfs_name), "/sys/bus/pci/rescan");
323+
324+
fail_on_quiet(ret < 0, err,
325+
"Error building the sysfs path for PCI rescan file");
326+
fail_on_quiet((size_t) ret >= sizeof(sysfs_name), err,
327+
"sysfs path too long for PCI rescan file");
328+
329+
/** Write a "1" to the PCI rescan file */
330+
ret = cli_write_one2file(sysfs_name);
331+
fail_on_quiet(ret != 0, err, "cli_write_one2file failed");
332+
333+
return 0;
334+
err:
335+
return -1;
336+
}
337+
230338
/**
231339
* Handle one PCI device directory with the given directory name, and see if
232340
* it is an AFI mbox slot. If so, initialize a slot device structure for it

0 commit comments

Comments
 (0)