From c77a036beceabbfd85b366193685cb49f38292bd Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Thu, 23 Oct 2008 14:08:16 +1100 Subject: ahci: Add support for Promise PDC42819 Add an appropriate entry for the Promise PDC42819 controller. It has an AHCI mode and so far works correctly with board_ahci. This chip is found on Promise's FastTrak TX2650 (2 port) and TX4650 (4 port) software-based RAID cards (for which there is a binary driver, t3sas) and can be found on some motherboards, for example the MSI K9A2 Platinum, which calls the chip a Promise T3 controller. Although this controller also supports SAS devices, its default bootup mode is AHCI and the binary driver has to do some magic to get the chip into the appropriate mode to drive SAS disks. Seeing as no documentation is provided by Promise, adding this entry to the ahci driver allows the controller to be useful to people as a SATA controller (with no ill effects on the system if a SAS disk is connected - probing of the port just times out with "link online but device misclassified"), without having to resort to using the binary driver. Users who require SAS or the proprietary software raid can get this functionality using the binary driver. Signed-off-by: Mark Nelson Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/ata/ahci.c') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index aeadd00411a..289719b2cb3 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -588,6 +588,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ + /* Promise */ + { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ + /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, -- cgit v1.2.3-70-g09d2 From eb40963c835c69681af516388a2a92b57e2f0fe7 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Thu, 16 Oct 2008 09:26:19 -0500 Subject: libata: ahci enclosure management led sync Synchronize ahci_sw_activity and ahci_sw_activity_blink with ata_port lock. Signed-off-by: David Milburn Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/ata/ahci.c') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 289719b2cb3..3c71d313343 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1223,6 +1223,7 @@ static void ahci_sw_activity_blink(unsigned long arg) struct ahci_em_priv *emp = &pp->em_priv[link->pmp]; unsigned long led_message = emp->led_state; u32 activity_led_state; + unsigned long flags; led_message &= 0xffff0000; led_message |= ap->port_no | (link->pmp << 8); @@ -1231,6 +1232,7 @@ static void ahci_sw_activity_blink(unsigned long arg) * toggle state of LED and reset timer. If not, * turn LED to desired idle state. */ + spin_lock_irqsave(ap->lock, flags); if (emp->saved_activity != emp->activity) { emp->saved_activity = emp->activity; /* get the current LED state */ @@ -1253,6 +1255,7 @@ static void ahci_sw_activity_blink(unsigned long arg) if (emp->blink_policy == BLINK_OFF) led_message |= (1 << 16); } + spin_unlock_irqrestore(ap->lock, flags); ahci_transmit_led_message(ap, led_message, 4); } -- cgit v1.2.3-70-g09d2 From 87943acf60898a3efb6b5ee85d4cc789898bf5e8 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Mon, 13 Oct 2008 14:38:36 -0500 Subject: libata: ahci enclosure management bit mask Enclosure management bit mask definitions. Signed-off-by: David Milburn Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'drivers/ata/ahci.c') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 3c71d313343..a67b8e7c712 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -49,6 +49,17 @@ #define DRV_NAME "ahci" #define DRV_VERSION "3.0" +/* Enclosure Management Control */ +#define EM_CTRL_MSG_TYPE 0x000f0000 + +/* Enclosure Management LED Message Type */ +#define EM_MSG_LED_HBA_PORT 0x0000000f +#define EM_MSG_LED_PMP_SLOT 0x0000ff00 +#define EM_MSG_LED_VALUE 0xffff0000 +#define EM_MSG_LED_VALUE_ACTIVITY 0x00070000 +#define EM_MSG_LED_VALUE_OFF 0xfff80000 +#define EM_MSG_LED_VALUE_ON 0x00010000 + static int ahci_skip_host_reset; module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444); MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)"); @@ -1225,7 +1236,7 @@ static void ahci_sw_activity_blink(unsigned long arg) u32 activity_led_state; unsigned long flags; - led_message &= 0xffff0000; + led_message &= EM_MSG_LED_VALUE; led_message |= ap->port_no | (link->pmp << 8); /* check to see if we've had activity. If so, @@ -1236,7 +1247,7 @@ static void ahci_sw_activity_blink(unsigned long arg) if (emp->saved_activity != emp->activity) { emp->saved_activity = emp->activity; /* get the current LED state */ - activity_led_state = led_message & 0x00010000; + activity_led_state = led_message & EM_MSG_LED_VALUE_ON; if (activity_led_state) activity_led_state = 0; @@ -1244,14 +1255,14 @@ static void ahci_sw_activity_blink(unsigned long arg) activity_led_state = 1; /* clear old state */ - led_message &= 0xfff8ffff; + led_message &= ~EM_MSG_LED_VALUE_ACTIVITY; /* toggle state */ led_message |= (activity_led_state << 16); mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100)); } else { /* switch to idle */ - led_message &= 0xfff8ffff; + led_message &= ~EM_MSG_LED_VALUE_ACTIVITY; if (emp->blink_policy == BLINK_OFF) led_message |= (1 << 16); } @@ -1300,7 +1311,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, struct ahci_em_priv *emp; /* get the slot number from the message */ - pmp = (state & 0x0000ff00) >> 8; + pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; if (pmp < MAX_SLOTS) emp = &pp->em_priv[pmp]; else @@ -1325,7 +1336,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, message[0] |= (4 << 8); /* ignore 0:4 of byte zero, fill in port info yourself */ - message[1] = ((state & 0xfffffff0) | ap->port_no); + message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no); /* write message to EM_LOC */ writel(message[0], mmio + hpriv->em_loc); @@ -1368,7 +1379,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, state = simple_strtoul(buf, NULL, 0); /* get the slot number from the message */ - pmp = (state & 0x0000ff00) >> 8; + pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; if (pmp < MAX_SLOTS) emp = &pp->em_priv[pmp]; else @@ -1379,7 +1390,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, * activity led through em_message */ if (emp->blink_policy) - state &= 0xfff8ffff; + state &= ~EM_MSG_LED_VALUE_ACTIVITY; return ahci_transmit_led_message(ap, state, size); } @@ -1398,16 +1409,16 @@ static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val) link->flags &= ~(ATA_LFLAG_SW_ACTIVITY); /* set the LED to OFF */ - port_led_state &= 0xfff80000; + port_led_state &= EM_MSG_LED_VALUE_OFF; 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 &= EM_MSG_LED_VALUE_OFF; port_led_state |= (ap->port_no | (link->pmp << 8)); - port_led_state |= 0x00010000; /* check this */ + port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */ ahci_transmit_led_message(ap, port_led_state, 4); } } @@ -2618,7 +2629,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) u32 em_loc = readl(mmio + HOST_EM_LOC); u32 em_ctl = readl(mmio + HOST_EM_CTL); - messages = (em_ctl & 0x000f0000) >> 16; + messages = (em_ctl & EM_CTRL_MSG_TYPE) >> 16; /* we only support LED message type right now */ if ((messages & 0x01) && (ahci_em_messages == 1)) { -- cgit v1.2.3-70-g09d2