X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Fpci%2Fpci.c;h=dc4f382140e50b2dc7814c81a860ba22e466afb6;hb=054229ebbdeb3f87d96c1abf93b511c86cd6ff0f;hp=7100064df42bc8937eb1fcbc9af9d9f39c07c6da;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vlib/pci/pci.c b/src/vlib/pci/pci.c index 7100064df42..dc4f382140e 100644 --- a/src/vlib/pci/pci.c +++ b/src/vlib/pci/pci.c @@ -52,25 +52,166 @@ vlib_pci_main_t pci_main; -vlib_pci_device_t * -vlib_get_pci_device (vlib_pci_addr_t * addr) +VLIB_REGISTER_LOG_CLASS (pci_log, static) = { + .class_name = "pci", +}; + +#define log_debug(h, f, ...) \ + vlib_log (VLIB_LOG_LEVEL_DEBUG, pci_log.class, "%U: " f, \ + format_vlib_pci_log, h, ##__VA_ARGS__) + +u8 * +format_vlib_pci_log (u8 *s, va_list *va) +{ + vlib_pci_dev_handle_t h = va_arg (*va, vlib_pci_dev_handle_t); + return format (s, "%U", format_vlib_pci_addr, + vlib_pci_get_addr (vlib_get_main (), h)); +} + +vlib_pci_device_info_t *__attribute__ ((weak)) +vlib_pci_get_device_info (vlib_main_t *vm, vlib_pci_addr_t *addr, + clib_error_t **error) { - vlib_pci_main_t *pm = &pci_main; - uword *p; - p = hash_get (pm->pci_dev_index_by_pci_addr, addr->as_u32); + if (error) + *error = clib_error_return (0, "unsupported"); + return 0; +} - if (p == 0) +clib_error_t *__attribute__ ((weak)) +vlib_pci_get_device_root_bus (vlib_pci_addr_t *addr, vlib_pci_addr_t *root_bus) +{ + return 0; +} + +vlib_pci_addr_t * __attribute__ ((weak)) vlib_pci_get_all_dev_addrs () +{ + return 0; +} + +static clib_error_t * +_vlib_pci_config_set_control_bit (vlib_main_t *vm, vlib_pci_dev_handle_t h, + u16 bit, int new_val, int *already_set) +{ + u16 control, old; + clib_error_t *err; + + err = vlib_pci_read_write_config ( + vm, h, VLIB_READ, STRUCT_OFFSET_OF (vlib_pci_config_t, command), &old, + STRUCT_SIZE_OF (vlib_pci_config_t, command)); + + if (err) + return err; + + control = new_val ? old | bit : old & ~bit; + *already_set = old == control; + if (*already_set) return 0; - return vec_elt_at_index (pm->pci_devs, p[0]); + return vlib_pci_read_write_config ( + vm, h, VLIB_WRITE, STRUCT_OFFSET_OF (vlib_pci_config_t, command), &control, + STRUCT_SIZE_OF (vlib_pci_config_t, command)); +} + +clib_error_t * +vlib_pci_intr_enable (vlib_main_t *vm, vlib_pci_dev_handle_t h) +{ + const vlib_pci_config_reg_command_t cmd = { .intx_disable = 1 }; + clib_error_t *err; + int already_set; + + err = _vlib_pci_config_set_control_bit (vm, h, cmd.as_u16, 0, &already_set); + log_debug (h, "interrupt%senabled", already_set ? " " : " already "); + return err; +} + +clib_error_t * +vlib_pci_intr_disable (vlib_main_t *vm, vlib_pci_dev_handle_t h) +{ + const vlib_pci_config_reg_command_t cmd = { .intx_disable = 1 }; + clib_error_t *err; + int already_set; + + err = _vlib_pci_config_set_control_bit (vm, h, cmd.as_u16, 1, &already_set); + log_debug (h, "interrupt%sdisabled", already_set ? " " : " already "); + return err; +} + +clib_error_t * +vlib_pci_bus_master_enable (vlib_main_t *vm, vlib_pci_dev_handle_t h) +{ + const vlib_pci_config_reg_command_t cmd = { .bus_master = 1 }; + clib_error_t *err; + int already_set; + + err = _vlib_pci_config_set_control_bit (vm, h, cmd.as_u16, 1, &already_set); + log_debug (h, "bus-master%senabled", already_set ? " " : " already "); + return err; +} + +clib_error_t * +vlib_pci_bus_master_disable (vlib_main_t *vm, vlib_pci_dev_handle_t h) +{ + const vlib_pci_config_reg_command_t cmd = { .bus_master = 1 }; + clib_error_t *err; + int already_set; + + err = _vlib_pci_config_set_control_bit (vm, h, cmd.as_u16, 0, &already_set); + log_debug (h, "bus-master%sdisabled", already_set ? " " : " already "); + return err; +} + +clib_error_t * +vlib_pci_function_level_reset (vlib_main_t *vm, vlib_pci_dev_handle_t h) +{ + vlib_pci_config_t cfg; + pci_capability_pcie_t *cap; + pci_capability_pcie_dev_control_t dev_control; + clib_error_t *err; + u8 offset; + + log_debug (h, "function level reset"); + + err = vlib_pci_read_write_config (vm, h, VLIB_READ, 0, &cfg, sizeof (cfg)); + if (err) + return err; + + offset = cfg.cap_ptr; + /* Make gcc happy, otherwise gcc fails build due to cap not set if offset == + * 0 */ + cap = (pci_capability_pcie_t *) (cfg.data + offset); + + while (offset) + { + cap = (pci_capability_pcie_t *) (cfg.data + offset); + + if (cap->capability_id == PCI_CAP_ID_PCIE) + break; + + offset = cap->next_offset; + } + + if (cap->capability_id != PCI_CAP_ID_PCIE) + return clib_error_return (0, "PCIe capability config not found"); + + if (cap->dev_caps.flr_capable == 0) + return clib_error_return (0, "PCIe function level reset not supported"); + + dev_control = cap->dev_control; + dev_control.function_level_reset = 1; + + if ((err = vlib_pci_write_config_u16 ( + vm, h, offset + STRUCT_OFFSET_OF (pci_capability_pcie_t, dev_control), + &dev_control.as_u16))) + return err; + + return 0; } static clib_error_t * show_pci_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - vlib_pci_main_t *pm = &pci_main; - vlib_pci_device_t *d; + vlib_pci_addr_t *addr = 0, *addrs; int show_all = 0; u8 *s = 0; @@ -83,32 +224,37 @@ show_pci_fn (vlib_main_t * vm, format_unformat_error, input); } - vlib_cli_output (vm, "%-13s%-5s%-12s%-13s%-16s%-32s%s", + vlib_cli_output (vm, "%-13s%-5s%-12s%-14s%-16s%-32s%s", "Address", "Sock", "VID:PID", "Link Speed", "Driver", "Product Name", "Vital Product Data"); - /* *INDENT-OFF* */ - pool_foreach (d, pm->pci_devs, ({ + addrs = vlib_pci_get_all_dev_addrs (); + + vec_foreach (addr, addrs) + { + vlib_pci_device_info_t *d; + d = vlib_pci_get_device_info (vm, addr, 0); - if (d->device_class != PCI_CLASS_NETWORK_ETHERNET && !show_all) - continue; + if (!d) + continue; - vec_reset_length (s); + if (d->device_class != PCI_CLASS_NETWORK_ETHERNET && !show_all) + continue; - if (d->numa_node >= 0) - s = format (s, " %d", d->numa_node); + vec_reset_length (s); + if (d->numa_node >= 0) + s = format (s, " %d", d->numa_node); - vlib_cli_output (vm, "%-13U%-5v%04x:%04x %-13U%-16s%-32v%U", - format_vlib_pci_addr, &d->bus_address, s, - d->vendor_id, d->device_id, - format_vlib_pci_link_speed, d, - d->driver_name ? (char *) d->driver_name : "", - d->product_name, - format_vlib_pci_vpd, d->vpd_r, 0); - })); -/* *INDENT-ON* */ + vlib_cli_output ( + vm, "%-13U%-5v%04x:%04x %-14U%-16s%-32v%U", format_vlib_pci_addr, + addr, s, d->vendor_id, d->device_id, format_vlib_pci_link_speed, d, + d->driver_name ? (char *) d->driver_name : "", d->product_name, + format_vlib_pci_vpd, d->vpd_r, (u8 *) 0); + vlib_pci_free_device_info (d); + } vec_free (s); + vec_free (addrs); return 0; } @@ -138,32 +284,56 @@ format_vlib_pci_addr (u8 * s, va_list * va) } u8 * -format_vlib_pci_handle (u8 * s, va_list * va) +format_vlib_pci_link_port (u8 *s, va_list *va) { - vlib_pci_addr_t *addr = va_arg (*va, vlib_pci_addr_t *); - return format (s, "%x/%x/%x", addr->bus, addr->slot, addr->function); + vlib_pci_config_t *c = va_arg (*va, vlib_pci_config_t *); + pci_capability_pcie_t *r = pci_config_find_capability (c, PCI_CAP_ID_PCIE); + + if (!r) + return format (s, "unknown"); + + return format (s, "P%d", r->link_caps.port_number); +} + +static u8 * +_vlib_pci_link_speed (u8 *s, u8 speed, u8 width) +{ + static char *speeds[] = { + [1] = "2.5", [2] = "5.0", [3] = "8.0", [4] = "16.0", [5] = "32.0" + }; + + if (speed > ARRAY_LEN (speeds) || speeds[speed] == 0) + s = format (s, "unknown speed"); + else + s = format (s, "%s GT/s", speeds[speed]); + + return format (s, " x%u", width); } u8 * -format_vlib_pci_link_speed (u8 * s, va_list * va) +format_vlib_pci_link_speed (u8 *s, va_list *va) { - vlib_pci_device_t *d = va_arg (*va, vlib_pci_device_t *); - pcie_config_regs_t *r = - pci_config_find_capability (&d->config0, PCI_CAP_ID_PCIE); - int width; + vlib_pci_config_t *c = va_arg (*va, vlib_pci_config_t *); + pci_capability_pcie_t *r = pci_config_find_capability (c, PCI_CAP_ID_PCIE); if (!r) return format (s, "unknown"); - width = (r->link_status >> 4) & 0x3f; + return _vlib_pci_link_speed (s, r->link_status.link_speed, + r->link_status.negotiated_link_width); +} + +u8 * +format_vlib_pci_link_speed_cap (u8 *s, va_list *va) +{ + vlib_pci_config_t *c = va_arg (*va, vlib_pci_config_t *); + pci_capability_pcie_t *r = pci_config_find_capability (c, PCI_CAP_ID_PCIE); + + if (!r) + return format (s, "unknown"); - if ((r->link_status & 0xf) == 1) - return format (s, "2.5 GT/s x%u", width); - if ((r->link_status & 0xf) == 2) - return format (s, "5.0 GT/s x%u", width); - if ((r->link_status & 0xf) == 3) - return format (s, "8.0 GT/s x%u", width); - return format (s, "unknown"); + return _vlib_pci_link_speed (s, r->link_caps.max_link_speed, + r->link_caps.max_link_width); } u8 * @@ -171,7 +341,7 @@ format_vlib_pci_vpd (u8 * s, va_list * args) { u8 *data = va_arg (*args, u8 *); u8 *id = va_arg (*args, u8 *); - uword indent = format_get_indent (s); + u32 indent = format_get_indent (s); char *string_types[] = { "PN", "EC", "SN", "MN", 0 }; uword p = 0; int first_line = 1; @@ -238,27 +408,8 @@ format_vlib_pci_vpd (u8 * s, va_list * args) return s; } - -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_pci_command, static) = { .path = "show pci", .short_help = "show pci [all]", .function = show_pci_fn, }; -/* *INDENT-ON* */ - -clib_error_t * -pci_bus_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (pci_bus_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */