blob: eed12110c0cd426e83592fb6dfa89f98cd852cc1 [file] [log] [blame]
/*
* Inject PCIE AER error into Linux kernel for testing
*
* Copyright 2009 Intel Corporation.
* Huang Ying <ying.huang@intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of the
* License.
*/
#include <stdio.h>
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include "aer.h"
#include "util.h"
#define AER_DEV "/dev/aer_inject"
#define CMDLINE_PCI_ID 0x0001
const char *prg_name;
static struct aer_error_inj aerr_cmdline;
static unsigned int cmdline_flags = 0;
void usage(const char *prgname)
{
fprintf(stderr,
"Usage: %s [-s|--id=PCI_ID] [FILE]\n"
" or: %s -v|--version\n"
" or: %s -h|--help\n"
"Inject an error into a PCIe device\n"
"\n"
" PCI_ID The [<domain>:]<bus>:<slot>.<func> of the device in\n"
" hex (same as lspci)\n"
" FILE Error data file (use stdin if ommitted)\n"
, prgname, prgname, prgname);
}
void version(const char *prgname)
{
fprintf(stderr,
"%s %s\n"
"Copyright 2009 Intel Corporation.\n"
"Huang Ying <ying.huang@intel.com>\n"
"\n"
"This program is free software; you can redistribute it and/or\n"
"modify it under the terms of the GNU General Public License as\n"
"published by the Free Software Foundation; version 2 of the\n"
"License.\n"
, prgname, AER_VERSION);
}
void init_aer(struct aer_error_inj *aerr)
{
memset(aerr, 0, sizeof(struct aer_error_inj));
}
void submit_aer(struct aer_error_inj *err)
{
int fd, ret;
if (cmdline_flags & CMDLINE_PCI_ID) {
err->domain = aerr_cmdline.domain;
err->bus = aerr_cmdline.bus;
err->dev = aerr_cmdline.dev;
err->fn = aerr_cmdline.fn;
}
fd = open(AER_DEV, O_WRONLY);
ERROR_EXIT_ON(fd <= 0, "Failed to open device file: %s", AER_DEV);
ret = write(fd, err, sizeof(struct aer_error_inj));
ERROR_EXIT_ON(ret != sizeof(struct aer_error_inj), "Failed to write");
close(fd);
}
int parse_options(int argc, char ***argv)
{
int ret;
int c, opt_index;
struct option long_options[] = {
{"version", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{"id", 1, 0, 's'},
{0, 0, 0, 0}
};
prg_name = basename(*argv[0]);
while (1) {
c = getopt_long(argc, *argv, "vhs:", long_options, &opt_index);
if (c == -1)
break;
switch (c) {
case 0:
break;
case 'v':
version(prg_name);
return 1;
case 's':
ret = parse_pci_id(optarg, &aerr_cmdline);
ERROR_EXIT_ON(ret, "Can not parse PCI_ID: %s\n",
optarg);
cmdline_flags |= CMDLINE_PCI_ID;
break;
case 'h':
case '?':
usage(prg_name);
return 1;
default:
usage(prg_name);
break;
}
}
(*argv) += optind;
return 0;
}
int main(int argc, char **argv)
{
init_aer(&aerr_cmdline);
if (parse_options(argc, &argv))
exit(1);
return parse_data(argv);
}