|
Packit |
7e09eb |
/*
|
|
Packit |
7e09eb |
* Intel(R) Enclosure LED Utilities
|
|
Packit |
7e09eb |
* Copyright (C) 2009-2020 Intel Corporation.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This program is free software; you can redistribute it and/or modify it
|
|
Packit |
7e09eb |
* under the terms and conditions of the GNU General Public License,
|
|
Packit |
7e09eb |
* version 2, as published by the Free Software Foundation.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
Packit |
7e09eb |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Packit |
7e09eb |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
Packit |
7e09eb |
* more details.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* You should have received a copy of the GNU General Public License along with
|
|
Packit |
7e09eb |
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
7e09eb |
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#include <dirent.h>
|
|
Packit |
7e09eb |
#include <fcntl.h>
|
|
Packit |
7e09eb |
#include <limits.h>
|
|
Packit |
7e09eb |
#include <stdint.h>
|
|
Packit |
7e09eb |
#include <stdio.h>
|
|
Packit |
7e09eb |
#include <stdlib.h>
|
|
Packit |
7e09eb |
#include <string.h>
|
|
Packit |
7e09eb |
#include <sys/types.h>
|
|
Packit |
7e09eb |
#include <unistd.h>
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#if _HAVE_DMALLOC_H
|
|
Packit |
7e09eb |
#include <dmalloc.h>
|
|
Packit |
7e09eb |
#endif
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#include "ahci.h"
|
|
Packit |
7e09eb |
#include "block.h"
|
|
Packit |
7e09eb |
#include "config.h"
|
|
Packit |
7e09eb |
#include "dellssd.h"
|
|
Packit |
7e09eb |
#include "pci_slot.h"
|
|
Packit |
7e09eb |
#include "raid.h"
|
|
Packit |
7e09eb |
#include "scsi.h"
|
|
Packit |
7e09eb |
#include "slave.h"
|
|
Packit |
7e09eb |
#include "smp.h"
|
|
Packit |
7e09eb |
#include "status.h"
|
|
Packit |
7e09eb |
#include "sysfs.h"
|
|
Packit |
7e09eb |
#include "utils.h"
|
|
Packit |
7e09eb |
#include "vmdssd.h"
|
|
Packit |
7e09eb |
#include "npem.h"
|
|
Packit |
7e09eb |
#include "amd.h"
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/* Global timestamp value. It shell be used to update a timestamp field of block
|
|
Packit |
7e09eb |
device structure. See block.h for details. */
|
|
Packit |
7e09eb |
time_t timestamp = 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
* @brief Determines if disk is attached directly or via expander
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
int dev_directly_attached(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
if (strstr(path, "/expander") == 0)
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
* @brief Determines a send function.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This is the internal function of 'block device' module. The function tries to
|
|
Packit |
7e09eb |
* determine a LED management protocol based on controller type and the given
|
|
Packit |
7e09eb |
* path to block device in sysfs tree. First it checks whether to use
|
|
Packit |
7e09eb |
* the default send function. If not it tries to read the content
|
|
Packit |
7e09eb |
* of em_message_type field from sysfs tree and determines
|
|
Packit |
7e09eb |
* the LED control protocol.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @param[in] cntrl type of a controller a device is connected to.
|
|
Packit |
7e09eb |
* @param[in] path path to a block device in sysfs tree.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @return Pointer to send message function if successful, otherwise the function
|
|
Packit |
7e09eb |
* returns the NULL pointer and it means either the controller does not
|
|
Packit |
7e09eb |
* support enclosure management or LED control protocol
|
|
Packit |
7e09eb |
* is not supported.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static send_message_t _get_send_fn(struct cntrl_device *cntrl, const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
send_message_t result = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (cntrl->cntrl_type == CNTRL_TYPE_AHCI) {
|
|
Packit |
7e09eb |
result = ahci_sgpio_write;
|
|
Packit |
7e09eb |
} else if (cntrl->cntrl_type == CNTRL_TYPE_SCSI
|
|
Packit |
7e09eb |
&& !dev_directly_attached(path)) {
|
|
Packit |
7e09eb |
result = scsi_ses_write;
|
|
Packit |
7e09eb |
} else if (cntrl->cntrl_type == CNTRL_TYPE_SCSI
|
|
Packit |
7e09eb |
&& dev_directly_attached(path)) {
|
|
Packit |
7e09eb |
result = scsi_smp_fill_buffer;
|
|
Packit |
7e09eb |
} else if (cntrl->cntrl_type == CNTRL_TYPE_DELLSSD) {
|
|
Packit |
7e09eb |
result = dellssd_write;
|
|
Packit |
7e09eb |
} else if (cntrl->cntrl_type == CNTRL_TYPE_VMD) {
|
|
Packit |
7e09eb |
result = vmdssd_write;
|
|
Packit |
7e09eb |
} else if (cntrl->cntrl_type == CNTRL_TYPE_NPEM) {
|
|
Packit |
7e09eb |
result = npem_write;
|
|
Packit |
7e09eb |
} else if (cntrl->cntrl_type == CNTRL_TYPE_AMD) {
|
|
Packit |
7e09eb |
result = amd_write;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return result;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int do_not_flush(struct block_device *device __attribute__ ((unused)))
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static flush_message_t _get_flush_fn(struct cntrl_device *cntrl, const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
flush_message_t result = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (cntrl->cntrl_type == CNTRL_TYPE_SCSI) {
|
|
Packit |
7e09eb |
if (dev_directly_attached(path))
|
|
Packit |
7e09eb |
result = scsi_smp_write_buffer;
|
|
Packit |
7e09eb |
else
|
|
Packit |
7e09eb |
result = scsi_ses_flush;
|
|
Packit |
7e09eb |
} else {
|
|
Packit |
7e09eb |
result = do_not_flush;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return result;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
* @brief Determines a host path to block device.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This is the internal function of 'block device' module. The function
|
|
Packit |
7e09eb |
* determines a host path to block device in sysfs.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @param[in] path path to block device in sysfs.
|
|
Packit |
7e09eb |
* @param[in] cntrl controller device the block
|
|
Packit |
7e09eb |
* device is connected to.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @return Pointer to memory block containing a host path. The memory block
|
|
Packit |
7e09eb |
* should be freed if one don't need the content.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static char *_get_host(char *path, struct cntrl_device *cntrl)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
char *result = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (cntrl->cntrl_type == CNTRL_TYPE_SCSI)
|
|
Packit |
7e09eb |
result = scsi_get_slot_path(path, cntrl->sysfs_path);
|
|
Packit |
7e09eb |
else if (cntrl->cntrl_type == CNTRL_TYPE_AHCI)
|
|
Packit |
7e09eb |
result = ahci_get_port_path(path);
|
|
Packit |
7e09eb |
else if (cntrl->cntrl_type == CNTRL_TYPE_DELLSSD)
|
|
Packit |
7e09eb |
result = dellssd_get_path(cntrl->sysfs_path);
|
|
Packit |
7e09eb |
else if (cntrl->cntrl_type == CNTRL_TYPE_VMD)
|
|
Packit |
7e09eb |
result = vmdssd_get_path(cntrl->sysfs_path);
|
|
Packit |
7e09eb |
else if (cntrl->cntrl_type == CNTRL_TYPE_NPEM)
|
|
Packit |
7e09eb |
result = npem_get_path(cntrl->sysfs_path);
|
|
Packit |
7e09eb |
else if (cntrl->cntrl_type == CNTRL_TYPE_AMD)
|
|
Packit |
7e09eb |
result = amd_get_path(path, cntrl->sysfs_path);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
return result;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int is_host_id_supported(const struct block_device *bd)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
if (!bd->cntrl)
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
switch (bd->cntrl->cntrl_type) {
|
|
Packit |
7e09eb |
case CNTRL_TYPE_DELLSSD:
|
|
Packit |
7e09eb |
case CNTRL_TYPE_VMD:
|
|
Packit |
7e09eb |
case CNTRL_TYPE_NPEM:
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
default:
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
* @brief Determines a storage controller.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This is the internal function of 'block device' module. The function gets
|
|
Packit |
7e09eb |
* a pointer to controller structure the device is connected to.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @param[in] cntrl_list pointer to list of supported controllers.
|
|
Packit |
7e09eb |
* @param[in] path path to block device in sysfs tree.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @return Pointer to controller structure if successful, otherwise the function
|
|
Packit |
7e09eb |
* returns NULL pointer. The NULL pointer means that block devices is
|
|
Packit |
7e09eb |
* connected to unsupported storage controller.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
struct cntrl_device *block_get_controller(const struct list *cntrl_list, char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct cntrl_device *cntrl;
|
|
Packit |
7e09eb |
struct cntrl_device *non_npem_cntrl = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
list_for_each(cntrl_list, cntrl) {
|
|
Packit |
7e09eb |
if (strncmp(cntrl->sysfs_path, path,
|
|
Packit |
7e09eb |
strlen(cntrl->sysfs_path)) == 0) {
|
|
Packit |
7e09eb |
if (cntrl->cntrl_type == CNTRL_TYPE_NPEM)
|
|
Packit |
7e09eb |
return cntrl;
|
|
Packit |
7e09eb |
non_npem_cntrl = cntrl;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return non_npem_cntrl;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
struct _host_type *block_get_host(struct cntrl_device *cntrl, int host_id)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct _host_type *hosts = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (!cntrl)
|
|
Packit |
7e09eb |
return hosts;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
hosts = cntrl->hosts;
|
|
Packit |
7e09eb |
while (hosts) {
|
|
Packit |
7e09eb |
if (hosts->host_id == host_id)
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
hosts = hosts->next;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return hosts;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/*
|
|
Packit |
7e09eb |
* Allocates a new block device structure. See block.h for details.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
struct block_device *block_device_init(const struct list *cntrl_list, const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct cntrl_device *cntrl;
|
|
Packit |
7e09eb |
char link[PATH_MAX];
|
|
Packit |
7e09eb |
char *host = NULL;
|
|
Packit |
7e09eb |
struct block_device *device = NULL;
|
|
Packit |
7e09eb |
struct pci_slot *pci_slot = NULL;
|
|
Packit |
7e09eb |
send_message_t send_fn = NULL;
|
|
Packit |
7e09eb |
flush_message_t flush_fn = NULL;
|
|
Packit |
7e09eb |
int host_id = -1;
|
|
Packit |
7e09eb |
char *host_name;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (realpath(path, link)) {
|
|
Packit |
7e09eb |
pci_slot = vmdssd_find_pci_slot(link);
|
|
Packit |
7e09eb |
cntrl = block_get_controller(cntrl_list, link);
|
|
Packit |
7e09eb |
if (cntrl != NULL) {
|
|
Packit |
7e09eb |
if (cntrl->cntrl_type == CNTRL_TYPE_VMD && !pci_slot)
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
host = _get_host(link, cntrl);
|
|
Packit |
7e09eb |
if (host == NULL)
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
host_name = get_path_hostN(link);
|
|
Packit |
7e09eb |
if (host_name) {
|
|
Packit |
7e09eb |
if (sscanf(host_name, "host%d", &host_id) != 1)
|
|
Packit |
7e09eb |
host_id = -1;
|
|
Packit |
7e09eb |
free(host_name);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
flush_fn = _get_flush_fn(cntrl, link);
|
|
Packit |
7e09eb |
send_fn = _get_send_fn(cntrl, link);
|
|
Packit |
7e09eb |
if (send_fn == NULL) {
|
|
Packit |
7e09eb |
free(host);
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
} else {
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
device = calloc(1, sizeof(*device));
|
|
Packit |
7e09eb |
if (device) {
|
|
Packit |
7e09eb |
struct _host_type *hosts = cntrl ? cntrl->hosts : NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
device->cntrl = cntrl;
|
|
Packit |
7e09eb |
device->sysfs_path = str_dup(link);
|
|
Packit |
7e09eb |
device->cntrl_path = host;
|
|
Packit |
7e09eb |
device->ibpi = IBPI_PATTERN_UNKNOWN;
|
|
Packit |
7e09eb |
device->ibpi_prev = IBPI_PATTERN_NONE;
|
|
Packit |
7e09eb |
device->send_fn = send_fn;
|
|
Packit |
7e09eb |
device->flush_fn = flush_fn;
|
|
Packit |
7e09eb |
device->timestamp = timestamp;
|
|
Packit |
7e09eb |
device->host = NULL;
|
|
Packit |
7e09eb |
device->host_id = host_id;
|
|
Packit |
7e09eb |
device->encl_index = -1;
|
|
Packit |
7e09eb |
device->raid_dev = NULL;
|
|
Packit |
7e09eb |
while (hosts) {
|
|
Packit |
7e09eb |
if (hosts->host_id == host_id) {
|
|
Packit |
7e09eb |
device->host = hosts;
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
hosts = hosts->next;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
if (cntrl && cntrl->cntrl_type == CNTRL_TYPE_SCSI) {
|
|
Packit |
7e09eb |
device->phy_index = cntrl_init_smp(link, cntrl);
|
|
Packit |
7e09eb |
if (!dev_directly_attached(link)
|
|
Packit |
7e09eb |
&& !scsi_get_enclosure(device)) {
|
|
Packit |
7e09eb |
log_debug("Device initialization failed for '%s'",
|
|
Packit |
7e09eb |
path);
|
|
Packit |
7e09eb |
free(device->sysfs_path);
|
|
Packit |
7e09eb |
free(device->cntrl_path);
|
|
Packit |
7e09eb |
free(device);
|
|
Packit |
7e09eb |
device = NULL;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
} else if (host) {
|
|
Packit |
7e09eb |
free(host);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return device;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
* Frees memory allocated for block device structure. See block.h for details.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
void block_device_fini(struct block_device *device)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
if (device) {
|
|
Packit |
7e09eb |
if (device->sysfs_path)
|
|
Packit |
7e09eb |
free(device->sysfs_path);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (device->cntrl_path)
|
|
Packit |
7e09eb |
free(device->cntrl_path);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (device->raid_dev)
|
|
Packit |
7e09eb |
raid_device_fini(device->raid_dev);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
free(device);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/*
|
|
Packit |
7e09eb |
* Duplicates a block device structure. See block.h for details.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
struct block_device *block_device_duplicate(struct block_device *block)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct block_device *result = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (block) {
|
|
Packit |
7e09eb |
result = calloc(1, sizeof(*result));
|
|
Packit |
7e09eb |
if (result) {
|
|
Packit |
7e09eb |
result->sysfs_path = str_dup(block->sysfs_path);
|
|
Packit |
7e09eb |
result->cntrl_path = str_dup(block->cntrl_path);
|
|
Packit |
7e09eb |
if (block->ibpi != IBPI_PATTERN_UNKNOWN)
|
|
Packit |
7e09eb |
result->ibpi = block->ibpi;
|
|
Packit |
7e09eb |
else
|
|
Packit |
7e09eb |
result->ibpi = IBPI_PATTERN_ONESHOT_NORMAL;
|
|
Packit |
7e09eb |
result->ibpi_prev = block->ibpi_prev;
|
|
Packit |
7e09eb |
result->send_fn = block->send_fn;
|
|
Packit |
7e09eb |
result->flush_fn = block->flush_fn;
|
|
Packit |
7e09eb |
result->timestamp = block->timestamp;
|
|
Packit |
7e09eb |
result->cntrl = block->cntrl;
|
|
Packit |
7e09eb |
result->host = block->host;
|
|
Packit |
7e09eb |
result->host_id = block->host_id;
|
|
Packit |
7e09eb |
result->phy_index = block->phy_index;
|
|
Packit |
7e09eb |
result->encl_index = block->encl_index;
|
|
Packit |
7e09eb |
result->enclosure = block->enclosure;
|
|
Packit |
7e09eb |
result->raid_dev =
|
|
Packit |
7e09eb |
raid_device_duplicate(block->raid_dev);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return result;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
int block_compare(const struct block_device *bd_old,
|
|
Packit |
7e09eb |
const struct block_device *bd_new)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
int i = 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (is_host_id_supported(bd_old) && bd_old->host_id == -1) {
|
|
Packit |
7e09eb |
log_debug("Device %s : No host_id!",
|
|
Packit |
7e09eb |
strstr(bd_old->sysfs_path, "host"));
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
if (is_host_id_supported(bd_new) && bd_new->host_id == -1) {
|
|
Packit |
7e09eb |
log_debug("Device %s : No host_id!",
|
|
Packit |
7e09eb |
strstr(bd_new->sysfs_path, "host"));
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (bd_old->cntrl->cntrl_type != bd_new->cntrl->cntrl_type)
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
switch (bd_old->cntrl->cntrl_type) {
|
|
Packit |
7e09eb |
case CNTRL_TYPE_AHCI:
|
|
Packit |
7e09eb |
/* Missing support for port multipliers. Compare just hostX. */
|
|
Packit |
7e09eb |
i = (bd_old->host_id == bd_new->host_id);
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
case CNTRL_TYPE_SCSI:
|
|
Packit |
7e09eb |
/* Host and phy is not enough. They might be DA or EA. */
|
|
Packit |
7e09eb |
if (dev_directly_attached(bd_old->sysfs_path) &&
|
|
Packit |
7e09eb |
dev_directly_attached(bd_new->sysfs_path)) {
|
|
Packit |
7e09eb |
/* Just compare host & phy */
|
|
Packit |
7e09eb |
i = (bd_old->host_id == bd_new->host_id) &&
|
|
Packit |
7e09eb |
(bd_old->phy_index == bd_new->phy_index);
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
if (!dev_directly_attached(bd_old->sysfs_path) &&
|
|
Packit |
7e09eb |
!dev_directly_attached(bd_new->sysfs_path)) {
|
|
Packit |
7e09eb |
/* Both expander attached */
|
|
Packit |
7e09eb |
i = (bd_old->host_id == bd_new->host_id) &&
|
|
Packit |
7e09eb |
(bd_old->phy_index == bd_new->phy_index);
|
|
Packit |
7e09eb |
i = i && (bd_old->enclosure == bd_new->enclosure);
|
|
Packit |
7e09eb |
i = i && (bd_old->encl_index == bd_new->encl_index);
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
/* */
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
case CNTRL_TYPE_VMD:
|
|
Packit |
7e09eb |
/* compare names and address of the drive */
|
|
Packit |
7e09eb |
i = (strcmp(bd_old->sysfs_path, bd_new->sysfs_path) == 0);
|
|
Packit |
7e09eb |
if (!i) {
|
|
Packit |
7e09eb |
struct pci_slot *old_slot, *new_slot;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
old_slot = vmdssd_find_pci_slot(bd_old->sysfs_path);
|
|
Packit |
7e09eb |
new_slot = vmdssd_find_pci_slot(bd_new->sysfs_path);
|
|
Packit |
7e09eb |
if (old_slot && new_slot)
|
|
Packit |
7e09eb |
i = (strcmp(old_slot->address, new_slot->address) == 0);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
case CNTRL_TYPE_NPEM:
|
|
Packit |
7e09eb |
/* check controller to determine slot. */
|
|
Packit |
7e09eb |
i = (strcmp(bd_old->cntrl_path, bd_new->cntrl_path) == 0);
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
case CNTRL_TYPE_DELLSSD:
|
|
Packit |
7e09eb |
default:
|
|
Packit |
7e09eb |
/* Just compare names */
|
|
Packit |
7e09eb |
i = (strcmp(bd_old->sysfs_path, bd_new->sysfs_path) == 0);
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return i;
|
|
Packit |
7e09eb |
}
|