From e5127339c6c48ae6f63f9dc841a94fe960d11496 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 31 Jul 2009 16:15:55 +1000 Subject: vgaarb: change API to target taking a device + lock/unlock not taking one working on the target device - a target device of NULL reselects the target that existed when we started. this is mainly to allow a udev posting tool to return to the state of what happened before it ran. --- include/pciaccess.h | 9 +-- src/common_vgaarb.c | 171 +++++++++++++++++++++++++++++++----------------- src/pciaccess_private.h | 2 + 3 files changed, 119 insertions(+), 63 deletions(-) diff --git a/include/pciaccess.h b/include/pciaccess.h index 9d68a08..71c831e 100644 --- a/include/pciaccess.h +++ b/include/pciaccess.h @@ -497,9 +497,10 @@ struct pci_pcmcia_bridge_info { int pci_device_vgaarb_init (void); void pci_device_vgaarb_fini (void); int pci_device_vgaarb_set_target (struct pci_device *dev); -int pci_device_vgaarb_decodes (struct pci_device *dev, int new_vga_rsrc); -int pci_device_vgaarb_lock (struct pci_device *dev); -int pci_device_vgaarb_trylock (struct pci_device *dev); -int pci_device_vgaarb_unlock (struct pci_device *dev); +/* use the targetted device */ +int pci_device_vgaarb_decodes (int new_vga_rsrc); +int pci_device_vgaarb_lock (void); +int pci_device_vgaarb_trylock (void); +int pci_device_vgaarb_unlock (void); #endif /* PCIACCESS_H */ diff --git a/src/common_vgaarb.c b/src/common_vgaarb.c index 79d3f93..5d46d70 100644 --- a/src/common_vgaarb.c +++ b/src/common_vgaarb.c @@ -38,13 +38,98 @@ #define BUFSIZE 64 +static int +parse_string_to_decodes_rsrc(char *input, int *vga_count, struct pci_slot_match *match) +{ + char *tok; + char count[16]; + + strncpy(count, input, 10); + count[11] = 0; + + tok = strtok(count,":"); + if (!tok) + goto fail; + tok = strtok(NULL, ""); + if (!tok) + goto fail; + + *vga_count = strtoul(tok, NULL, 10); + if (*vga_count == LONG_MAX) + goto fail; + +#ifdef DEBUG + fprintf(stderr,"vga count is %d\n", *vga_count); +#endif + + tok = strtok(input, ","); + if (!tok) + goto fail; + + if (match) { + tok = strtok(NULL, ":"); + if (!tok) + goto fail; + match->domain = strtoul(tok, NULL, 16); + + tok = strtok(NULL, ":"); + if (!tok) + goto fail; + match->bus = strtoul(tok, NULL, 16); + + tok = strtok(NULL, "."); + if (!tok) + goto fail; + match->dev = strtoul(tok, NULL, 16); + + tok = strtok(NULL, "."); + if (!tok) + goto fail; + match->func = strtoul(tok, NULL, 16); + } + + tok = strtok(NULL, ","); + if (!tok) + goto fail; + tok = strtok(tok, "="); + if (!tok) + goto fail; + tok = strtok(NULL, "="); + if (!tok) + goto fail; + + if (!strncmp(tok, "io+mem", 6)) + return VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM; + if (!strncmp(tok, "io", 2)) + return VGA_ARB_RSRC_LEGACY_IO; + if (!strncmp(tok, "mem", 3)) + return VGA_ARB_RSRC_LEGACY_MEM; +fail: + return VGA_ARB_RSRC_NONE; +} + int pci_device_vgaarb_init(void) { + struct pci_slot_match match; + char buf[BUFSIZE]; + int ret, rsrc; if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR)) < 0) { return errno; } + ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE); + if (ret <= 0) + return -1; + + memset(&match, 0xff, sizeof(match)); + /* need to find the device to go back to and what it was decoding */ + rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, &match); + + pci_sys->vga_default_dev = pci_device_find_by_slot(match.domain, match.bus, match.dev, match.func); + + if (pci_sys->vga_default_dev) + pci_sys->vga_default_dev->vgaarb_rsrc = rsrc; return 0; } @@ -100,53 +185,6 @@ vgaarb_write(int fd, char *buf, int len) return 0; } -static int -parse_string_to_decodes_rsrc(char *input, int *vga_count) -{ - char *tok; - char count[16]; - - strncpy(count, input, 10); - count[11] = 0; - - tok = strtok(count,":"); - if (!tok) - goto fail; - tok = strtok(NULL, ""); - if (!tok) - goto fail; - - *vga_count = strtoul(tok, NULL, 10); - if (*vga_count == LONG_MAX) - goto fail; - -#ifdef DEBUG - fprintf(stderr,"vga count is %d\n", *vga_count); -#endif - - tok = strtok(input, ","); - if (!tok) - goto fail; - - tok = strtok(NULL, ","); - if (!tok) - goto fail; - tok = strtok(tok, "="); - if (!tok) - goto fail; - tok = strtok(NULL, "="); - if (!tok) - goto fail; - - if (!strncmp(tok, "io+mem", 6)) - return VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM; - if (!strncmp(tok, "io", 2)) - return VGA_ARB_RSRC_LEGACY_IO; - if (!strncmp(tok, "mem", 3)) - return VGA_ARB_RSRC_LEGACY_MEM; -fail: - return VGA_ARB_RSRC_NONE; -} static const char * rsrc_to_str(int iostate) @@ -169,13 +207,14 @@ pci_device_vgaarb_set_target(struct pci_device *dev) int len; char buf[BUFSIZE]; int ret; - int rsrc; if (!dev) - len = snprintf(buf, BUFSIZE, "default"); - else - len = snprintf(buf, BUFSIZE, "target PCI:%d:%d:%d.%d", - dev->domain, dev->bus, dev->dev, dev->func); + dev = pci_sys->vga_default_dev; + if (!dev) + return -1; + + len = snprintf(buf, BUFSIZE, "target PCI:%d:%d:%d.%d", + dev->domain, dev->bus, dev->dev, dev->func); ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len); if (ret) @@ -185,19 +224,21 @@ pci_device_vgaarb_set_target(struct pci_device *dev) if (ret <= 0) return -1; - rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count); - if (dev) - dev->vgaarb_rsrc = rsrc; + dev->vgaarb_rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, NULL); + pci_sys->vga_target = dev; return 0; } int -pci_device_vgaarb_decodes(struct pci_device *dev, int new_vgaarb_rsrc) +pci_device_vgaarb_decodes(int new_vgaarb_rsrc) { int len; char buf[BUFSIZE]; int ret; + struct pci_device *dev = pci_sys->vga_target; + if (!dev) + return -1; if (dev->vgaarb_rsrc == new_vgaarb_rsrc) return 0; @@ -209,10 +250,14 @@ pci_device_vgaarb_decodes(struct pci_device *dev, int new_vgaarb_rsrc) } int -pci_device_vgaarb_lock(struct pci_device *dev) +pci_device_vgaarb_lock(void) { int len; char buf[BUFSIZE]; + struct pci_device *dev = pci_sys->vga_target; + + if (!dev) + return -1; if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1) return 0; @@ -223,10 +268,14 @@ pci_device_vgaarb_lock(struct pci_device *dev) } int -pci_device_vgaarb_trylock(struct pci_device *dev) +pci_device_vgaarb_trylock(void) { int len; char buf[BUFSIZE]; + struct pci_device *dev = pci_sys->vga_target; + + if (!dev) + return -1; if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1) return 0; @@ -237,10 +286,14 @@ pci_device_vgaarb_trylock(struct pci_device *dev) } int -pci_device_vgaarb_unlock(struct pci_device *dev) +pci_device_vgaarb_unlock(void) { int len; char buf[BUFSIZE]; + struct pci_device *dev = pci_sys->vga_target; + + if (!dev) + return -1; if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1) return 0; diff --git a/src/pciaccess_private.h b/src/pciaccess_private.h index b97d31b..a9d8df0 100644 --- a/src/pciaccess_private.h +++ b/src/pciaccess_private.h @@ -134,6 +134,8 @@ struct pci_system { #endif int vgaarb_fd; int vga_count; + struct pci_device *vga_target; + struct pci_device *vga_default_dev; }; extern struct pci_system * pci_sys; -- cgit v1.2.3