summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2012-03-16 15:41:29 -0700
committerStephen Hemminger <shemminger@vyatta.com>2012-03-16 15:41:29 -0700
commit3dcf4140386b3e63955790d87093521f021bedee (patch)
tree1d1eeb5723da2b0a9c6cc1e848824010c16fc6bb
parent868f348533d99b05782cd8bfedb18b9f91b393bc (diff)
downloadvyatta-biosdevname-3dcf4140386b3e63955790d87093521f021bedee.tar.gz
vyatta-biosdevname-3dcf4140386b3e63955790d87093521f021bedee.zip
Add option to search for device based on pci-id
To support case where device is not in kernel (userspace networking) need a method for finding device by pci-id. Biosdevname was already building the table, this just adds an alternative lookup algorithm.
-rw-r--r--src/bios_dev_name.c43
-rw-r--r--src/bios_dev_name.h2
-rw-r--r--src/bios_device.c32
-rw-r--r--src/libbiosdevname.h1
-rw-r--r--src/pci.c2
-rw-r--r--src/pci.h1
6 files changed, 66 insertions, 15 deletions
diff --git a/src/bios_dev_name.c b/src/bios_dev_name.c
index dd47fc3..ae994ab 100644
--- a/src/bios_dev_name.c
+++ b/src/bios_dev_name.c
@@ -24,6 +24,7 @@ static void usage(void)
fprintf(stderr, "Usage: biosdevname [options] [args]...\n");
fprintf(stderr, " Options:\n");
fprintf(stderr, " -i or --interface treat [args] as ethernet devs\n");
+ fprintf(stderr, " --pci-spec treat [args] as PCI specification\n");
fprintf(stderr, " -d or --debug enable debugging\n");
fprintf(stderr, " --policy [physical | all_ethN ]\n");
fprintf(stderr, " --prefix [string] string use for embedded NICs (default='em')\n");
@@ -36,6 +37,12 @@ static void usage(void)
fprintf(stderr, " You must be root to run this, as it must read from /dev/mem.\n");
}
+static void conflict(void)
+{
+ fprintf(stderr, "can't use both interface and pci options\n");
+ exit(1);
+}
+
static int
set_policy(const char *arg)
{
@@ -65,6 +72,7 @@ parse_opts(int argc, char **argv)
{"nopirq", no_argument, 0, 'x'},
{"invm", no_argument, 0, 'V'},
{"smbios", required_argument, 0, 's'},
+ {"pci-spec", no_argument, 0, 'S'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
@@ -77,8 +85,15 @@ parse_opts(int argc, char **argv)
opts.debug = 1;
break;
case 'i':
+ if (opts.usepci)
+ conflict();
opts.interface = 1;
break;
+ case 'S':
+ if (opts.interface)
+ conflict();
+ opts.usepci = 1;
+ break;
case 'p':
opts.namingpolicy = set_policy(optarg);
break;
@@ -172,21 +187,29 @@ int main(int argc, char *argv[])
goto out_cleanup;
}
-
- if (!opts.interface) {
+ if (opts.interface) {
+ for (i=0; i<opts.argc; i++) {
+ name = kern_to_bios(cookie, opts.argv[i]);
+ if (name)
+ printf("%s\n", name);
+ else
+ rc |= 2; /* one or more given devices weren't found */
+ }
+ } else if(opts.usepci) {
+ for (i=0; i<opts.argc; i++) {
+ name = pci_to_bios(cookie, opts.argv[i]);
+ if (name)
+ printf("%s\n", name);
+ else
+ rc |= 2;
+ }
+ } else {
fprintf(stderr, "Unknown device type, try passing an option like -i\n");
rc = 1;
goto out_usage;
}
- for (i=0; i<opts.argc; i++) {
- name = kern_to_bios(cookie, opts.argv[i]);
- if (name) {
- printf("%s\n", name);
- }
- else
- rc |= 2; /* one or more given devices weren't found */
- }
+
goto out_cleanup;
out_usage:
diff --git a/src/bios_dev_name.h b/src/bios_dev_name.h
index 636c5e1..98197d4 100644
--- a/src/bios_dev_name.h
+++ b/src/bios_dev_name.h
@@ -15,6 +15,6 @@ struct bios_dev_name_opts {
const char *prefix;
unsigned int debug:1;
unsigned int interface:1;
+ unsigned int usepci:1;
};
-
#endif /* GLUE_H_INCLUDED */
diff --git a/src/bios_device.c b/src/bios_device.c
index 24b0a77..e04c5b9 100644
--- a/src/bios_device.c
+++ b/src/bios_device.c
@@ -89,6 +89,33 @@ char * kern_to_bios(void *cookie,
return NULL;
}
+char * pci_to_bios(void *cookie, const char *s)
+{
+ struct libbiosdevname_state *state = cookie;
+ struct bios_device *dev;
+ int domain=0, bus=0, device=0, func=0;
+
+ if (parse_pci_name(s, &domain, &bus, &device, &func)) {
+ fprintf(stderr, "%s is not a valid pci device name\n", s);
+ return NULL;
+ }
+
+ if (!state)
+ return NULL;
+
+ list_for_each_entry(dev, &state->bios_devices, node) {
+ const struct pci_device *pci = dev->pcidev;
+
+ if(pci &&
+ pci->pci_dev->domain == domain &&
+ pci->pci_dev->bus == bus &&
+ pci->pci_dev->dev == device &&
+ pci->pci_dev->func == func)
+ return dev->bios_name;
+ }
+ return NULL;
+}
+
void unparse_bios_device_list(void *cookie)
{
struct libbiosdevname_state *state = cookie;
@@ -220,8 +247,6 @@ static void match_eth_and_pci_devs(struct libbiosdevname_state *state)
unparse_pci_name(pci_name, sizeof(pci_name), p->pci_dev);
n = find_net_device_by_bus_info(state, pci_name);
- if (!n)
- continue;
b = malloc(sizeof(*b));
if (!b)
@@ -230,7 +255,8 @@ static void match_eth_and_pci_devs(struct libbiosdevname_state *state)
INIT_LIST_HEAD(&b->node);
b->pcidev = p;
b->netdev = n;
- claim_netdev(b->netdev);
+ if (n)
+ claim_netdev(b->netdev);
list_add(&b->node, &state->bios_devices);
}
}
diff --git a/src/libbiosdevname.h b/src/libbiosdevname.h
index 37eccb1..505b234 100644
--- a/src/libbiosdevname.h
+++ b/src/libbiosdevname.h
@@ -14,6 +14,7 @@ enum namingpolicy {
extern void * setup_bios_devices(int namingpolicy, const char *prefix);
extern void cleanup_bios_devices(void *cookie);
extern char * kern_to_bios(void *cookie, const char *devname);
+extern char * pci_to_bios(void *cookie, const char *spec);
extern void unparse_bios_devices(void *cookie);
extern void unparse_bios_device_by_name(void *cookie, const char *name);
diff --git a/src/pci.c b/src/pci.c
index 9b9703a..31b4457 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -365,7 +365,7 @@ static int read_virtfn_index(unsigned int *index, const struct pci_dev *pdev)
return rc;
}
-static int parse_pci_name(const char *s, int *domain, int *bus, int *dev, int *func)
+int parse_pci_name(const char *s, int *domain, int *bus, int *dev, int *func)
{
int err;
/* The domain part was added in 2.6 kernels. Test for that first. */
diff --git a/src/pci.h b/src/pci.h
index 374f7b3..9c21d5c 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -57,6 +57,7 @@ extern void free_pci_devices(struct libbiosdevname_state *state);
extern struct pci_device * find_dev_by_pci(const struct libbiosdevname_state *state, const struct pci_dev *p);
extern struct pci_device * find_pci_dev_by_pci_addr(const struct libbiosdevname_state *state, const int domain, const int bus, const int device, const int func);
extern struct pci_device * find_dev_by_pci_name(const struct libbiosdevname_state *state, const char *s);
+extern int parse_pci_name(const char *s, int *domain, int *bus, int *dev, int *func);
extern int unparse_pci_device(char *buf, const int size, const struct pci_device *p);
extern int unparse_pci_name(char *buf, int size, const struct pci_dev *pdev);