static int usnic_vnic_discover_resources(struct pci_dev *pdev, struct usnic_vnic *vnic) { enum usnic_vnic_res_type res_type; int i; int err = 0; for (i = 0; i < ARRAY_SIZE(vnic->bar); i++) { if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM)) continue; vnic->bar[i].len = pci_resource_len(pdev, i); vnic->bar[i].vaddr = pci_iomap(pdev, i, vnic->bar[i].len); if (!vnic->bar[i].vaddr) { usnic_err("Cannot memory-map BAR %d, aborting\n", i); err = -ENODEV; goto out_clean_bar; } vnic->bar[i].bus_addr = pci_resource_start(pdev, i); } vnic->vdev = vnic_dev_register(NULL, pdev, pdev, vnic->bar, ARRAY_SIZE(vnic->bar)); if (!vnic->vdev) { usnic_err("Failed to register device %s\n", pci_name(pdev)); err = -EINVAL; goto out_clean_bar; } for (res_type = USNIC_VNIC_RES_TYPE_EOL + 1; res_type < USNIC_VNIC_RES_TYPE_MAX; res_type++) { err = usnic_vnic_alloc_res_chunk(vnic, res_type, &vnic->chunks[res_type]); if (err) { usnic_err("Failed to alloc res %s with err %d\n", usnic_vnic_res_type_to_str(res_type), err); goto out_clean_chunks; } } return 0; out_clean_chunks: for (res_type--; res_type > USNIC_VNIC_RES_TYPE_EOL; res_type--) usnic_vnic_free_res_chunk(&vnic->chunks[res_type]); vnic_dev_unregister(vnic->vdev); out_clean_bar: for (i = 0; i < ARRAY_SIZE(vnic->bar); i++) { if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM)) continue; if (!vnic->bar[i].vaddr) break; iounmap(vnic->bar[i].vaddr); } return err; }
int usnic_vnic_dump(struct usnic_vnic *vnic, char *buf, int buf_sz, void *hdr_obj, int (*printtitle)(void *, char*, int), int (*printcols)(char *, int), int (*printrow)(void *, char *, int)) { struct usnic_vnic_res_chunk *chunk; struct usnic_vnic_res *res; struct vnic_dev_bar *bar0; int i, j, offset; offset = 0; bar0 = usnic_vnic_get_bar(vnic, 0); offset += scnprintf(buf + offset, buf_sz - offset, "VF:%hu BAR0 bus_addr=%pa vaddr=0x%p size=%ld ", usnic_vnic_get_index(vnic), &bar0->bus_addr, bar0->vaddr, bar0->len); if (printtitle) offset += printtitle(hdr_obj, buf + offset, buf_sz - offset); offset += scnprintf(buf + offset, buf_sz - offset, "\n"); offset += scnprintf(buf + offset, buf_sz - offset, "|RES\t|CTRL_PIN\t\t|IN_USE\t"); if (printcols) offset += printcols(buf + offset, buf_sz - offset); offset += scnprintf(buf + offset, buf_sz - offset, "\n"); spin_lock(&vnic->res_lock); for (i = 0; i < ARRAY_SIZE(vnic->chunks); i++) { chunk = &vnic->chunks[i]; for (j = 0; j < chunk->cnt; j++) { res = chunk->res[j]; offset += scnprintf(buf + offset, buf_sz - offset, "|%s[%u]\t|0x%p\t|%u\t", usnic_vnic_res_type_to_str(res->type), res->vnic_idx, res->ctrl, !!res->owner); if (printrow) { offset += printrow(res->owner, buf + offset, buf_sz - offset); } offset += scnprintf(buf + offset, buf_sz - offset, "\n"); } } spin_unlock(&vnic->res_lock); return offset; }
int usnic_vnic_spec_dump(char *buf, int buf_sz, struct usnic_vnic_res_spec *res_spec) { enum usnic_vnic_res_type res_type; int res_cnt; int i; int offset = 0; for (i = 0; i < USNIC_VNIC_RES_TYPE_MAX; i++) { res_type = res_spec->resources[i].type; res_cnt = res_spec->resources[i].cnt; offset += scnprintf(buf + offset, buf_sz - offset, "Res: %s Cnt: %d ", usnic_vnic_res_type_to_str(res_type), res_cnt); } return offset; }
/* * Report the configuration for this PF */ static ssize_t usnic_ib_show_config(struct device *device, struct device_attribute *attr, char *buf) { struct usnic_ib_dev *us_ibdev; char *ptr; unsigned left; unsigned n; enum usnic_vnic_res_type res_type; us_ibdev = container_of(device, struct usnic_ib_dev, ib_dev.dev); /* Buffer space limit is 1 page */ ptr = buf; left = PAGE_SIZE; mutex_lock(&us_ibdev->usdev_lock); if (atomic_read(&us_ibdev->vf_cnt.refcount) > 0) { char *busname; /* * bus name seems to come with annoying prefix. * Remove it if it is predictable */ busname = us_ibdev->pdev->bus->name; if (strncmp(busname, "PCI Bus ", 8) == 0) busname += 8; n = scnprintf(ptr, left, "%s: %s:%d.%d, %s, %pM, %u VFs\n Per VF:", us_ibdev->ib_dev.name, busname, PCI_SLOT(us_ibdev->pdev->devfn), PCI_FUNC(us_ibdev->pdev->devfn), netdev_name(us_ibdev->netdev), us_ibdev->ufdev->mac, atomic_read(&us_ibdev->vf_cnt.refcount)); UPDATE_PTR_LEFT(n, ptr, left); for (res_type = USNIC_VNIC_RES_TYPE_EOL; res_type < USNIC_VNIC_RES_TYPE_MAX; res_type++) { if (us_ibdev->vf_res_cnt[res_type] == 0) continue; n = scnprintf(ptr, left, " %d %s%s", us_ibdev->vf_res_cnt[res_type], usnic_vnic_res_type_to_str(res_type), (res_type < (USNIC_VNIC_RES_TYPE_MAX - 1)) ? "," : ""); UPDATE_PTR_LEFT(n, ptr, left); } n = scnprintf(ptr, left, "\n"); UPDATE_PTR_LEFT(n, ptr, left); } else { n = scnprintf(ptr, left, "%s: no VFs\n", us_ibdev->ib_dev.name); UPDATE_PTR_LEFT(n, ptr, left); } mutex_unlock(&us_ibdev->usdev_lock); return ptr - buf; }