|
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 <limits.h>
|
|
Packit |
7e09eb |
#include <stdint.h>
|
|
Packit |
7e09eb |
#include <stdio.h>
|
|
Packit |
7e09eb |
#include <stdlib.h>
|
|
Packit |
7e09eb |
#include <string.h>
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#if _HAVE_DMALLOC_H
|
|
Packit |
7e09eb |
#include <dmalloc.h>
|
|
Packit |
7e09eb |
#endif
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#include "cntrl.h"
|
|
Packit |
7e09eb |
#include "config.h"
|
|
Packit |
7e09eb |
#include "config_file.h"
|
|
Packit |
7e09eb |
#include "list.h"
|
|
Packit |
7e09eb |
#include "smp.h"
|
|
Packit |
7e09eb |
#include "status.h"
|
|
Packit |
7e09eb |
#include "sysfs.h"
|
|
Packit |
7e09eb |
#include "utils.h"
|
|
Packit |
7e09eb |
#include "amd.h"
|
|
Packit |
7e09eb |
#include "npem.h"
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
* @brief Name of controllers types.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This is internal array with names of controller types. Array can be use to
|
|
Packit |
7e09eb |
* translate enumeration type into the string.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static const char * const ctrl_type_str[] = {
|
|
Packit |
7e09eb |
[CNTRL_TYPE_UNKNOWN] = "?",
|
|
Packit |
7e09eb |
[CNTRL_TYPE_DELLSSD] = "Dell SSD",
|
|
Packit |
7e09eb |
[CNTRL_TYPE_VMD] = "VMD",
|
|
Packit |
7e09eb |
[CNTRL_TYPE_SCSI] = "SCSI",
|
|
Packit |
7e09eb |
[CNTRL_TYPE_AHCI] = "AHCI",
|
|
Packit |
7e09eb |
[CNTRL_TYPE_NPEM] = "NPEM",
|
|
Packit |
7e09eb |
[CNTRL_TYPE_AMD] = "AMD",
|
|
Packit |
7e09eb |
};
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static int _is_storage_controller(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
uint64_t class = get_uint64(path, 0, "class");
|
|
Packit |
7e09eb |
return (class & 0xff0000L) == 0x010000L;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static int _is_isci_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
return sysfs_check_driver(path, "isci");
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static int _is_cntrl(const char *path, const char *type)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
char temp[PATH_MAX], link[PATH_MAX], *t;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
snprintf(temp, sizeof(temp), "%s/driver", path);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (realpath(temp, link) == NULL)
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
t = strrchr(link, '/');
|
|
Packit |
7e09eb |
if ((t != NULL) && (strcmp(t + 1, type) != 0))
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int _is_ahci_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
return _is_cntrl(path, "ahci");
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int _is_nvme_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
return _is_cntrl(path, "nvme");
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int _is_intel_ahci_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
if (!_is_ahci_cntrl(path))
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
return get_uint64(path, 0, "vendor") == 0x8086L;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int _is_amd_ahci_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
if (!_is_ahci_cntrl(path))
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
return get_uint64(path, 0, "vendor") == 0x1022L;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int _is_amd_nvme_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
char tmp[PATH_MAX];
|
|
Packit |
7e09eb |
char *t;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (!_is_nvme_cntrl(path))
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
sprintf(tmp, "%s", path);
|
|
Packit |
7e09eb |
t = strrchr(tmp, '/');
|
|
Packit |
7e09eb |
if (!t)
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
t++;
|
|
Packit |
7e09eb |
*t = '\0';
|
|
Packit |
7e09eb |
return get_uint64(tmp, 0, "vendor") == 0x1022L;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int _is_amd_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
if (_is_amd_ahci_cntrl(path))
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (_is_amd_nvme_cntrl(path))
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
extern int get_dell_server_type(void);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int _is_dellssd_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
uint64_t vdr, dev, svdr, cls;
|
|
Packit |
7e09eb |
int gen = 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
vdr = get_uint64(path, 0, "vendor");
|
|
Packit |
7e09eb |
dev = get_uint64(path, 0, "device");
|
|
Packit |
7e09eb |
cls = get_uint64(path, 0, "class");
|
|
Packit |
7e09eb |
svdr = get_uint64(path, 0, "subsystem_vendor");
|
|
Packit |
7e09eb |
if (cls == 0x10802)
|
|
Packit |
7e09eb |
gen = get_dell_server_type();
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
return ((vdr == 0x1344L && dev == 0x5150L) || /* micron ssd */
|
|
Packit |
7e09eb |
(gen != 0) || /* Dell Server+NVME */
|
|
Packit |
7e09eb |
(svdr == 0x1028 && cls == 0x10802)); /* nvmhci ssd */
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static int _is_smp_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
int result = 0;
|
|
Packit |
7e09eb |
struct list dir;
|
|
Packit |
7e09eb |
char *p;
|
|
Packit |
7e09eb |
char host_path[PATH_MAX] = { 0 };
|
|
Packit |
7e09eb |
if (scan_dir(path, &dir) == 0) {
|
|
Packit |
7e09eb |
const char *dir_path;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
list_for_each(&dir, dir_path) {
|
|
Packit |
7e09eb |
p = strrchr(dir_path, '/');
|
|
Packit |
7e09eb |
if (!p++)
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
if (strncmp(p, "host", strlen("host")) == 0) {
|
|
Packit |
7e09eb |
snprintf(host_path, sizeof(host_path),
|
|
Packit |
7e09eb |
"%s/%s/bsg/sas_%s", path, p, p);
|
|
Packit |
7e09eb |
result = smp_write_gpio(host_path,
|
|
Packit |
7e09eb |
GPIO_REG_TYPE_TX,
|
|
Packit |
7e09eb |
0,
|
|
Packit |
7e09eb |
0,
|
|
Packit |
7e09eb |
"",
|
|
Packit |
7e09eb |
0) == 0;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
list_erase(&dir;;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
return result;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int _is_vmd_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
return sysfs_check_driver(path, "vmd");
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int _is_npem_cntrl(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
return is_npem_capable(path);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
* @brief Determines the type of controller.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This is internal function of 'controller device' module. The function
|
|
Packit |
7e09eb |
* determines the type of controller device. It might be AHCI, SCSI or
|
|
Packit |
7e09eb |
* UNKNOWN device type.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @param[in] path path to controller device in sysfs tree.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @return The type of controller device. If the type returned is
|
|
Packit |
7e09eb |
* CNTRL_TYPE_UNKNOWN this means a controller device is not
|
|
Packit |
7e09eb |
* supported.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static enum cntrl_type _get_type(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
enum cntrl_type type = CNTRL_TYPE_UNKNOWN;
|
|
Packit |
7e09eb |
if (_is_npem_cntrl(path)) {
|
|
Packit |
7e09eb |
type = CNTRL_TYPE_NPEM;
|
|
Packit |
7e09eb |
} else if (_is_vmd_cntrl(path)) {
|
|
Packit |
7e09eb |
type = CNTRL_TYPE_VMD;
|
|
Packit |
7e09eb |
} else if (_is_dellssd_cntrl(path)) {
|
|
Packit |
7e09eb |
type = CNTRL_TYPE_DELLSSD;
|
|
Packit |
7e09eb |
} else if (_is_storage_controller(path)) {
|
|
Packit |
7e09eb |
if (_is_intel_ahci_cntrl(path))
|
|
Packit |
7e09eb |
type = CNTRL_TYPE_AHCI;
|
|
Packit |
7e09eb |
else if (_is_amd_cntrl(path))
|
|
Packit |
7e09eb |
type = CNTRL_TYPE_AMD;
|
|
Packit |
7e09eb |
else if (_is_isci_cntrl(path)
|
|
Packit |
7e09eb |
|| sysfs_enclosure_attached_to_cntrl(path)
|
|
Packit |
7e09eb |
|| _is_smp_cntrl(path))
|
|
Packit |
7e09eb |
type = CNTRL_TYPE_SCSI;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return type;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
struct _host_type *alloc_host(int id, struct _host_type *next)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct _host_type *host = NULL;
|
|
Packit |
7e09eb |
host = malloc(sizeof(struct _host_type));
|
|
Packit |
7e09eb |
if (host) {
|
|
Packit |
7e09eb |
host->host_id = id;
|
|
Packit |
7e09eb |
host->ibpi_state_buffer = NULL;
|
|
Packit |
7e09eb |
memset(host->bitstream, 0, sizeof(host->bitstream));
|
|
Packit |
7e09eb |
host->flush = 0;
|
|
Packit |
7e09eb |
host->ports = 0;
|
|
Packit |
7e09eb |
host->next = next;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return host;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
void free_hosts(struct _host_type *h)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct _host_type *t;
|
|
Packit |
7e09eb |
while (h) {
|
|
Packit |
7e09eb |
t = h->next;
|
|
Packit |
7e09eb |
free(h->ibpi_state_buffer);
|
|
Packit |
7e09eb |
free(h);
|
|
Packit |
7e09eb |
h = t;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
void _find_host(const char *path, struct _host_type **hosts)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
const int host_len = sizeof("host") - 1;
|
|
Packit |
7e09eb |
char *p;
|
|
Packit |
7e09eb |
int index = -1;
|
|
Packit |
7e09eb |
struct _host_type *th;
|
|
Packit |
7e09eb |
DIR *d;
|
|
Packit |
7e09eb |
struct dirent *de;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
p = strrchr(path, '/');
|
|
Packit |
7e09eb |
if (!p++)
|
|
Packit |
7e09eb |
return;
|
|
Packit |
7e09eb |
if (strncmp(p, "host", host_len - 1) == 0) {
|
|
Packit |
7e09eb |
index = atoi(p + host_len);
|
|
Packit |
7e09eb |
th = alloc_host(index, (*hosts) ? (*hosts) : NULL);
|
|
Packit |
7e09eb |
if (!th)
|
|
Packit |
7e09eb |
return;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
d = opendir(path);
|
|
Packit |
7e09eb |
if(!d) {
|
|
Packit |
7e09eb |
free(th);
|
|
Packit |
7e09eb |
return;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
while ((de = readdir(d))) {
|
|
Packit |
7e09eb |
if (strncmp(de->d_name, "phy-", strlen("phy-")) == 0) {
|
|
Packit |
7e09eb |
th->ports++;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
closedir(d);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
*hosts = th;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
* @brief Get all instances of separate hosts on isci controller.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static struct _host_type *_cntrl_get_hosts(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct _host_type *hosts = NULL;
|
|
Packit |
7e09eb |
struct list dir;
|
|
Packit |
7e09eb |
if (scan_dir(path, &dir) == 0) {
|
|
Packit |
7e09eb |
const char *dir_path;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
list_for_each(&dir, dir_path)
|
|
Packit |
7e09eb |
_find_host(dir_path, &hosts);
|
|
Packit |
7e09eb |
list_erase(&dir;;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return hosts;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
* @brief Check if enclosure management is enabled.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This is internal function of 'controller device' module. The function checks
|
|
Packit |
7e09eb |
* whether enclosure management is enabled for AHCI controller.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @param[in] path path to controller device in sysfs tree.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* @return 1 if enclosure management is enabled, otherwise the function returns 0.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static unsigned int _ahci_em_messages(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
/* first, open ...driver/module/parameters/ahci_em_messages
|
|
Packit |
7e09eb |
* then open /sys/module/libahci/parameters/ahci_em_messages
|
|
Packit |
7e09eb |
* and check if it is set to enabled.
|
|
Packit |
7e09eb |
* if so, check if 'holders' of libahci points the same driver name
|
|
Packit |
7e09eb |
* as device given by path
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
char buf[PATH_MAX];
|
|
Packit |
7e09eb |
char *link, *name;
|
|
Packit |
7e09eb |
DIR *dh;
|
|
Packit |
7e09eb |
struct dirent *de = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/* old kernel (prior to 2.6.36) */
|
|
Packit |
7e09eb |
if (get_int(path, 0, "driver/module/parameters/ahci_em_messages") != 0)
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/* parameter type changed from int to bool since kernel v3.13 */
|
|
Packit |
7e09eb |
if (!get_int("", 0, "sys/module/libahci/parameters/ahci_em_messages")) {
|
|
Packit |
7e09eb |
if (!get_bool("", 0, "sys/module/libahci/parameters/ahci_em_messages"))
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (snprintf(buf, sizeof(buf), "%s/%s", path, "driver") < 0)
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
link = realpath(buf, NULL);
|
|
Packit |
7e09eb |
if (!link)
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
name = strrchr(link, '/');
|
|
Packit |
7e09eb |
if (!name++) {
|
|
Packit |
7e09eb |
free(link);
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/* check if the directory /sys/module/libahci/holders exists */
|
|
Packit |
7e09eb |
dh = opendir("/sys/module/libahci/holders");
|
|
Packit |
7e09eb |
if (dh) {
|
|
Packit |
7e09eb |
/* name contain controller name (ie. ahci),*/
|
|
Packit |
7e09eb |
/* so check if libahci holds this driver */
|
|
Packit |
7e09eb |
while ((de = readdir(dh))) {
|
|
Packit |
7e09eb |
if (!strcmp(de->d_name, name))
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
closedir(dh);
|
|
Packit |
7e09eb |
free(link);
|
|
Packit |
7e09eb |
return de ? 1 : 0;
|
|
Packit |
7e09eb |
} else {
|
|
Packit |
7e09eb |
free(link);
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/*
|
|
Packit |
7e09eb |
* Allocates memory for a new controller device structure. See cntrl.h for
|
|
Packit |
7e09eb |
* details.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
struct cntrl_device *cntrl_device_init(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
unsigned int em_enabled;
|
|
Packit |
7e09eb |
enum cntrl_type type;
|
|
Packit |
7e09eb |
struct cntrl_device *device = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
type = _get_type(path);
|
|
Packit |
7e09eb |
if (type != CNTRL_TYPE_UNKNOWN) {
|
|
Packit |
7e09eb |
switch (type) {
|
|
Packit |
7e09eb |
case CNTRL_TYPE_DELLSSD:
|
|
Packit |
7e09eb |
case CNTRL_TYPE_SCSI:
|
|
Packit |
7e09eb |
case CNTRL_TYPE_VMD:
|
|
Packit |
7e09eb |
case CNTRL_TYPE_NPEM:
|
|
Packit |
7e09eb |
em_enabled = 1;
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
case CNTRL_TYPE_AHCI:
|
|
Packit |
7e09eb |
em_enabled = _ahci_em_messages(path);
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
case CNTRL_TYPE_AMD:
|
|
Packit |
7e09eb |
em_enabled = amd_em_enabled(path);
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
default:
|
|
Packit |
7e09eb |
em_enabled = 0;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
if (em_enabled) {
|
|
Packit |
7e09eb |
if (!list_is_empty(&conf.cntrls_whitelist)) {
|
|
Packit |
7e09eb |
char *cntrl = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
list_for_each(&conf.cntrls_whitelist, cntrl) {
|
|
Packit |
7e09eb |
if (match_string(cntrl, path))
|
|
Packit |
7e09eb |
break;
|
|
Packit |
7e09eb |
cntrl = NULL;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
if (!cntrl) {
|
|
Packit |
7e09eb |
log_debug("%s not found on whitelist, ignoring", path);
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
} else if (!list_is_empty(&conf.cntrls_blacklist)) {
|
|
Packit |
7e09eb |
char *cntrl;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
list_for_each(&conf.cntrls_blacklist, cntrl) {
|
|
Packit |
7e09eb |
if (match_string(cntrl, path)) {
|
|
Packit |
7e09eb |
log_debug("%s found on blacklist, ignoring",
|
|
Packit |
7e09eb |
path);
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
device = malloc(sizeof(struct cntrl_device));
|
|
Packit |
7e09eb |
if (device) {
|
|
Packit |
7e09eb |
if (type == CNTRL_TYPE_SCSI) {
|
|
Packit |
7e09eb |
device->isci_present = _is_isci_cntrl(path);
|
|
Packit |
7e09eb |
device->hosts = _cntrl_get_hosts(path);
|
|
Packit |
7e09eb |
} else {
|
|
Packit |
7e09eb |
device->isci_present = 0;
|
|
Packit |
7e09eb |
device->hosts = NULL;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
device->cntrl_type = type;
|
|
Packit |
7e09eb |
device->sysfs_path = str_dup(path);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
} else {
|
|
Packit |
7e09eb |
log_error
|
|
Packit |
7e09eb |
("controller discovery: %s - enclosure " \
|
|
Packit |
7e09eb |
"management not supported.", path);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return device;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/*
|
|
Packit |
7e09eb |
* Frees memory allocated for controller device structure. See cntrl.h for
|
|
Packit |
7e09eb |
* details.
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
void cntrl_device_fini(struct cntrl_device *device)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
if (device) {
|
|
Packit |
7e09eb |
free(device->sysfs_path);
|
|
Packit |
7e09eb |
free_hosts(device->hosts);
|
|
Packit |
7e09eb |
free(device);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
void print_cntrl(struct cntrl_device *ctrl_dev)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
printf("%s (%s)\n", ctrl_dev->sysfs_path,
|
|
Packit |
7e09eb |
ctrl_type_str[ctrl_dev->cntrl_type]);
|
|
Packit |
7e09eb |
}
|