|
@@ -67,6 +67,20 @@ static int ses_probe(struct device *dev)
|
|
|
#define SES_TIMEOUT (30 * HZ)
|
|
|
#define SES_RETRIES 3
|
|
|
|
|
|
+static void init_device_slot_control(unsigned char *dest_desc,
|
|
|
+ struct enclosure_component *ecomp,
|
|
|
+ unsigned char *status)
|
|
|
+{
|
|
|
+ memcpy(dest_desc, status, 4);
|
|
|
+ dest_desc[0] = 0;
|
|
|
+ /* only clear byte 1 for ENCLOSURE_COMPONENT_DEVICE */
|
|
|
+ if (ecomp->type == ENCLOSURE_COMPONENT_DEVICE)
|
|
|
+ dest_desc[1] = 0;
|
|
|
+ dest_desc[2] &= 0xde;
|
|
|
+ dest_desc[3] &= 0x3c;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static int ses_recv_diag(struct scsi_device *sdev, int page_code,
|
|
|
void *buf, int bufflen)
|
|
|
{
|
|
@@ -178,14 +192,22 @@ static int ses_set_fault(struct enclosure_device *edev,
|
|
|
struct enclosure_component *ecomp,
|
|
|
enum enclosure_component_setting val)
|
|
|
{
|
|
|
- unsigned char desc[4] = {0 };
|
|
|
+ unsigned char desc[4];
|
|
|
+ unsigned char *desc_ptr;
|
|
|
+
|
|
|
+ desc_ptr = ses_get_page2_descriptor(edev, ecomp);
|
|
|
+
|
|
|
+ if (!desc_ptr)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ init_device_slot_control(desc, ecomp, desc_ptr);
|
|
|
|
|
|
switch (val) {
|
|
|
case ENCLOSURE_SETTING_DISABLED:
|
|
|
- /* zero is disabled */
|
|
|
+ desc[3] &= 0xdf;
|
|
|
break;
|
|
|
case ENCLOSURE_SETTING_ENABLED:
|
|
|
- desc[3] = 0x20;
|
|
|
+ desc[3] |= 0x20;
|
|
|
break;
|
|
|
default:
|
|
|
/* SES doesn't do the SGPIO blink settings */
|
|
@@ -219,14 +241,22 @@ static int ses_set_locate(struct enclosure_device *edev,
|
|
|
struct enclosure_component *ecomp,
|
|
|
enum enclosure_component_setting val)
|
|
|
{
|
|
|
- unsigned char desc[4] = {0 };
|
|
|
+ unsigned char desc[4];
|
|
|
+ unsigned char *desc_ptr;
|
|
|
+
|
|
|
+ desc_ptr = ses_get_page2_descriptor(edev, ecomp);
|
|
|
+
|
|
|
+ if (!desc_ptr)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ init_device_slot_control(desc, ecomp, desc_ptr);
|
|
|
|
|
|
switch (val) {
|
|
|
case ENCLOSURE_SETTING_DISABLED:
|
|
|
- /* zero is disabled */
|
|
|
+ desc[2] &= 0xfd;
|
|
|
break;
|
|
|
case ENCLOSURE_SETTING_ENABLED:
|
|
|
- desc[2] = 0x02;
|
|
|
+ desc[2] |= 0x02;
|
|
|
break;
|
|
|
default:
|
|
|
/* SES doesn't do the SGPIO blink settings */
|
|
@@ -239,15 +269,23 @@ static int ses_set_active(struct enclosure_device *edev,
|
|
|
struct enclosure_component *ecomp,
|
|
|
enum enclosure_component_setting val)
|
|
|
{
|
|
|
- unsigned char desc[4] = {0 };
|
|
|
+ unsigned char desc[4];
|
|
|
+ unsigned char *desc_ptr;
|
|
|
+
|
|
|
+ desc_ptr = ses_get_page2_descriptor(edev, ecomp);
|
|
|
+
|
|
|
+ if (!desc_ptr)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ init_device_slot_control(desc, ecomp, desc_ptr);
|
|
|
|
|
|
switch (val) {
|
|
|
case ENCLOSURE_SETTING_DISABLED:
|
|
|
- /* zero is disabled */
|
|
|
+ desc[2] &= 0x7f;
|
|
|
ecomp->active = 0;
|
|
|
break;
|
|
|
case ENCLOSURE_SETTING_ENABLED:
|
|
|
- desc[2] = 0x80;
|
|
|
+ desc[2] |= 0x80;
|
|
|
ecomp->active = 1;
|
|
|
break;
|
|
|
default:
|
|
@@ -265,12 +303,53 @@ static int ses_show_id(struct enclosure_device *edev, char *buf)
|
|
|
return sprintf(buf, "%#llx\n", id);
|
|
|
}
|
|
|
|
|
|
+static void ses_get_power_status(struct enclosure_device *edev,
|
|
|
+ struct enclosure_component *ecomp)
|
|
|
+{
|
|
|
+ unsigned char *desc;
|
|
|
+
|
|
|
+ desc = ses_get_page2_descriptor(edev, ecomp);
|
|
|
+ if (desc)
|
|
|
+ ecomp->power_status = (desc[3] & 0x10) ? 0 : 1;
|
|
|
+}
|
|
|
+
|
|
|
+static int ses_set_power_status(struct enclosure_device *edev,
|
|
|
+ struct enclosure_component *ecomp,
|
|
|
+ int val)
|
|
|
+{
|
|
|
+ unsigned char desc[4];
|
|
|
+ unsigned char *desc_ptr;
|
|
|
+
|
|
|
+ desc_ptr = ses_get_page2_descriptor(edev, ecomp);
|
|
|
+
|
|
|
+ if (!desc_ptr)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ init_device_slot_control(desc, ecomp, desc_ptr);
|
|
|
+
|
|
|
+ switch (val) {
|
|
|
+ /* power = 1 is device_off = 0 and vice versa */
|
|
|
+ case 0:
|
|
|
+ desc[3] |= 0x10;
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ desc[3] &= 0xef;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ ecomp->power_status = val;
|
|
|
+ return ses_set_page2_descriptor(edev, ecomp, desc);
|
|
|
+}
|
|
|
+
|
|
|
static struct enclosure_component_callbacks ses_enclosure_callbacks = {
|
|
|
.get_fault = ses_get_fault,
|
|
|
.set_fault = ses_set_fault,
|
|
|
.get_status = ses_get_status,
|
|
|
.get_locate = ses_get_locate,
|
|
|
.set_locate = ses_set_locate,
|
|
|
+ .get_power_status = ses_get_power_status,
|
|
|
+ .set_power_status = ses_set_power_status,
|
|
|
.set_active = ses_set_active,
|
|
|
.show_id = ses_show_id,
|
|
|
};
|
|
@@ -449,6 +528,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
|
|
|
ecomp = &edev->component[components++];
|
|
|
|
|
|
if (!IS_ERR(ecomp)) {
|
|
|
+ ses_get_power_status(edev, ecomp);
|
|
|
if (addl_desc_ptr)
|
|
|
ses_process_descriptor(
|
|
|
ecomp,
|