git: 44a78c21df4c - stable/13 - ocs_fc: Add gendump and dump_to_host ioctl command support.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 17 Dec 2021 10:37:09 UTC
The branch stable/13 has been updated by ram: URL: https://cgit.FreeBSD.org/src/commit/?id=44a78c21df4c344f24e5f6dc3c6010a87c330644 commit 44a78c21df4c344f24e5f6dc3c6010a87c330644 Author: Ram Kishore Vegesna <ram@FreeBSD.org> AuthorDate: 2021-06-24 07:05:00 +0000 Commit: Ram Kishore Vegesna <ram@FreeBSD.org> CommitDate: 2021-12-17 10:30:59 +0000 ocs_fc: Add gendump and dump_to_host ioctl command support. Support to generate firmware dump. Approved by: mav(mentor) (cherry picked from commit 29e2dbd42c3e2e10e606b3414f4d0c53021d4e86) Add ocs_gendump.c to the build, missed in 29e2dbd42c3e. (cherry picked from commit d0732fa81963d336099a6b134a1eb4be867bfa8b) --- sys/conf/files | 1 + sys/dev/ocs_fc/ocs_gendump.c | 388 +++++++++++++++++++++++++++++++++++++++++++ sys/dev/ocs_fc/ocs_gendump.h | 42 +++++ sys/dev/ocs_fc/ocs_ioctl.c | 13 +- sys/dev/ocs_fc/ocs_ioctl.h | 3 + sys/dev/ocs_fc/ocs_mgmt.c | 152 ++--------------- sys/dev/ocs_fc/ocs_os.c | 3 +- sys/dev/ocs_fc/ocs_os.h | 3 +- sys/modules/ocs_fc/Makefile | 3 +- 9 files changed, 450 insertions(+), 158 deletions(-) diff --git a/sys/conf/files b/sys/conf/files index abfc1f9101ae..6b78b509f8ad 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2603,6 +2603,7 @@ dev/oce/oce_mbox.c optional oce pci dev/oce/oce_queue.c optional oce pci dev/oce/oce_sysctl.c optional oce pci dev/oce/oce_util.c optional oce pci +dev/ocs_fc/ocs_gendump.c optional ocs_fc pci dev/ocs_fc/ocs_pci.c optional ocs_fc pci dev/ocs_fc/ocs_ioctl.c optional ocs_fc pci dev/ocs_fc/ocs_os.c optional ocs_fc pci diff --git a/sys/dev/ocs_fc/ocs_gendump.c b/sys/dev/ocs_fc/ocs_gendump.c new file mode 100644 index 000000000000..d24870f39668 --- /dev/null +++ b/sys/dev/ocs_fc/ocs_gendump.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2021 Broadcom. All rights reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "ocs.h" +#include "ocs_gendump.h" + +/* Reset all the functions associated with a bus/dev */ +static int +ocs_gen_dump_reset(uint8_t bus, uint8_t dev) +{ + uint32_t index = 0; + ocs_t *ocs; + int rc = 0; + + while ((ocs = ocs_get_instance(index++)) != NULL) { + uint8_t ocs_bus, ocs_dev, ocs_func; + ocs_domain_t *domain; + + ocs_get_bus_dev_func(ocs, &ocs_bus, &ocs_dev, &ocs_func); + + if (!(ocs_bus == bus && ocs_dev == dev)) + continue; + + if (ocs_hw_reset(&ocs->hw, OCS_HW_RESET_FUNCTION)) { + ocs_log_test(ocs, "failed to reset port\n"); + rc = -1; + continue; + } + + ocs_log_debug(ocs, "successfully reset port\n"); + while ((domain = ocs_list_get_head(&ocs->domain_list)) != NULL) { + ocs_log_debug(ocs, "free domain %p\n", domain); + ocs_domain_force_free(domain); + } + /* now initialize hw so user can read the dump in */ + if (ocs_hw_init(&ocs->hw)) { + ocs_log_err(ocs, "failed to initialize hw\n"); + rc = -1; + } else { + ocs_log_debug(ocs, "successfully initialized hw\n"); + } + } + return rc; +} + +int +ocs_gen_dump(ocs_t *ocs) +{ + uint32_t reset_required; + uint32_t dump_ready; + uint32_t ms_waited; + uint8_t bus, dev, func; + int rc = 0; + int index = 0, port_index = 0; + ocs_t *nxt_ocs; + uint8_t nxt_bus, nxt_dev, nxt_func; + uint8_t prev_port_state[OCS_MAX_HBA_PORTS] = {0,}; + ocs_xport_stats_t link_status; + + ocs_get_bus_dev_func(ocs, &bus, &dev, &func); + + /* Drop link on all ports belongs to this HBA*/ + while ((nxt_ocs = ocs_get_instance(index++)) != NULL) { + ocs_get_bus_dev_func(nxt_ocs, &nxt_bus, &nxt_dev, &nxt_func); + + if (!(bus == nxt_bus && dev == nxt_dev)) + continue; + + if ((port_index >= OCS_MAX_HBA_PORTS)) + continue; + + /* Check current link status and save for future use */ + if (ocs_xport_status(nxt_ocs->xport, OCS_XPORT_PORT_STATUS, + &link_status) == 0) { + if (link_status.value == OCS_XPORT_PORT_ONLINE) { + prev_port_state[port_index] = 1; + ocs_xport_control(nxt_ocs->xport, + OCS_XPORT_PORT_OFFLINE); + } else { + prev_port_state[port_index] = 0; + } + } + port_index++; + } + + /* Wait until all ports have quiesced */ + for (index = 0; (nxt_ocs = ocs_get_instance(index++)) != NULL; ) { + ms_waited = 0; + for (;;) { + ocs_xport_stats_t status; + + ocs_xport_status(nxt_ocs->xport, OCS_XPORT_IS_QUIESCED, + &status); + if (status.value) { + ocs_log_debug(nxt_ocs, "port quiesced\n"); + break; + } + + ocs_msleep(10); + ms_waited += 10; + if (ms_waited > 60000) { + ocs_log_test(nxt_ocs, + "timed out waiting for port to quiesce\n"); + break; + } + } + } + + /* Initiate dump */ + if (ocs_hw_raise_ue(&ocs->hw, 1) == OCS_HW_RTN_SUCCESS) { + + /* Wait for dump to complete */ + ocs_log_debug(ocs, "Dump requested, wait for completion.\n"); + + dump_ready = 0; + ms_waited = 0; + while ((!dump_ready) && (ms_waited < 30000)) { + ocs_hw_get(&ocs->hw, OCS_HW_DUMP_READY, &dump_ready); + ocs_udelay(10000); + ms_waited += 10; + } + + if (!dump_ready) { + ocs_log_test(ocs, "Failed to see dump after 30 secs\n"); + rc = -1; + } else { + ocs_log_debug(ocs, "sucessfully generated dump\n"); + } + + /* now reset port */ + ocs_hw_get(&ocs->hw, OCS_HW_RESET_REQUIRED, &reset_required); + ocs_log_debug(ocs, "reset required=%d\n", reset_required); + if (reset_required) { + if (ocs_gen_dump_reset(bus, dev) == 0) { + ocs_log_debug(ocs, "all devices reset\n"); + } else { + ocs_log_test(ocs, "all devices NOT reset\n"); + } + } + } else { + ocs_log_test(ocs, "dump request to hw failed\n"); + rc = -1; + } + + index = port_index = 0; + nxt_ocs = NULL; + /* Bring links on each HBA port to previous state*/ + while ((nxt_ocs = ocs_get_instance(index++)) != NULL) { + ocs_get_bus_dev_func(nxt_ocs, &nxt_bus, &nxt_dev, &nxt_func); + if (port_index > OCS_MAX_HBA_PORTS) { + ocs_log_err(NULL, "port index(%d) out of boundary\n", + port_index); + rc = -1; + break; + } + if ((bus == nxt_bus) && (dev == nxt_dev) && + prev_port_state[port_index++]) { + ocs_xport_control(nxt_ocs->xport, OCS_XPORT_PORT_ONLINE); + } + } + + return rc; +} + +int +ocs_fdb_dump(ocs_t *ocs) +{ + uint32_t dump_ready; + uint32_t ms_waited; + int rc = 0; + +#define FDB 2 + + /* Initiate dump */ + if (ocs_hw_raise_ue(&ocs->hw, FDB) == OCS_HW_RTN_SUCCESS) { + + /* Wait for dump to complete */ + ocs_log_debug(ocs, "Dump requested, wait for completion.\n"); + + dump_ready = 0; + ms_waited = 0; + while ((!(dump_ready == FDB)) && (ms_waited < 10000)) { + ocs_hw_get(&ocs->hw, OCS_HW_DUMP_READY, &dump_ready); + ocs_udelay(10000); + ms_waited += 10; + } + + if (!dump_ready) { + ocs_log_err(ocs, "Failed to see dump after 10 secs\n"); + return -1; + } + + ocs_log_debug(ocs, "sucessfully generated dump\n"); + + } else { + ocs_log_err(ocs, "dump request to hw failed\n"); + rc = -1; + } + + return rc; +} + +/** + * @brief Create a Lancer dump into a memory buffer + * @par Description + * This function creates a DMA buffer to hold a Lancer dump, + * sets the dump location to point to that buffer, then calls + * ocs_gen_dump to cause a dump to be transfered to the buffer. + * After the dump is complete it copies the dump to the provided + * user space buffer. + * + * @param ocs Pointer to ocs structure + * @param buf User space buffer in which to store the dump + * @param buflen Length of the user buffer in bytes + * + * @return Returns 0 on success, non-zero on error. + */ +int +ocs_dump_to_host(ocs_t *ocs, void *buf, uint32_t buflen) +{ + int rc; + uint32_t i, num_buffers; + ocs_dma_t *dump_buffers; + uint32_t rem_bytes, offset; + + if (buflen == 0) { + ocs_log_test(ocs, "zero buffer length is invalid\n"); + return -1; + } + + num_buffers = ((buflen + OCS_MAX_DMA_ALLOC - 1) / OCS_MAX_DMA_ALLOC); + + dump_buffers = ocs_malloc(ocs, sizeof(ocs_dma_t) * num_buffers, + OCS_M_ZERO | OCS_M_NOWAIT); + if (dump_buffers == NULL) { + ocs_log_err(ocs, "Failed to dump buffers\n"); + return -1; + } + + /* Allocate a DMA buffers to hold the dump */ + rem_bytes = buflen; + for (i = 0; i < num_buffers; i++) { + uint32_t num_bytes = MIN(rem_bytes, OCS_MAX_DMA_ALLOC); + + rc = ocs_dma_alloc(ocs, &dump_buffers[i], num_bytes, + OCS_MIN_DMA_ALIGNMENT); + if (rc) { + ocs_log_err(ocs, "Failed to allocate dump buffer\n"); + + /* Free any previously allocated buffers */ + goto free_and_return; + } + rem_bytes -= num_bytes; + } + + rc = ocs_hw_set_dump_location(&ocs->hw, num_buffers, dump_buffers, 0); + if (rc) { + ocs_log_test(ocs, "ocs_hw_set_dump_location failed\n"); + goto free_and_return; + } + + /* Generate the dump */ + rc = ocs_gen_dump(ocs); + if (rc) { + ocs_log_test(ocs, "ocs_gen_dump failed\n"); + goto free_and_return; + } + + /* Copy the dump from the DMA buffer into the user buffer */ + offset = 0; + for (i = 0; i < num_buffers; i++) { + if (ocs_copy_to_user((uint8_t*)buf + offset, + dump_buffers[i].virt, dump_buffers[i].size)) { + ocs_log_test(ocs, "ocs_copy_to_user failed\n"); + rc = -1; + } + offset += dump_buffers[i].size; + } + +free_and_return: + /* Free the DMA buffer and return */ + for (i = 0; i < num_buffers; i++) { + ocs_dma_free(ocs, &dump_buffers[i]); + } + ocs_free(ocs, dump_buffers, sizeof(ocs_dma_t) * num_buffers); + return rc; +} + +int +ocs_function_speciic_dump(ocs_t *ocs, void *buf, uint32_t buflen) +{ + int rc; + uint32_t i, num_buffers; + ocs_dma_t *dump_buffers; + uint32_t rem_bytes, offset; + + if (buflen == 0) { + ocs_log_err(ocs, "zero buffer length is invalid\n"); + return -1; + } + + num_buffers = ((buflen + OCS_MAX_DMA_ALLOC - 1) / OCS_MAX_DMA_ALLOC); + + dump_buffers = ocs_malloc(ocs, sizeof(ocs_dma_t) * num_buffers, + OCS_M_ZERO | OCS_M_NOWAIT); + if (dump_buffers == NULL) { + ocs_log_err(ocs, "Failed to allocate dump buffers\n"); + return -1; + } + + /* Allocate a DMA buffers to hold the dump */ + rem_bytes = buflen; + for (i = 0; i < num_buffers; i++) { + uint32_t num_bytes = MIN(rem_bytes, OCS_MAX_DMA_ALLOC); + rc = ocs_dma_alloc(ocs, &dump_buffers[i], num_bytes, + OCS_MIN_DMA_ALIGNMENT); + if (rc) { + ocs_log_err(ocs, "Failed to allocate dma buffer\n"); + + /* Free any previously allocated buffers */ + goto free_and_return; + } + rem_bytes -= num_bytes; + } + + /* register buffers for function spcific dump */ + rc = ocs_hw_set_dump_location(&ocs->hw, num_buffers, dump_buffers, 1); + if (rc) { + ocs_log_err(ocs, "ocs_hw_set_dump_location failed\n"); + goto free_and_return; + } + + /* Invoke dump by setting fdd=1 and ip=1 in sliport_control register */ + rc = ocs_fdb_dump(ocs); + if (rc) { + ocs_log_err(ocs, "ocs_gen_dump failed\n"); + goto free_and_return; + } + + /* Copy the dump from the DMA buffer into the user buffer */ + offset = 0; + for (i = 0; i < num_buffers; i++) { + if (ocs_copy_to_user((uint8_t*)buf + offset, + dump_buffers[i].virt, dump_buffers[i].size)) { + ocs_log_err(ocs, "ocs_copy_to_user failed\n"); + rc = -1; + } + offset += dump_buffers[i].size; + } + +free_and_return: + /* Free the DMA buffer and return */ + for (i = 0; i < num_buffers; i++) { + ocs_dma_free(ocs, &dump_buffers[i]); + } + ocs_free(ocs, dump_buffers, sizeof(ocs_dma_t) * num_buffers); + return rc; + +} diff --git a/sys/dev/ocs_fc/ocs_gendump.h b/sys/dev/ocs_fc/ocs_gendump.h new file mode 100644 index 000000000000..2343003feef6 --- /dev/null +++ b/sys/dev/ocs_fc/ocs_gendump.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Broadcom. All rights reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#if !defined(__OCS_GENDUMP_H__) +#define __OCS_GENDUMP_H__ +extern int ocs_gen_dump(ocs_t *ocs); +extern int ocs_fdb_dump(ocs_t *ocs); +extern int ocs_dump_to_host(ocs_t *ocs, void *buf, uint32_t buflen); +extern int ocs_function_speciic_dump(ocs_t *ocs, void *buf, uint32_t buflen); + +#define OCS_MAX_HBA_PORTS 4 + +#endif // __OCS_GENDUMP_H__ diff --git a/sys/dev/ocs_fc/ocs_ioctl.c b/sys/dev/ocs_fc/ocs_ioctl.c index 13d80bd3edde..c0576bd6600f 100644 --- a/sys/dev/ocs_fc/ocs_ioctl.c +++ b/sys/dev/ocs_fc/ocs_ioctl.c @@ -60,22 +60,12 @@ ocs_firmware_write(ocs_t *ocs, const uint8_t *buf, size_t buf_len, uint8_t *chan static int ocs_open(struct cdev *cdev, int flags, int fmt, struct thread *td) { -#if 0 - struct ocs_softc *ocs = cdev->si_drv1; - - device_printf(ocs->dev, "%s\n", __func__); -#endif return 0; } static int ocs_close(struct cdev *cdev, int flag, int fmt, struct thread *td) { -#if 0 - struct ocs_softc *ocs = cdev->si_drv1; - - device_printf(ocs->dev, "%s\n", __func__); -#endif return 0; } @@ -95,7 +85,8 @@ __ocs_ioctl_mbox_cb(ocs_hw_t *hw, int32_t status, uint8_t *mqe, void *arg) } static int -ocs_process_sli_config (ocs_t *ocs, ocs_ioctl_elxu_mbox_t *mcmd, ocs_dma_t *dma){ +ocs_process_sli_config (ocs_t *ocs, ocs_ioctl_elxu_mbox_t *mcmd, ocs_dma_t *dma) +{ sli4_cmd_sli_config_t *sli_config = (sli4_cmd_sli_config_t *)mcmd->payload; if (sli_config->emb) { diff --git a/sys/dev/ocs_fc/ocs_ioctl.h b/sys/dev/ocs_fc/ocs_ioctl.h index ad2460d09b87..f2a291843d5a 100644 --- a/sys/dev/ocs_fc/ocs_ioctl.h +++ b/sys/dev/ocs_fc/ocs_ioctl.h @@ -303,18 +303,21 @@ typedef struct { typedef struct { uint8_t *name; /*<< Input: name of property to retrieve */ + uint16_t name_len; /*<< Input: Length of name */ uint8_t *value; /*<< Output: user space buffer in which to place the response */ uint32_t value_length; /*<< Input: size of the user space buffer */ } ocs_ioctl_cmd_get_t; typedef struct { uint8_t *name; /*<< Input: name of property to set */ + uint16_t name_len; /*<< Input: Length of name */ uint8_t *value; /*<< Input: user space buffer which contains the new value */ int32_t result; /*<< Output: result */ } ocs_ioctl_cmd_set_t; typedef struct { uint8_t *name; /*<< Input: name of action to execute */ + uint16_t name_len; /*<< Input: Length of name */ void *arg_in; /*<< Input: pointer to argument in user space */ uint32_t arg_in_length; /*<< Input: size of arg_in in bytes */ void *arg_out; /*<< Output: pointer to argument from kernel to user */ diff --git a/sys/dev/ocs_fc/ocs_mgmt.c b/sys/dev/ocs_fc/ocs_mgmt.c index 1f22a0316791..ff0e028caea2 100644 --- a/sys/dev/ocs_fc/ocs_mgmt.c +++ b/sys/dev/ocs_fc/ocs_mgmt.c @@ -42,6 +42,7 @@ #include "ocs.h" #include "ocs_mgmt.h" +#include "ocs_gendump.h" #include "ocs_vpd.h" #define SFP_PAGE_SIZE 128 @@ -55,11 +56,6 @@ static int ocs_mgmt_function_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_l static void ocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, uint32_t change_status, void *arg); static int ocs_mgmt_force_assert(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t); -#if defined(OCS_INCLUDE_RAMD) -static int32_t -ocs_mgmt_read_phys(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t); -#endif - /* Getters */ static void get_nodes_count(ocs_t *, char *, ocs_textbuf_t*); @@ -141,9 +137,6 @@ static int set_nv_wwn(ocs_t*, char*, char*); static int set_loglevel(ocs_t*, char*, char*); static void ocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg); -#if defined(OCS_INCLUDE_RAMD) -static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr); -#endif ocs_mgmt_table_entry_t mgmt_table[] = { {"nodes_count", get_nodes_count, NULL, NULL}, @@ -193,9 +186,6 @@ ocs_mgmt_table_entry_t mgmt_table[] = { {"firmware_write", NULL, NULL, ocs_mgmt_firmware_write}, {"firmware_reset", NULL, NULL, ocs_mgmt_firmware_reset}, {"function_reset", NULL, NULL, ocs_mgmt_function_reset}, -#if defined(OCS_INCLUDE_RAMD) - {"read_phys", NULL, NULL, ocs_mgmt_read_phys}, -#endif {"force_assert", NULL, NULL, ocs_mgmt_force_assert}, {"tgt_rscn_delay", get_tgt_rscn_delay, set_tgt_rscn_delay, NULL}, @@ -490,6 +480,15 @@ ocs_mgmt_exec(ocs_t *ocs, char *action, void *arg_in, } } + /* See if it's a value I can supply */ + if (ocs_strcmp(unqualified_name, "driver/gendump") == 0) { + return ocs_gen_dump(ocs); + } + + if (ocs_strcmp(unqualified_name, "driver/dump_to_host") == 0) { + return ocs_dump_to_host(ocs, arg_out, arg_out_length); + } + if ((ocs->mgmt_functions) && (ocs->mgmt_functions->exec_handler)) { result = ocs->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length, arg_out, arg_out_length, ocs); @@ -559,137 +558,6 @@ ocs_mgmt_get_all(ocs_t *ocs, ocs_textbuf_t *textbuf) ocs_mgmt_end_unnumbered_section(textbuf, "ocs"); } -#if defined(OCS_INCLUDE_RAMD) -static int32_t -ocs_mgmt_read_phys(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length) -{ - uint32_t length; - char addr_str[80]; - uintptr_t target_addr; - void* vaddr = NULL; - ocs_ramdisc_t **ramdisc_array; - uint32_t ramdisc_count; - - if ((arg_in == NULL) || - (arg_in_length == 0) || - (arg_out == NULL) || - (arg_out_length == 0)) { - return -1; - } - - if (arg_in_length > 80) { - arg_in_length = 80; - } - - if (ocs_copy_from_user(addr_str, arg_in, arg_in_length)) { - ocs_log_test(ocs, "Failed to copy addr from user\n"); - return -EFAULT; - } - - target_addr = (uintptr_t)ocs_strtoul(addr_str, NULL, 0); - /* addr_str must be the physical address of a buffer that was reported - * in an SGL. Search ramdiscs looking for a segment that contains that - * physical address - */ - - if (ocs->tgt_ocs.use_global_ramd) { - /* Only one target */ - ramdisc_count = ocs->tgt_ocs.rdisc_count; - ramdisc_array = ocs->tgt_ocs.rdisc; - vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr); - } else { - /* Multiple targets. Each target is on a sport */ - uint32_t domain_idx; - - for (domain_idx=0; domain_idx<ocs->domain_instance_count; domain_idx++) { - ocs_domain_t *domain; - uint32_t sport_idx; - - domain = ocs_domain_get_instance(ocs, domain_idx); - for (sport_idx=0; sport_idx < domain->sport_instance_count; sport_idx++) { - ocs_sport_t *sport; - - sport = ocs_sport_get_instance(domain, sport_idx); - ramdisc_count = sport->tgt_sport.rdisc_count; - ramdisc_array = sport->tgt_sport.rdisc; - vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr); - - if (vaddr != NULL) { - break; - } - } - } - } - - length = arg_out_length; - - if (vaddr != NULL) { - if (ocs_copy_to_user(arg_out, vaddr, length)) { - ocs_log_test(ocs, "Failed to copy buffer to user\n"); - return -EFAULT; - } - - return 0; - } else { - return -EFAULT; - } - -} - -/* - * This function searches a target for a given physical address. - * The target is made up of a number of LUNs, each represented by - * a ocs_ramdisc_t. - */ -static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr) -{ - void *vaddr = NULL; - uint32_t ramdisc_idx; - - /* Check each ramdisc */ - for (ramdisc_idx=0; ramdisc_idx<ramdisc_count; ramdisc_idx++) { - uint32_t segment_idx; - ocs_ramdisc_t *rdisc; - rdisc = ramdisc_array[ramdisc_idx]; - /* Check each segment in the ramdisc */ - for (segment_idx=0; segment_idx<rdisc->segment_count; segment_idx++) { - ramdisc_segment_t *segment = rdisc->segments[segment_idx]; - uintptr_t segment_start; - uintptr_t segment_end; - uint32_t offset; - - segment_start = segment->data_segment.phys; - segment_end = segment->data_segment.phys + segment->data_segment.size - 1; - if ((target_addr >= segment_start) && (target_addr <= segment_end)) { - /* Found the target address */ - offset = target_addr - segment_start; - vaddr = (uint32_t*)segment->data_segment.virt + offset; - } - - if (rdisc->dif_separate) { - segment_start = segment->dif_segment.phys; - segment_end = segment->data_segment.phys + segment->dif_segment.size - 1; - if ((target_addr >= segment_start) && (target_addr <= segment_end)) { - /* Found the target address */ - offset = target_addr - segment_start; - vaddr = (uint32_t*)segment->dif_segment.virt + offset; - } - } - - if (vaddr != NULL) { - break; - } - } - - if (vaddr != NULL) { - break; - } - } - - return vaddr; -} -#endif - static int32_t ocs_mgmt_firmware_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length) { diff --git a/sys/dev/ocs_fc/ocs_os.c b/sys/dev/ocs_fc/ocs_os.c index 985a611ba91e..4e4edea2e63f 100644 --- a/sys/dev/ocs_fc/ocs_os.c +++ b/sys/dev/ocs_fc/ocs_os.c @@ -883,13 +883,12 @@ ocs_pci_model(uint16_t vendor, uint16_t device) return "unknown"; } -int32_t +void ocs_get_bus_dev_func(ocs_t *ocs, uint8_t* bus, uint8_t* dev, uint8_t* func) { *bus = pci_get_bus(ocs->dev); *dev = pci_get_slot(ocs->dev); *func= pci_get_function(ocs->dev); - return 0; } /** diff --git a/sys/dev/ocs_fc/ocs_os.h b/sys/dev/ocs_fc/ocs_os.h index a7ad51257641..9ab3be96ec2e 100644 --- a/sys/dev/ocs_fc/ocs_os.h +++ b/sys/dev/ocs_fc/ocs_os.h @@ -1050,9 +1050,8 @@ typedef struct ocs_pci_reg_s { * @param dev Pointer to location to store the device number. * @param func Pointer to location to store the function number. * - * @return Returns 0. */ -extern int32_t +extern void ocs_get_bus_dev_func(ocs_t *ocs, uint8_t* bus, uint8_t* dev, uint8_t* func); extern ocs_t *ocs_get_instance(uint32_t index); diff --git a/sys/modules/ocs_fc/Makefile b/sys/modules/ocs_fc/Makefile index 9bab50eba5bc..8d546f9eabfd 100644 --- a/sys/modules/ocs_fc/Makefile +++ b/sys/modules/ocs_fc/Makefile @@ -33,7 +33,8 @@ SRCS += \ ocs_scsi.c \ ocs_unsol.c \ ocs_ddump.c \ - ocs_mgmt.c + ocs_mgmt.c \ + ocs_gendump.c # CAM initiator/target