mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (49 commits) libata-sff: separate out BMDMA qc_issue libata-sff: prd is BMDMA specific libata-sff: ata_sff_[dumb_]qc_prep are BMDMA specific libata-sff: separate out BMDMA EH libata-sff: port_task is SFF specific libata-sff: ap->[last_]ctl are SFF specific libata-sff: rename ap->ops->drain_fifo() to sff_drain_fifo() libata-sff: introduce ata_sff_init/exit() and ata_sff_port_init() libata-sff: clean up BMDMA initialization libata-sff: clean up inheritance in several drivers libata-sff: reorder SFF/BMDMA functions sata_inic162x: kill PORT_PRD_ADDR initialization libata: kill ATA_FLAG_DISABLED libata-sff: kill unused prototype and make ata_dev_select() static libata-sff: update bmdma host bus error handling sata_mv: remove unnecessary initialization sata_inic162x: inic162x is not dependent on CONFIG_ATA_SFF pata_sch: use ata_pci_sff_init_one() pata_sil680: Do our own exec_command posting libata: Remove excess delay in the tf_load path ...
This commit is contained in:
@@ -81,16 +81,14 @@ void (*port_disable) (struct ata_port *);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Called from ata_bus_probe() and ata_bus_reset() error paths,
|
||||
as well as when unregistering from the SCSI module (rmmod, hot
|
||||
unplug).
|
||||
Called from ata_bus_probe() error path, as well as when
|
||||
unregistering from the SCSI module (rmmod, hot unplug).
|
||||
This function should do whatever needs to be done to take the
|
||||
port out of use. In most cases, ata_port_disable() can be used
|
||||
as this hook.
|
||||
</para>
|
||||
<para>
|
||||
Called from ata_bus_probe() on a failed probe.
|
||||
Called from ata_bus_reset() on a failed bus reset.
|
||||
Called from ata_scsi_release().
|
||||
</para>
|
||||
|
||||
@@ -227,6 +225,18 @@ u8 (*sff_check_altstatus)(struct ata_port *ap);
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Write specific ATA shadow register</title>
|
||||
<programlisting>
|
||||
void (*sff_set_devctl)(struct ata_port *ap, u8 ctl);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Write the device control ATA shadow register to the hardware.
|
||||
Most drivers don't need to define this.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Select ATA device on bus</title>
|
||||
<programlisting>
|
||||
void (*sff_dev_select)(struct ata_port *ap, unsigned int device);
|
||||
|
||||
@@ -65,6 +65,14 @@ config SATA_AHCI
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SATA_AHCI_PLATFORM
|
||||
tristate "Platform AHCI SATA support"
|
||||
help
|
||||
This option enables support for Platform AHCI Serial ATA
|
||||
controllers.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SATA_SIL24
|
||||
tristate "Silicon Image 3124/3132 SATA support"
|
||||
depends on PCI
|
||||
@@ -73,6 +81,12 @@ config SATA_SIL24
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SATA_INIC162X
|
||||
tristate "Initio 162x SATA support"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables support for Initio 162x Serial ATA.
|
||||
|
||||
config SATA_FSL
|
||||
tristate "Freescale 3.0Gbps SATA support"
|
||||
depends on FSL_SOC
|
||||
@@ -213,12 +227,6 @@ config SATA_VITESSE
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SATA_INIC162X
|
||||
tristate "Initio 162x SATA support"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables support for Initio 162x Serial ATA.
|
||||
|
||||
config PATA_ACPI
|
||||
tristate "ACPI firmware driver for PATA"
|
||||
depends on ATA_ACPI
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
obj-$(CONFIG_ATA) += libata.o
|
||||
|
||||
obj-$(CONFIG_SATA_AHCI) += ahci.o
|
||||
obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o
|
||||
obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
|
||||
obj-$(CONFIG_SATA_SVW) += sata_svw.o
|
||||
obj-$(CONFIG_ATA_PIIX) += ata_piix.o
|
||||
obj-$(CONFIG_SATA_PROMISE) += sata_promise.o
|
||||
|
||||
2574
drivers/ata/ahci.c
2574
drivers/ata/ahci.c
File diff suppressed because it is too large
Load Diff
343
drivers/ata/ahci.h
Normal file
343
drivers/ata/ahci.h
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* ahci.h - Common AHCI SATA definitions and declarations
|
||||
*
|
||||
* Maintained by: Jeff Garzik <jgarzik@pobox.com>
|
||||
* Please ALWAYS copy linux-ide@vger.kernel.org
|
||||
* on emails.
|
||||
*
|
||||
* Copyright 2004-2005 Red Hat, Inc.
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* libata documentation is available via 'make {ps|pdf}docs',
|
||||
* as Documentation/DocBook/libata.*
|
||||
*
|
||||
* AHCI hardware documentation:
|
||||
* http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
|
||||
* http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AHCI_H
|
||||
#define _AHCI_H
|
||||
|
||||
#include <linux/libata.h>
|
||||
|
||||
/* 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
|
||||
|
||||
enum {
|
||||
AHCI_MAX_PORTS = 32,
|
||||
AHCI_MAX_SG = 168, /* hardware max is 64K */
|
||||
AHCI_DMA_BOUNDARY = 0xffffffff,
|
||||
AHCI_MAX_CMDS = 32,
|
||||
AHCI_CMD_SZ = 32,
|
||||
AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
|
||||
AHCI_RX_FIS_SZ = 256,
|
||||
AHCI_CMD_TBL_CDB = 0x40,
|
||||
AHCI_CMD_TBL_HDR_SZ = 0x80,
|
||||
AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
|
||||
AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
|
||||
AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
|
||||
AHCI_RX_FIS_SZ,
|
||||
AHCI_PORT_PRIV_FBS_DMA_SZ = AHCI_CMD_SLOT_SZ +
|
||||
AHCI_CMD_TBL_AR_SZ +
|
||||
(AHCI_RX_FIS_SZ * 16),
|
||||
AHCI_IRQ_ON_SG = (1 << 31),
|
||||
AHCI_CMD_ATAPI = (1 << 5),
|
||||
AHCI_CMD_WRITE = (1 << 6),
|
||||
AHCI_CMD_PREFETCH = (1 << 7),
|
||||
AHCI_CMD_RESET = (1 << 8),
|
||||
AHCI_CMD_CLR_BUSY = (1 << 10),
|
||||
|
||||
RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
|
||||
RX_FIS_SDB = 0x58, /* offset of SDB FIS data */
|
||||
RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
|
||||
|
||||
/* global controller registers */
|
||||
HOST_CAP = 0x00, /* host capabilities */
|
||||
HOST_CTL = 0x04, /* global host control */
|
||||
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_CAP2 = 0x24, /* host capabilities, extended */
|
||||
|
||||
/* HOST_CTL bits */
|
||||
HOST_RESET = (1 << 0), /* reset controller; self-clear */
|
||||
HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
|
||||
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
|
||||
|
||||
/* HOST_CAP bits */
|
||||
HOST_CAP_SXS = (1 << 5), /* Supports External SATA */
|
||||
HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
|
||||
HOST_CAP_CCC = (1 << 7), /* Command Completion Coalescing */
|
||||
HOST_CAP_PART = (1 << 13), /* Partial state capable */
|
||||
HOST_CAP_SSC = (1 << 14), /* Slumber state capable */
|
||||
HOST_CAP_PIO_MULTI = (1 << 15), /* PIO multiple DRQ support */
|
||||
HOST_CAP_FBS = (1 << 16), /* FIS-based switching support */
|
||||
HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
|
||||
HOST_CAP_ONLY = (1 << 18), /* Supports AHCI mode only */
|
||||
HOST_CAP_CLO = (1 << 24), /* Command List Override support */
|
||||
HOST_CAP_LED = (1 << 25), /* Supports activity LED */
|
||||
HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
|
||||
HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
|
||||
HOST_CAP_MPS = (1 << 28), /* Mechanical presence switch */
|
||||
HOST_CAP_SNTF = (1 << 29), /* SNotification register */
|
||||
HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
|
||||
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
|
||||
|
||||
/* HOST_CAP2 bits */
|
||||
HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */
|
||||
HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */
|
||||
HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */
|
||||
|
||||
/* registers for each SATA port */
|
||||
PORT_LST_ADDR = 0x00, /* command list DMA addr */
|
||||
PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */
|
||||
PORT_FIS_ADDR = 0x08, /* FIS rx buf addr */
|
||||
PORT_FIS_ADDR_HI = 0x0c, /* FIS rx buf addr hi */
|
||||
PORT_IRQ_STAT = 0x10, /* interrupt status */
|
||||
PORT_IRQ_MASK = 0x14, /* interrupt enable/disable mask */
|
||||
PORT_CMD = 0x18, /* port command */
|
||||
PORT_TFDATA = 0x20, /* taskfile data */
|
||||
PORT_SIG = 0x24, /* device TF signature */
|
||||
PORT_CMD_ISSUE = 0x38, /* command issue */
|
||||
PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */
|
||||
PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */
|
||||
PORT_SCR_ERR = 0x30, /* SATA phy register: SError */
|
||||
PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
|
||||
PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
|
||||
PORT_FBS = 0x40, /* FIS-based Switching */
|
||||
|
||||
/* PORT_IRQ_{STAT,MASK} bits */
|
||||
PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
|
||||
PORT_IRQ_TF_ERR = (1 << 30), /* task file error */
|
||||
PORT_IRQ_HBUS_ERR = (1 << 29), /* host bus fatal error */
|
||||
PORT_IRQ_HBUS_DATA_ERR = (1 << 28), /* host bus data error */
|
||||
PORT_IRQ_IF_ERR = (1 << 27), /* interface fatal error */
|
||||
PORT_IRQ_IF_NONFATAL = (1 << 26), /* interface non-fatal error */
|
||||
PORT_IRQ_OVERFLOW = (1 << 24), /* xfer exhausted available S/G */
|
||||
PORT_IRQ_BAD_PMP = (1 << 23), /* incorrect port multiplier */
|
||||
|
||||
PORT_IRQ_PHYRDY = (1 << 22), /* PhyRdy changed */
|
||||
PORT_IRQ_DEV_ILCK = (1 << 7), /* device interlock */
|
||||
PORT_IRQ_CONNECT = (1 << 6), /* port connect change status */
|
||||
PORT_IRQ_SG_DONE = (1 << 5), /* descriptor processed */
|
||||
PORT_IRQ_UNK_FIS = (1 << 4), /* unknown FIS rx'd */
|
||||
PORT_IRQ_SDB_FIS = (1 << 3), /* Set Device Bits FIS rx'd */
|
||||
PORT_IRQ_DMAS_FIS = (1 << 2), /* DMA Setup FIS rx'd */
|
||||
PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */
|
||||
PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */
|
||||
|
||||
PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR |
|
||||
PORT_IRQ_IF_ERR |
|
||||
PORT_IRQ_CONNECT |
|
||||
PORT_IRQ_PHYRDY |
|
||||
PORT_IRQ_UNK_FIS |
|
||||
PORT_IRQ_BAD_PMP,
|
||||
PORT_IRQ_ERROR = PORT_IRQ_FREEZE |
|
||||
PORT_IRQ_TF_ERR |
|
||||
PORT_IRQ_HBUS_DATA_ERR,
|
||||
DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
|
||||
PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
|
||||
PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
|
||||
|
||||
/* PORT_CMD bits */
|
||||
PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
|
||||
PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
|
||||
PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
|
||||
PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */
|
||||
PORT_CMD_PMP = (1 << 17), /* PMP attached */
|
||||
PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
|
||||
PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
|
||||
PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
|
||||
PORT_CMD_CLO = (1 << 3), /* Command list override */
|
||||
PORT_CMD_POWER_ON = (1 << 2), /* Power up device */
|
||||
PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
|
||||
PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
|
||||
|
||||
PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */
|
||||
PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
|
||||
PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
|
||||
PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
|
||||
|
||||
PORT_FBS_DWE_OFFSET = 16, /* FBS device with error offset */
|
||||
PORT_FBS_ADO_OFFSET = 12, /* FBS active dev optimization offset */
|
||||
PORT_FBS_DEV_OFFSET = 8, /* FBS device to issue offset */
|
||||
PORT_FBS_DEV_MASK = (0xf << PORT_FBS_DEV_OFFSET), /* FBS.DEV */
|
||||
PORT_FBS_SDE = (1 << 2), /* FBS single device error */
|
||||
PORT_FBS_DEC = (1 << 1), /* FBS device error clear */
|
||||
PORT_FBS_EN = (1 << 0), /* Enable FBS */
|
||||
|
||||
/* hpriv->flags bits */
|
||||
AHCI_HFLAG_NO_NCQ = (1 << 0),
|
||||
AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */
|
||||
AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */
|
||||
AHCI_HFLAG_32BIT_ONLY = (1 << 3), /* force 32bit */
|
||||
AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
|
||||
AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
|
||||
AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
|
||||
AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
|
||||
AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
|
||||
AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
|
||||
AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
|
||||
AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as
|
||||
link offline */
|
||||
AHCI_HFLAG_NO_SNTF = (1 << 12), /* no sntf */
|
||||
AHCI_HFLAG_NO_FPDMA_AA = (1 << 13), /* no FPDMA AA */
|
||||
|
||||
/* ap->flags bits */
|
||||
|
||||
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||
ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
|
||||
ATA_FLAG_IPM,
|
||||
|
||||
ICH_MAP = 0x90, /* ICH MAP register */
|
||||
|
||||
/* em constants */
|
||||
EM_MAX_SLOTS = 8,
|
||||
EM_MAX_RETRY = 5,
|
||||
|
||||
/* em_ctl bits */
|
||||
EM_CTL_RST = (1 << 9), /* Reset */
|
||||
EM_CTL_TM = (1 << 8), /* Transmit Message */
|
||||
EM_CTL_MR = (1 << 0), /* Message Recieved */
|
||||
EM_CTL_ALHD = (1 << 26), /* Activity LED */
|
||||
EM_CTL_XMT = (1 << 25), /* Transmit Only */
|
||||
EM_CTL_SMB = (1 << 24), /* Single Message Buffer */
|
||||
|
||||
/* em message type */
|
||||
EM_MSG_TYPE_LED = (1 << 0), /* LED */
|
||||
EM_MSG_TYPE_SAFTE = (1 << 1), /* SAF-TE */
|
||||
EM_MSG_TYPE_SES2 = (1 << 2), /* SES-2 */
|
||||
EM_MSG_TYPE_SGPIO = (1 << 3), /* SGPIO */
|
||||
};
|
||||
|
||||
struct ahci_cmd_hdr {
|
||||
__le32 opts;
|
||||
__le32 status;
|
||||
__le32 tbl_addr;
|
||||
__le32 tbl_addr_hi;
|
||||
__le32 reserved[4];
|
||||
};
|
||||
|
||||
struct ahci_sg {
|
||||
__le32 addr;
|
||||
__le32 addr_hi;
|
||||
__le32 reserved;
|
||||
__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_port_priv {
|
||||
struct ata_link *active_link;
|
||||
struct ahci_cmd_hdr *cmd_slot;
|
||||
dma_addr_t cmd_slot_dma;
|
||||
void *cmd_tbl;
|
||||
dma_addr_t cmd_tbl_dma;
|
||||
void *rx_fis;
|
||||
dma_addr_t rx_fis_dma;
|
||||
/* for NCQ spurious interrupt analysis */
|
||||
unsigned int ncq_saw_d2h:1;
|
||||
unsigned int ncq_saw_dmas:1;
|
||||
unsigned int ncq_saw_sdb:1;
|
||||
u32 intr_mask; /* interrupts to enable */
|
||||
bool fbs_supported; /* set iff FBS is supported */
|
||||
bool fbs_enabled; /* set iff FBS is enabled */
|
||||
int fbs_last_dev; /* save FBS.DEV of last FIS */
|
||||
/* enclosure management info per PM slot */
|
||||
struct ahci_em_priv em_priv[EM_MAX_SLOTS];
|
||||
};
|
||||
|
||||
struct ahci_host_priv {
|
||||
void __iomem * mmio; /* bus-independant mem map */
|
||||
unsigned int flags; /* AHCI_HFLAG_* */
|
||||
u32 cap; /* cap to use */
|
||||
u32 cap2; /* cap2 to use */
|
||||
u32 port_map; /* port map to use */
|
||||
u32 saved_cap; /* saved initial cap */
|
||||
u32 saved_cap2; /* saved initial cap2 */
|
||||
u32 saved_port_map; /* saved initial port_map */
|
||||
u32 em_loc; /* enclosure management location */
|
||||
u32 em_buf_sz; /* EM buffer size in byte */
|
||||
u32 em_msg_type; /* EM message type */
|
||||
};
|
||||
|
||||
extern int ahci_ignore_sss;
|
||||
|
||||
extern struct scsi_host_template ahci_sht;
|
||||
extern struct ata_port_operations ahci_ops;
|
||||
|
||||
void ahci_save_initial_config(struct device *dev,
|
||||
struct ahci_host_priv *hpriv,
|
||||
unsigned int force_port_map,
|
||||
unsigned int mask_port_map);
|
||||
void ahci_init_controller(struct ata_host *host);
|
||||
int ahci_reset_controller(struct ata_host *host);
|
||||
|
||||
int ahci_do_softreset(struct ata_link *link, unsigned int *class,
|
||||
int pmp, unsigned long deadline,
|
||||
int (*check_ready)(struct ata_link *link));
|
||||
|
||||
int ahci_stop_engine(struct ata_port *ap);
|
||||
void ahci_start_engine(struct ata_port *ap);
|
||||
int ahci_check_ready(struct ata_link *link);
|
||||
int ahci_kick_engine(struct ata_port *ap);
|
||||
void ahci_set_em_messages(struct ahci_host_priv *hpriv,
|
||||
struct ata_port_info *pi);
|
||||
int ahci_reset_em(struct ata_host *host);
|
||||
irqreturn_t ahci_interrupt(int irq, void *dev_instance);
|
||||
void ahci_print_info(struct ata_host *host, const char *scc_s);
|
||||
|
||||
static inline void __iomem *__ahci_port_base(struct ata_host *host,
|
||||
unsigned int port_no)
|
||||
{
|
||||
struct ahci_host_priv *hpriv = host->private_data;
|
||||
void __iomem *mmio = hpriv->mmio;
|
||||
|
||||
return mmio + 0x100 + (port_no * 0x80);
|
||||
}
|
||||
|
||||
static inline void __iomem *ahci_port_base(struct ata_port *ap)
|
||||
{
|
||||
return __ahci_port_base(ap->host, ap->port_no);
|
||||
}
|
||||
|
||||
static inline int ahci_nr_ports(u32 cap)
|
||||
{
|
||||
return (cap & 0x1f) + 1;
|
||||
}
|
||||
|
||||
#endif /* _AHCI_H */
|
||||
192
drivers/ata/ahci_platform.c
Normal file
192
drivers/ata/ahci_platform.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* AHCI SATA platform driver
|
||||
*
|
||||
* Copyright 2004-2005 Red Hat, Inc.
|
||||
* Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2010 MontaVista Software, LLC.
|
||||
* Anton Vorontsov <avorontsov@ru.mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/libata.h>
|
||||
#include <linux/ahci_platform.h>
|
||||
#include "ahci.h"
|
||||
|
||||
static int __init ahci_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ahci_platform_data *pdata = dev->platform_data;
|
||||
struct ata_port_info pi = {
|
||||
.flags = AHCI_FLAG_COMMON,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &ahci_ops,
|
||||
};
|
||||
const struct ata_port_info *ppi[] = { &pi, NULL };
|
||||
struct ahci_host_priv *hpriv;
|
||||
struct ata_host *host;
|
||||
struct resource *mem;
|
||||
int irq;
|
||||
int n_ports;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!mem) {
|
||||
dev_err(dev, "no mmio space\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0) {
|
||||
dev_err(dev, "no irq\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pdata && pdata->init) {
|
||||
rc = pdata->init(dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (pdata && pdata->ata_port_info)
|
||||
pi = *pdata->ata_port_info;
|
||||
|
||||
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
|
||||
if (!hpriv) {
|
||||
rc = -ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
hpriv->flags |= (unsigned long)pi.private_data;
|
||||
|
||||
hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
|
||||
if (!hpriv->mmio) {
|
||||
dev_err(dev, "can't map %pR\n", mem);
|
||||
rc = -ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
ahci_save_initial_config(dev, hpriv,
|
||||
pdata ? pdata->force_port_map : 0,
|
||||
pdata ? pdata->mask_port_map : 0);
|
||||
|
||||
/* prepare host */
|
||||
if (hpriv->cap & HOST_CAP_NCQ)
|
||||
pi.flags |= ATA_FLAG_NCQ;
|
||||
|
||||
if (hpriv->cap & HOST_CAP_PMP)
|
||||
pi.flags |= ATA_FLAG_PMP;
|
||||
|
||||
ahci_set_em_messages(hpriv, &pi);
|
||||
|
||||
/* 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
|
||||
* both CAP.NP and port_map.
|
||||
*/
|
||||
n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
|
||||
|
||||
host = ata_host_alloc_pinfo(dev, ppi, n_ports);
|
||||
if (!host) {
|
||||
rc = -ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
host->private_data = hpriv;
|
||||
|
||||
if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
|
||||
host->flags |= ATA_HOST_PARALLEL_SCAN;
|
||||
else
|
||||
printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
|
||||
|
||||
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];
|
||||
|
||||
ata_port_desc(ap, "mmio %pR", mem);
|
||||
ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
|
||||
|
||||
/* 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 = hpriv->em_msg_type;
|
||||
|
||||
/* disabled/not-implemented port */
|
||||
if (!(hpriv->port_map & (1 << i)))
|
||||
ap->ops = &ata_dummy_port_ops;
|
||||
}
|
||||
|
||||
rc = ahci_reset_controller(host);
|
||||
if (rc)
|
||||
goto err0;
|
||||
|
||||
ahci_init_controller(host);
|
||||
ahci_print_info(host, "platform");
|
||||
|
||||
rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
|
||||
&ahci_sht);
|
||||
if (rc)
|
||||
goto err0;
|
||||
|
||||
return 0;
|
||||
err0:
|
||||
if (pdata && pdata->exit)
|
||||
pdata->exit(dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __devexit ahci_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ahci_platform_data *pdata = dev->platform_data;
|
||||
struct ata_host *host = dev_get_drvdata(dev);
|
||||
|
||||
ata_host_detach(host);
|
||||
|
||||
if (pdata && pdata->exit)
|
||||
pdata->exit(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ahci_driver = {
|
||||
.probe = ahci_probe,
|
||||
.remove = __devexit_p(ahci_remove),
|
||||
.driver = {
|
||||
.name = "ahci",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ahci_init(void)
|
||||
{
|
||||
return platform_driver_probe(&ahci_driver, ahci_probe);
|
||||
}
|
||||
module_init(ahci_init);
|
||||
|
||||
static void __exit ahci_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ahci_driver);
|
||||
}
|
||||
module_exit(ahci_exit);
|
||||
|
||||
MODULE_DESCRIPTION("AHCI SATA platform driver");
|
||||
MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:ahci");
|
||||
2216
drivers/ata/libahci.c
Normal file
2216
drivers/ata/libahci.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,7 @@
|
||||
#include <linux/libata.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
#include "libata.h"
|
||||
|
||||
@@ -96,7 +97,6 @@ static void ata_dev_xfermask(struct ata_device *dev);
|
||||
static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
|
||||
|
||||
unsigned int ata_print_id = 1;
|
||||
static struct workqueue_struct *ata_wq;
|
||||
|
||||
struct workqueue_struct *ata_aux_wq;
|
||||
|
||||
@@ -1685,52 +1685,6 @@ unsigned long ata_id_xfermask(const u16 *id)
|
||||
return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_pio_queue_task - Queue port_task
|
||||
* @ap: The ata_port to queue port_task for
|
||||
* @data: data for @fn to use
|
||||
* @delay: delay time in msecs for workqueue function
|
||||
*
|
||||
* Schedule @fn(@data) for execution after @delay jiffies using
|
||||
* port_task. There is one port_task per port and it's the
|
||||
* user(low level driver)'s responsibility to make sure that only
|
||||
* one task is active at any given time.
|
||||
*
|
||||
* libata core layer takes care of synchronization between
|
||||
* port_task and EH. ata_pio_queue_task() may be ignored for EH
|
||||
* synchronization.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
void ata_pio_queue_task(struct ata_port *ap, void *data, unsigned long delay)
|
||||
{
|
||||
ap->port_task_data = data;
|
||||
|
||||
/* may fail if ata_port_flush_task() in progress */
|
||||
queue_delayed_work(ata_wq, &ap->port_task, msecs_to_jiffies(delay));
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_port_flush_task - Flush port_task
|
||||
* @ap: The ata_port to flush port_task for
|
||||
*
|
||||
* After this function completes, port_task is guranteed not to
|
||||
* be running or scheduled.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep)
|
||||
*/
|
||||
void ata_port_flush_task(struct ata_port *ap)
|
||||
{
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
cancel_rearming_delayed_work(&ap->port_task);
|
||||
|
||||
if (ata_msg_ctl(ap))
|
||||
ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __func__);
|
||||
}
|
||||
|
||||
static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct completion *waiting = qc->private_data;
|
||||
@@ -1852,7 +1806,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
|
||||
|
||||
rc = wait_for_completion_timeout(&wait, msecs_to_jiffies(timeout));
|
||||
|
||||
ata_port_flush_task(ap);
|
||||
ata_sff_flush_pio_task(ap);
|
||||
|
||||
if (!rc) {
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
@@ -1906,22 +1860,6 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
|
||||
ap->qc_active = preempted_qc_active;
|
||||
ap->nr_active_links = preempted_nr_active_links;
|
||||
|
||||
/* XXX - Some LLDDs (sata_mv) disable port on command failure.
|
||||
* Until those drivers are fixed, we detect the condition
|
||||
* here, fail the command with AC_ERR_SYSTEM and reenable the
|
||||
* port.
|
||||
*
|
||||
* Note that this doesn't change any behavior as internal
|
||||
* command failure results in disabling the device in the
|
||||
* higher layer for LLDDs without new reset/EH callbacks.
|
||||
*
|
||||
* Kill the following code as soon as those drivers are fixed.
|
||||
*/
|
||||
if (ap->flags & ATA_FLAG_DISABLED) {
|
||||
err_mask |= AC_ERR_SYSTEM;
|
||||
ata_port_probe(ap);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
if ((err_mask & AC_ERR_TIMEOUT) && auto_timeout)
|
||||
@@ -2767,8 +2705,6 @@ int ata_bus_probe(struct ata_port *ap)
|
||||
int rc;
|
||||
struct ata_device *dev;
|
||||
|
||||
ata_port_probe(ap);
|
||||
|
||||
ata_for_each_dev(dev, &ap->link, ALL)
|
||||
tries[dev->devno] = ATA_PROBE_MAX_TRIES;
|
||||
|
||||
@@ -2796,8 +2732,7 @@ int ata_bus_probe(struct ata_port *ap)
|
||||
ap->ops->phy_reset(ap);
|
||||
|
||||
ata_for_each_dev(dev, &ap->link, ALL) {
|
||||
if (!(ap->flags & ATA_FLAG_DISABLED) &&
|
||||
dev->class != ATA_DEV_UNKNOWN)
|
||||
if (dev->class != ATA_DEV_UNKNOWN)
|
||||
classes[dev->devno] = dev->class;
|
||||
else
|
||||
classes[dev->devno] = ATA_DEV_NONE;
|
||||
@@ -2805,8 +2740,6 @@ int ata_bus_probe(struct ata_port *ap)
|
||||
dev->class = ATA_DEV_UNKNOWN;
|
||||
}
|
||||
|
||||
ata_port_probe(ap);
|
||||
|
||||
/* read IDENTIFY page and configure devices. We have to do the identify
|
||||
specific sequence bass-ackwards so that PDIAG- is released by
|
||||
the slave device */
|
||||
@@ -2856,8 +2789,6 @@ int ata_bus_probe(struct ata_port *ap)
|
||||
ata_for_each_dev(dev, &ap->link, ENABLED)
|
||||
return 0;
|
||||
|
||||
/* no device present, disable port */
|
||||
ata_port_disable(ap);
|
||||
return -ENODEV;
|
||||
|
||||
fail:
|
||||
@@ -2888,22 +2819,6 @@ int ata_bus_probe(struct ata_port *ap)
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_port_probe - Mark port as enabled
|
||||
* @ap: Port for which we indicate enablement
|
||||
*
|
||||
* Modify @ap data structure such that the system
|
||||
* thinks that the entire port is enabled.
|
||||
*
|
||||
* LOCKING: host lock, or some other form of
|
||||
* serialization.
|
||||
*/
|
||||
|
||||
void ata_port_probe(struct ata_port *ap)
|
||||
{
|
||||
ap->flags &= ~ATA_FLAG_DISABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* sata_print_link_status - Print SATA link status
|
||||
* @link: SATA link to printk link status about
|
||||
@@ -2950,26 +2865,6 @@ struct ata_device *ata_dev_pair(struct ata_device *adev)
|
||||
return pair;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_port_disable - Disable port.
|
||||
* @ap: Port to be disabled.
|
||||
*
|
||||
* Modify @ap data structure such that the system
|
||||
* thinks that the entire port is disabled, and should
|
||||
* never attempt to probe or communicate with devices
|
||||
* on this port.
|
||||
*
|
||||
* LOCKING: host lock, or some other form of
|
||||
* serialization.
|
||||
*/
|
||||
|
||||
void ata_port_disable(struct ata_port *ap)
|
||||
{
|
||||
ap->link.device[0].class = ATA_DEV_NONE;
|
||||
ap->link.device[1].class = ATA_DEV_NONE;
|
||||
ap->flags |= ATA_FLAG_DISABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* sata_down_spd_limit - adjust SATA spd limit downward
|
||||
* @link: Link to adjust SATA spd limit for
|
||||
@@ -3631,9 +3526,15 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
|
||||
int (*check_ready)(struct ata_link *link))
|
||||
{
|
||||
unsigned long start = jiffies;
|
||||
unsigned long nodev_deadline = ata_deadline(start, ATA_TMOUT_FF_WAIT);
|
||||
unsigned long nodev_deadline;
|
||||
int warned = 0;
|
||||
|
||||
/* choose which 0xff timeout to use, read comment in libata.h */
|
||||
if (link->ap->host->flags & ATA_HOST_PARALLEL_SCAN)
|
||||
nodev_deadline = ata_deadline(start, ATA_TMOUT_FF_WAIT_LONG);
|
||||
else
|
||||
nodev_deadline = ata_deadline(start, ATA_TMOUT_FF_WAIT);
|
||||
|
||||
/* Slave readiness can't be tested separately from master. On
|
||||
* M/S emulation configuration, this function should be called
|
||||
* only on the master and it will handle both master and slave.
|
||||
@@ -3651,12 +3552,12 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
|
||||
if (ready > 0)
|
||||
return 0;
|
||||
|
||||
/* -ENODEV could be transient. Ignore -ENODEV if link
|
||||
/*
|
||||
* -ENODEV could be transient. Ignore -ENODEV if link
|
||||
* is online. Also, some SATA devices take a long
|
||||
* time to clear 0xff after reset. For example,
|
||||
* HHD424020F7SV00 iVDR needs >= 800ms while Quantum
|
||||
* GoVault needs even more than that. Wait for
|
||||
* ATA_TMOUT_FF_WAIT on -ENODEV if link isn't offline.
|
||||
* time to clear 0xff after reset. Wait for
|
||||
* ATA_TMOUT_FF_WAIT[_LONG] on -ENODEV if link isn't
|
||||
* offline.
|
||||
*
|
||||
* Note that some PATA controllers (pata_ali) explode
|
||||
* if status register is read more than once when
|
||||
@@ -5557,30 +5458,6 @@ void ata_host_resume(struct ata_host *host)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ata_port_start - Set port up for dma.
|
||||
* @ap: Port to initialize
|
||||
*
|
||||
* Called just after data structures for each port are
|
||||
* initialized. Allocates space for PRD table.
|
||||
*
|
||||
* May be used as the port_start() entry in ata_port_operations.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
int ata_port_start(struct ata_port *ap)
|
||||
{
|
||||
struct device *dev = ap->dev;
|
||||
|
||||
ap->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma,
|
||||
GFP_KERNEL);
|
||||
if (!ap->prd)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_init - Initialize an ata_device structure
|
||||
* @dev: Device structure to initialize
|
||||
@@ -5709,12 +5586,9 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
|
||||
|
||||
ap->pflags |= ATA_PFLAG_INITIALIZING;
|
||||
ap->lock = &host->lock;
|
||||
ap->flags = ATA_FLAG_DISABLED;
|
||||
ap->print_id = -1;
|
||||
ap->ctl = ATA_DEVCTL_OBS;
|
||||
ap->host = host;
|
||||
ap->dev = host->dev;
|
||||
ap->last_ctl = 0xFF;
|
||||
|
||||
#if defined(ATA_VERBOSE_DEBUG)
|
||||
/* turn on all debugging levels */
|
||||
@@ -5725,11 +5599,6 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
|
||||
ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ATA_SFF
|
||||
INIT_DELAYED_WORK(&ap->port_task, ata_pio_task);
|
||||
#else
|
||||
INIT_DELAYED_WORK(&ap->port_task, NULL);
|
||||
#endif
|
||||
INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
|
||||
INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
|
||||
INIT_LIST_HEAD(&ap->eh_done_q);
|
||||
@@ -5747,6 +5616,8 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
|
||||
ap->stats.unhandled_irq = 1;
|
||||
ap->stats.idle_irq = 1;
|
||||
#endif
|
||||
ata_sff_port_init(ap);
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
||||
@@ -6138,8 +6009,6 @@ static void async_port_probe(void *data, async_cookie_t cookie)
|
||||
struct ata_eh_info *ehi = &ap->link.eh_info;
|
||||
unsigned long flags;
|
||||
|
||||
ata_port_probe(ap);
|
||||
|
||||
/* kick EH for boot probing */
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
@@ -6663,62 +6532,43 @@ static void __init ata_parse_force_param(void)
|
||||
|
||||
static int __init ata_init(void)
|
||||
{
|
||||
ata_parse_force_param();
|
||||
int rc = -ENOMEM;
|
||||
|
||||
/*
|
||||
* FIXME: In UP case, there is only one workqueue thread and if you
|
||||
* have more than one PIO device, latency is bloody awful, with
|
||||
* occasional multi-second "hiccups" as one PIO device waits for
|
||||
* another. It's an ugly wart that users DO occasionally complain
|
||||
* about; luckily most users have at most one PIO polled device.
|
||||
*/
|
||||
ata_wq = create_workqueue("ata");
|
||||
if (!ata_wq)
|
||||
goto free_force_tbl;
|
||||
ata_parse_force_param();
|
||||
|
||||
ata_aux_wq = create_singlethread_workqueue("ata_aux");
|
||||
if (!ata_aux_wq)
|
||||
goto free_wq;
|
||||
goto fail;
|
||||
|
||||
rc = ata_sff_init();
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
|
||||
return 0;
|
||||
|
||||
free_wq:
|
||||
destroy_workqueue(ata_wq);
|
||||
free_force_tbl:
|
||||
fail:
|
||||
kfree(ata_force_tbl);
|
||||
return -ENOMEM;
|
||||
if (ata_aux_wq)
|
||||
destroy_workqueue(ata_aux_wq);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit ata_exit(void)
|
||||
{
|
||||
ata_sff_exit();
|
||||
kfree(ata_force_tbl);
|
||||
destroy_workqueue(ata_wq);
|
||||
destroy_workqueue(ata_aux_wq);
|
||||
}
|
||||
|
||||
subsys_initcall(ata_init);
|
||||
module_exit(ata_exit);
|
||||
|
||||
static unsigned long ratelimit_time;
|
||||
static DEFINE_SPINLOCK(ata_ratelimit_lock);
|
||||
static DEFINE_RATELIMIT_STATE(ratelimit, HZ / 5, 1);
|
||||
|
||||
int ata_ratelimit(void)
|
||||
{
|
||||
int rc;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ata_ratelimit_lock, flags);
|
||||
|
||||
if (time_after(jiffies, ratelimit_time)) {
|
||||
rc = 1;
|
||||
ratelimit_time = jiffies + (HZ/5);
|
||||
} else
|
||||
rc = 0;
|
||||
|
||||
spin_unlock_irqrestore(&ata_ratelimit_lock, flags);
|
||||
|
||||
return rc;
|
||||
return __ratelimit(&ratelimit);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6826,11 +6676,9 @@ EXPORT_SYMBOL_GPL(ata_xfer_mode2mask);
|
||||
EXPORT_SYMBOL_GPL(ata_xfer_mode2shift);
|
||||
EXPORT_SYMBOL_GPL(ata_mode_string);
|
||||
EXPORT_SYMBOL_GPL(ata_id_xfermask);
|
||||
EXPORT_SYMBOL_GPL(ata_port_start);
|
||||
EXPORT_SYMBOL_GPL(ata_do_set_mode);
|
||||
EXPORT_SYMBOL_GPL(ata_std_qc_defer);
|
||||
EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
|
||||
EXPORT_SYMBOL_GPL(ata_port_probe);
|
||||
EXPORT_SYMBOL_GPL(ata_dev_disable);
|
||||
EXPORT_SYMBOL_GPL(sata_set_spd);
|
||||
EXPORT_SYMBOL_GPL(ata_wait_after_reset);
|
||||
@@ -6842,7 +6690,6 @@ EXPORT_SYMBOL_GPL(sata_std_hardreset);
|
||||
EXPORT_SYMBOL_GPL(ata_std_postreset);
|
||||
EXPORT_SYMBOL_GPL(ata_dev_classify);
|
||||
EXPORT_SYMBOL_GPL(ata_dev_pair);
|
||||
EXPORT_SYMBOL_GPL(ata_port_disable);
|
||||
EXPORT_SYMBOL_GPL(ata_ratelimit);
|
||||
EXPORT_SYMBOL_GPL(ata_wait_register);
|
||||
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
|
||||
@@ -6864,7 +6711,6 @@ EXPORT_SYMBOL_GPL(ata_id_c_string);
|
||||
EXPORT_SYMBOL_GPL(ata_do_dev_read_id);
|
||||
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
|
||||
|
||||
EXPORT_SYMBOL_GPL(ata_pio_queue_task);
|
||||
EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
|
||||
EXPORT_SYMBOL_GPL(ata_timing_find_mode);
|
||||
EXPORT_SYMBOL_GPL(ata_timing_compute);
|
||||
|
||||
@@ -550,8 +550,8 @@ void ata_scsi_error(struct Scsi_Host *host)
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
/* synchronize with port task */
|
||||
ata_port_flush_task(ap);
|
||||
/* make sure sff pio task is not running */
|
||||
ata_sff_flush_pio_task(ap);
|
||||
|
||||
/* synchronize with host lock and sort out timeouts */
|
||||
|
||||
@@ -3684,7 +3684,7 @@ void ata_std_error_handler(struct ata_port *ap)
|
||||
ata_reset_fn_t hardreset = ops->hardreset;
|
||||
|
||||
/* ignore built-in hardreset if SCR access is not available */
|
||||
if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
|
||||
if (hardreset == sata_std_hardreset && !sata_scr_valid(&ap->link))
|
||||
hardreset = NULL;
|
||||
|
||||
ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
|
||||
|
||||
@@ -231,10 +231,14 @@ static const char *sata_pmp_spec_rev_str(const u32 *gscr)
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
#define PMP_GSCR_SII_POL 129
|
||||
|
||||
static int sata_pmp_configure(struct ata_device *dev, int print_info)
|
||||
{
|
||||
struct ata_port *ap = dev->link->ap;
|
||||
u32 *gscr = dev->gscr;
|
||||
u16 vendor = sata_pmp_gscr_vendor(gscr);
|
||||
u16 devid = sata_pmp_gscr_devid(gscr);
|
||||
unsigned int err_mask = 0;
|
||||
const char *reason;
|
||||
int nr_ports, rc;
|
||||
@@ -260,12 +264,34 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Disable sending Early R_OK.
|
||||
* With "cached read" HDD testing and multiple ports busy on a SATA
|
||||
* host controller, 3726 PMP will very rarely drop a deferred
|
||||
* R_OK that was intended for the host. Symptom will be all
|
||||
* 5 drives under test will timeout, get reset, and recover.
|
||||
*/
|
||||
if (vendor == 0x1095 && devid == 0x3726) {
|
||||
u32 reg;
|
||||
|
||||
err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, ®);
|
||||
if (err_mask) {
|
||||
rc = -EIO;
|
||||
reason = "failed to read Sil3726 Private Register";
|
||||
goto fail;
|
||||
}
|
||||
reg &= ~0x1;
|
||||
err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
|
||||
if (err_mask) {
|
||||
rc = -EIO;
|
||||
reason = "failed to write Sil3726 Private Register";
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (print_info) {
|
||||
ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, "
|
||||
"0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
|
||||
sata_pmp_spec_rev_str(gscr),
|
||||
sata_pmp_gscr_vendor(gscr),
|
||||
sata_pmp_gscr_devid(gscr),
|
||||
sata_pmp_spec_rev_str(gscr), vendor, devid,
|
||||
sata_pmp_gscr_rev(gscr),
|
||||
nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
|
||||
gscr[SATA_PMP_GSCR_FEAT]);
|
||||
|
||||
@@ -3345,9 +3345,6 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
|
||||
struct ata_link *link;
|
||||
struct ata_device *dev;
|
||||
|
||||
if (ap->flags & ATA_FLAG_DISABLED)
|
||||
return;
|
||||
|
||||
repeat:
|
||||
ata_for_each_link(link, ap, EDGE) {
|
||||
ata_for_each_dev(dev, link, ENABLED) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,17 +38,6 @@ struct ata_scsi_args {
|
||||
void (*done)(struct scsi_cmnd *);
|
||||
};
|
||||
|
||||
static inline int ata_is_builtin_hardreset(ata_reset_fn_t reset)
|
||||
{
|
||||
if (reset == sata_std_hardreset)
|
||||
return 1;
|
||||
#ifdef CONFIG_ATA_SFF
|
||||
if (reset == sata_sff_hardreset)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* libata-core.c */
|
||||
enum {
|
||||
/* flags for ata_dev_read_id() */
|
||||
@@ -79,7 +68,6 @@ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
|
||||
u64 block, u32 n_block, unsigned int tf_flags,
|
||||
unsigned int tag);
|
||||
extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
|
||||
extern void ata_port_flush_task(struct ata_port *ap);
|
||||
extern unsigned ata_exec_internal(struct ata_device *dev,
|
||||
struct ata_taskfile *tf, const u8 *cdb,
|
||||
int dma_dir, void *buf, unsigned int buflen,
|
||||
@@ -202,10 +190,19 @@ static inline int sata_pmp_attach(struct ata_device *dev)
|
||||
|
||||
/* libata-sff.c */
|
||||
#ifdef CONFIG_ATA_SFF
|
||||
extern void ata_dev_select(struct ata_port *ap, unsigned int device,
|
||||
unsigned int wait, unsigned int can_sleep);
|
||||
extern u8 ata_irq_on(struct ata_port *ap);
|
||||
extern void ata_pio_task(struct work_struct *work);
|
||||
extern void ata_sff_flush_pio_task(struct ata_port *ap);
|
||||
extern void ata_sff_port_init(struct ata_port *ap);
|
||||
extern int ata_sff_init(void);
|
||||
extern void ata_sff_exit(void);
|
||||
#else /* CONFIG_ATA_SFF */
|
||||
static inline void ata_sff_flush_pio_task(struct ata_port *ap)
|
||||
{ }
|
||||
static inline void ata_sff_port_init(struct ata_port *ap)
|
||||
{ }
|
||||
static inline int ata_sff_init(void)
|
||||
{ return 0; }
|
||||
static inline void ata_sff_exit(void)
|
||||
{ }
|
||||
#endif /* CONFIG_ATA_SFF */
|
||||
|
||||
#endif /* __LIBATA_H__ */
|
||||
|
||||
@@ -101,7 +101,7 @@ static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device
|
||||
static unsigned long pacpi_mode_filter(struct ata_device *adev, unsigned long mask)
|
||||
{
|
||||
struct pata_acpi *acpi = adev->link->ap->private_data;
|
||||
return ata_bmdma_mode_filter(adev, mask & acpi->mask[adev->devno]);
|
||||
return mask & acpi->mask[adev->devno];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,7 +172,7 @@ static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc)
|
||||
struct pata_acpi *acpi = ap->private_data;
|
||||
|
||||
if (acpi->gtm.flags & 0x10)
|
||||
return ata_sff_qc_issue(qc);
|
||||
return ata_bmdma_qc_issue(qc);
|
||||
|
||||
if (adev != acpi->last) {
|
||||
pacpi_set_piomode(ap, adev);
|
||||
@@ -180,7 +180,7 @@ static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc)
|
||||
pacpi_set_dmamode(ap, adev);
|
||||
acpi->last = adev;
|
||||
}
|
||||
return ata_sff_qc_issue(qc);
|
||||
return ata_bmdma_qc_issue(qc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,7 +205,7 @@ static int pacpi_port_start(struct ata_port *ap)
|
||||
return -ENOMEM;
|
||||
acpi->mask[0] = pacpi_discover_modes(ap, &ap->link.device[0]);
|
||||
acpi->mask[1] = pacpi_discover_modes(ap, &ap->link.device[1]);
|
||||
ret = ata_sff_port_start(ap);
|
||||
ret = ata_bmdma_port_start(ap);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ static unsigned long ali_20_filter(struct ata_device *adev, unsigned long mask)
|
||||
ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
|
||||
if (strstr(model_num, "WDC"))
|
||||
return mask &= ~ATA_MASK_UDMA;
|
||||
return ata_bmdma_mode_filter(adev, mask);
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -202,7 +202,6 @@ static struct ata_port_operations pata_at91_port_ops = {
|
||||
.sff_data_xfer = pata_at91_data_xfer_noirq,
|
||||
.set_piomode = pata_at91_set_piomode,
|
||||
.cable_detect = ata_cable_40wire,
|
||||
.port_start = ATA_OP_NULL,
|
||||
};
|
||||
|
||||
static int __devinit pata_at91_probe(struct platform_device *pdev)
|
||||
|
||||
@@ -217,7 +217,7 @@ static struct scsi_host_template atiixp_sht = {
|
||||
static struct ata_port_operations atiixp_port_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
|
||||
.qc_prep = ata_sff_dumb_qc_prep,
|
||||
.qc_prep = ata_bmdma_dumb_qc_prep,
|
||||
.bmdma_start = atiixp_bmdma_start,
|
||||
.bmdma_stop = atiixp_bmdma_stop,
|
||||
|
||||
|
||||
@@ -820,6 +820,18 @@ static void bfin_dev_select(struct ata_port *ap, unsigned int device)
|
||||
ata_sff_pause(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_set_devctl - Write device control reg
|
||||
* @ap: port where the device is
|
||||
* @ctl: value to write
|
||||
*/
|
||||
|
||||
static u8 bfin_set_devctl(struct ata_port *ap, u8 ctl)
|
||||
{
|
||||
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
|
||||
write_atapi_register(base, ATA_REG_CTRL, ctl);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_bmdma_setup - Set up IDE DMA transaction
|
||||
* @qc: Info associated with this ATA transaction.
|
||||
@@ -1215,56 +1227,6 @@ static void bfin_irq_clear(struct ata_port *ap)
|
||||
| MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_irq_on - Enable interrupts on a port.
|
||||
* @ap: Port on which interrupts are enabled.
|
||||
*
|
||||
* Note: Original code is ata_sff_irq_on().
|
||||
*/
|
||||
|
||||
static unsigned char bfin_irq_on(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
|
||||
u8 tmp;
|
||||
|
||||
dev_dbg(ap->dev, "in atapi irq on\n");
|
||||
ap->ctl &= ~ATA_NIEN;
|
||||
ap->last_ctl = ap->ctl;
|
||||
|
||||
write_atapi_register(base, ATA_REG_CTRL, ap->ctl);
|
||||
tmp = ata_wait_idle(ap);
|
||||
|
||||
bfin_irq_clear(ap);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_freeze - Freeze DMA controller port
|
||||
* @ap: port to freeze
|
||||
*
|
||||
* Note: Original code is ata_sff_freeze().
|
||||
*/
|
||||
|
||||
static void bfin_freeze(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
|
||||
|
||||
dev_dbg(ap->dev, "in atapi dma freeze\n");
|
||||
ap->ctl |= ATA_NIEN;
|
||||
ap->last_ctl = ap->ctl;
|
||||
|
||||
write_atapi_register(base, ATA_REG_CTRL, ap->ctl);
|
||||
|
||||
/* Under certain circumstances, some controllers raise IRQ on
|
||||
* ATA_NIEN manipulation. Also, many controllers fail to mask
|
||||
* previously pending IRQ on ATA_NIEN assertion. Clear it.
|
||||
*/
|
||||
ap->ops->sff_check_status(ap);
|
||||
|
||||
bfin_irq_clear(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfin_thaw - Thaw DMA controller port
|
||||
* @ap: port to thaw
|
||||
@@ -1276,7 +1238,7 @@ void bfin_thaw(struct ata_port *ap)
|
||||
{
|
||||
dev_dbg(ap->dev, "in atapi dma thaw\n");
|
||||
bfin_check_status(ap);
|
||||
bfin_irq_on(ap);
|
||||
ata_sff_irq_on(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1293,7 +1255,7 @@ static void bfin_postreset(struct ata_link *link, unsigned int *classes)
|
||||
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
|
||||
|
||||
/* re-enable interrupts */
|
||||
bfin_irq_on(ap);
|
||||
ata_sff_irq_on(ap);
|
||||
|
||||
/* is double-select really necessary? */
|
||||
if (classes[0] != ATA_DEV_NONE)
|
||||
@@ -1438,18 +1400,12 @@ static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance)
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
struct ata_port *ap;
|
||||
struct ata_port *ap = host->ports[i];
|
||||
struct ata_queued_cmd *qc;
|
||||
|
||||
ap = host->ports[i];
|
||||
if (ap &&
|
||||
!(ap->flags & ATA_FLAG_DISABLED)) {
|
||||
struct ata_queued_cmd *qc;
|
||||
|
||||
qc = ata_qc_from_tag(ap, ap->link.active_tag);
|
||||
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
|
||||
(qc->flags & ATA_QCFLAG_ACTIVE))
|
||||
handled |= bfin_ata_host_intr(ap, qc);
|
||||
}
|
||||
qc = ata_qc_from_tag(ap, ap->link.active_tag);
|
||||
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
|
||||
handled |= bfin_ata_host_intr(ap, qc);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
@@ -1465,7 +1421,7 @@ static struct scsi_host_template bfin_sht = {
|
||||
};
|
||||
|
||||
static struct ata_port_operations bfin_pata_ops = {
|
||||
.inherits = &ata_sff_port_ops,
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
|
||||
.set_piomode = bfin_set_piomode,
|
||||
.set_dmamode = bfin_set_dmamode,
|
||||
@@ -1476,6 +1432,7 @@ static struct ata_port_operations bfin_pata_ops = {
|
||||
.sff_check_status = bfin_check_status,
|
||||
.sff_check_altstatus = bfin_check_altstatus,
|
||||
.sff_dev_select = bfin_dev_select,
|
||||
.sff_set_devctl = bfin_set_devctl,
|
||||
|
||||
.bmdma_setup = bfin_bmdma_setup,
|
||||
.bmdma_start = bfin_bmdma_start,
|
||||
@@ -1485,13 +1442,11 @@ static struct ata_port_operations bfin_pata_ops = {
|
||||
|
||||
.qc_prep = ata_noop_qc_prep,
|
||||
|
||||
.freeze = bfin_freeze,
|
||||
.thaw = bfin_thaw,
|
||||
.softreset = bfin_softreset,
|
||||
.postreset = bfin_postreset,
|
||||
|
||||
.sff_irq_clear = bfin_irq_clear,
|
||||
.sff_irq_on = bfin_irq_on,
|
||||
|
||||
.port_start = bfin_port_start,
|
||||
.port_stop = bfin_port_stop,
|
||||
|
||||
@@ -153,24 +153,20 @@ static int cmd640_port_start(struct ata_port *ap)
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
struct cmd640_reg *timing;
|
||||
|
||||
int ret = ata_sff_port_start(ap);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
timing = devm_kzalloc(&pdev->dev, sizeof(struct cmd640_reg), GFP_KERNEL);
|
||||
if (timing == NULL)
|
||||
return -ENOMEM;
|
||||
timing->last = -1; /* Force a load */
|
||||
ap->private_data = timing;
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct scsi_host_template cmd640_sht = {
|
||||
ATA_BMDMA_SHT(DRV_NAME),
|
||||
ATA_PIO_SHT(DRV_NAME),
|
||||
};
|
||||
|
||||
static struct ata_port_operations cmd640_port_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
.inherits = &ata_sff_port_ops,
|
||||
/* In theory xfer_noirq is not needed once we kill the prefetcher */
|
||||
.sff_data_xfer = ata_sff_data_xfer_noirq,
|
||||
.qc_issue = cmd640_qc_issue,
|
||||
@@ -181,13 +177,10 @@ static struct ata_port_operations cmd640_port_ops = {
|
||||
|
||||
static void cmd640_hardware_init(struct pci_dev *pdev)
|
||||
{
|
||||
u8 r;
|
||||
u8 ctrl;
|
||||
|
||||
/* CMD640 detected, commiserations */
|
||||
pci_write_config_byte(pdev, 0x5B, 0x00);
|
||||
/* Get version info */
|
||||
pci_read_config_byte(pdev, CFR, &r);
|
||||
/* PIO0 command cycles */
|
||||
pci_write_config_byte(pdev, CMDTIM, 0);
|
||||
/* 512 byte bursts (sector) */
|
||||
|
||||
@@ -110,7 +110,7 @@ static struct scsi_host_template cs5520_sht = {
|
||||
|
||||
static struct ata_port_operations cs5520_port_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
.qc_prep = ata_sff_dumb_qc_prep,
|
||||
.qc_prep = ata_bmdma_dumb_qc_prep,
|
||||
.cable_detect = ata_cable_40wire,
|
||||
.set_piomode = cs5520_set_piomode,
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user