|
@@ -56,6 +56,12 @@ MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)
|
|
|
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,
|
|
@@ -98,6 +104,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 */
|
|
@@ -105,6 +113,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 */
|
|
@@ -202,6 +211,11 @@ enum {
|
|
|
ATA_FLAG_IPM,
|
|
|
|
|
|
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 {
|
|
@@ -219,12 +233,21 @@ struct ahci_sg {
|
|
|
__le32 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 {
|
|
@@ -240,6 +263,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);
|
|
@@ -277,9 +302,20 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
|
|
|
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 device_attribute *ahci_shost_attrs[] = {
|
|
|
&dev_attr_link_power_management_policy,
|
|
|
+ &dev_attr_em_message_type,
|
|
|
+ &dev_attr_em_message,
|
|
|
+ NULL
|
|
|
+};
|
|
|
+
|
|
|
+static struct device_attribute *ahci_sdev_attrs[] = {
|
|
|
+ &dev_attr_sw_activity,
|
|
|
NULL
|
|
|
};
|
|
|
|
|
@@ -289,6 +325,7 @@ static struct scsi_host_template ahci_sht = {
|
|
|
.sg_tablesize = AHCI_MAX_SG,
|
|
|
.dma_boundary = AHCI_DMA_BOUNDARY,
|
|
|
.shost_attrs = ahci_shost_attrs,
|
|
|
+ .sdev_attrs = ahci_sdev_attrs,
|
|
|
};
|
|
|
|
|
|
static struct ata_port_operations ahci_ops = {
|
|
@@ -316,6 +353,10 @@ static struct ata_port_operations ahci_ops = {
|
|
|
|
|
|
.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,
|
|
|
#ifdef CONFIG_PM
|
|
|
.port_suspend = ahci_port_suspend,
|
|
|
.port_resume = ahci_port_resume,
|
|
@@ -561,6 +602,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)
|
|
|
{
|
|
@@ -1031,11 +1077,28 @@ static void ahci_power_down(struct ata_port *ap)
|
|
|
|
|
|
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)
|
|
@@ -1079,12 +1142,15 @@ static int ahci_reset_controller(struct ata_host *host)
|
|
|
readl(mmio + HOST_CTL); /* flush */
|
|
|
}
|
|
|
|
|
|
- /* reset must complete within 1 second, or
|
|
|
+ /*
|
|
|
+ * to perform host reset, OS should set HOST_RESET
|
|
|
+ * and poll until this bit is read to be "0".
|
|
|
+ * reset must complete within 1 second, or
|
|
|
* the hardware should be considered fried.
|
|
|
*/
|
|
|
- ssleep(1);
|
|
|
+ tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
|
|
|
+ HOST_RESET, 10, 1000);
|
|
|
|
|
|
- tmp = readl(mmio + HOST_CTL);
|
|
|
if (tmp & HOST_RESET) {
|
|
|
dev_printk(KERN_ERR, host->dev,
|
|
|
"controller reset failed (0x%x)\n", tmp);
|
|
@@ -1116,6 +1182,230 @@ static int ahci_reset_controller(struct ata_host *host)
|
|
|
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)
|
|
@@ -1846,7 +2136,8 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
|
|
|
if (qc->tf.protocol == ATA_PROT_NCQ)
|
|
|
writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
|
|
|
writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
|
|
|
- readl(port_mmio + PORT_CMD_ISSUE); /* flush */
|
|
|
+
|
|
|
+ ahci_sw_activity(qc->dev->link);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -2154,7 +2445,8 @@ static void ahci_print_info(struct ata_host *host)
|
|
|
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 " : "",
|
|
@@ -2171,7 +2463,8 @@ static void ahci_print_info(struct ata_host *host)
|
|
|
cap & (1 << 17) ? "pmp " : "",
|
|
|
cap & (1 << 15) ? "pio " : "",
|
|
|
cap & (1 << 14) ? "slum " : "",
|
|
|
- cap & (1 << 13) ? "part " : ""
|
|
|
+ cap & (1 << 13) ? "part " : "",
|
|
|
+ cap & (1 << 6) ? "ems ": ""
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -2291,6 +2584,24 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/* CAP.NP sometimes indicate the index of the last enabled
|
|
|
* port, at other times, that of the last possible port, so
|
|
|
* determining the maximum port number requires looking at
|
|
@@ -2304,6 +2615,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
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];
|
|
|
|
|
@@ -2314,6 +2628,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
/* 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;
|
|
|
+
|
|
|
+
|
|
|
/* disabled/not-implemented port */
|
|
|
if (!(hpriv->port_map & (1 << i)))
|
|
|
ap->ops = &ata_dummy_port_ops;
|