ocs_fc: Add gendump and dump_to_host ioctl command support.

Support to generate firmware dump.

Approved by: mav(mentor)
This commit is contained in:
Ram Kishore Vegesna 2021-06-24 12:35:00 +05:30
parent 2b2c460d7b
commit 29e2dbd42c
8 changed files with 449 additions and 158 deletions

View File

@ -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;
}

View File

@ -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__

View File

@ -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) {

View File

@ -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 */

View File

@ -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)
{

View File

@ -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;
}
/**

View File

@ -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);

View File

@ -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