1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

Accept interface name and PCIe BDF when connecting to device

This commit is contained in:
Alex Forencich 2022-01-08 15:32:50 -08:00
parent 23f635f273
commit eba32ce8a5
3 changed files with 166 additions and 85 deletions

View File

@ -347,13 +347,13 @@ int file_type_from_ext(const char *file_name)
return FILE_TYPE_BIN;
}
int pcie_hot_reset(const char *pcie_port_path)
int pcie_hot_reset(const char *pci_port_path)
{
int fd;
char path[PATH_MAX+32];
char buf[32];
snprintf(path, sizeof(path), "%s/config", pcie_port_path);
snprintf(path, sizeof(path), "%s/config", pci_port_path);
fd = open(path, O_RDWR);
@ -381,14 +381,14 @@ int pcie_hot_reset(const char *pcie_port_path)
return 0;
}
int pcie_disable_fatal_err(const char *pcie_port_path)
int pcie_disable_fatal_err(const char *pci_port_path)
{
int fd;
char path[PATH_MAX+32];
char buf[32];
int offset;
snprintf(path, sizeof(path), "%s/config", pcie_port_path);
snprintf(path, sizeof(path), "%s/config", pci_port_path);
fd = open(path, O_RDWR);
@ -451,8 +451,8 @@ int main(int argc, char *argv[])
FILE *write_file = NULL;
char path[PATH_MAX+32];
char device_path[PATH_MAX];
char port_path[PATH_MAX];
char pci_device_path[PATH_MAX];
char pci_port_path[PATH_MAX];
char *ptr;
int slot = -1;
@ -526,47 +526,24 @@ int main(int argc, char *argv[])
return -1;
}
// determine sysfs path of PCIe device
// first, try to find via miscdevice
ptr = strrchr(device, '/');
ptr = ptr ? ptr+1 : device;
snprintf(path, sizeof(path), "/sys/class/misc/%s/device", ptr);
if (!realpath(path, device_path))
if (!dev->pci_device_path[0])
{
// that failed, perhaps it was a PCIe resource
strcpy(path, device);
ptr = strrchr(path, '/');
if (ptr)
*ptr = 0;
if (!realpath(path, device_path))
{
perror("failed to determine device path");
ret = -1;
goto err;
}
}
// PCIe device will have a config space, so check for that
snprintf(path, sizeof(path), "%s/config", device_path);
if (access(path, F_OK))
{
perror("failed to determine device path");
fprintf(stderr, "Failed to determine PCIe device path\n");
ret = -1;
goto err;
}
// snprintf(device_path, sizeof(device_path), dev->device_path)
snprintf(pci_device_path, sizeof(pci_device_path), "%s", dev->pci_device_path);
// determine sysfs path of upstream port
strcpy(port_path, device_path);
ptr = strrchr(port_path, '/');
snprintf(pci_port_path, sizeof(pci_port_path), "%s", pci_device_path);
ptr = strrchr(pci_port_path, '/');
if (ptr)
*ptr = 0;
printf("PCIe ID (device): %s\n", strrchr(device_path, '/')+1);
printf("PCIe ID (upstream port): %s\n", strrchr(port_path, '/')+1);
printf("PCIe ID (device): %s\n", strrchr(pci_device_path, '/')+1);
printf("PCIe ID (upstream port): %s\n", strrchr(pci_port_path, '/')+1);
uint32_t flash_format = 0;
const char *fpga_part = get_fpga_part(dev->fpga_id);
@ -1216,27 +1193,23 @@ skip_flash:
// disable fatal error reporting on port (to prevent IPMI-triggered reboot)
printf("Disabling PCIe fatal error reporting on port...\n");
pcie_disable_fatal_err(port_path);
pcie_disable_fatal_err(pci_port_path);
// disconnect from device
mqnic_close(dev);
dev = NULL;
// attempt to disconnect driver
ptr = strrchr(device_path, '/');
if (ptr)
{
snprintf(path, sizeof(path), "%s/driver/unbind", device_path);
snprintf(path, sizeof(path), "%s/driver/unbind", pci_device_path);
if (access(path, F_OK) == 0)
{
printf("Unbinding driver...\n");
write_str_to_file(path, ptr+1);
}
else
{
printf("No driver bound\n");
}
if (access(path, F_OK) == 0)
{
printf("Unbinding driver...\n");
write_str_to_file(path, ptr+1);
}
else
{
printf("No driver bound\n");
}
sleep(1);
@ -1245,7 +1218,7 @@ skip_flash:
if (action_boot)
{
// reconnect directly to device
snprintf(path, sizeof(path), "%s/resource0", device_path);
snprintf(path, sizeof(path), "%s/resource0", pci_device_path);
dev = mqnic_open(path);
if (!dev)
@ -1269,7 +1242,7 @@ skip_flash:
// remove PCIe device
printf("Removing device...\n");
snprintf(path, sizeof(path), "%s/remove", device_path);
snprintf(path, sizeof(path), "%s/remove", pci_device_path);
if (write_1_to_file(path))
{
@ -1289,13 +1262,13 @@ skip_flash:
for (int tries = 5; tries > 0; tries--)
{
printf("Performing hot reset on upstream port...\n");
pcie_hot_reset(port_path);
pcie_hot_reset(pci_port_path);
sleep(2);
printf("Rescanning on upstream port...\n");
snprintf(path, sizeof(path), "%s/rescan", port_path);
snprintf(path, sizeof(path), "%s/rescan", pci_port_path);
if (write_1_to_file(path))
{
@ -1305,7 +1278,7 @@ skip_flash:
}
// PCIe device will have a config space, so check for that
snprintf(path, sizeof(path), "%s/config", device_path);
snprintf(path, sizeof(path), "%s/config", pci_device_path);
if (access(path, F_OK) == 0)
{

View File

@ -33,8 +33,10 @@ either expressed or implied, of The Regents of the University of California.
#include "mqnic.h"
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -43,18 +45,29 @@ either expressed or implied, of The Regents of the University of California.
#include <sys/mman.h>
#include <sys/stat.h>
struct mqnic *mqnic_open(const char *dev_name)
static int mqnic_try_open(struct mqnic *dev, const char *fmt, ...)
{
struct mqnic *dev = calloc(1, sizeof(struct mqnic));
va_list ap;
char path[PATH_MAX+32];
struct stat st;
char *ptr;
if (!dev)
{
perror("memory allocation failed");
goto fail_alloc;
}
va_start(ap, fmt);
vsnprintf(dev->device_path, sizeof(dev->device_path), fmt, ap);
va_end(ap);
dev->fd = open(dev_name, O_RDWR);
dev->pci_device_path[0] = 0;
if (access(dev->device_path, W_OK))
return -1;
if (stat(dev->device_path, &st))
return -1;
if (S_ISDIR(st.st_mode))
return -1;
dev->fd = open(dev->device_path, O_RDWR);
if (dev->fd < 0)
{
@ -82,6 +95,35 @@ struct mqnic *mqnic_open(const char *dev_name)
dev->regs_size = info.regs_size;
}
// determine sysfs path of PCIe device
// first, try to find via miscdevice
ptr = strrchr(dev->device_path, '/');
ptr = ptr ? ptr+1 : dev->device_path;
snprintf(path, sizeof(path), "/sys/class/misc/%s/device", ptr);
if (!realpath(path, dev->pci_device_path))
{
// that failed, perhaps it was a PCIe resource
snprintf(path, sizeof(path), "%s", dev->device_path);
ptr = strrchr(path, '/');
if (ptr)
*ptr = 0;
if (!realpath(path, dev->pci_device_path))
dev->pci_device_path[0] = 0;
}
// PCIe device will have a config space, so check for that
if (dev->pci_device_path[0])
{
snprintf(path, sizeof(path), "%s/config", dev->pci_device_path);
if (access(path, F_OK))
dev->pci_device_path[0] = 0;
}
// map registers
dev->regs = (volatile uint8_t *)mmap(NULL, dev->regs_size, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, 0);
if (dev->regs == MAP_FAILED)
{
@ -89,20 +131,12 @@ struct mqnic *mqnic_open(const char *dev_name)
goto fail_mmap_regs;
}
if (mqnic_reg_read32(dev->regs, 4) == 0xffffffff)
if (dev->pci_device_path[0] && mqnic_reg_read32(dev->regs, 4) == 0xffffffff)
{
// if we were given a PCIe resource, then we may need to enable the device
char path[PATH_MAX+32];
char *ptr;
snprintf(path, sizeof(path), "%s/enable", dev->pci_device_path);
strcpy(path, dev_name);
ptr = strrchr(path, '/');
if (ptr)
{
strcpy(++ptr, "enable");
}
if (access(path, F_OK) == 0)
if (access(path, W_OK) == 0)
{
FILE *fp = fopen(path, "w");
@ -137,6 +171,85 @@ struct mqnic *mqnic_open(const char *dev_name)
goto fail_enum;
}
return 0;
fail_enum:
if (dev->rb_list)
free_reg_block_list(dev->rb_list);
fail_reset:
munmap((void *)dev->regs, dev->regs_size);
fail_mmap_regs:
fail_ioctl:
fail_fstat:
close(dev->fd);
fail_open:
return -1;
}
static int mqnic_try_open_if_name(struct mqnic *dev, const char *if_name)
{
DIR *folder;
struct dirent *entry;
char path[PATH_MAX];
snprintf(path, sizeof(path), "/sys/class/net/%s/device/misc/", if_name);
folder = opendir(path);
if (!folder)
return -1;
while ((entry = readdir(folder)))
{
if (entry->d_name[0] != '.')
break;
}
if (!entry)
{
closedir(folder);
return -1;
}
snprintf(path, sizeof(path), "/dev/%s", entry->d_name);
closedir(folder);
return mqnic_try_open(dev, "%s", path);
}
struct mqnic *mqnic_open(const char *dev_name)
{
struct mqnic *dev = calloc(1, sizeof(struct mqnic));
if (!dev)
{
perror("memory allocation failed");
goto fail_alloc;
}
// absolute path
if (mqnic_try_open(dev, "%s", dev_name) == 0)
goto open;
// network interface
if (mqnic_try_open_if_name(dev, dev_name) == 0)
goto open;
// PCIe sysfs path
if (mqnic_try_open(dev, "%s/resource0", dev_name) == 0)
goto open;
// PCIe BDF (dddd:xx:yy.z)
if (mqnic_try_open(dev, "/sys/bus/pci/devices/%s/resource0", dev_name) == 0)
goto open;
// PCIe BDF (xx:yy.z)
if (mqnic_try_open(dev, "/sys/bus/pci/devices/0000:%s/resource0", dev_name) == 0)
goto open;
goto fail_open;
open:
dev->fpga_id = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FPGA_ID);
dev->fw_id = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FW_ID);
dev->fw_ver = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FW_VER);
@ -186,15 +299,6 @@ struct mqnic *mqnic_open(const char *dev_name)
skip_interface:
return dev;
fail:
fail_enum:
fail_reset:
mqnic_close(dev);
return NULL;
fail_mmap_regs:
fail_ioctl:
fail_fstat:
close(dev->fd);
fail_open:
free(dev);
fail_alloc:

View File

@ -34,6 +34,7 @@ either expressed or implied, of The Regents of the University of California.
#ifndef MQNIC_H
#define MQNIC_H
#include <limits.h>
#include <stdint.h>
#include <unistd.h>
@ -152,6 +153,9 @@ struct mqnic {
char build_date_str[32];
struct mqnic_if *interfaces[MQNIC_MAX_IF];
char device_path[PATH_MAX];
char pci_device_path[PATH_MAX];
};
struct mqnic *mqnic_open(const char *dev_name);