On Tue, Dec 15, 2009 at 07:30:28PM +0100, Alexander Graf wrote: > When using -pcidevice on a device that is already in use by a kernel driver > all the user gets is the following (very useful) information: > > Failed to assign device "04:00.0" : Device or resource busy > Failed to deassign device "04:00.0" : Invalid argument > Error initializing device pci-assign > > Since I usually prefer to have my computer do the thinking for me, I figured > it might be a good idea to check and see if a device is actually used by a > driver. If so, tell the user. > > So with this patch applied you get the following output: > > Failed to assign device "04:00.0" : Device or resource busy > *** The driver 'igb' is occupying your device 04:00.0. > *** > *** You can try the following commands to free it: > *** > *** $ echo "8086 150a" > /sys/bus/pci/drivers/pci-stub/new_id > *** $ echo "0000:04:00.0" > /sys/bus/pci/drivers/igb/unbind > *** $ echo "0000:04:00.0" > /sys/bus/pci/drivers/pci-stub/bind > *** $ echo "8086 150a" > /sys/bus/pci/drivers/pci-stub/remove_id > *** > Failed to deassign device "04:00.0" : Invalid argument > Error initializing device pci-assign > > That should keep people like me from doing the most obvious misuses :-). > > CC: Daniel P. Berrange <berrange@xxxxxxxxxx> > Signed-off-by: Alexander Graf <agraf@xxxxxxx> Acked-by: Michael S. Tsirkin <mst@xxxxxxxxxx> > --- > > v1 -> v2: > > - add more helpful guidance thanks to Daniel Berrange > > v2 -> v3: > > - clear name variable before using it, thus 0-terminating the string > - fix region numbers > - use correct unbind/bind names > > v3 -> v4: > > - split id retrieval part > - mst comments > --- > hw/device-assignment.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++- > 1 files changed, 53 insertions(+), 2 deletions(-) > > diff --git a/hw/device-assignment.c b/hw/device-assignment.c > index 566671c..d7a03c9 100644 > --- a/hw/device-assignment.c > +++ b/hw/device-assignment.c > @@ -756,6 +756,54 @@ static uint32_t calc_assigned_dev_id(uint8_t bus, uint8_t devfn) > return (uint32_t)bus << 8 | (uint32_t)devfn; > } > > +static void assign_failed_examine(AssignedDevice *dev) > +{ > + char name[PATH_MAX], dir[PATH_MAX], driver[PATH_MAX] = {}, *ns; > + uint16_t vendor_id, device_id; > + int r; > + > + /* XXX implement multidomain */ > + sprintf(dir, "/sys/bus/pci/devices/0000:%02x:%02x.%01x/", > + dev->host.bus, dev->host.dev, dev->host.func); > + > + sprintf(name, "%sdriver", dir); > + > + r = readlink(name, driver, sizeof(driver)); > + if ((r <= 0) || !(ns = strrchr(driver, '/')) || r >= sizeof(driver)) { > + goto fail; > + } > + > + ns++; > + > + if (get_real_vendor_id(dir, &vendor_id) || > + get_real_device_id(dir, &device_id)) { > + goto fail; > + } > + > + fprintf(stderr, "*** The driver '%s' is occupying your device " > + "%02x:%02x.%x.\n", > + ns, dev->host.bus, dev->host.dev, dev->host.func); > + fprintf(stderr, "***\n"); > + fprintf(stderr, "*** You can try the following commands to free it:\n"); > + fprintf(stderr, "***\n"); > + fprintf(stderr, "*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub/" > + "new_id\n", vendor_id, device_id); > + fprintf(stderr, "*** $ echo \"0000:%02x:%02x.%x\" > /sys/bus/pci/drivers/" > + "%s/unbind\n", > + dev->host.bus, dev->host.dev, dev->host.func, ns); > + fprintf(stderr, "*** $ echo \"0000:%02x:%02x.%x\" > /sys/bus/pci/drivers/" > + "pci-stub/bind\n", > + dev->host.bus, dev->host.dev, dev->host.func); > + fprintf(stderr, "*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub" > + "/remove_id\n", vendor_id, device_id); > + fprintf(stderr, "***\n"); > + > + return; > + > +fail: > + fprintf(stderr, "Couldn't find out why.\n"); > +} > + > static int assign_device(AssignedDevice *dev) > { > struct kvm_assigned_pci_dev assigned_dev_data; > @@ -781,9 +829,12 @@ static int assign_device(AssignedDevice *dev) > #endif > > r = kvm_assign_pci_device(kvm_context, &assigned_dev_data); > - if (r < 0) > - fprintf(stderr, "Failed to assign device \"%s\" : %s\n", > + if (r < 0) { > + fprintf(stderr, "Failed to assign device \"%s\" : %s\n", > dev->dev.qdev.id, strerror(-r)); > + > + assign_failed_examine(dev); > + } > return r; > } > > -- > 1.6.0.2 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html