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; return FILE_TYPE_BIN;
} }
int pcie_hot_reset(const char *pcie_port_path) int pcie_hot_reset(const char *pci_port_path)
{ {
int fd; int fd;
char path[PATH_MAX+32]; char path[PATH_MAX+32];
char buf[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); fd = open(path, O_RDWR);
@ -381,14 +381,14 @@ int pcie_hot_reset(const char *pcie_port_path)
return 0; return 0;
} }
int pcie_disable_fatal_err(const char *pcie_port_path) int pcie_disable_fatal_err(const char *pci_port_path)
{ {
int fd; int fd;
char path[PATH_MAX+32]; char path[PATH_MAX+32];
char buf[32]; char buf[32];
int offset; 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); fd = open(path, O_RDWR);
@ -451,8 +451,8 @@ int main(int argc, char *argv[])
FILE *write_file = NULL; FILE *write_file = NULL;
char path[PATH_MAX+32]; char path[PATH_MAX+32];
char device_path[PATH_MAX]; char pci_device_path[PATH_MAX];
char port_path[PATH_MAX]; char pci_port_path[PATH_MAX];
char *ptr; char *ptr;
int slot = -1; int slot = -1;
@ -526,47 +526,24 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
// determine sysfs path of PCIe device if (!dev->pci_device_path[0])
// 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))
{ {
// that failed, perhaps it was a PCIe resource fprintf(stderr, "Failed to determine PCIe device path\n");
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");
ret = -1; ret = -1;
goto err; 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 // determine sysfs path of upstream port
strcpy(port_path, device_path); snprintf(pci_port_path, sizeof(pci_port_path), "%s", pci_device_path);
ptr = strrchr(port_path, '/'); ptr = strrchr(pci_port_path, '/');
if (ptr) if (ptr)
*ptr = 0; *ptr = 0;
printf("PCIe ID (device): %s\n", strrchr(device_path, '/')+1); printf("PCIe ID (device): %s\n", strrchr(pci_device_path, '/')+1);
printf("PCIe ID (upstream port): %s\n", strrchr(port_path, '/')+1); printf("PCIe ID (upstream port): %s\n", strrchr(pci_port_path, '/')+1);
uint32_t flash_format = 0; uint32_t flash_format = 0;
const char *fpga_part = get_fpga_part(dev->fpga_id); 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) // disable fatal error reporting on port (to prevent IPMI-triggered reboot)
printf("Disabling PCIe fatal error reporting on port...\n"); 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 // disconnect from device
mqnic_close(dev); mqnic_close(dev);
dev = NULL; dev = NULL;
// attempt to disconnect driver // attempt to disconnect driver
ptr = strrchr(device_path, '/'); snprintf(path, sizeof(path), "%s/driver/unbind", pci_device_path);
if (ptr)
{
snprintf(path, sizeof(path), "%s/driver/unbind", device_path);
if (access(path, F_OK) == 0) if (access(path, F_OK) == 0)
{ {
printf("Unbinding driver...\n"); printf("Unbinding driver...\n");
write_str_to_file(path, ptr+1); write_str_to_file(path, ptr+1);
} }
else else
{ {
printf("No driver bound\n"); printf("No driver bound\n");
}
} }
sleep(1); sleep(1);
@ -1245,7 +1218,7 @@ skip_flash:
if (action_boot) if (action_boot)
{ {
// reconnect directly to device // 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); dev = mqnic_open(path);
if (!dev) if (!dev)
@ -1269,7 +1242,7 @@ skip_flash:
// remove PCIe device // remove PCIe device
printf("Removing device...\n"); 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)) if (write_1_to_file(path))
{ {
@ -1289,13 +1262,13 @@ skip_flash:
for (int tries = 5; tries > 0; tries--) for (int tries = 5; tries > 0; tries--)
{ {
printf("Performing hot reset on upstream port...\n"); printf("Performing hot reset on upstream port...\n");
pcie_hot_reset(port_path); pcie_hot_reset(pci_port_path);
sleep(2); sleep(2);
printf("Rescanning on upstream port...\n"); 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)) if (write_1_to_file(path))
{ {
@ -1305,7 +1278,7 @@ skip_flash:
} }
// PCIe device will have a config space, so check for that // 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) 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 "mqnic.h"
#include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.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/mman.h>
#include <sys/stat.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; struct stat st;
char *ptr;
if (!dev) va_start(ap, fmt);
{ vsnprintf(dev->device_path, sizeof(dev->device_path), fmt, ap);
perror("memory allocation failed"); va_end(ap);
goto fail_alloc;
}
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) if (dev->fd < 0)
{ {
@ -82,6 +95,35 @@ struct mqnic *mqnic_open(const char *dev_name)
dev->regs_size = info.regs_size; 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); dev->regs = (volatile uint8_t *)mmap(NULL, dev->regs_size, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, 0);
if (dev->regs == MAP_FAILED) if (dev->regs == MAP_FAILED)
{ {
@ -89,20 +131,12 @@ struct mqnic *mqnic_open(const char *dev_name)
goto fail_mmap_regs; 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 // if we were given a PCIe resource, then we may need to enable the device
char path[PATH_MAX+32]; snprintf(path, sizeof(path), "%s/enable", dev->pci_device_path);
char *ptr;
strcpy(path, dev_name); if (access(path, W_OK) == 0)
ptr = strrchr(path, '/');
if (ptr)
{
strcpy(++ptr, "enable");
}
if (access(path, F_OK) == 0)
{ {
FILE *fp = fopen(path, "w"); FILE *fp = fopen(path, "w");
@ -137,6 +171,85 @@ struct mqnic *mqnic_open(const char *dev_name)
goto fail_enum; 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->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_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); 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: skip_interface:
return dev; return dev;
fail:
fail_enum:
fail_reset:
mqnic_close(dev);
return NULL;
fail_mmap_regs:
fail_ioctl:
fail_fstat:
close(dev->fd);
fail_open: fail_open:
free(dev); free(dev);
fail_alloc: fail_alloc:

View File

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