@@ -30,6 +30,7 @@
#define PCID_CMD_LIST "ls"
#define PCID_CMD_UNBIND "unbind"
+#define PCID_CMD_RESET "reset"
#define PCID_CMD_DIR_ID "dir_id"
#define PCID_CMD_WRITE "write"
@@ -1635,37 +1635,26 @@ static int libxl__device_pci_reset(libxl__gc *gc, unsigned int domain, unsigned
unsigned int dev, unsigned int func)
{
char *reset;
- int fd, rc;
-
- reset = GCSPRINTF("%s/do_flr", SYSFS_PCIBACK_DRIVER);
- fd = open(reset, O_WRONLY);
- if (fd >= 0) {
- char *buf = GCSPRINTF(PCI_BDF, domain, bus, dev, func);
- rc = write(fd, buf, strlen(buf));
- if (rc < 0)
- LOGD(ERROR, domain, "write to %s returned %d", reset, rc);
- close(fd);
- return rc < 0 ? rc : 0;
- }
- if (errno != ENOENT)
- LOGED(ERROR, domain, "Failed to access pciback path %s", reset);
- reset = GCSPRINTF("%s/"PCI_BDF"/reset", SYSFS_PCI_DEV, domain, bus, dev, func);
- fd = open(reset, O_WRONLY);
- if (fd >= 0) {
- rc = write(fd, "1", 1);
- if (rc < 0)
- LOGED(ERROR, domain, "write to %s returned %d", reset, rc);
- close(fd);
- return rc < 0 ? rc : 0;
- }
- if (errno == ENOENT) {
- LOGD(ERROR, domain,
- "The kernel doesn't support reset from sysfs for PCI device "PCI_BDF,
- domain, bus, dev, func);
- } else {
- LOGED(ERROR, domain, "Failed to access reset path %s", reset);
+ char *buf;
+ struct vchan_info *vchan;
+ libxl__json_object *args = NULL, *result = NULL;
+
+ vchan = pci_prepare_vchan(gc);
+ if (!vchan)
+ return -1;
+
+ reset = GCSPRINTF("%s", "/do_flr");
+ buf = GCSPRINTF(PCI_BDF, domain, bus, dev, func);
+
+ libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_PATH, reset);
+ libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, buf);
+ result = vchan_send_command(gc, vchan, PCID_CMD_RESET, args);
+ if (!result) {
+ LOGD(ERROR, domain, "write to %s returned error", reset);
+ return -1;
}
- return -1;
+
+ return 0;
}
int libxl__device_pci_setdefault(libxl__gc *gc, uint32_t domid,
@@ -2085,20 +2074,35 @@ static void do_pci_remove(libxl__egc *egc, pci_remove_state *prs)
goto out_fail;
}
} else {
- char *sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/resource", pci->domain,
+ char *sysfs_path = GCSPRINTF("/"PCI_BDF"/resource", pci->domain,
pci->bus, pci->dev, pci->func);
- FILE *f = fopen(sysfs_path, "r");
unsigned int start = 0, end = 0, flags = 0, size = 0;
int irq = 0;
int i;
+ struct vchan_info *vchan;
+ libxl__json_object *args = NULL, *result = NULL;
+ const libxl__json_object *addr;
+ int j = 0;
- if (f == NULL) {
- LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
+ vchan = pci_prepare_vchan(gc);
+ if (!vchan)
+ goto out_fail;
+ libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, sysfs_path);
+ result = vchan_send_command(gc, vchan, PCID_CMD_READ_RESOURCES, args);
+ if (!result) {
+ LOGED(ERROR, domainid, "Couldn't get resources from %s", sysfs_path);
+ rc = ERROR_FAIL;
goto skip1;
}
+
for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
- if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
- continue;
+ addr = libxl__json_array_get(result, j++);
+ start = libxl__json_object_get_integer(addr);
+ addr = libxl__json_array_get(result, j++);
+ end = libxl__json_object_get_integer(addr);
+ addr = libxl__json_array_get(result, j++);
+ flags = libxl__json_object_get_integer(addr);
+
size = end - start + 1;
if (start) {
if (flags & PCI_BAR_IO) {
@@ -2119,16 +2123,21 @@ static void do_pci_remove(libxl__egc *egc, pci_remove_state *prs)
}
}
}
- fclose(f);
+
skip1:
- sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
+ sysfs_path = GCSPRINTF("/"PCI_BDF"/irq", pci->domain,
pci->bus, pci->dev, pci->func);
- f = fopen(sysfs_path, "r");
- if (f == NULL) {
- LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
+ libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, sysfs_path);
+ libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID, PCID_PCI_DEV);
+ result = vchan_send_command(gc, vchan, PCID_CMD_READ_HEX, args);
+ if (!result) {
+ LOGED(ERROR, domainid, "Couldn't get irq from %s", sysfs_path);
+ rc = ERROR_FAIL;
goto skip_irq;
}
- if ((fscanf(f, "%u", &irq) == 1) && irq) {
+
+ irq = libxl__json_object_get_integer(result);
+ if (irq) {
rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
if (rc < 0) {
LOGED(ERROR, domainid, "xc_physdev_unmap_pirq irq=%d", irq);
@@ -2138,7 +2147,6 @@ skip1:
LOGED(ERROR, domainid, "xc_domain_irq_permission irq=%d", irq);
}
}
- fclose(f);
}
skip_irq:
rc = 0;
@@ -348,6 +348,67 @@ out:
return result;
}
+static libxl__json_object *process_reset_cmd(libxl__gc *gc,
+ const struct libxl__json_object *resp)
+{
+ libxl__json_object *result = NULL;
+ const libxl__json_object *args, *pci_path, *pci_info;
+ char *reset;
+ int rc, fd;
+
+ args = libxl__json_map_get(PCID_MSG_FIELD_ARGS, resp, JSON_MAP);
+ if (!args)
+ goto out;
+ pci_info = libxl__json_map_get(PCID_CMD_PCI_INFO, args, JSON_ANY);
+ if (!pci_info)
+ goto out;
+ pci_path = libxl__json_map_get(PCID_CMD_PCI_PATH, args, JSON_ANY);
+
+ reset = libxl__sprintf(gc, SYSFS_PCIBACK_DRIVER"%s", pci_path->u.string);
+ fd = open(reset, O_WRONLY);
+ if (fd >= 0) {
+ rc = write(fd, pci_info->u.string, strlen(pci_info->u.string));
+ if (rc < 0) {
+ LOGE(ERROR, "write to %s returned %d\n", reset, rc);
+ goto out;
+ }
+ close(fd);
+ goto success;
+ }
+ if (errno != ENOENT)
+ LOGE(ERROR, "Failed to access pciback path %s\n", reset);
+
+ reset = libxl__sprintf(gc, "%s/%s/reset", SYSFS_PCI_DEV, pci_info->u.string);
+ fd = open(reset, O_WRONLY);
+ if (fd >= 0) {
+ rc = write(fd, "1", 1);
+ if (rc < 0) {
+ LOGE(ERROR, "write to %s returned %d\n", reset, rc);
+ goto out;
+ }
+ close(fd);
+ goto success;
+ }
+ if (errno == ENOENT)
+ LOGE(ERROR,
+ "The kernel doesn't support reset from sysfs for PCI device %s\n",
+ pci_info->u.string);
+ else
+ LOGE(ERROR, "Failed to access reset path %s\n", reset);
+ goto out;
+
+success:
+ result = libxl__json_object_alloc(gc, JSON_STRING);
+ if (!result) {
+ LOGE(ERROR, "Memory allocation failed\n");
+ goto out;
+ }
+ result->u.string = pci_path->u.string;
+
+out:
+ return result;
+}
+
static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
libxl__json_object **result)
{
@@ -373,6 +434,8 @@ static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
*result = process_read_rsc_cmd(gc, request);
else if (strcmp(command_name, PCID_CMD_UNBIND) == 0)
*result = process_unbind_cmd(gc, request);
+ else if (strcmp(command_name, PCID_CMD_RESET) == 0)
+ *result = process_reset_cmd(gc, request);
else
return ERROR_NOTFOUND;