* [PATCH] libata: add enclosure management support
@ 2008-01-16 0:44 Kristen Carlson Accardi
2008-01-17 22:50 ` James Bottomley
0 siblings, 1 reply; 14+ messages in thread
From: Kristen Carlson Accardi @ 2008-01-16 0:44 UTC (permalink / raw)
To: jeff; +Cc: linux-ide
Add Enclosure Management support to libata and ahci.
This patch adds support for the LED protocol, as defined in the AHCI spec.
It adds a generic em_message and em_type sysfs entry per host. It also adds
a sw_activity field per existing drive.
The em_message field can be used by the driver to take enclosure management
commands from userspace. In the case of the LED protocol, writes and reads
from em_message correspond to the LED message format as defined in the
AHCI spec.
em_message type is a read only file that displays the current enclosure
management protocol that is used by the driver.
sw_activity is used by drivers which support software controlled activity LEDs.
It has the following valid values:
0 OFF - the LED is not activated on activity
1 BLINK_ON - the LED blinks on every 10ms when activity is detected.
2 BLINK_OFF - the LED is on when idle, and blinks off every 10ms when
activity is detected.
It's important to note that the user must turn sw_activity OFF it they wish
to control the activity LED via the em_message file.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
---
I'm concerned about my locking, cause I usually suck at figuring out when I
need it. If you could review that really carefully, I'd appreciate it.
Thanks!
drivers/ata/ahci.c | 321 +++++++++++++++++++++++++++++++++++++++++++++-
drivers/ata/libata-scsi.c | 77 +++++++++++
include/linux/libata.h | 22 +++
3 files changed, 418 insertions(+), 2 deletions(-)
Index: linux-2.6/drivers/ata/ahci.c
===================================================================
--- linux-2.6.orig/drivers/ata/ahci.c 2007-12-19 16:10:50.000000000 -0800
+++ linux-2.6/drivers/ata/ahci.c 2008-01-15 16:34:30.000000000 -0800
@@ -52,6 +52,12 @@
static int ahci_enable_alpm(struct ata_port *ap,
enum link_pm policy);
static void ahci_disable_alpm(struct ata_port *ap);
+static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
+static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
+ size_t size);
+static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
+ ssize_t size);
+#define MAX_SLOTS 8
enum {
AHCI_PCI_BAR = 5,
@@ -92,6 +98,8 @@ enum {
HOST_IRQ_STAT = 0x08, /* interrupt status */
HOST_PORTS_IMPL = 0x0c, /* bitmap of implemented ports */
HOST_VERSION = 0x10, /* AHCI spec. version compliancy */
+ HOST_EM_LOC = 0x1c, /* Enclosure Management location */
+ HOST_EM_CTL = 0x20, /* Enclosure Management Control */
/* HOST_CTL bits */
HOST_RESET = (1 << 0), /* reset controller; self-clear */
@@ -99,6 +107,7 @@ enum {
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
/* HOST_CAP bits */
+ HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
HOST_CAP_SSC = (1 << 14), /* Slumber capable */
HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
HOST_CAP_CLO = (1 << 24), /* Command List Override support */
@@ -195,6 +204,11 @@ enum {
AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY,
ICH_MAP = 0x90, /* ICH MAP register */
+
+ /* em_ctl bits */
+ EM_CTL_RST = (1 << 9), /* Reset */
+ EM_CTL_TM = (1 << 8), /* Transmit Message */
+ EM_CTL_ALHD = (1 << 26), /* Activity LED */
};
struct ahci_cmd_hdr {
@@ -212,12 +226,21 @@ struct ahci_sg {
u32 flags_size;
};
+struct ahci_em_priv {
+ enum sw_activity blink_policy;
+ struct timer_list timer;
+ unsigned long saved_activity;
+ unsigned long activity;
+ unsigned long led_state;
+};
+
struct ahci_host_priv {
unsigned int flags; /* AHCI_HFLAG_* */
u32 cap; /* cap to use */
u32 port_map; /* port map to use */
u32 saved_cap; /* saved initial cap */
u32 saved_port_map; /* saved initial port_map */
+ u32 em_loc; /* enclosure management location */
};
struct ahci_port_priv {
@@ -233,6 +256,8 @@ struct ahci_port_priv {
unsigned int ncq_saw_dmas:1;
unsigned int ncq_saw_sdb:1;
u32 intr_mask; /* interrupts to enable */
+ struct ahci_em_priv em_priv[MAX_SLOTS];/* enclosure management info
+ * per PM slot */
};
static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
@@ -262,9 +287,20 @@ static int ahci_port_suspend(struct ata_
static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int ahci_pci_device_resume(struct pci_dev *pdev);
#endif
+static ssize_t ahci_activity_show(struct ata_device *dev, char *buf);
+static ssize_t ahci_activity_store(struct ata_device *dev,
+ enum sw_activity val);
+static void ahci_init_sw_activity(struct ata_link *link);
static struct class_device_attribute *ahci_shost_attrs[] = {
&class_device_attr_link_power_management_policy,
+ &class_device_attr_em_message_type,
+ &class_device_attr_em_message,
+ NULL
+};
+
+static struct device_attribute *ahci_sdev_attrs[] = {
+ &dev_attr_sw_activity,
NULL
};
@@ -286,6 +322,7 @@ static struct scsi_host_template ahci_sh
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
.shost_attrs = ahci_shost_attrs,
+ .sdev_attrs = ahci_sdev_attrs,
};
static const struct ata_port_operations ahci_ops = {
@@ -320,6 +357,11 @@ static const struct ata_port_operations
.enable_pm = ahci_enable_alpm,
.disable_pm = ahci_disable_alpm,
+ .em_show = ahci_led_show,
+ .em_store = ahci_led_store,
+ .sw_activity_show = ahci_activity_show,
+ .sw_activity_store = ahci_activity_store,
+
.port_start = ahci_port_start,
.port_stop = ahci_port_stop,
};
@@ -578,6 +620,11 @@ static struct pci_driver ahci_pci_driver
#endif
};
+static int ahci_em_messages = 1;
+module_param(ahci_em_messages, int, 0444);
+/* add other LED protocol types when they become supported */
+MODULE_PARM_DESC(ahci_em_messages,
+ "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
static inline int ahci_nr_ports(u32 cap)
{
@@ -1005,11 +1052,28 @@ static void ahci_power_down(struct ata_p
static void ahci_start_port(struct ata_port *ap)
{
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ata_link *link;
+ struct ahci_em_priv *emp;
+
/* enable FIS reception */
ahci_start_fis_rx(ap);
/* enable DMA */
ahci_start_engine(ap);
+
+ /* turn on LEDs */
+ if (ap->flags & ATA_FLAG_EM) {
+ ata_port_for_each_link(link, ap) {
+ emp = &pp->em_priv[link->pmp];
+ ahci_transmit_led_message(ap, emp->led_state, 4);
+ }
+ }
+
+ if (ap->flags & ATA_FLAG_SW_ACTIVITY)
+ ata_port_for_each_link(link, ap)
+ ahci_init_sw_activity(link);
+
}
static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
@@ -1085,6 +1149,230 @@ static int ahci_reset_controller(struct
return 0;
}
+static void ahci_sw_activity(struct ata_link *link)
+{
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
+
+ if (!(link->flags & ATA_LFLAG_SW_ACTIVITY))
+ return;
+
+ emp->activity++;
+ if (!timer_pending(&emp->timer))
+ mod_timer(&emp->timer, jiffies + msecs_to_jiffies(10));
+}
+
+static void ahci_sw_activity_blink(unsigned long arg)
+{
+ struct ata_link *link = (struct ata_link *)arg;
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
+ unsigned long led_message = emp->led_state;
+ u32 activity_led_state;
+
+ led_message &= 0xffff0000;
+ led_message |= ap->port_no | (link->pmp << 8);
+
+ /* check to see if we've had activity. If so,
+ * toggle state of LED and reset timer. If not,
+ * turn LED to desired idle state.
+ */
+ if (emp->saved_activity != emp->activity) {
+ emp->saved_activity = emp->activity;
+ /* get the current LED state */
+ activity_led_state = led_message & 0x00010000;
+
+ if (activity_led_state)
+ activity_led_state = 0;
+ else
+ activity_led_state = 1;
+
+ /* clear old state */
+ led_message &= 0xfff8ffff;
+
+ /* toggle state */
+ led_message |= (activity_led_state << 16);
+ mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
+ } else {
+ /* switch to idle */
+ led_message &= 0xfff8ffff;
+ if (emp->blink_policy == BLINK_OFF)
+ led_message |= (1 << 16);
+ }
+ ahci_transmit_led_message(ap, led_message, 4);
+}
+
+static void ahci_init_sw_activity(struct ata_link *link)
+{
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
+
+ /* init activity stats, setup timer */
+ emp->saved_activity = emp->activity = 0;
+ setup_timer(&emp->timer, ahci_sw_activity_blink, (unsigned long)link);
+
+ /* check our blink policy and set flag for link if it's enabled */
+ if (emp->blink_policy)
+ link->flags |= ATA_LFLAG_SW_ACTIVITY;
+}
+
+static int ahci_reset_em(struct ata_host *host)
+{
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
+ u32 em_ctl;
+
+ em_ctl = readl(mmio + HOST_EM_CTL);
+ if ((em_ctl & EM_CTL_TM) || (em_ctl & EM_CTL_RST))
+ return -EINVAL;
+
+ writel(em_ctl | EM_CTL_RST, mmio + HOST_EM_CTL);
+ return 0;
+}
+
+static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
+ ssize_t size)
+{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ struct ahci_port_priv *pp = ap->private_data;
+ void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
+ u32 em_ctl;
+ u32 message[] = {0, 0};
+ unsigned int flags;
+ int pmp;
+ struct ahci_em_priv *emp;
+
+ /* get the slot number from the message */
+ pmp = (state & 0x0000ff00) >> 8;
+ if (pmp < MAX_SLOTS)
+ emp = &pp->em_priv[pmp];
+ else
+ return -EINVAL;
+
+ spin_lock_irqsave(ap->lock, flags);
+
+ /*
+ * if we are still busy transmitting a previous message,
+ * do not allow
+ */
+ em_ctl = readl(mmio + HOST_EM_CTL);
+ if (em_ctl & EM_CTL_TM) {
+ spin_unlock_irqrestore(ap->lock, flags);
+ return -EINVAL;
+ }
+
+ /*
+ * create message header - this is all zero except for
+ * the message size, which is 4 bytes.
+ */
+ message[0] |= (4 << 8);
+
+ /* ignore 0:4 of byte zero, fill in port info yourself */
+ message[1] = ((state & 0xfffffff0) | ap->port_no);
+
+ /* write message to EM_LOC */
+ writel(message[0], mmio + hpriv->em_loc);
+ writel(message[1], mmio + hpriv->em_loc+4);
+
+ /* save off new led state for port/slot */
+ emp->led_state = message[1];
+
+ /*
+ * tell hardware to transmit the message
+ */
+ writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL);
+
+ spin_unlock_irqrestore(ap->lock, flags);
+ return size;
+}
+
+static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
+{
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ata_link *link;
+ struct ahci_em_priv *emp;
+ int rc = 0;
+
+ ata_port_for_each_link(link, ap) {
+ emp = &pp->em_priv[link->pmp];
+ rc += sprintf(buf, "%lx\n", emp->led_state);
+ }
+ return rc;
+}
+
+static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
+ size_t size)
+{
+ int state;
+ int pmp;
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_em_priv *emp;
+
+ state = simple_strtoul(buf, NULL, 0);
+
+ /* get the slot number from the message */
+ pmp = (state & 0x0000ff00) >> 8;
+ if (pmp < MAX_SLOTS)
+ emp = &pp->em_priv[pmp];
+ else
+ return -EINVAL;
+
+ /* mask off the activity bits if we are in sw_activity
+ * mode, user should turn off sw_activity before setting
+ * activity led through em_message
+ */
+ if (emp->blink_policy)
+ state &= 0xfff8ffff;
+
+ return ahci_transmit_led_message(ap, state, size);
+}
+
+static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
+{
+ struct ata_link *link = dev->link;
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
+ u32 port_led_state = emp->led_state;
+
+ /* save the desired Activity LED behavior */
+ if (val == OFF) {
+ /* clear LFLAG */
+ link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
+
+ /* set the LED to OFF */
+ port_led_state &= 0xfff80000;
+ port_led_state |= (ap->port_no | (link->pmp << 8));
+ ahci_transmit_led_message(ap, port_led_state, 4);
+ } else {
+ link->flags |= ATA_LFLAG_SW_ACTIVITY;
+ if (val == BLINK_OFF) {
+ /* set LED to ON for idle */
+ port_led_state &= 0xfff80000;
+ port_led_state |= (ap->port_no | (link->pmp << 8));
+ port_led_state |= 0x00010000; /* check this */
+ ahci_transmit_led_message(ap, port_led_state, 4);
+ }
+ }
+ emp->blink_policy = val;
+ return 0;
+}
+
+static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
+{
+ struct ata_link *link = dev->link;
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
+
+ /* display the saved value of activity behavior for this
+ * disk.
+ */
+ return sprintf(buf, "%d\n", emp->blink_policy);
+}
+
static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
int port_no, void __iomem *mmio,
void __iomem *port_mmio)
@@ -1781,6 +2069,8 @@ static unsigned int ahci_qc_issue(struct
writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
readl(port_mmio + PORT_CMD_ISSUE); /* flush */
+ ahci_sw_activity(qc->dev->link);
+
return 0;
}
@@ -2113,7 +2403,8 @@ static void ahci_print_info(struct ata_h
dev_printk(KERN_INFO, &pdev->dev,
"flags: "
"%s%s%s%s%s%s%s"
- "%s%s%s%s%s%s%s\n"
+ "%s%s%s%s%s%s%s"
+ "%s\n"
,
cap & (1 << 31) ? "64bit " : "",
@@ -2130,7 +2421,8 @@ static void ahci_print_info(struct ata_h
cap & (1 << 17) ? "pmp " : "",
cap & (1 << 15) ? "pio " : "",
cap & (1 << 14) ? "slum " : "",
- cap & (1 << 13) ? "part " : ""
+ cap & (1 << 13) ? "part " : "",
+ cap & (1 << 6) ? "ems ": ""
);
}
@@ -2241,12 +2533,33 @@ static int ahci_init_one(struct pci_dev
if (hpriv->cap & HOST_CAP_PMP)
pi.flags |= ATA_FLAG_PMP;
+ if (ahci_em_messages && (hpriv->cap & HOST_CAP_EMS)) {
+ u8 messages;
+ void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
+ u32 em_loc = readl(mmio + HOST_EM_LOC);
+ u32 em_ctl = readl(mmio + HOST_EM_CTL);
+
+ messages = (em_ctl & 0x000f0000) >> 16;
+
+ /* we only support LED message type right now */
+ if ((messages & 0x01) && (ahci_em_messages == 1)) {
+ /* store em_loc */
+ hpriv->em_loc = ((em_loc >> 16) * 4);
+ pi.flags |= ATA_FLAG_EM;
+ if (!(em_ctl & EM_CTL_ALHD))
+ pi.flags |= ATA_FLAG_SW_ACTIVITY;
+ }
+ }
+
host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map));
if (!host)
return -ENOMEM;
host->iomap = pcim_iomap_table(pdev);
host->private_data = hpriv;
+ if (pi.flags & ATA_FLAG_EM)
+ ahci_reset_em(host);
+
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
void __iomem *port_mmio = ahci_port_base(ap);
@@ -2258,6 +2571,10 @@ static int ahci_init_one(struct pci_dev
/* set initial link pm policy */
ap->pm_policy = NOT_AVAILABLE;
+ /* set enclosure management message type */
+ if (ap->flags & ATA_FLAG_EM)
+ ap->em_message_type = ahci_em_messages;
+
/* standard SATA port setup */
if (hpriv->port_map & (1 << i))
ap->ioaddr.cmd_addr = port_mmio;
Index: linux-2.6/drivers/ata/libata-scsi.c
===================================================================
--- linux-2.6.orig/drivers/ata/libata-scsi.c 2008-01-15 13:32:27.000000000 -0800
+++ linux-2.6/drivers/ata/libata-scsi.c 2008-01-15 15:02:25.000000000 -0800
@@ -178,6 +178,83 @@ CLASS_DEVICE_ATTR(link_power_management_
ata_scsi_lpm_show, ata_scsi_lpm_put);
EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy);
+static ssize_t
+ata_scsi_em_message_store(struct class_device *class_dev, const char *buf,
+ size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct ata_port *ap = ata_shost_to_port(shost);
+ if (ap->ops->em_store && (ap->flags & ATA_FLAG_EM))
+ return ap->ops->em_store(ap, buf, count);
+ return -EINVAL;
+}
+
+static ssize_t
+ata_scsi_em_message_show(struct class_device *class_dev, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct ata_port *ap = ata_shost_to_port(shost);
+
+ if (ap->ops->em_show && (ap->flags & ATA_FLAG_EM))
+ return ap->ops->em_show(ap, buf);
+ return -EINVAL;
+}
+CLASS_DEVICE_ATTR(em_message, S_IRUGO | S_IWUGO,
+ ata_scsi_em_message_show, ata_scsi_em_message_store);
+EXPORT_SYMBOL_GPL(class_device_attr_em_message);
+
+static ssize_t
+ata_scsi_em_message_type_show(struct class_device *class_dev, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct ata_port *ap = ata_shost_to_port(shost);
+
+ return snprintf(buf, 23, "%d\n", ap->em_message_type);
+}
+CLASS_DEVICE_ATTR(em_message_type, S_IRUGO,
+ ata_scsi_em_message_type_show, NULL);
+EXPORT_SYMBOL_GPL(class_device_attr_em_message_type);
+
+static ssize_t
+ata_scsi_activity_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ata_port *ap = ata_shost_to_port(sdev->host);
+ struct ata_device *atadev = ata_scsi_find_dev(ap, sdev);
+
+ if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY))
+ return ap->ops->sw_activity_show(atadev, buf);
+ return -EINVAL;
+}
+
+static ssize_t
+ata_scsi_activity_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ata_port *ap = ata_shost_to_port(sdev->host);
+ struct ata_device *atadev = ata_scsi_find_dev(ap, sdev);
+ enum sw_activity val;
+ int rc;
+
+ if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) {
+ val = simple_strtoul(buf, NULL, 0);
+ switch (val) {
+ case OFF: case BLINK_ON: case BLINK_OFF:
+ rc = ap->ops->sw_activity_store(atadev, val);
+ if (!rc)
+ return count;
+ else
+ return rc;
+ }
+ }
+ return -EINVAL;
+}
+DEVICE_ATTR(sw_activity, S_IWUGO | S_IRUGO, ata_scsi_activity_show,
+ ata_scsi_activity_store);
+EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
+
static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *))
{
Index: linux-2.6/include/linux/libata.h
===================================================================
--- linux-2.6.orig/include/linux/libata.h 2007-12-19 16:11:01.000000000 -0800
+++ linux-2.6/include/linux/libata.h 2008-01-15 15:02:25.000000000 -0800
@@ -169,6 +169,7 @@ enum {
ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
ATA_LFLAG_NO_RETRY = (1 << 5), /* don't retry this link */
ATA_LFLAG_DISABLED = (1 << 6), /* link is disabled */
+ ATA_LFLAG_SW_ACTIVITY = (1 << 7), /* keep activity stats */
/* struct ata_port flags */
ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */
@@ -191,6 +192,10 @@ enum {
ATA_FLAG_AN = (1 << 18), /* controller supports AN */
ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */
ATA_FLAG_IPM = (1 << 20), /* driver can handle IPM */
+ ATA_FLAG_EM = (1 << 21), /* driver supports enclosure
+ * management */
+ ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity
+ * led */
/* The following flag belongs to ap->pflags but is kept in
* ap->flags because it's referenced in many LLDs and will be
@@ -398,7 +403,17 @@ enum link_pm {
MAX_PERFORMANCE,
MEDIUM_POWER,
};
+
+enum sw_activity {
+ OFF,
+ BLINK_ON,
+ BLINK_OFF,
+};
+
extern struct class_device_attribute class_device_attr_link_power_management_policy;
+extern struct class_device_attribute class_device_attr_em_message_type;
+extern struct class_device_attribute class_device_attr_em_message;
+extern struct device_attribute dev_attr_sw_activity;
struct ata_ioports {
void __iomem *cmd_addr;
@@ -652,6 +667,7 @@ struct ata_port {
struct timer_list fastdrain_timer;
unsigned long fastdrain_cnt;
+ int em_message_type;
void *private_data;
#ifdef CONFIG_ATA_ACPI
@@ -724,6 +740,12 @@ struct ata_port_operations {
void (*bmdma_stop) (struct ata_queued_cmd *qc);
u8 (*bmdma_status) (struct ata_port *ap);
+ ssize_t (*em_show)(struct ata_port *ap, char *buf);
+ ssize_t (*em_store)(struct ata_port *ap, const char *message,
+ size_t size);
+ ssize_t (*sw_activity_show)(struct ata_device *dev, char *buf);
+ ssize_t (*sw_activity_store)(struct ata_device *dev,
+ enum sw_activity val);
};
struct ata_port_info {
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-16 0:44 [PATCH] libata: add enclosure management support Kristen Carlson Accardi
@ 2008-01-17 22:50 ` James Bottomley
2008-01-17 23:36 ` Kristen Carlson Accardi
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: James Bottomley @ 2008-01-17 22:50 UTC (permalink / raw)
To: Kristen Carlson Accardi; +Cc: jeff, linux-ide
On Tue, 2008-01-15 at 16:44 -0800, Kristen Carlson Accardi wrote:
> Add Enclosure Management support to libata and ahci.
>
> This patch adds support for the LED protocol, as defined in the AHCI spec.
> It adds a generic em_message and em_type sysfs entry per host. It also adds
> a sw_activity field per existing drive.
>
> The em_message field can be used by the driver to take enclosure management
> commands from userspace. In the case of the LED protocol, writes and reads
> from em_message correspond to the LED message format as defined in the
> AHCI spec.
>
> em_message type is a read only file that displays the current enclosure
> management protocol that is used by the driver.
>
> sw_activity is used by drivers which support software controlled activity LEDs.
> It has the following valid values:
>
> 0 OFF - the LED is not activated on activity
> 1 BLINK_ON - the LED blinks on every 10ms when activity is detected.
> 2 BLINK_OFF - the LED is on when idle, and blinks off every 10ms when
> activity is detected.
>
> It's important to note that the user must turn sw_activity OFF it they wish
> to control the activity LED via the em_message file.
One of the things we really need to do is to get some type of generic
enclosure support. I note that ahci support three standard eclosure
management protocols (SAF-TE, SES-2, SFF-8485 SGPIO) as well as the one
proprietary one you've chosen to implement. Is that because no-one in
the field has actually connected AHCI up to anything supporting one of
the standard protocols?
I'm looking at this from slightly the other way around: the SAS
protocol is virtually mandating SFF-8485 as the enclosure protocol to
the point that it's actually built into the sas management protocol ...
I was starting to wonder how we should be taking advantage of this.
The implementation probably should be generic (above SCSI or IDE or ATA)
but it would obviously need to tap into the subsytem/transport/device
specific pieces, so possibly block looks to be the right place to start?
James
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-17 22:50 ` James Bottomley
@ 2008-01-17 23:36 ` Kristen Carlson Accardi
2008-01-18 1:55 ` Jeff Garzik
2008-01-18 16:52 ` Kristen Carlson Accardi
2 siblings, 0 replies; 14+ messages in thread
From: Kristen Carlson Accardi @ 2008-01-17 23:36 UTC (permalink / raw)
To: James Bottomley; +Cc: jeff, linux-ide
On Thu, 17 Jan 2008 16:50:42 -0600
James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> On Tue, 2008-01-15 at 16:44 -0800, Kristen Carlson Accardi wrote:
> > Add Enclosure Management support to libata and ahci.
> >
> > This patch adds support for the LED protocol, as defined in the
> > AHCI spec. It adds a generic em_message and em_type sysfs entry per
> > host. It also adds a sw_activity field per existing drive.
> >
> > The em_message field can be used by the driver to take enclosure
> > management commands from userspace. In the case of the LED
> > protocol, writes and reads from em_message correspond to the LED
> > message format as defined in the AHCI spec.
> >
> > em_message type is a read only file that displays the current
> > enclosure management protocol that is used by the driver.
> >
> > sw_activity is used by drivers which support software controlled
> > activity LEDs. It has the following valid values:
> >
> > 0 OFF - the LED is not activated on activity
> > 1 BLINK_ON - the LED blinks on every 10ms when activity is
> > detected. 2 BLINK_OFF - the LED is on when idle, and blinks
> > off every 10ms when activity is detected.
> >
> > It's important to note that the user must turn sw_activity OFF it
> > they wish to control the activity LED via the em_message file.
>
> One of the things we really need to do is to get some type of generic
> enclosure support. I note that ahci support three standard eclosure
> management protocols (SAF-TE, SES-2, SFF-8485 SGPIO) as well as the
> one proprietary one you've chosen to implement. Is that because
> no-one in the field has actually connected AHCI up to anything
> supporting one of the standard protocols?
Correct - I've not seen any AHCI hardware that supports anything but
the LED protocol so far.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-17 22:50 ` James Bottomley
2008-01-17 23:36 ` Kristen Carlson Accardi
@ 2008-01-18 1:55 ` Jeff Garzik
2008-01-18 16:52 ` Kristen Carlson Accardi
2 siblings, 0 replies; 14+ messages in thread
From: Jeff Garzik @ 2008-01-18 1:55 UTC (permalink / raw)
To: James Bottomley; +Cc: Kristen Carlson Accardi, linux-ide
James Bottomley wrote:
> One of the things we really need to do is to get some type of generic
> enclosure support. I note that ahci support three standard eclosure
> management protocols (SAF-TE, SES-2, SFF-8485 SGPIO) as well as the one
> proprietary one you've chosen to implement. Is that because no-one in
> the field has actually connected AHCI up to anything supporting one of
> the standard protocols?
NVIDIA posted SGPIO support, FWIW...
Jeff
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-17 22:50 ` James Bottomley
2008-01-17 23:36 ` Kristen Carlson Accardi
2008-01-18 1:55 ` Jeff Garzik
@ 2008-01-18 16:52 ` Kristen Carlson Accardi
2008-01-18 17:11 ` James Bottomley
2 siblings, 1 reply; 14+ messages in thread
From: Kristen Carlson Accardi @ 2008-01-18 16:52 UTC (permalink / raw)
To: James Bottomley; +Cc: jeff, linux-ide
On Thu, 17 Jan 2008 16:50:42 -0600
James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> On Tue, 2008-01-15 at 16:44 -0800, Kristen Carlson Accardi wrote:
> > Add Enclosure Management support to libata and ahci.
> >
> > This patch adds support for the LED protocol, as defined in the
> > AHCI spec. It adds a generic em_message and em_type sysfs entry per
> > host. It also adds a sw_activity field per existing drive.
> >
> > The em_message field can be used by the driver to take enclosure
> > management commands from userspace. In the case of the LED
> > protocol, writes and reads from em_message correspond to the LED
> > message format as defined in the AHCI spec.
> >
> > em_message type is a read only file that displays the current
> > enclosure management protocol that is used by the driver.
> >
> > sw_activity is used by drivers which support software controlled
> > activity LEDs. It has the following valid values:
> >
> > 0 OFF - the LED is not activated on activity
> > 1 BLINK_ON - the LED blinks on every 10ms when activity is
> > detected. 2 BLINK_OFF - the LED is on when idle, and blinks
> > off every 10ms when activity is detected.
> >
> > It's important to note that the user must turn sw_activity OFF it
> > they wish to control the activity LED via the em_message file.
>
> One of the things we really need to do is to get some type of generic
> enclosure support. I note that ahci support three standard eclosure
> management protocols (SAF-TE, SES-2, SFF-8485 SGPIO) as well as the
> one proprietary one you've chosen to implement. Is that because
> no-one in the field has actually connected AHCI up to anything
> supporting one of the standard protocols?
>
> I'm looking at this from slightly the other way around: the SAS
> protocol is virtually mandating SFF-8485 as the enclosure protocol to
> the point that it's actually built into the sas management
> protocol ... I was starting to wonder how we should be taking
> advantage of this.
>
> The implementation probably should be generic (above SCSI or IDE or
> ATA) but it would obviously need to tap into the
> subsytem/transport/device specific pieces, so possibly block looks to
> be the right place to start?
>
> James
>
>
I originally thought to try to make a generic enclosure management
framework that we could hook individual EM protocols into. Then I
started to wonder why we needed to add knowledge of these protocols
into the kernel. At least the AHCI hardware which I'm familiar with,
has no need to know anything about the protocol. It abstracts
everything into just a message. So, the design that I did in this
patch does the same thing. You export the type of protocol the driver
is configured to accept, then the message buffer and leave it up to
user space to understand the individual protocol. This works for all
supported EM protocols. As far as I can see, most of these management
protocols are better suited to being implemented in user space
anyway.
As far as block, I'm not sure that makes sense, but maybe I'm
misunderstanding what you want. The em message needs to be associated
with the controller, not with individual devices. The reason for this
is that the user may wish to locate a drive bay that has no disk in
it, so they need to be able to send enclosure messages regardless of
whether there's a block device associated with it.
Kristen
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-18 16:52 ` Kristen Carlson Accardi
@ 2008-01-18 17:11 ` James Bottomley
2008-01-18 17:41 ` Kristen Carlson Accardi
0 siblings, 1 reply; 14+ messages in thread
From: James Bottomley @ 2008-01-18 17:11 UTC (permalink / raw)
To: kristen.c.accardi; +Cc: jeff, linux-ide
On Fri, 2008-01-18 at 08:52 -0800, Kristen Carlson Accardi wrote:
> On Thu, 17 Jan 2008 16:50:42 -0600
> James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>
> > On Tue, 2008-01-15 at 16:44 -0800, Kristen Carlson Accardi wrote:
> > > Add Enclosure Management support to libata and ahci.
> > >
> > > This patch adds support for the LED protocol, as defined in the
> > > AHCI spec. It adds a generic em_message and em_type sysfs entry per
> > > host. It also adds a sw_activity field per existing drive.
> > >
> > > The em_message field can be used by the driver to take enclosure
> > > management commands from userspace. In the case of the LED
> > > protocol, writes and reads from em_message correspond to the LED
> > > message format as defined in the AHCI spec.
> > >
> > > em_message type is a read only file that displays the current
> > > enclosure management protocol that is used by the driver.
> > >
> > > sw_activity is used by drivers which support software controlled
> > > activity LEDs. It has the following valid values:
> > >
> > > 0 OFF - the LED is not activated on activity
> > > 1 BLINK_ON - the LED blinks on every 10ms when activity is
> > > detected. 2 BLINK_OFF - the LED is on when idle, and blinks
> > > off every 10ms when activity is detected.
> > >
> > > It's important to note that the user must turn sw_activity OFF it
> > > they wish to control the activity LED via the em_message file.
> >
> > One of the things we really need to do is to get some type of generic
> > enclosure support. I note that ahci support three standard eclosure
> > management protocols (SAF-TE, SES-2, SFF-8485 SGPIO) as well as the
> > one proprietary one you've chosen to implement. Is that because
> > no-one in the field has actually connected AHCI up to anything
> > supporting one of the standard protocols?
> >
> > I'm looking at this from slightly the other way around: the SAS
> > protocol is virtually mandating SFF-8485 as the enclosure protocol to
> > the point that it's actually built into the sas management
> > protocol ... I was starting to wonder how we should be taking
> > advantage of this.
> >
> > The implementation probably should be generic (above SCSI or IDE or
> > ATA) but it would obviously need to tap into the
> > subsytem/transport/device specific pieces, so possibly block looks to
> > be the right place to start?
> >
> > James
> >
> >
>
> I originally thought to try to make a generic enclosure management
> framework that we could hook individual EM protocols into. Then I
> started to wonder why we needed to add knowledge of these protocols
> into the kernel. At least the AHCI hardware which I'm familiar with,
> has no need to know anything about the protocol. It abstracts
> everything into just a message. So, the design that I did in this
> patch does the same thing. You export the type of protocol the driver
> is configured to accept, then the message buffer and leave it up to
> user space to understand the individual protocol. This works for all
> supported EM protocols. As far as I can see, most of these management
> protocols are better suited to being implemented in user space
> anyway.
It's one way to look at it, if we go with SFF-8485 and the AHCI specific
protocol. Basically both of them are only about flashing LEDs. The
SAF-TE and SES protocols are much more comprehensive (and include things
like environmental monitors, temperature, fans, etc.).
I think SFF-8485 still needs the LED frequency generators for RAW mode,
so putting them in AHCI is a bit too low down. There's also the
question of a common user space interface for both.
> As far as block, I'm not sure that makes sense, but maybe I'm
> misunderstanding what you want. The em message needs to be associated
> with the controller, not with individual devices. The reason for this
> is that the user may wish to locate a drive bay that has no disk in
> it, so they need to be able to send enclosure messages regardless of
> whether there's a block device associated with it.
It's actually worse than that: enclosures aren't tied to HBAs even.
They're things that appear on Busses. Take FC as the logical extreme:
you can have tons of different enclosures on a single FC bus.
But you can see from this, that enclosures are really separate devices
(separate from their contents or their connected HBA).
The thought about block is basically that SGPIO is a frame in/frame out
protocol. It would probably have a raw interface via bsg a bit like SMP
does. However, I wouldn't necessarily tie it to block. It would
probably be tied to generic devices which get placed in the device tree
at appropriate locations. Ideally, we can place a SGPIO enclosure
device properly whether it's tied to SAS, FC or AHCI.
James
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-18 17:11 ` James Bottomley
@ 2008-01-18 17:41 ` Kristen Carlson Accardi
2008-01-19 0:16 ` James Bottomley
0 siblings, 1 reply; 14+ messages in thread
From: Kristen Carlson Accardi @ 2008-01-18 17:41 UTC (permalink / raw)
To: James Bottomley; +Cc: jeff, linux-ide
On Fri, 18 Jan 2008 11:11:21 -0600
James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>
> On Fri, 2008-01-18 at 08:52 -0800, Kristen Carlson Accardi wrote:
> > On Thu, 17 Jan 2008 16:50:42 -0600
> > James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> >
> > > On Tue, 2008-01-15 at 16:44 -0800, Kristen Carlson Accardi wrote:
> > > > Add Enclosure Management support to libata and ahci.
> > > >
> > > > This patch adds support for the LED protocol, as defined in the
> > > > AHCI spec. It adds a generic em_message and em_type sysfs entry
> > > > per host. It also adds a sw_activity field per existing drive.
> > > >
> > > > The em_message field can be used by the driver to take enclosure
> > > > management commands from userspace. In the case of the LED
> > > > protocol, writes and reads from em_message correspond to the LED
> > > > message format as defined in the AHCI spec.
> > > >
> > > > em_message type is a read only file that displays the current
> > > > enclosure management protocol that is used by the driver.
> > > >
> > > > sw_activity is used by drivers which support software controlled
> > > > activity LEDs. It has the following valid values:
> > > >
> > > > 0 OFF - the LED is not activated on activity
> > > > 1 BLINK_ON - the LED blinks on every 10ms when activity
> > > > is detected. 2 BLINK_OFF - the LED is on when idle, and
> > > > blinks off every 10ms when activity is detected.
> > > >
> > > > It's important to note that the user must turn sw_activity OFF
> > > > it they wish to control the activity LED via the em_message
> > > > file.
> > >
> > > One of the things we really need to do is to get some type of
> > > generic enclosure support. I note that ahci support three
> > > standard eclosure management protocols (SAF-TE, SES-2, SFF-8485
> > > SGPIO) as well as the one proprietary one you've chosen to
> > > implement. Is that because no-one in the field has actually
> > > connected AHCI up to anything supporting one of the standard
> > > protocols?
> > >
> > > I'm looking at this from slightly the other way around: the SAS
> > > protocol is virtually mandating SFF-8485 as the enclosure
> > > protocol to the point that it's actually built into the sas
> > > management protocol ... I was starting to wonder how we should be
> > > taking advantage of this.
> > >
> > > The implementation probably should be generic (above SCSI or IDE
> > > or ATA) but it would obviously need to tap into the
> > > subsytem/transport/device specific pieces, so possibly block
> > > looks to be the right place to start?
> > >
> > > James
> > >
> > >
> >
> > I originally thought to try to make a generic enclosure management
> > framework that we could hook individual EM protocols into. Then I
> > started to wonder why we needed to add knowledge of these protocols
> > into the kernel. At least the AHCI hardware which I'm familiar
> > with, has no need to know anything about the protocol. It abstracts
> > everything into just a message. So, the design that I did in this
> > patch does the same thing. You export the type of protocol the
> > driver is configured to accept, then the message buffer and leave
> > it up to user space to understand the individual protocol. This
> > works for all supported EM protocols. As far as I can see, most of
> > these management protocols are better suited to being implemented
> > in user space anyway.
>
> It's one way to look at it, if we go with SFF-8485 and the AHCI
> specific protocol. Basically both of them are only about flashing
> LEDs. The SAF-TE and SES protocols are much more comprehensive (and
> include things like environmental monitors, temperature, fans, etc.).
Even these though can be boiled down to read a message/write a
message.
>
> I think SFF-8485 still needs the LED frequency generators for RAW
> mode, so putting them in AHCI is a bit too low down. There's also the
> question of a common user space interface for both.
My reading of SFF-8485 leads me to believe that even in raw bit stream
mode you are still just reading/writing message buffers.
>
> > As far as block, I'm not sure that makes sense, but maybe I'm
> > misunderstanding what you want. The em message needs to be
> > associated with the controller, not with individual devices. The
> > reason for this is that the user may wish to locate a drive bay
> > that has no disk in it, so they need to be able to send enclosure
> > messages regardless of whether there's a block device associated
> > with it.
>
> It's actually worse than that: enclosures aren't tied to HBAs even.
> They're things that appear on Busses. Take FC as the logical extreme:
> you can have tons of different enclosures on a single FC bus.
For SATA they are tied to the controller. Maybe it's not feasible to
come up with a solution that is generic to something like FC and SATA
on the other end.
>
> But you can see from this, that enclosures are really separate devices
> (separate from their contents or their connected HBA).
>
> The thought about block is basically that SGPIO is a frame in/frame
> out protocol. It would probably have a raw interface via bsg a bit
> like SMP does. However, I wouldn't necessarily tie it to block. It
> would probably be tied to generic devices which get placed in the
> device tree at appropriate locations. Ideally, we can place a SGPIO
> enclosure device properly whether it's tied to SAS, FC or AHCI.
>
> James
>
>
This seems like maybe something we could work on in an evolutionary
way as the need presents itself. Honestly, without any SATA hardware
that supports something beyond what this patch can support, it seems a
lot of effort for little gain to try to share code, especially since
the SATA devices wouldn't even use it. With both the AHCI and the nvidia
EM solutions that are out there, that seems unneccessary.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-18 17:41 ` Kristen Carlson Accardi
@ 2008-01-19 0:16 ` James Bottomley
2008-01-19 0:35 ` Kristen Carlson Accardi
2008-01-19 0:52 ` Kristen Carlson Accardi
0 siblings, 2 replies; 14+ messages in thread
From: James Bottomley @ 2008-01-19 0:16 UTC (permalink / raw)
To: kristen.c.accardi; +Cc: jeff, linux-ide
On Fri, 2008-01-18 at 09:41 -0800, Kristen Carlson Accardi wrote:
> On Fri, 18 Jan 2008 11:11:21 -0600
> James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>
> >
> > On Fri, 2008-01-18 at 08:52 -0800, Kristen Carlson Accardi wrote:
> > > On Thu, 17 Jan 2008 16:50:42 -0600
> > > James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> > >
> > > > On Tue, 2008-01-15 at 16:44 -0800, Kristen Carlson Accardi wrote:
> > > > > Add Enclosure Management support to libata and ahci.
> > > > >
> > > > > This patch adds support for the LED protocol, as defined in the
> > > > > AHCI spec. It adds a generic em_message and em_type sysfs entry
> > > > > per host. It also adds a sw_activity field per existing drive.
> > > > >
> > > > > The em_message field can be used by the driver to take enclosure
> > > > > management commands from userspace. In the case of the LED
> > > > > protocol, writes and reads from em_message correspond to the LED
> > > > > message format as defined in the AHCI spec.
> > > > >
> > > > > em_message type is a read only file that displays the current
> > > > > enclosure management protocol that is used by the driver.
> > > > >
> > > > > sw_activity is used by drivers which support software controlled
> > > > > activity LEDs. It has the following valid values:
> > > > >
> > > > > 0 OFF - the LED is not activated on activity
> > > > > 1 BLINK_ON - the LED blinks on every 10ms when activity
> > > > > is detected. 2 BLINK_OFF - the LED is on when idle, and
> > > > > blinks off every 10ms when activity is detected.
> > > > >
> > > > > It's important to note that the user must turn sw_activity OFF
> > > > > it they wish to control the activity LED via the em_message
> > > > > file.
> > > >
> > > > One of the things we really need to do is to get some type of
> > > > generic enclosure support. I note that ahci support three
> > > > standard eclosure management protocols (SAF-TE, SES-2, SFF-8485
> > > > SGPIO) as well as the one proprietary one you've chosen to
> > > > implement. Is that because no-one in the field has actually
> > > > connected AHCI up to anything supporting one of the standard
> > > > protocols?
> > > >
> > > > I'm looking at this from slightly the other way around: the SAS
> > > > protocol is virtually mandating SFF-8485 as the enclosure
> > > > protocol to the point that it's actually built into the sas
> > > > management protocol ... I was starting to wonder how we should be
> > > > taking advantage of this.
> > > >
> > > > The implementation probably should be generic (above SCSI or IDE
> > > > or ATA) but it would obviously need to tap into the
> > > > subsytem/transport/device specific pieces, so possibly block
> > > > looks to be the right place to start?
> > > >
> > > > James
> > > >
> > > >
> > >
> > > I originally thought to try to make a generic enclosure management
> > > framework that we could hook individual EM protocols into. Then I
> > > started to wonder why we needed to add knowledge of these protocols
> > > into the kernel. At least the AHCI hardware which I'm familiar
> > > with, has no need to know anything about the protocol. It abstracts
> > > everything into just a message. So, the design that I did in this
> > > patch does the same thing. You export the type of protocol the
> > > driver is configured to accept, then the message buffer and leave
> > > it up to user space to understand the individual protocol. This
> > > works for all supported EM protocols. As far as I can see, most of
> > > these management protocols are better suited to being implemented
> > > in user space anyway.
> >
> > It's one way to look at it, if we go with SFF-8485 and the AHCI
> > specific protocol. Basically both of them are only about flashing
> > LEDs. The SAF-TE and SES protocols are much more comprehensive (and
> > include things like environmental monitors, temperature, fans, etc.).
>
> Even these though can be boiled down to read a message/write a
> message.
That's true of almost every protocol in the end. I was thinking of the
abstraction. The messages lead to flashing lights in the enclosures.
They also have interactive knobs that users twiddle on the other end.
We really need a uniform user interface abstraction for enclosures.
> >
> > I think SFF-8485 still needs the LED frequency generators for RAW
> > mode, so putting them in AHCI is a bit too low down. There's also the
> > question of a common user space interface for both.
>
> My reading of SFF-8485 leads me to believe that even in raw bit stream
> mode you are still just reading/writing message buffers.
>
> >
> > > As far as block, I'm not sure that makes sense, but maybe I'm
> > > misunderstanding what you want. The em message needs to be
> > > associated with the controller, not with individual devices. The
> > > reason for this is that the user may wish to locate a drive bay
> > > that has no disk in it, so they need to be able to send enclosure
> > > messages regardless of whether there's a block device associated
> > > with it.
> >
> > It's actually worse than that: enclosures aren't tied to HBAs even.
> > They're things that appear on Busses. Take FC as the logical extreme:
> > you can have tons of different enclosures on a single FC bus.
>
> For SATA they are tied to the controller. Maybe it's not feasible to
> come up with a solution that is generic to something like FC and SATA
> on the other end.
So how does this work if the enclosure includes a SATA Port Multiplier?
> >
> > But you can see from this, that enclosures are really separate devices
> > (separate from their contents or their connected HBA).
> >
> > The thought about block is basically that SGPIO is a frame in/frame
> > out protocol. It would probably have a raw interface via bsg a bit
> > like SMP does. However, I wouldn't necessarily tie it to block. It
> > would probably be tied to generic devices which get placed in the
> > device tree at appropriate locations. Ideally, we can place a SGPIO
> > enclosure device properly whether it's tied to SAS, FC or AHCI.
> >
> > James
> >
> >
>
> This seems like maybe something we could work on in an evolutionary
> way as the need presents itself. Honestly, without any SATA hardware
> that supports something beyond what this patch can support, it seems a
> lot of effort for little gain to try to share code, especially since
> the SATA devices wouldn't even use it. With both the AHCI and the nvidia
> EM solutions that are out there, that seems unneccessary.
Unfortunately, all the dual SAS/SATA enclosures seem to be coming with
either SGPIO devices or full fledged SES-2 devices. I've actually got
both (a backplane with SGPIO and an internal SAS/SATA enclosure with
SES-2). Unfortunately, I don't have the necessary information to drive
the SGPIO one ... it's connected directly to an aix94xx using the mini4i
SGPIO signals ... I think aic94xx can drive them, we just don't have the
programming information. The other is a standard SES-2 device, which I
think I might be able to get working.
James
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-19 0:16 ` James Bottomley
@ 2008-01-19 0:35 ` Kristen Carlson Accardi
2008-01-19 0:47 ` James Bottomley
2008-01-19 0:52 ` Kristen Carlson Accardi
1 sibling, 1 reply; 14+ messages in thread
From: Kristen Carlson Accardi @ 2008-01-19 0:35 UTC (permalink / raw)
To: James Bottomley; +Cc: jeff, linux-ide
On Fri, 18 Jan 2008 18:16:34 -0600
James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> On Fri, 2008-01-18 at 09:41 -0800, Kristen Carlson Accardi wrote:
> > On Fri, 18 Jan 2008 11:11:21 -0600
> > James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> >
> > >
> > > On Fri, 2008-01-18 at 08:52 -0800, Kristen Carlson Accardi wrote:
> > > > On Thu, 17 Jan 2008 16:50:42 -0600
> > > > James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> > > >
> > > > > On Tue, 2008-01-15 at 16:44 -0800, Kristen Carlson Accardi
> > > > > wrote:
> > > > > > Add Enclosure Management support to libata and ahci.
> > > > > >
> > > > > > This patch adds support for the LED protocol, as defined in
> > > > > > the AHCI spec. It adds a generic em_message and em_type
> > > > > > sysfs entry per host. It also adds a sw_activity field per
> > > > > > existing drive.
> > > > > >
> > > > > > The em_message field can be used by the driver to take
> > > > > > enclosure management commands from userspace. In the case
> > > > > > of the LED protocol, writes and reads from em_message
> > > > > > correspond to the LED message format as defined in the AHCI
> > > > > > spec.
> > > > > >
> > > > > > em_message type is a read only file that displays the
> > > > > > current enclosure management protocol that is used by the
> > > > > > driver.
> > > > > >
> > > > > > sw_activity is used by drivers which support software
> > > > > > controlled activity LEDs. It has the following valid values:
> > > > > >
> > > > > > 0 OFF - the LED is not activated on activity
> > > > > > 1 BLINK_ON - the LED blinks on every 10ms when
> > > > > > activity is detected. 2 BLINK_OFF - the LED is on
> > > > > > when idle, and blinks off every 10ms when activity is
> > > > > > detected.
> > > > > >
> > > > > > It's important to note that the user must turn sw_activity
> > > > > > OFF it they wish to control the activity LED via the
> > > > > > em_message file.
> > > > >
> > > > > One of the things we really need to do is to get some type of
> > > > > generic enclosure support. I note that ahci support three
> > > > > standard eclosure management protocols (SAF-TE, SES-2,
> > > > > SFF-8485 SGPIO) as well as the one proprietary one you've
> > > > > chosen to implement. Is that because no-one in the field has
> > > > > actually connected AHCI up to anything supporting one of the
> > > > > standard protocols?
> > > > >
> > > > > I'm looking at this from slightly the other way around: the
> > > > > SAS protocol is virtually mandating SFF-8485 as the enclosure
> > > > > protocol to the point that it's actually built into the sas
> > > > > management protocol ... I was starting to wonder how we
> > > > > should be taking advantage of this.
> > > > >
> > > > > The implementation probably should be generic (above SCSI or
> > > > > IDE or ATA) but it would obviously need to tap into the
> > > > > subsytem/transport/device specific pieces, so possibly block
> > > > > looks to be the right place to start?
> > > > >
> > > > > James
> > > > >
> > > > >
> > > >
> > > > I originally thought to try to make a generic enclosure
> > > > management framework that we could hook individual EM protocols
> > > > into. Then I started to wonder why we needed to add knowledge
> > > > of these protocols into the kernel. At least the AHCI hardware
> > > > which I'm familiar with, has no need to know anything about the
> > > > protocol. It abstracts everything into just a message. So,
> > > > the design that I did in this patch does the same thing. You
> > > > export the type of protocol the driver is configured to accept,
> > > > then the message buffer and leave it up to user space to
> > > > understand the individual protocol. This works for all
> > > > supported EM protocols. As far as I can see, most of these
> > > > management protocols are better suited to being implemented in
> > > > user space anyway.
> > >
> > > It's one way to look at it, if we go with SFF-8485 and the AHCI
> > > specific protocol. Basically both of them are only about flashing
> > > LEDs. The SAF-TE and SES protocols are much more comprehensive
> > > (and include things like environmental monitors, temperature,
> > > fans, etc.).
> >
> > Even these though can be boiled down to read a message/write a
> > message.
>
> That's true of almost every protocol in the end. I was thinking of
> the abstraction. The messages lead to flashing lights in the
> enclosures. They also have interactive knobs that users twiddle on
> the other end. We really need a uniform user interface abstraction
> for enclosures.
>
> > >
> > > I think SFF-8485 still needs the LED frequency generators for RAW
> > > mode, so putting them in AHCI is a bit too low down. There's
> > > also the question of a common user space interface for both.
> >
> > My reading of SFF-8485 leads me to believe that even in raw bit
> > stream mode you are still just reading/writing message buffers.
> >
> > >
> > > > As far as block, I'm not sure that makes sense, but maybe I'm
> > > > misunderstanding what you want. The em message needs to be
> > > > associated with the controller, not with individual devices.
> > > > The reason for this is that the user may wish to locate a drive
> > > > bay that has no disk in it, so they need to be able to send
> > > > enclosure messages regardless of whether there's a block device
> > > > associated with it.
> > >
> > > It's actually worse than that: enclosures aren't tied to HBAs
> > > even. They're things that appear on Busses. Take FC as the
> > > logical extreme: you can have tons of different enclosures on a
> > > single FC bus.
> >
> > For SATA they are tied to the controller. Maybe it's not feasible
> > to come up with a solution that is generic to something like FC and
> > SATA on the other end.
>
> So how does this work if the enclosure includes a SATA Port
> Multiplier?
The protocol specifies the disk number, which is included in the
message. For the AHCI LED protocol, the message contains the AP and
the PM slot number.
<snip>
> Unfortunately, all the dual SAS/SATA enclosures seem to be coming with
> either SGPIO devices or full fledged SES-2 devices. I've actually got
> both (a backplane with SGPIO and an internal SAS/SATA enclosure with
> SES-2). Unfortunately, I don't have the necessary information to
> drive the SGPIO one ... it's connected directly to an aix94xx using
> the mini4i SGPIO signals ... I think aic94xx can drive them, we just
> don't have the programming information. The other is a standard
> SES-2 device, which I think I might be able to get working.
>
Having documentation would be pretty helpful :). I know for ICH8, if
you read the docs it says that it supports SGPIO as well. But then you
realize it supports SGPIO via the LED protocol, wired up to translate
LED to SGPIO via hardware. But, even if it did support straight SGPIO,
this design can accommodate that. Can we see the documentation for the
SES-2 device?
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-19 0:35 ` Kristen Carlson Accardi
@ 2008-01-19 0:47 ` James Bottomley
2008-01-19 0:55 ` Kristen Carlson Accardi
0 siblings, 1 reply; 14+ messages in thread
From: James Bottomley @ 2008-01-19 0:47 UTC (permalink / raw)
To: kristen.c.accardi; +Cc: jeff, linux-ide
On Fri, 2008-01-18 at 16:35 -0800, Kristen Carlson Accardi wrote:
> > Unfortunately, all the dual SAS/SATA enclosures seem to be coming with
> > either SGPIO devices or full fledged SES-2 devices. I've actually got
> > both (a backplane with SGPIO and an internal SAS/SATA enclosure with
> > SES-2). Unfortunately, I don't have the necessary information to
> > drive the SGPIO one ... it's connected directly to an aix94xx using
> > the mini4i SGPIO signals ... I think aic94xx can drive them, we just
> > don't have the programming information. The other is a standard
> > SES-2 device, which I think I might be able to get working.
> >
>
> Having documentation would be pretty helpful :). I know for ICH8, if
> you read the docs it says that it supports SGPIO as well. But then you
> realize it supports SGPIO via the LED protocol, wired up to translate
> LED to SGPIO via hardware. But, even if it did support straight SGPIO,
> this design can accommodate that. Can we see the documentation for the
> SES-2 device?
Yes, sure; SES-2 is here (usual place, since it's a SCSI standard):
http://www.t10.org/ftp/t10/drafts/ses2/ses2r19a.pdf
SGPIO is more convoluted. The canonical link is
http://www.sffcommittee.com/ but that just seems to send you back to
seagate. The actual standard is this one:
ftp://ftp.seagate.com/sff/SFF-8485.PDF
James
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-19 0:16 ` James Bottomley
2008-01-19 0:35 ` Kristen Carlson Accardi
@ 2008-01-19 0:52 ` Kristen Carlson Accardi
2008-01-21 18:12 ` James Bottomley
1 sibling, 1 reply; 14+ messages in thread
From: Kristen Carlson Accardi @ 2008-01-19 0:52 UTC (permalink / raw)
To: James Bottomley; +Cc: jeff, linux-ide
On Fri, 18 Jan 2008 18:16:34 -0600
James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> On Fri, 2008-01-18 at 09:41 -0800, Kristen Carlson Accardi wrote:
> > On Fri, 18 Jan 2008 11:11:21 -0600
> > James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> >
> > >
> > > On Fri, 2008-01-18 at 08:52 -0800, Kristen Carlson Accardi wrote:
> > > > On Thu, 17 Jan 2008 16:50:42 -0600
> > > > James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> > > >
> > > > > On Tue, 2008-01-15 at 16:44 -0800, Kristen Carlson Accardi
> > > > > wrote:
> > > > > > Add Enclosure Management support to libata and ahci.
> > > > > >
> > > > > > This patch adds support for the LED protocol, as defined in
> > > > > > the AHCI spec. It adds a generic em_message and em_type
> > > > > > sysfs entry per host. It also adds a sw_activity field per
> > > > > > existing drive.
> > > > > >
> > > > > > The em_message field can be used by the driver to take
> > > > > > enclosure management commands from userspace. In the case
> > > > > > of the LED protocol, writes and reads from em_message
> > > > > > correspond to the LED message format as defined in the AHCI
> > > > > > spec.
> > > > > >
> > > > > > em_message type is a read only file that displays the
> > > > > > current enclosure management protocol that is used by the
> > > > > > driver.
> > > > > >
> > > > > > sw_activity is used by drivers which support software
> > > > > > controlled activity LEDs. It has the following valid values:
> > > > > >
> > > > > > 0 OFF - the LED is not activated on activity
> > > > > > 1 BLINK_ON - the LED blinks on every 10ms when
> > > > > > activity is detected. 2 BLINK_OFF - the LED is on
> > > > > > when idle, and blinks off every 10ms when activity is
> > > > > > detected.
> > > > > >
> > > > > > It's important to note that the user must turn sw_activity
> > > > > > OFF it they wish to control the activity LED via the
> > > > > > em_message file.
> > > > >
> > > > > One of the things we really need to do is to get some type of
> > > > > generic enclosure support. I note that ahci support three
> > > > > standard eclosure management protocols (SAF-TE, SES-2,
> > > > > SFF-8485 SGPIO) as well as the one proprietary one you've
> > > > > chosen to implement. Is that because no-one in the field has
> > > > > actually connected AHCI up to anything supporting one of the
> > > > > standard protocols?
> > > > >
> > > > > I'm looking at this from slightly the other way around: the
> > > > > SAS protocol is virtually mandating SFF-8485 as the enclosure
> > > > > protocol to the point that it's actually built into the sas
> > > > > management protocol ... I was starting to wonder how we
> > > > > should be taking advantage of this.
> > > > >
> > > > > The implementation probably should be generic (above SCSI or
> > > > > IDE or ATA) but it would obviously need to tap into the
> > > > > subsytem/transport/device specific pieces, so possibly block
> > > > > looks to be the right place to start?
> > > > >
> > > > > James
> > > > >
> > > > >
> > > >
> > > > I originally thought to try to make a generic enclosure
> > > > management framework that we could hook individual EM protocols
> > > > into. Then I started to wonder why we needed to add knowledge
> > > > of these protocols into the kernel. At least the AHCI hardware
> > > > which I'm familiar with, has no need to know anything about the
> > > > protocol. It abstracts everything into just a message. So,
> > > > the design that I did in this patch does the same thing. You
> > > > export the type of protocol the driver is configured to accept,
> > > > then the message buffer and leave it up to user space to
> > > > understand the individual protocol. This works for all
> > > > supported EM protocols. As far as I can see, most of these
> > > > management protocols are better suited to being implemented in
> > > > user space anyway.
> > >
> > > It's one way to look at it, if we go with SFF-8485 and the AHCI
> > > specific protocol. Basically both of them are only about flashing
> > > LEDs. The SAF-TE and SES protocols are much more comprehensive
> > > (and include things like environmental monitors, temperature,
> > > fans, etc.).
> >
> > Even these though can be boiled down to read a message/write a
> > message.
>
> That's true of almost every protocol in the end. I was thinking of
> the abstraction. The messages lead to flashing lights in the
> enclosures. They also have interactive knobs that users twiddle on
> the other end. We really need a uniform user interface abstraction
> for enclosures.
>
I guess I'm still not seeing why this abstraction needs to be in the
kernel. Why can't it be a user space library with a generic buffer to
send/receive messages.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-19 0:47 ` James Bottomley
@ 2008-01-19 0:55 ` Kristen Carlson Accardi
2008-01-19 2:33 ` James Bottomley
0 siblings, 1 reply; 14+ messages in thread
From: Kristen Carlson Accardi @ 2008-01-19 0:55 UTC (permalink / raw)
To: James Bottomley; +Cc: jeff, linux-ide
On Fri, 18 Jan 2008 18:47:18 -0600
James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> On Fri, 2008-01-18 at 16:35 -0800, Kristen Carlson Accardi wrote:
> > > Unfortunately, all the dual SAS/SATA enclosures seem to be coming
> > > with either SGPIO devices or full fledged SES-2 devices. I've
> > > actually got both (a backplane with SGPIO and an internal
> > > SAS/SATA enclosure with SES-2). Unfortunately, I don't have the
> > > necessary information to drive the SGPIO one ... it's connected
> > > directly to an aix94xx using the mini4i SGPIO signals ... I think
> > > aic94xx can drive them, we just don't have the programming
> > > information. The other is a standard SES-2 device, which I think
> > > I might be able to get working.
> > >
> >
> > Having documentation would be pretty helpful :). I know for ICH8,
> > if you read the docs it says that it supports SGPIO as well. But
> > then you realize it supports SGPIO via the LED protocol, wired up
> > to translate LED to SGPIO via hardware. But, even if it did
> > support straight SGPIO, this design can accommodate that. Can we
> > see the documentation for the SES-2 device?
>
> Yes, sure; SES-2 is here (usual place, since it's a SCSI standard):
>
> http://www.t10.org/ftp/t10/drafts/ses2/ses2r19a.pdf
>
> SGPIO is more convoluted. The canonical link is
> http://www.sffcommittee.com/ but that just seems to send you back to
> seagate. The actual standard is this one:
>
> ftp://ftp.seagate.com/sff/SFF-8485.PDF
>
> James
>
>
No, I meant for the actual device. The specs don't help all that much
in the area of actually transmitting the messages at the driver level -
at least they don't for AHCI.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-19 0:55 ` Kristen Carlson Accardi
@ 2008-01-19 2:33 ` James Bottomley
0 siblings, 0 replies; 14+ messages in thread
From: James Bottomley @ 2008-01-19 2:33 UTC (permalink / raw)
To: kristen.c.accardi; +Cc: jeff, linux-ide
On Fri, 2008-01-18 at 16:55 -0800, Kristen Carlson Accardi wrote:
> On Fri, 18 Jan 2008 18:47:18 -0600
> James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>
> > On Fri, 2008-01-18 at 16:35 -0800, Kristen Carlson Accardi wrote:
> > > > Unfortunately, all the dual SAS/SATA enclosures seem to be coming
> > > > with either SGPIO devices or full fledged SES-2 devices. I've
> > > > actually got both (a backplane with SGPIO and an internal
> > > > SAS/SATA enclosure with SES-2). Unfortunately, I don't have the
> > > > necessary information to drive the SGPIO one ... it's connected
> > > > directly to an aix94xx using the mini4i SGPIO signals ... I think
> > > > aic94xx can drive them, we just don't have the programming
> > > > information. The other is a standard SES-2 device, which I think
> > > > I might be able to get working.
> > > >
> > >
> > > Having documentation would be pretty helpful :). I know for ICH8,
> > > if you read the docs it says that it supports SGPIO as well. But
> > > then you realize it supports SGPIO via the LED protocol, wired up
> > > to translate LED to SGPIO via hardware. But, even if it did
> > > support straight SGPIO, this design can accommodate that. Can we
> > > see the documentation for the SES-2 device?
> >
> > Yes, sure; SES-2 is here (usual place, since it's a SCSI standard):
> >
> > http://www.t10.org/ftp/t10/drafts/ses2/ses2r19a.pdf
> >
> > SGPIO is more convoluted. The canonical link is
> > http://www.sffcommittee.com/ but that just seems to send you back to
> > seagate. The actual standard is this one:
> >
> > ftp://ftp.seagate.com/sff/SFF-8485.PDF
> >
> > James
> >
> >
>
> No, I meant for the actual device. The specs don't help all that much
> in the area of actually transmitting the messages at the driver level -
> at least they don't for AHCI.
OK, now I'm confused. A SES-2 device is a SCSI device. The standard
defines everything for them. They sit on the bus like any other SCSI
device.
SGPIO is a separate bus; it's also fully defined in SFF-8485, so my
SFF-8485 compliant backplane should be fully defined by the spec as
well. If you're asking how the SGPIO transciever in the aic94xx works,
that's the piece I don't know ... it's not in the RAZOR spec.
James
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libata: add enclosure management support
2008-01-19 0:52 ` Kristen Carlson Accardi
@ 2008-01-21 18:12 ` James Bottomley
0 siblings, 0 replies; 14+ messages in thread
From: James Bottomley @ 2008-01-21 18:12 UTC (permalink / raw)
To: kristen.c.accardi; +Cc: jeff, linux-ide
On Fri, 2008-01-18 at 16:52 -0800, Kristen Carlson Accardi wrote:
> On Fri, 18 Jan 2008 18:16:34 -0600
> James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>
> > On Fri, 2008-01-18 at 09:41 -0800, Kristen Carlson Accardi wrote:
> > > On Fri, 18 Jan 2008 11:11:21 -0600
> > > James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> > >
> > > >
> > > > On Fri, 2008-01-18 at 08:52 -0800, Kristen Carlson Accardi wrote:
> > > > > On Thu, 17 Jan 2008 16:50:42 -0600
> > > > > James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> > > > >
> > > > > > On Tue, 2008-01-15 at 16:44 -0800, Kristen Carlson Accardi
> > > > > > wrote:
> > > > > > > Add Enclosure Management support to libata and ahci.
> > > > > > >
> > > > > > > This patch adds support for the LED protocol, as defined in
> > > > > > > the AHCI spec. It adds a generic em_message and em_type
> > > > > > > sysfs entry per host. It also adds a sw_activity field per
> > > > > > > existing drive.
> > > > > > >
> > > > > > > The em_message field can be used by the driver to take
> > > > > > > enclosure management commands from userspace. In the case
> > > > > > > of the LED protocol, writes and reads from em_message
> > > > > > > correspond to the LED message format as defined in the AHCI
> > > > > > > spec.
> > > > > > >
> > > > > > > em_message type is a read only file that displays the
> > > > > > > current enclosure management protocol that is used by the
> > > > > > > driver.
> > > > > > >
> > > > > > > sw_activity is used by drivers which support software
> > > > > > > controlled activity LEDs. It has the following valid values:
> > > > > > >
> > > > > > > 0 OFF - the LED is not activated on activity
> > > > > > > 1 BLINK_ON - the LED blinks on every 10ms when
> > > > > > > activity is detected. 2 BLINK_OFF - the LED is on
> > > > > > > when idle, and blinks off every 10ms when activity is
> > > > > > > detected.
> > > > > > >
> > > > > > > It's important to note that the user must turn sw_activity
> > > > > > > OFF it they wish to control the activity LED via the
> > > > > > > em_message file.
> > > > > >
> > > > > > One of the things we really need to do is to get some type of
> > > > > > generic enclosure support. I note that ahci support three
> > > > > > standard eclosure management protocols (SAF-TE, SES-2,
> > > > > > SFF-8485 SGPIO) as well as the one proprietary one you've
> > > > > > chosen to implement. Is that because no-one in the field has
> > > > > > actually connected AHCI up to anything supporting one of the
> > > > > > standard protocols?
> > > > > >
> > > > > > I'm looking at this from slightly the other way around: the
> > > > > > SAS protocol is virtually mandating SFF-8485 as the enclosure
> > > > > > protocol to the point that it's actually built into the sas
> > > > > > management protocol ... I was starting to wonder how we
> > > > > > should be taking advantage of this.
> > > > > >
> > > > > > The implementation probably should be generic (above SCSI or
> > > > > > IDE or ATA) but it would obviously need to tap into the
> > > > > > subsytem/transport/device specific pieces, so possibly block
> > > > > > looks to be the right place to start?
> > > > > >
> > > > > > James
> > > > > >
> > > > > >
> > > > >
> > > > > I originally thought to try to make a generic enclosure
> > > > > management framework that we could hook individual EM protocols
> > > > > into. Then I started to wonder why we needed to add knowledge
> > > > > of these protocols into the kernel. At least the AHCI hardware
> > > > > which I'm familiar with, has no need to know anything about the
> > > > > protocol. It abstracts everything into just a message. So,
> > > > > the design that I did in this patch does the same thing. You
> > > > > export the type of protocol the driver is configured to accept,
> > > > > then the message buffer and leave it up to user space to
> > > > > understand the individual protocol. This works for all
> > > > > supported EM protocols. As far as I can see, most of these
> > > > > management protocols are better suited to being implemented in
> > > > > user space anyway.
> > > >
> > > > It's one way to look at it, if we go with SFF-8485 and the AHCI
> > > > specific protocol. Basically both of them are only about flashing
> > > > LEDs. The SAF-TE and SES protocols are much more comprehensive
> > > > (and include things like environmental monitors, temperature,
> > > > fans, etc.).
> > >
> > > Even these though can be boiled down to read a message/write a
> > > message.
> >
> > That's true of almost every protocol in the end. I was thinking of
> > the abstraction. The messages lead to flashing lights in the
> > enclosures. They also have interactive knobs that users twiddle on
> > the other end. We really need a uniform user interface abstraction
> > for enclosures.
> >
>
> I guess I'm still not seeing why this abstraction needs to be in the
> kernel. Why can't it be a user space library with a generic buffer to
> send/receive messages.
OK, code demonstrates better I suppose. Here's an enclosure abstraction
that manifests correctly in sysfs and should allow us all (AHCI, SGPIO
and SES) to play in the same sandbox.
James
---
>From c4d1deff6105831ec7d71641aeb74b945474fef2 Mon Sep 17 00:00:00 2001
From: James Bottomley <jejb@localhost.localdomain>
Date: Sun, 20 Jan 2008 07:34:58 -0600
Subject: [SCSI] enclosure: add support for enclosure services
The enclosure misc device is really just a library providing sysfs
support for physical enclosure devices and their components.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
drivers/misc/Kconfig | 10 +
drivers/misc/Makefile | 1 +
drivers/misc/enclosure.c | 409 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/enclosure.h | 116 +++++++++++++
4 files changed, 536 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/enclosure.c
create mode 100644 include/linux/enclosure.h
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b5e67c0..c6e5c09 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -11,6 +11,7 @@ menuconfig MISC_DEVICES
If you say N, all options in this submenu will be skipped and disabled.
+
if MISC_DEVICES
config IBM_ASM
@@ -232,4 +233,13 @@ config ATMEL_SSC
If unsure, say N.
+config ENCLOSURE_SERVICES
+ tristate "Enclosure Services"
+ default n
+ help
+ Provides support for intelligent enclosures (bays which
+ contain storage devices). You also need either a host
+ driver (SCSI/ATA) which supports enclosures
+ or a SCSI enclosure device (SES) to use these services.
+
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 87f2685..de9f1f5 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
+obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
\ No newline at end of file
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
new file mode 100644
index 0000000..6d4746f
--- /dev/null
+++ b/drivers/misc/enclosure.c
@@ -0,0 +1,409 @@
+/*
+ * Enclosure Services
+ *
+ * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
+ *
+**-----------------------------------------------------------------------------
+**
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License
+** version 2 as published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+*/
+#include <linux/device.h>
+#include <linux/enclosure.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+static LIST_HEAD(container_list);
+static DEFINE_MUTEX(container_list_lock);
+static struct class enclosure_class;
+static struct class enclosure_component_class;
+
+struct enclosure_device *enclosure_find(struct device *dev)
+{
+ struct enclosure_device *edev = NULL;
+
+ mutex_lock(&container_list_lock);
+ list_for_each_entry(edev, &container_list, node) {
+ if (edev->cdev.dev == dev) {
+ mutex_unlock(&container_list_lock);
+ return edev;
+ }
+ }
+ mutex_unlock(&container_list_lock);
+
+ return NULL;
+}
+EXPORT_SYMBOL(enclosure_find);
+
+/**
+ * enclosure_register - register device as an enclosure
+ *
+ * @dev: device containing the enclosure
+ * @components: number of components in the enclosure
+ *
+ * This sets up the device for being an enclosure. Note that @dev does
+ * not have to be a dedicated enclosure device. It may be some other type
+ * of device that additionally responds to enclosure services
+ */
+struct enclosure_device *
+enclosure_register(struct device *dev, const char *name, int components,
+ struct enclosure_component_callbacks *cb)
+{
+ struct enclosure_device *edev =
+ kzalloc(sizeof(struct enclosure_device) +
+ sizeof(struct enclosure_component)*components,
+ GFP_KERNEL);
+ int err, i;
+
+ if (!edev)
+ return ERR_PTR(-ENOMEM);
+
+ if (!cb)
+ return ERR_PTR(-EINVAL);
+
+ edev->components = components;
+
+ edev->cdev.class = &enclosure_class;
+ edev->cdev.dev = get_device(dev);
+ edev->cb = cb;
+ snprintf(edev->cdev.class_id, BUS_ID_SIZE, "%s", name);
+ err = class_device_register(&edev->cdev);
+ if (err)
+ goto err;
+
+ for (i = 0; i < components; i++)
+ edev->component[i].number = -1;
+
+ mutex_lock(&container_list_lock);
+ list_add_tail(&edev->node, &container_list);
+ mutex_unlock(&container_list_lock);
+
+ return edev;
+
+ err:
+ put_device(edev->cdev.dev);
+ kfree(edev);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(enclosure_register);
+
+static struct enclosure_component_callbacks enclosure_null_callbacks;
+
+/**
+ * enclosure_unregister - remove an enclosure
+ *
+ * @edev: the registered enclosure to remove;
+ */
+void enclosure_unregister(struct enclosure_device *edev)
+{
+ int i;
+
+ if (!edev)
+ return;
+
+ mutex_lock(&container_list_lock);
+ list_del(&edev->node);
+ mutex_unlock(&container_list_lock);
+
+ for (i = 0; i < edev->components; i++)
+ if (edev->component[i].number != -1)
+ class_device_unregister(&edev->component[i].cdev);
+
+ class_device_unregister(&edev->cdev);
+ /* prevent any callbacks into service user */
+ edev->cb = &enclosure_null_callbacks;
+}
+EXPORT_SYMBOL_GPL(enclosure_unregister);
+
+static void enclosure_release(struct class_device *cdev)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev);
+
+ put_device(cdev->dev);
+ kfree(edev);
+}
+
+static void enclosure_component_release(struct class_device *cdev)
+{
+ if (cdev->dev)
+ put_device(cdev->dev);
+ class_device_put(cdev->parent);
+}
+
+int enclosure_component_register(struct enclosure_device *edev,
+ unsigned int number,
+ enum enclosure_component_type type,
+ const char *name)
+{
+ struct enclosure_component *ecomp;
+ struct class_device *cdev;
+ int err;
+
+ if (!edev || number >= edev->components)
+ return -EINVAL;
+
+ ecomp = &edev->component[number];
+
+ if (ecomp->number != -1)
+ return -EINVAL;
+
+ ecomp->type = type;
+ ecomp->number = number;
+ cdev = &ecomp->cdev;
+ cdev->parent = class_device_get(&edev->cdev);
+ cdev->class = &enclosure_component_class;
+ if (name)
+ snprintf(cdev->class_id, BUS_ID_SIZE, "%s", name);
+ else
+ snprintf(cdev->class_id, BUS_ID_SIZE, "%d", number);
+
+ err = class_device_register(cdev);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(enclosure_component_register);
+
+int enclosure_add_device(struct enclosure_device *edev, int component,
+ struct device *dev)
+{
+ struct class_device *cdev;
+
+ if (!edev || component >= edev->components)
+ return -EINVAL;
+
+ cdev = &edev->component[component].cdev;
+
+ class_device_del(cdev);
+ if (cdev->dev)
+ put_device(cdev->dev);
+ cdev->dev = get_device(dev);
+ return class_device_add(cdev);
+}
+EXPORT_SYMBOL_GPL(enclosure_add_device);
+
+int enclosure_remove_device(struct enclosure_device *edev, int component)
+{
+ struct class_device *cdev;
+
+ if (!edev || component >= edev->components)
+ return -EINVAL;
+
+ cdev = &edev->component[component].cdev;
+
+ class_device_del(cdev);
+ if (cdev->dev)
+ put_device(cdev->dev);
+ cdev->dev = NULL;
+ return class_device_add(cdev);
+}
+EXPORT_SYMBOL_GPL(enclosure_remove_device);
+
+/*
+ * sysfs pieces below
+ */
+
+static ssize_t enclosure_show_components(struct class_device *cdev, char *buf)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev);
+
+ return snprintf(buf, 40, "%d\n", edev->components);
+}
+
+static struct class_device_attribute enclosure_attrs[] = {
+ __ATTR(components, S_IRUGO, enclosure_show_components, NULL),
+ __ATTR_NULL
+};
+
+static struct class enclosure_class = {
+ .name = "enclosure",
+ .owner = THIS_MODULE,
+ .release = enclosure_release,
+ .class_dev_attrs = enclosure_attrs,
+};
+
+static char *enclosure_status [] = {
+ [ENCLOSURE_STATUS_UNSUPPORTED] = "unsupported",
+ [ENCLOSURE_STATUS_OK] = "OK",
+ [ENCLOSURE_STATUS_CRITICAL] = "critical",
+ [ENCLOSURE_STATUS_NON_CRITICAL] = "non-critical",
+ [ENCLOSURE_STATUS_UNRECOVERABLE] = "unrecoverable",
+ [ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
+ [ENCLOSURE_STATUS_UNKNOWN] = "unknown",
+ [ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
+};
+
+static char *enclosure_type [] = {
+ [ENCLOSURE_COMPONENT_DEVICE] = "device",
+ [ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
+};
+
+static ssize_t get_component_fault(struct class_device *cdev, char *buf)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+ if (edev->cb->get_fault)
+ edev->cb->get_fault(edev, ecomp);
+ return snprintf(buf, 40, "%d\n", ecomp->fault);
+}
+
+static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
+ size_t count)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+ int val = simple_strtoul(buf, NULL, 0);
+
+ if (edev->cb->set_fault)
+ edev->cb->set_fault(edev, ecomp, val);
+ return count;
+}
+
+static ssize_t get_component_status(struct class_device *cdev, char *buf)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+ if (edev->cb->get_status)
+ edev->cb->get_status(edev, ecomp);
+ return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]);
+}
+
+static ssize_t set_component_status(struct class_device *cdev, const char *buf,
+ size_t count)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+ int i;
+
+ for (i = 0; enclosure_status[i]; i++) {
+ if (strncmp(buf, enclosure_status[i],
+ strlen(enclosure_status[i])) == 0 &&
+ buf[strlen(enclosure_status[i])] == '\n')
+ break;
+ }
+
+ if (enclosure_status[i] && edev->cb->set_status) {
+ edev->cb->set_status(edev, ecomp, i);
+ return count;
+ } else
+ return -EINVAL;
+}
+
+static ssize_t get_component_active(struct class_device *cdev, char *buf)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+ if (edev->cb->get_active)
+ edev->cb->get_active(edev, ecomp);
+ return snprintf(buf, 40, "%d\n", ecomp->active);
+}
+
+static ssize_t set_component_active(struct class_device *cdev, const char *buf,
+ size_t count)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+ int val = simple_strtoul(buf, NULL, 0);
+
+ if (edev->cb->set_active)
+ edev->cb->set_active(edev, ecomp, val);
+ return count;
+}
+
+static ssize_t get_component_locate(struct class_device *cdev, char *buf)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+ if (edev->cb->get_locate)
+ edev->cb->get_locate(edev, ecomp);
+ return snprintf(buf, 40, "%d\n", ecomp->locate);
+}
+
+static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
+ size_t count)
+{
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+ int val = simple_strtoul(buf, NULL, 0);
+
+ if (edev->cb->set_locate)
+ edev->cb->set_locate(edev, ecomp, val);
+ return count;
+}
+
+static ssize_t get_component_type(struct class_device *cdev, char *buf)
+{
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+ return snprintf(buf, 40, "%s\n", enclosure_type[ecomp->type]);
+}
+
+
+static struct class_device_attribute enclosure_component_attrs[] = {
+ __ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
+ set_component_fault),
+ __ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
+ set_component_status),
+ __ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
+ set_component_active),
+ __ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
+ set_component_locate),
+ __ATTR(type, S_IRUGO, get_component_type, NULL),
+ __ATTR_NULL
+};
+
+static struct class enclosure_component_class = {
+ .name = "enclosure_component",
+ .owner = THIS_MODULE,
+ .class_dev_attrs = enclosure_component_attrs,
+ .release = enclosure_component_release,
+};
+
+static int __init enclosure_init(void)
+{
+ int err;
+
+ err = class_register(&enclosure_class);
+ if (err)
+ return err;
+ err = class_register(&enclosure_component_class);
+ if (err)
+ goto err_out;
+
+ return 0;
+ err_out:
+ class_unregister(&enclosure_class);
+
+ return err;
+}
+
+static void __exit enclosure_exit(void)
+{
+ class_unregister(&enclosure_component_class);
+ class_unregister(&enclosure_class);
+}
+
+module_init(enclosure_init);
+module_exit(enclosure_exit);
+
+MODULE_AUTHOR("James Bottomley");
+MODULE_DESCRIPTION("Enclosure Services");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
new file mode 100644
index 0000000..cc83acf
--- /dev/null
+++ b/include/linux/enclosure.h
@@ -0,0 +1,116 @@
+/*
+ * Enclosure Services
+ *
+ * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
+ *
+**-----------------------------------------------------------------------------
+**
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License
+** version 2 as published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+*/
+#ifndef _LINUX_ENCLOSURE_H_
+#define _LINUX_ENCLOSURE_H_
+
+#include <linux/device.h>
+#include <linux/list.h>
+
+/* A few generic types ... taken from ses-2 */
+enum enclosure_component_type {
+ ENCLOSURE_COMPONENT_DEVICE = 0x01,
+ ENCLOSURE_COMPONENT_ARRAY_DEVICE = 0x17,
+};
+
+/* ses-2 common element status */
+enum enclosure_status {
+ ENCLOSURE_STATUS_UNSUPPORTED = 0,
+ ENCLOSURE_STATUS_OK,
+ ENCLOSURE_STATUS_CRITICAL,
+ ENCLOSURE_STATUS_NON_CRITICAL,
+ ENCLOSURE_STATUS_UNRECOVERABLE,
+ ENCLOSURE_STATUS_NOT_INSTALLED,
+ ENCLOSURE_STATUS_UNKNOWN,
+ ENCLOSURE_STATUS_UNAVAILABLE,
+};
+
+/* SFF-8485 activity light settings */
+enum enclosure_component_setting {
+ ENCLOSURE_SETTING_DISABLED = 0,
+ ENCLOSURE_SETTING_ENABLED = 1,
+ ENCLOSURE_SETTING_BLINK_A_ON_OFF = 2,
+ ENCLOSURE_SETTING_BLINK_A_OFF_ON = 3,
+ ENCLOSURE_SETTING_BLINK_B_ON_OFF = 6,
+ ENCLOSURE_SETTING_BLINK_B_OFF_ON = 7,
+};
+
+struct enclosure_device;
+struct enclosure_component;
+struct enclosure_component_callbacks {
+ void (*get_status)(struct enclosure_device *,
+ struct enclosure_component *);
+ int (*set_status)(struct enclosure_device *,
+ struct enclosure_component *,
+ enum enclosure_status);
+ void (*get_fault)(struct enclosure_device *,
+ struct enclosure_component *);
+ int (*set_fault)(struct enclosure_device *,
+ struct enclosure_component *,
+ enum enclosure_component_setting);
+ void (*get_active)(struct enclosure_device *,
+ struct enclosure_component *);
+ int (*set_active)(struct enclosure_device *,
+ struct enclosure_component *,
+ enum enclosure_component_setting);
+ void (*get_locate)(struct enclosure_device *,
+ struct enclosure_component *);
+ int (*set_locate)(struct enclosure_device *,
+ struct enclosure_component *,
+ enum enclosure_component_setting);
+};
+
+
+struct enclosure_component {
+ struct class_device cdev;
+ enum enclosure_component_type type;
+ int number;
+ int fault;
+ int active;
+ int locate;
+ enum enclosure_status status;
+};
+
+struct enclosure_device {
+ void *scratch;
+ struct list_head node;
+ struct class_device cdev;
+ struct enclosure_component_callbacks *cb;
+ int components;
+ struct enclosure_component component[0];
+};
+
+#define to_enclosure_device(x) container_of((x), struct enclosure_device, cdev)
+#define to_enclosure_component(x) container_of((x), struct enclosure_component, cdev)
+
+struct enclosure_device *
+enclosure_register(struct device *, const char *, int,
+ struct enclosure_component_callbacks *);
+void enclosure_unregister(struct enclosure_device *);
+int enclosure_component_register(struct enclosure_device *, unsigned int,
+ enum enclosure_component_type, const char *);
+int enclosure_add_device(struct enclosure_device *enclosure, int component,
+ struct device *dev);
+int enclosure_remove_device(struct enclosure_device *enclosure, int component);
+struct enclosure_device *enclosure_find(struct device *dev);
+
+#endif /* _LINUX_ENCLOSURE_H_ */
--
1.5.3.8
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2008-01-21 18:12 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-16 0:44 [PATCH] libata: add enclosure management support Kristen Carlson Accardi
2008-01-17 22:50 ` James Bottomley
2008-01-17 23:36 ` Kristen Carlson Accardi
2008-01-18 1:55 ` Jeff Garzik
2008-01-18 16:52 ` Kristen Carlson Accardi
2008-01-18 17:11 ` James Bottomley
2008-01-18 17:41 ` Kristen Carlson Accardi
2008-01-19 0:16 ` James Bottomley
2008-01-19 0:35 ` Kristen Carlson Accardi
2008-01-19 0:47 ` James Bottomley
2008-01-19 0:55 ` Kristen Carlson Accardi
2008-01-19 2:33 ` James Bottomley
2008-01-19 0:52 ` Kristen Carlson Accardi
2008-01-21 18:12 ` James Bottomley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).