|
Packit |
7e09eb |
/*
|
|
Packit |
7e09eb |
* Intel(R) Enclosure LED Utilities
|
|
Packit Service |
cb68d2 |
* Copyright (C) 2009-2021 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 <errno.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 <unistd.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 "enclosure.h"
|
|
Packit |
7e09eb |
#include "list.h"
|
|
Packit |
7e09eb |
#include "scsi.h"
|
|
Packit |
7e09eb |
#include "ses.h"
|
|
Packit |
7e09eb |
#include "status.h"
|
|
Packit |
7e09eb |
#include "sysfs.h"
|
|
Packit |
7e09eb |
#include "utils.h"
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static char *get_drive_end_dev(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
char *s, *c, *p;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
c = strstr(path, "end_device");
|
|
Packit |
7e09eb |
if (!c)
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
s = strchr(c, '/');
|
|
Packit |
7e09eb |
if (!s)
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
p = calloc(s - c + 1, sizeof(*p));
|
|
Packit |
7e09eb |
if (!p)
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
strncpy(p, c, s - c);
|
|
Packit |
7e09eb |
return p;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static uint64_t get_drive_sas_addr(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
uint64_t ret = 0;
|
|
Packit |
7e09eb |
size_t size = strlen(path) * 2;
|
|
Packit |
7e09eb |
char *buff, *end_dev;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/* Make big buffer. */
|
|
Packit |
7e09eb |
buff = malloc(size + 1);
|
|
Packit |
7e09eb |
if (!buff)
|
|
Packit |
7e09eb |
return ret;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
end_dev = get_drive_end_dev(path);
|
|
Packit |
7e09eb |
if (!end_dev) {
|
|
Packit |
7e09eb |
free(buff);
|
|
Packit |
7e09eb |
return ret;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
snprintf(buff, size, "/sys/class/sas_end_device/%s/device/sas_device/%s",
|
|
Packit |
7e09eb |
end_dev, end_dev);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
ret = get_uint64(buff, ret, "sas_address");
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
free(end_dev);
|
|
Packit |
7e09eb |
free(buff);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
return ret;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
int scsi_get_enclosure(struct block_device *device)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct enclosure_device *encl;
|
|
Packit Service |
cb68d2 |
uint64_t addr;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (!device || !device->sysfs_path)
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit Service |
cb68d2 |
addr = get_drive_sas_addr(device->sysfs_path);
|
|
Packit Service |
cb68d2 |
if (!addr)
|
|
Packit Service |
cb68d2 |
return 0;
|
|
Packit Service |
cb68d2 |
|
|
Packit |
7e09eb |
list_for_each(sysfs_get_enclosure_devices(), encl) {
|
|
Packit Service |
cb68d2 |
int i;
|
|
Packit Service |
cb68d2 |
|
|
Packit Service |
cb68d2 |
for (i = 0; i < encl->slots_count; i++) {
|
|
Packit Service |
cb68d2 |
if (encl->slots[i].sas_addr == addr) {
|
|
Packit Service |
cb68d2 |
device->enclosure = encl;
|
|
Packit Service |
cb68d2 |
device->encl_index = device->enclosure->slots[i].index;
|
|
Packit Service |
cb68d2 |
return 1;
|
|
Packit Service |
cb68d2 |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit Service |
cb68d2 |
return 0;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
int scsi_ses_write(struct block_device *device, enum ibpi_pattern ibpi)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
if (!device || !device->sysfs_path || !device->enclosure ||
|
|
Packit |
7e09eb |
device->encl_index == -1)
|
|
Packit |
7e09eb |
__set_errno_and_return(EINVAL);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/* write only if state has changed */
|
|
Packit |
7e09eb |
if (ibpi == device->ibpi_prev)
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if ((ibpi < IBPI_PATTERN_NORMAL) || (ibpi > SES_REQ_FAULT))
|
|
Packit |
7e09eb |
__set_errno_and_return(ERANGE);
|
|
Packit |
7e09eb |
|
|
Packit Service |
cb68d2 |
return ses_write_msg(ibpi, &device->enclosure->ses_pages, device->encl_index);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
int scsi_ses_flush(struct block_device *device)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
int ret;
|
|
Packit Service |
cb68d2 |
int fd;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (!device || !device->enclosure)
|
|
Packit |
7e09eb |
return 1;
|
|
Packit |
7e09eb |
|
|
Packit Service |
cb68d2 |
if (!device->enclosure->ses_pages.changes)
|
|
Packit |
7e09eb |
return 0;
|
|
Packit |
7e09eb |
|
|
Packit Service |
cb68d2 |
fd = enclosure_open(device->enclosure);
|
|
Packit Service |
cb68d2 |
if (fd == -1)
|
|
Packit Service |
cb68d2 |
return 1;
|
|
Packit Service |
cb68d2 |
|
|
Packit Service |
cb68d2 |
ret = ses_send_diag(fd, &device->enclosure->ses_pages);
|
|
Packit Service |
cb68d2 |
|
|
Packit Service |
cb68d2 |
close(fd);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
return ret;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit Service |
cb68d2 |
char *scsi_get_host_path(const char *path, const char *ctrl_path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
char *host;
|
|
Packit |
7e09eb |
char host_path[PATH_MAX] = { 0 };
|
|
Packit |
7e09eb |
size_t ctrl_path_len = strlen(ctrl_path);
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (strncmp(path, ctrl_path, ctrl_path_len) != 0)
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
host = get_path_hostN(path);
|
|
Packit |
7e09eb |
if (host) {
|
|
Packit |
7e09eb |
snprintf(host_path, sizeof(host_path), "%s/%s/bsg/sas_%s",
|
|
Packit |
7e09eb |
ctrl_path, host, host);
|
|
Packit |
7e09eb |
free(host);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return str_dup(host_path);
|
|
Packit |
7e09eb |
}
|