| // SPDX-License-Identifier: GPL-2.0 |
| |
| /* |
| * Copyright (C) 2023 Alibaba Corporation |
| * Authors: Shuai Xue |
| * |
| * This software may be redistributed and/or modified under the terms of |
| * the GNU General Public License ("GPL") version 2 only as published by the |
| * Free Software Foundation. |
| */ |
| |
| #include "einj.h" |
| |
| char *progname; |
| int Sflag; |
| long pagesize; |
| |
| static void check_configuration(void) |
| { |
| if (!is_privileged() || !is_einj_support()) |
| exit(1); |
| } |
| |
| static void inject_pcie_error(unsigned long long type, int sbdf) |
| { |
| wfile(EINJ_ETYPE, type); |
| wfile(EINJ_SBDF, sbdf); |
| wfile(EINJ_FLAGS, 0x4); |
| wfile(EINJ_NOTRIGGER, 0); |
| wfile(EINJ_DOIT, 1); |
| } |
| |
| static int split(char dst[][16], const char *str, const char *spl) |
| { |
| int count = 0; |
| char *ret; |
| char *tmp = strdup(str); |
| |
| while ((ret = strsep(&tmp, spl))) { |
| if (!(*ret)) |
| continue; |
| strcpy(dst[count++], ret); |
| } |
| free(tmp); |
| return count; |
| } |
| |
| static int slot2sbdf(const char *slot) |
| { |
| char bdf[3][16]; |
| int bus, dev, func, bdf_count; |
| |
| /* get bus, device and function */ |
| bdf_count = split(bdf, slot, ":."); |
| if (bdf_count != 3) { |
| printf("invalid bdf, please check!\n"); |
| return -EINVAL; |
| } |
| sscanf(bdf[0], "%x", &bus); |
| sscanf(bdf[1], "%x", &dev); |
| sscanf(bdf[2], "%x", &func); |
| |
| return (bus << 16) | (dev << 11) | (func << 8); |
| } |
| |
| |
| static void show_help(void) |
| { |
| struct test *t; |
| |
| printf("Usage: %s [-s slot][-t type]\n", progname); |
| printf(" e.g. inject non-fatal into rootport\n"); |
| printf(" ./einj_pcie_err -s 7b:05.0 -t 0x80\n"); |
| |
| exit(0); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int rp_sbdf, c; |
| char *bdf, *type_name; |
| unsigned long long type; |
| |
| progname = argv[0]; |
| check_configuration(); |
| |
| while ((c = getopt(argc, argv, "s:t:")) != -1) |
| switch (c) { |
| case 's': |
| bdf = strdup(optarg); |
| rp_sbdf = slot2sbdf(optarg); |
| break; |
| case 't': |
| type = strtol(optarg, NULL, 0); |
| type_name = lookup_type_name(type); |
| break; |
| case 'h': case '?': |
| show_help(); |
| } |
| printf("Injecting %s into Rootport %s (%x)\n", type_name, bdf, rp_sbdf); |
| |
| inject_pcie_error(type, rp_sbdf); |
| |
| return 0; |
| } |