123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520 |
- /*
- * sata_nv.c - NVIDIA nForce SATA
- *
- * Copyright 2004 NVIDIA Corp. All rights reserved.
- * Copyright 2004 Andrew Chew
- *
- *
- * 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.*
- *
- * No hardware documentation available outside of NVIDIA.
- * This driver programs the NVIDIA SATA controller in a similar
- * fashion as with other PCI IDE BMDMA controllers, with a few
- * NV-specific details such as register offsets, SATA phy location,
- * hotplug info, etc.
- *
- * CK804/MCP04 controllers support an alternate programming interface
- * similar to the ADMA specification (with some modifications).
- * This allows the use of NCQ. Non-DMA-mapped ATA commands are still
- * sent through the legacy interface.
- *
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/gfp.h>
- #include <linux/pci.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- #include <linux/device.h>
- #include <scsi/scsi_host.h>
- #include <scsi/scsi_device.h>
- #include <linux/libata.h>
- #define DRV_NAME "sata_nv"
- #define DRV_VERSION "3.5"
- #define NV_ADMA_DMA_BOUNDARY 0xffffffffUL
- enum {
- NV_MMIO_BAR = 5,
- NV_PORTS = 2,
- NV_PIO_MASK = ATA_PIO4,
- NV_MWDMA_MASK = ATA_MWDMA2,
- NV_UDMA_MASK = ATA_UDMA6,
- NV_PORT0_SCR_REG_OFFSET = 0x00,
- NV_PORT1_SCR_REG_OFFSET = 0x40,
- /* INT_STATUS/ENABLE */
- NV_INT_STATUS = 0x10,
- NV_INT_ENABLE = 0x11,
- NV_INT_STATUS_CK804 = 0x440,
- NV_INT_ENABLE_CK804 = 0x441,
- /* INT_STATUS/ENABLE bits */
- NV_INT_DEV = 0x01,
- NV_INT_PM = 0x02,
- NV_INT_ADDED = 0x04,
- NV_INT_REMOVED = 0x08,
- NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */
- NV_INT_ALL = 0x0f,
- NV_INT_MASK = NV_INT_DEV |
- NV_INT_ADDED | NV_INT_REMOVED,
- /* INT_CONFIG */
- NV_INT_CONFIG = 0x12,
- NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI
- // For PCI config register 20
- NV_MCP_SATA_CFG_20 = 0x50,
- NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04,
- NV_MCP_SATA_CFG_20_PORT0_EN = (1 << 17),
- NV_MCP_SATA_CFG_20_PORT1_EN = (1 << 16),
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN = (1 << 14),
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN = (1 << 12),
- NV_ADMA_MAX_CPBS = 32,
- NV_ADMA_CPB_SZ = 128,
- NV_ADMA_APRD_SZ = 16,
- NV_ADMA_SGTBL_LEN = (1024 - NV_ADMA_CPB_SZ) /
- NV_ADMA_APRD_SZ,
- NV_ADMA_SGTBL_TOTAL_LEN = NV_ADMA_SGTBL_LEN + 5,
- NV_ADMA_SGTBL_SZ = NV_ADMA_SGTBL_LEN * NV_ADMA_APRD_SZ,
- NV_ADMA_PORT_PRIV_DMA_SZ = NV_ADMA_MAX_CPBS *
- (NV_ADMA_CPB_SZ + NV_ADMA_SGTBL_SZ),
- /* BAR5 offset to ADMA general registers */
- NV_ADMA_GEN = 0x400,
- NV_ADMA_GEN_CTL = 0x00,
- NV_ADMA_NOTIFIER_CLEAR = 0x30,
- /* BAR5 offset to ADMA ports */
- NV_ADMA_PORT = 0x480,
- /* size of ADMA port register space */
- NV_ADMA_PORT_SIZE = 0x100,
- /* ADMA port registers */
- NV_ADMA_CTL = 0x40,
- NV_ADMA_CPB_COUNT = 0x42,
- NV_ADMA_NEXT_CPB_IDX = 0x43,
- NV_ADMA_STAT = 0x44,
- NV_ADMA_CPB_BASE_LOW = 0x48,
- NV_ADMA_CPB_BASE_HIGH = 0x4C,
- NV_ADMA_APPEND = 0x50,
- NV_ADMA_NOTIFIER = 0x68,
- NV_ADMA_NOTIFIER_ERROR = 0x6C,
- /* NV_ADMA_CTL register bits */
- NV_ADMA_CTL_HOTPLUG_IEN = (1 << 0),
- NV_ADMA_CTL_CHANNEL_RESET = (1 << 5),
- NV_ADMA_CTL_GO = (1 << 7),
- NV_ADMA_CTL_AIEN = (1 << 8),
- NV_ADMA_CTL_READ_NON_COHERENT = (1 << 11),
- NV_ADMA_CTL_WRITE_NON_COHERENT = (1 << 12),
- /* CPB response flag bits */
- NV_CPB_RESP_DONE = (1 << 0),
- NV_CPB_RESP_ATA_ERR = (1 << 3),
- NV_CPB_RESP_CMD_ERR = (1 << 4),
- NV_CPB_RESP_CPB_ERR = (1 << 7),
- /* CPB control flag bits */
- NV_CPB_CTL_CPB_VALID = (1 << 0),
- NV_CPB_CTL_QUEUE = (1 << 1),
- NV_CPB_CTL_APRD_VALID = (1 << 2),
- NV_CPB_CTL_IEN = (1 << 3),
- NV_CPB_CTL_FPDMA = (1 << 4),
- /* APRD flags */
- NV_APRD_WRITE = (1 << 1),
- NV_APRD_END = (1 << 2),
- NV_APRD_CONT = (1 << 3),
- /* NV_ADMA_STAT flags */
- NV_ADMA_STAT_TIMEOUT = (1 << 0),
- NV_ADMA_STAT_HOTUNPLUG = (1 << 1),
- NV_ADMA_STAT_HOTPLUG = (1 << 2),
- NV_ADMA_STAT_CPBERR = (1 << 4),
- NV_ADMA_STAT_SERROR = (1 << 5),
- NV_ADMA_STAT_CMD_COMPLETE = (1 << 6),
- NV_ADMA_STAT_IDLE = (1 << 8),
- NV_ADMA_STAT_LEGACY = (1 << 9),
- NV_ADMA_STAT_STOPPED = (1 << 10),
- NV_ADMA_STAT_DONE = (1 << 12),
- NV_ADMA_STAT_ERR = NV_ADMA_STAT_CPBERR |
- NV_ADMA_STAT_TIMEOUT,
- /* port flags */
- NV_ADMA_PORT_REGISTER_MODE = (1 << 0),
- NV_ADMA_ATAPI_SETUP_COMPLETE = (1 << 1),
- /* MCP55 reg offset */
- NV_CTL_MCP55 = 0x400,
- NV_INT_STATUS_MCP55 = 0x440,
- NV_INT_ENABLE_MCP55 = 0x444,
- NV_NCQ_REG_MCP55 = 0x448,
- /* MCP55 */
- NV_INT_ALL_MCP55 = 0xffff,
- NV_INT_PORT_SHIFT_MCP55 = 16, /* each port occupies 16 bits */
- NV_INT_MASK_MCP55 = NV_INT_ALL_MCP55 & 0xfffd,
- /* SWNCQ ENABLE BITS*/
- NV_CTL_PRI_SWNCQ = 0x02,
- NV_CTL_SEC_SWNCQ = 0x04,
- /* SW NCQ status bits*/
- NV_SWNCQ_IRQ_DEV = (1 << 0),
- NV_SWNCQ_IRQ_PM = (1 << 1),
- NV_SWNCQ_IRQ_ADDED = (1 << 2),
- NV_SWNCQ_IRQ_REMOVED = (1 << 3),
- NV_SWNCQ_IRQ_BACKOUT = (1 << 4),
- NV_SWNCQ_IRQ_SDBFIS = (1 << 5),
- NV_SWNCQ_IRQ_DHREGFIS = (1 << 6),
- NV_SWNCQ_IRQ_DMASETUP = (1 << 7),
- NV_SWNCQ_IRQ_HOTPLUG = NV_SWNCQ_IRQ_ADDED |
- NV_SWNCQ_IRQ_REMOVED,
- };
- /* ADMA Physical Region Descriptor - one SG segment */
- struct nv_adma_prd {
- __le64 addr;
- __le32 len;
- u8 flags;
- u8 packet_len;
- __le16 reserved;
- };
- enum nv_adma_regbits {
- CMDEND = (1 << 15), /* end of command list */
- WNB = (1 << 14), /* wait-not-BSY */
- IGN = (1 << 13), /* ignore this entry */
- CS1n = (1 << (4 + 8)), /* std. PATA signals follow... */
- DA2 = (1 << (2 + 8)),
- DA1 = (1 << (1 + 8)),
- DA0 = (1 << (0 + 8)),
- };
- /* ADMA Command Parameter Block
- The first 5 SG segments are stored inside the Command Parameter Block itself.
- If there are more than 5 segments the remainder are stored in a separate
- memory area indicated by next_aprd. */
- struct nv_adma_cpb {
- u8 resp_flags; /* 0 */
- u8 reserved1; /* 1 */
- u8 ctl_flags; /* 2 */
- /* len is length of taskfile in 64 bit words */
- u8 len; /* 3 */
- u8 tag; /* 4 */
- u8 next_cpb_idx; /* 5 */
- __le16 reserved2; /* 6-7 */
- __le16 tf[12]; /* 8-31 */
- struct nv_adma_prd aprd[5]; /* 32-111 */
- __le64 next_aprd; /* 112-119 */
- __le64 reserved3; /* 120-127 */
- };
- struct nv_adma_port_priv {
- struct nv_adma_cpb *cpb;
- dma_addr_t cpb_dma;
- struct nv_adma_prd *aprd;
- dma_addr_t aprd_dma;
- void __iomem *ctl_block;
- void __iomem *gen_block;
- void __iomem *notifier_clear_block;
- u64 adma_dma_mask;
- u8 flags;
- int last_issue_ncq;
- };
- struct nv_host_priv {
- unsigned long type;
- };
- struct defer_queue {
- u32 defer_bits;
- unsigned int head;
- unsigned int tail;
- unsigned int tag[ATA_MAX_QUEUE];
- };
- enum ncq_saw_flag_list {
- ncq_saw_d2h = (1U << 0),
- ncq_saw_dmas = (1U << 1),
- ncq_saw_sdb = (1U << 2),
- ncq_saw_backout = (1U << 3),
- };
- struct nv_swncq_port_priv {
- struct ata_bmdma_prd *prd; /* our SG list */
- dma_addr_t prd_dma; /* and its DMA mapping */
- void __iomem *sactive_block;
- void __iomem *irq_block;
- void __iomem *tag_block;
- u32 qc_active;
- unsigned int last_issue_tag;
- /* fifo circular queue to store deferral command */
- struct defer_queue defer_queue;
- /* for NCQ interrupt analysis */
- u32 dhfis_bits;
- u32 dmafis_bits;
- u32 sdbfis_bits;
- unsigned int ncq_flags;
- };
- #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & (1 << (19 + (12 * (PORT)))))
- static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
- #ifdef CONFIG_PM_SLEEP
- static int nv_pci_device_resume(struct pci_dev *pdev);
- #endif
- static void nv_ck804_host_stop(struct ata_host *host);
- static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
- static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
- static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
- static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
- static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
- static int nv_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline);
- static void nv_nf2_freeze(struct ata_port *ap);
- static void nv_nf2_thaw(struct ata_port *ap);
- static void nv_ck804_freeze(struct ata_port *ap);
- static void nv_ck804_thaw(struct ata_port *ap);
- static int nv_adma_slave_config(struct scsi_device *sdev);
- static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
- static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
- static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc);
- static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance);
- static void nv_adma_irq_clear(struct ata_port *ap);
- static int nv_adma_port_start(struct ata_port *ap);
- static void nv_adma_port_stop(struct ata_port *ap);
- #ifdef CONFIG_PM
- static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
- static int nv_adma_port_resume(struct ata_port *ap);
- #endif
- static void nv_adma_freeze(struct ata_port *ap);
- static void nv_adma_thaw(struct ata_port *ap);
- static void nv_adma_error_handler(struct ata_port *ap);
- static void nv_adma_host_stop(struct ata_host *host);
- static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);
- static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
- static void nv_mcp55_thaw(struct ata_port *ap);
- static void nv_mcp55_freeze(struct ata_port *ap);
- static void nv_swncq_error_handler(struct ata_port *ap);
- static int nv_swncq_slave_config(struct scsi_device *sdev);
- static int nv_swncq_port_start(struct ata_port *ap);
- static void nv_swncq_qc_prep(struct ata_queued_cmd *qc);
- static void nv_swncq_fill_sg(struct ata_queued_cmd *qc);
- static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc);
- static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis);
- static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance);
- #ifdef CONFIG_PM
- static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg);
- static int nv_swncq_port_resume(struct ata_port *ap);
- #endif
- enum nv_host_type
- {
- GENERIC,
- NFORCE2,
- NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */
- CK804,
- ADMA,
- MCP5x,
- SWNCQ,
- };
- static const struct pci_device_id nv_pci_tbl[] = {
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), NFORCE2 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), NFORCE3 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), NFORCE3 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), MCP5x },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), MCP5x },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), MCP5x },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), MCP5x },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
- { } /* terminate list */
- };
- static struct pci_driver nv_pci_driver = {
- .name = DRV_NAME,
- .id_table = nv_pci_tbl,
- .probe = nv_init_one,
- #ifdef CONFIG_PM_SLEEP
- .suspend = ata_pci_device_suspend,
- .resume = nv_pci_device_resume,
- #endif
- .remove = ata_pci_remove_one,
- };
- static struct scsi_host_template nv_sht = {
- ATA_BMDMA_SHT(DRV_NAME),
- };
- static struct scsi_host_template nv_adma_sht = {
- ATA_NCQ_SHT(DRV_NAME),
- .can_queue = NV_ADMA_MAX_CPBS,
- .sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN,
- .dma_boundary = NV_ADMA_DMA_BOUNDARY,
- .slave_configure = nv_adma_slave_config,
- };
- static struct scsi_host_template nv_swncq_sht = {
- ATA_NCQ_SHT(DRV_NAME),
- .can_queue = ATA_MAX_QUEUE,
- .sg_tablesize = LIBATA_MAX_PRD,
- .dma_boundary = ATA_DMA_BOUNDARY,
- .slave_configure = nv_swncq_slave_config,
- };
- /*
- * NV SATA controllers have various different problems with hardreset
- * protocol depending on the specific controller and device.
- *
- * GENERIC:
- *
- * bko11195 reports that link doesn't come online after hardreset on
- * generic nv's and there have been several other similar reports on
- * linux-ide.
- *
- * bko12351#c23 reports that warmplug on MCP61 doesn't work with
- * softreset.
- *
- * NF2/3:
- *
- * bko3352 reports nf2/3 controllers can't determine device signature
- * reliably after hardreset. The following thread reports detection
- * failure on cold boot with the standard debouncing timing.
- *
- * http://thread.gmane.org/gmane.linux.ide/34098
- *
- * bko12176 reports that hardreset fails to bring up the link during
- * boot on nf2.
- *
- * CK804:
- *
- * For initial probing after boot and hot plugging, hardreset mostly
- * works fine on CK804 but curiously, reprobing on the initial port
- * by rescanning or rmmod/insmod fails to acquire the initial D2H Reg
- * FIS in somewhat undeterministic way.
- *
- * SWNCQ:
- *
- * bko12351 reports that when SWNCQ is enabled, for hotplug to work,
- * hardreset should be used and hardreset can't report proper
- * signature, which suggests that mcp5x is closer to nf2 as long as
- * reset quirkiness is concerned.
- *
- * bko12703 reports that boot probing fails for intel SSD with
- * hardreset. Link fails to come online. Softreset works fine.
- *
- * The failures are varied but the following patterns seem true for
- * all flavors.
- *
- * - Softreset during boot always works.
- *
- * - Hardreset during boot sometimes fails to bring up the link on
- * certain comibnations and device signature acquisition is
- * unreliable.
- *
- * - Hardreset is often necessary after hotplug.
- *
- * So, preferring softreset for boot probing and error handling (as
- * hardreset might bring down the link) but using hardreset for
- * post-boot probing should work around the above issues in most
- * cases. Define nv_hardreset() which only kicks in for post-boot
- * probing and use it for all variants.
- */
- static struct ata_port_operations nv_generic_ops = {
- .inherits = &ata_bmdma_port_ops,
- .lost_interrupt = ATA_OP_NULL,
- .scr_read = nv_scr_read,
- .scr_write = nv_scr_write,
- .hardreset = nv_hardreset,
- };
- static struct ata_port_operations nv_nf2_ops = {
- .inherits = &nv_generic_ops,
- .freeze = nv_nf2_freeze,
- .thaw = nv_nf2_thaw,
- };
- static struct ata_port_operations nv_ck804_ops = {
- .inherits = &nv_generic_ops,
- .freeze = nv_ck804_freeze,
- .thaw = nv_ck804_thaw,
- .host_stop = nv_ck804_host_stop,
- };
- static struct ata_port_operations nv_adma_ops = {
- .inherits = &nv_ck804_ops,
- .check_atapi_dma = nv_adma_check_atapi_dma,
- .sff_tf_read = nv_adma_tf_read,
- .qc_defer = ata_std_qc_defer,
- .qc_prep = nv_adma_qc_prep,
- .qc_issue = nv_adma_qc_issue,
- .sff_irq_clear = nv_adma_irq_clear,
- .freeze = nv_adma_freeze,
- .thaw = nv_adma_thaw,
- .error_handler = nv_adma_error_handler,
- .post_internal_cmd = nv_adma_post_internal_cmd,
- .port_start = nv_adma_port_start,
- .port_stop = nv_adma_port_stop,
- #ifdef CONFIG_PM
- .port_suspend = nv_adma_port_suspend,
- .port_resume = nv_adma_port_resume,
- #endif
- .host_stop = nv_adma_host_stop,
- };
- static struct ata_port_operations nv_swncq_ops = {
- .inherits = &nv_generic_ops,
- .qc_defer = ata_std_qc_defer,
- .qc_prep = nv_swncq_qc_prep,
- .qc_issue = nv_swncq_qc_issue,
- .freeze = nv_mcp55_freeze,
- .thaw = nv_mcp55_thaw,
- .error_handler = nv_swncq_error_handler,
- #ifdef CONFIG_PM
- .port_suspend = nv_swncq_port_suspend,
- .port_resume = nv_swncq_port_resume,
- #endif
- .port_start = nv_swncq_port_start,
- };
- struct nv_pi_priv {
- irq_handler_t irq_handler;
- struct scsi_host_template *sht;
- };
- #define NV_PI_PRIV(_irq_handler, _sht) \
- &(struct nv_pi_priv){ .irq_handler = _irq_handler, .sht = _sht }
- static const struct ata_port_info nv_port_info[] = {
- /* generic */
- {
- .flags = ATA_FLAG_SATA,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_generic_ops,
- .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
- },
- /* nforce2/3 */
- {
- .flags = ATA_FLAG_SATA,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_nf2_ops,
- .private_data = NV_PI_PRIV(nv_nf2_interrupt, &nv_sht),
- },
- /* ck804 */
- {
- .flags = ATA_FLAG_SATA,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_ck804_ops,
- .private_data = NV_PI_PRIV(nv_ck804_interrupt, &nv_sht),
- },
- /* ADMA */
- {
- .flags = ATA_FLAG_SATA | ATA_FLAG_NCQ,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_adma_ops,
- .private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht),
- },
- /* MCP5x */
- {
- .flags = ATA_FLAG_SATA,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_generic_ops,
- .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
- },
- /* SWNCQ */
- {
- .flags = ATA_FLAG_SATA | ATA_FLAG_NCQ,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_swncq_ops,
- .private_data = NV_PI_PRIV(nv_swncq_interrupt, &nv_swncq_sht),
- },
- };
- MODULE_AUTHOR("NVIDIA");
- MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
- MODULE_LICENSE("GPL");
- MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
- MODULE_VERSION(DRV_VERSION);
- static bool adma_enabled;
- static bool swncq_enabled = true;
- static bool msi_enabled;
- static void nv_adma_register_mode(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 tmp, status;
- int count = 0;
- if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
- return;
- status = readw(mmio + NV_ADMA_STAT);
- while (!(status & NV_ADMA_STAT_IDLE) && count < 20) {
- ndelay(50);
- status = readw(mmio + NV_ADMA_STAT);
- count++;
- }
- if (count == 20)
- ata_port_warn(ap, "timeout waiting for ADMA IDLE, stat=0x%hx\n",
- status);
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
- count = 0;
- status = readw(mmio + NV_ADMA_STAT);
- while (!(status & NV_ADMA_STAT_LEGACY) && count < 20) {
- ndelay(50);
- status = readw(mmio + NV_ADMA_STAT);
- count++;
- }
- if (count == 20)
- ata_port_warn(ap,
- "timeout waiting for ADMA LEGACY, stat=0x%hx\n",
- status);
- pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
- }
- static void nv_adma_mode(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 tmp, status;
- int count = 0;
- if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE))
- return;
- WARN_ON(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE);
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
- status = readw(mmio + NV_ADMA_STAT);
- while (((status & NV_ADMA_STAT_LEGACY) ||
- !(status & NV_ADMA_STAT_IDLE)) && count < 20) {
- ndelay(50);
- status = readw(mmio + NV_ADMA_STAT);
- count++;
- }
- if (count == 20)
- ata_port_warn(ap,
- "timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",
- status);
- pp->flags &= ~NV_ADMA_PORT_REGISTER_MODE;
- }
- static int nv_adma_slave_config(struct scsi_device *sdev)
- {
- struct ata_port *ap = ata_shost_to_port(sdev->host);
- struct nv_adma_port_priv *pp = ap->private_data;
- struct nv_adma_port_priv *port0, *port1;
- struct scsi_device *sdev0, *sdev1;
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- unsigned long segment_boundary, flags;
- unsigned short sg_tablesize;
- int rc;
- int adma_enable;
- u32 current_reg, new_reg, config_mask;
- rc = ata_scsi_slave_config(sdev);
- if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun)
- /* Not a proper libata device, ignore */
- return rc;
- spin_lock_irqsave(ap->lock, flags);
- if (ap->link.device[sdev->id].class == ATA_DEV_ATAPI) {
- /*
- * NVIDIA reports that ADMA mode does not support ATAPI commands.
- * Therefore ATAPI commands are sent through the legacy interface.
- * However, the legacy interface only supports 32-bit DMA.
- * Restrict DMA parameters as required by the legacy interface
- * when an ATAPI device is connected.
- */
- segment_boundary = ATA_DMA_BOUNDARY;
- /* Subtract 1 since an extra entry may be needed for padding, see
- libata-scsi.c */
- sg_tablesize = LIBATA_MAX_PRD - 1;
- /* Since the legacy DMA engine is in use, we need to disable ADMA
- on the port. */
- adma_enable = 0;
- nv_adma_register_mode(ap);
- } else {
- segment_boundary = NV_ADMA_DMA_BOUNDARY;
- sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN;
- adma_enable = 1;
- }
- pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, ¤t_reg);
- if (ap->port_no == 1)
- config_mask = NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN;
- else
- config_mask = NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN;
- if (adma_enable) {
- new_reg = current_reg | config_mask;
- pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE;
- } else {
- new_reg = current_reg & ~config_mask;
- pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE;
- }
- if (current_reg != new_reg)
- pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg);
- port0 = ap->host->ports[0]->private_data;
- port1 = ap->host->ports[1]->private_data;
- sdev0 = ap->host->ports[0]->link.device[0].sdev;
- sdev1 = ap->host->ports[1]->link.device[0].sdev;
- if ((port0->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
- (port1->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
- /** We have to set the DMA mask to 32-bit if either port is in
- ATAPI mode, since they are on the same PCI device which is
- used for DMA mapping. If we set the mask we also need to set
- the bounce limit on both ports to ensure that the block
- layer doesn't feed addresses that cause DMA mapping to
- choke. If either SCSI device is not allocated yet, it's OK
- since that port will discover its correct setting when it
- does get allocated.
- Note: Setting 32-bit mask should not fail. */
- if (sdev0)
- blk_queue_bounce_limit(sdev0->request_queue,
- ATA_DMA_MASK);
- if (sdev1)
- blk_queue_bounce_limit(sdev1->request_queue,
- ATA_DMA_MASK);
- dma_set_mask(&pdev->dev, ATA_DMA_MASK);
- } else {
- /** This shouldn't fail as it was set to this value before */
- dma_set_mask(&pdev->dev, pp->adma_dma_mask);
- if (sdev0)
- blk_queue_bounce_limit(sdev0->request_queue,
- pp->adma_dma_mask);
- if (sdev1)
- blk_queue_bounce_limit(sdev1->request_queue,
- pp->adma_dma_mask);
- }
- blk_queue_segment_boundary(sdev->request_queue, segment_boundary);
- blk_queue_max_segments(sdev->request_queue, sg_tablesize);
- ata_port_info(ap,
- "DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
- (unsigned long long)*ap->host->dev->dma_mask,
- segment_boundary, sg_tablesize);
- spin_unlock_irqrestore(ap->lock, flags);
- return rc;
- }
- static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- return !(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE);
- }
- static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
- {
- /* Other than when internal or pass-through commands are executed,
- the only time this function will be called in ADMA mode will be
- if a command fails. In the failure case we don't care about going
- into register mode with ADMA commands pending, as the commands will
- all shortly be aborted anyway. We assume that NCQ commands are not
- issued via passthrough, which is the only way that switching into
- ADMA mode could abort outstanding commands. */
- nv_adma_register_mode(ap);
- ata_sff_tf_read(ap, tf);
- }
- static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
- {
- unsigned int idx = 0;
- if (tf->flags & ATA_TFLAG_ISADDR) {
- if (tf->flags & ATA_TFLAG_LBA48) {
- cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature | WNB);
- cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->hob_lbal);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->hob_lbam);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->hob_lbah);
- cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature);
- } else
- cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature | WNB);
- cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->nsect);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->lbal);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->lbam);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah);
- }
- if (tf->flags & ATA_TFLAG_DEVICE)
- cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device);
- cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND);
- while (idx < 12)
- cpb[idx++] = cpu_to_le16(IGN);
- return idx;
- }
- static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- u8 flags = pp->cpb[cpb_num].resp_flags;
- VPRINTK("CPB %d, flags=0x%x\n", cpb_num, flags);
- if (unlikely((force_err ||
- flags & (NV_CPB_RESP_ATA_ERR |
- NV_CPB_RESP_CMD_ERR |
- NV_CPB_RESP_CPB_ERR)))) {
- struct ata_eh_info *ehi = &ap->link.eh_info;
- int freeze = 0;
- ata_ehi_clear_desc(ehi);
- __ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x: ", flags);
- if (flags & NV_CPB_RESP_ATA_ERR) {
- ata_ehi_push_desc(ehi, "ATA error");
- ehi->err_mask |= AC_ERR_DEV;
- } else if (flags & NV_CPB_RESP_CMD_ERR) {
- ata_ehi_push_desc(ehi, "CMD error");
- ehi->err_mask |= AC_ERR_DEV;
- } else if (flags & NV_CPB_RESP_CPB_ERR) {
- ata_ehi_push_desc(ehi, "CPB error");
- ehi->err_mask |= AC_ERR_SYSTEM;
- freeze = 1;
- } else {
- /* notifier error, but no error in CPB flags? */
- ata_ehi_push_desc(ehi, "unknown");
- ehi->err_mask |= AC_ERR_OTHER;
- freeze = 1;
- }
- /* Kill all commands. EH will determine what actually failed. */
- if (freeze)
- ata_port_freeze(ap);
- else
- ata_port_abort(ap);
- return -1;
- }
- if (likely(flags & NV_CPB_RESP_DONE))
- return 1;
- return 0;
- }
- static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
- {
- struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
- /* freeze if hotplugged */
- if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
- ata_port_freeze(ap);
- return 1;
- }
- /* bail out if not our interrupt */
- if (!(irq_stat & NV_INT_DEV))
- return 0;
- /* DEV interrupt w/ no active qc? */
- if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
- ata_sff_check_status(ap);
- return 1;
- }
- /* handle interrupt */
- return ata_bmdma_port_intr(ap, qc);
- }
- static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- int i, handled = 0;
- u32 notifier_clears[2];
- spin_lock(&host->lock);
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 status;
- u32 gen_ctl;
- u32 notifier, notifier_error;
- notifier_clears[i] = 0;
- /* if ADMA is disabled, use standard ata interrupt handler */
- if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
- u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
- >> (NV_INT_PORT_SHIFT * i);
- handled += nv_host_intr(ap, irq_stat);
- continue;
- }
- /* if in ATA register mode, check for standard interrupts */
- if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
- u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
- >> (NV_INT_PORT_SHIFT * i);
- if (ata_tag_valid(ap->link.active_tag))
- /** NV_INT_DEV indication seems unreliable
- at times at least in ADMA mode. Force it
- on always when a command is active, to
- prevent losing interrupts. */
- irq_stat |= NV_INT_DEV;
- handled += nv_host_intr(ap, irq_stat);
- }
- notifier = readl(mmio + NV_ADMA_NOTIFIER);
- notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
- notifier_clears[i] = notifier | notifier_error;
- gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
- if (!NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier &&
- !notifier_error)
- /* Nothing to do */
- continue;
- status = readw(mmio + NV_ADMA_STAT);
- /*
- * Clear status. Ensure the controller sees the
- * clearing before we start looking at any of the CPB
- * statuses, so that any CPB completions after this
- * point in the handler will raise another interrupt.
- */
- writew(status, mmio + NV_ADMA_STAT);
- readw(mmio + NV_ADMA_STAT); /* flush posted write */
- rmb();
- handled++; /* irq handled if we got here */
- /* freeze if hotplugged or controller error */
- if (unlikely(status & (NV_ADMA_STAT_HOTPLUG |
- NV_ADMA_STAT_HOTUNPLUG |
- NV_ADMA_STAT_TIMEOUT |
- NV_ADMA_STAT_SERROR))) {
- struct ata_eh_info *ehi = &ap->link.eh_info;
- ata_ehi_clear_desc(ehi);
- __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status);
- if (status & NV_ADMA_STAT_TIMEOUT) {
- ehi->err_mask |= AC_ERR_SYSTEM;
- ata_ehi_push_desc(ehi, "timeout");
- } else if (status & NV_ADMA_STAT_HOTPLUG) {
- ata_ehi_hotplugged(ehi);
- ata_ehi_push_desc(ehi, "hotplug");
- } else if (status & NV_ADMA_STAT_HOTUNPLUG) {
- ata_ehi_hotplugged(ehi);
- ata_ehi_push_desc(ehi, "hot unplug");
- } else if (status & NV_ADMA_STAT_SERROR) {
- /* let EH analyze SError and figure out cause */
- ata_ehi_push_desc(ehi, "SError");
- } else
- ata_ehi_push_desc(ehi, "unknown");
- ata_port_freeze(ap);
- continue;
- }
- if (status & (NV_ADMA_STAT_DONE |
- NV_ADMA_STAT_CPBERR |
- NV_ADMA_STAT_CMD_COMPLETE)) {
- u32 check_commands = notifier_clears[i];
- u32 done_mask = 0;
- int pos, rc;
- if (status & NV_ADMA_STAT_CPBERR) {
- /* check all active commands */
- if (ata_tag_valid(ap->link.active_tag))
- check_commands = 1 <<
- ap->link.active_tag;
- else
- check_commands = ap->link.sactive;
- }
- /* check CPBs for completed commands */
- while ((pos = ffs(check_commands))) {
- pos--;
- rc = nv_adma_check_cpb(ap, pos,
- notifier_error & (1 << pos));
- if (rc > 0)
- done_mask |= 1 << pos;
- else if (unlikely(rc < 0))
- check_commands = 0;
- check_commands &= ~(1 << pos);
- }
- ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
- }
- }
- if (notifier_clears[0] || notifier_clears[1]) {
- /* Note: Both notifier clear registers must be written
- if either is set, even if one is zero, according to NVIDIA. */
- struct nv_adma_port_priv *pp = host->ports[0]->private_data;
- writel(notifier_clears[0], pp->notifier_clear_block);
- pp = host->ports[1]->private_data;
- writel(notifier_clears[1], pp->notifier_clear_block);
- }
- spin_unlock(&host->lock);
- return IRQ_RETVAL(handled);
- }
- static void nv_adma_freeze(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 tmp;
- nv_ck804_freeze(ap);
- if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
- return;
- /* clear any outstanding CK804 notifications */
- writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
- ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
- /* Disable interrupt */
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
- mmio + NV_ADMA_CTL);
- readw(mmio + NV_ADMA_CTL); /* flush posted write */
- }
- static void nv_adma_thaw(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 tmp;
- nv_ck804_thaw(ap);
- if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
- return;
- /* Enable interrupt */
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
- mmio + NV_ADMA_CTL);
- readw(mmio + NV_ADMA_CTL); /* flush posted write */
- }
- static void nv_adma_irq_clear(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u32 notifier_clears[2];
- if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
- ata_bmdma_irq_clear(ap);
- return;
- }
- /* clear any outstanding CK804 notifications */
- writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
- ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
- /* clear ADMA status */
- writew(0xffff, mmio + NV_ADMA_STAT);
- /* clear notifiers - note both ports need to be written with
- something even though we are only clearing on one */
- if (ap->port_no == 0) {
- notifier_clears[0] = 0xFFFFFFFF;
- notifier_clears[1] = 0;
- } else {
- notifier_clears[0] = 0;
- notifier_clears[1] = 0xFFFFFFFF;
- }
- pp = ap->host->ports[0]->private_data;
- writel(notifier_clears[0], pp->notifier_clear_block);
- pp = ap->host->ports[1]->private_data;
- writel(notifier_clears[1], pp->notifier_clear_block);
- }
- static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
- ata_bmdma_post_internal_cmd(qc);
- }
- static int nv_adma_port_start(struct ata_port *ap)
- {
- struct device *dev = ap->host->dev;
- struct nv_adma_port_priv *pp;
- int rc;
- void *mem;
- dma_addr_t mem_dma;
- void __iomem *mmio;
- struct pci_dev *pdev = to_pci_dev(dev);
- u16 tmp;
- VPRINTK("ENTER\n");
- /* Ensure DMA mask is set to 32-bit before allocating legacy PRD and
- pad buffers */
- rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
- if (rc)
- return rc;
- rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
- if (rc)
- return rc;
- /* we might fallback to bmdma, allocate bmdma resources */
- rc = ata_bmdma_port_start(ap);
- if (rc)
- return rc;
- pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
- if (!pp)
- return -ENOMEM;
- mmio = ap->host->iomap[NV_MMIO_BAR] + NV_ADMA_PORT +
- ap->port_no * NV_ADMA_PORT_SIZE;
- pp->ctl_block = mmio;
- pp->gen_block = ap->host->iomap[NV_MMIO_BAR] + NV_ADMA_GEN;
- pp->notifier_clear_block = pp->gen_block +
- NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no);
- /* Now that the legacy PRD and padding buffer are allocated we can
- safely raise the DMA mask to allocate the CPB/APRD table.
- These are allowed to fail since we store the value that ends up
- being used to set as the bounce limit in slave_config later if
- needed. */
- dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
- dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
- pp->adma_dma_mask = *dev->dma_mask;
- mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ,
- &mem_dma, GFP_KERNEL);
- if (!mem)
- return -ENOMEM;
- memset(mem, 0, NV_ADMA_PORT_PRIV_DMA_SZ);
- /*
- * First item in chunk of DMA memory:
- * 128-byte command parameter block (CPB)
- * one for each command tag
- */
- pp->cpb = mem;
- pp->cpb_dma = mem_dma;
- writel(mem_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW);
- writel((mem_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
- mem += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
- mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
- /*
- * Second item: block of ADMA_SGTBL_LEN s/g entries
- */
- pp->aprd = mem;
- pp->aprd_dma = mem_dma;
- ap->private_data = pp;
- /* clear any outstanding interrupt conditions */
- writew(0xffff, mmio + NV_ADMA_STAT);
- /* initialize port variables */
- pp->flags = NV_ADMA_PORT_REGISTER_MODE;
- /* clear CPB fetch count */
- writew(0, mmio + NV_ADMA_CPB_COUNT);
- /* clear GO for register mode, enable interrupt */
- tmp = readw(mmio + NV_ADMA_CTL);
- writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
- NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw(mmio + NV_ADMA_CTL); /* flush posted write */
- udelay(1);
- writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw(mmio + NV_ADMA_CTL); /* flush posted write */
- return 0;
- }
- static void nv_adma_port_stop(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- VPRINTK("ENTER\n");
- writew(0, mmio + NV_ADMA_CTL);
- }
- #ifdef CONFIG_PM
- static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- /* Go to register mode - clears GO */
- nv_adma_register_mode(ap);
- /* clear CPB fetch count */
- writew(0, mmio + NV_ADMA_CPB_COUNT);
- /* disable interrupt, shut down port */
- writew(0, mmio + NV_ADMA_CTL);
- return 0;
- }
- static int nv_adma_port_resume(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 tmp;
- /* set CPB block location */
- writel(pp->cpb_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW);
- writel((pp->cpb_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
- /* clear any outstanding interrupt conditions */
- writew(0xffff, mmio + NV_ADMA_STAT);
- /* initialize port variables */
- pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
- /* clear CPB fetch count */
- writew(0, mmio + NV_ADMA_CPB_COUNT);
- /* clear GO for register mode, enable interrupt */
- tmp = readw(mmio + NV_ADMA_CTL);
- writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
- NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw(mmio + NV_ADMA_CTL); /* flush posted write */
- udelay(1);
- writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw(mmio + NV_ADMA_CTL); /* flush posted write */
- return 0;
- }
- #endif
- static void nv_adma_setup_port(struct ata_port *ap)
- {
- void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
- struct ata_ioports *ioport = &ap->ioaddr;
- VPRINTK("ENTER\n");
- mmio += NV_ADMA_PORT + ap->port_no * NV_ADMA_PORT_SIZE;
- ioport->cmd_addr = mmio;
- ioport->data_addr = mmio + (ATA_REG_DATA * 4);
- ioport->error_addr =
- ioport->feature_addr = mmio + (ATA_REG_ERR * 4);
- ioport->nsect_addr = mmio + (ATA_REG_NSECT * 4);
- ioport->lbal_addr = mmio + (ATA_REG_LBAL * 4);
- ioport->lbam_addr = mmio + (ATA_REG_LBAM * 4);
- ioport->lbah_addr = mmio + (ATA_REG_LBAH * 4);
- ioport->device_addr = mmio + (ATA_REG_DEVICE * 4);
- ioport->status_addr =
- ioport->command_addr = mmio + (ATA_REG_STATUS * 4);
- ioport->altstatus_addr =
- ioport->ctl_addr = mmio + 0x20;
- }
- static int nv_adma_host_init(struct ata_host *host)
- {
- struct pci_dev *pdev = to_pci_dev(host->dev);
- unsigned int i;
- u32 tmp32;
- VPRINTK("ENTER\n");
- /* enable ADMA on the ports */
- pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
- tmp32 |= NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN |
- NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN;
- pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
- for (i = 0; i < host->n_ports; i++)
- nv_adma_setup_port(host->ports[i]);
- return 0;
- }
- static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
- struct scatterlist *sg,
- int idx,
- struct nv_adma_prd *aprd)
- {
- u8 flags = 0;
- if (qc->tf.flags & ATA_TFLAG_WRITE)
- flags |= NV_APRD_WRITE;
- if (idx == qc->n_elem - 1)
- flags |= NV_APRD_END;
- else if (idx != 4)
- flags |= NV_APRD_CONT;
- aprd->addr = cpu_to_le64(((u64)sg_dma_address(sg)));
- aprd->len = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */
- aprd->flags = flags;
- aprd->packet_len = 0;
- }
- static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- struct nv_adma_prd *aprd;
- struct scatterlist *sg;
- unsigned int si;
- VPRINTK("ENTER\n");
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
- aprd = (si < 5) ? &cpb->aprd[si] :
- &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5)];
- nv_adma_fill_aprd(qc, sg, si, aprd);
- }
- if (si > 5)
- cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
- else
- cpb->next_aprd = cpu_to_le64(0);
- }
- static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- /* ADMA engine can only be used for non-ATAPI DMA commands,
- or interrupt-driven no-data commands. */
- if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
- (qc->tf.flags & ATA_TFLAG_POLLING))
- return 1;
- if ((qc->flags & ATA_QCFLAG_DMAMAP) ||
- (qc->tf.protocol == ATA_PROT_NODATA))
- return 0;
- return 1;
- }
- static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- struct nv_adma_cpb *cpb = &pp->cpb[qc->tag];
- u8 ctl_flags = NV_CPB_CTL_CPB_VALID |
- NV_CPB_CTL_IEN;
- if (nv_adma_use_reg_mode(qc)) {
- BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
- (qc->flags & ATA_QCFLAG_DMAMAP));
- nv_adma_register_mode(qc->ap);
- ata_bmdma_qc_prep(qc);
- return;
- }
- cpb->resp_flags = NV_CPB_RESP_DONE;
- wmb();
- cpb->ctl_flags = 0;
- wmb();
- cpb->len = 3;
- cpb->tag = qc->tag;
- cpb->next_cpb_idx = 0;
- /* turn on NCQ flags for NCQ commands */
- if (qc->tf.protocol == ATA_PROT_NCQ)
- ctl_flags |= NV_CPB_CTL_QUEUE | NV_CPB_CTL_FPDMA;
- VPRINTK("qc->flags = 0x%lx\n", qc->flags);
- nv_adma_tf_to_cpb(&qc->tf, cpb->tf);
- if (qc->flags & ATA_QCFLAG_DMAMAP) {
- nv_adma_fill_sg(qc, cpb);
- ctl_flags |= NV_CPB_CTL_APRD_VALID;
- } else
- memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5);
- /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID
- until we are finished filling in all of the contents */
- wmb();
- cpb->ctl_flags = ctl_flags;
- wmb();
- cpb->resp_flags = 0;
- }
- static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- int curr_ncq = (qc->tf.protocol == ATA_PROT_NCQ);
- VPRINTK("ENTER\n");
- /* We can't handle result taskfile with NCQ commands, since
- retrieving the taskfile switches us out of ADMA mode and would abort
- existing commands. */
- if (unlikely(qc->tf.protocol == ATA_PROT_NCQ &&
- (qc->flags & ATA_QCFLAG_RESULT_TF))) {
- ata_dev_err(qc->dev, "NCQ w/ RESULT_TF not allowed\n");
- return AC_ERR_SYSTEM;
- }
- if (nv_adma_use_reg_mode(qc)) {
- /* use ATA register mode */
- VPRINTK("using ATA register mode: 0x%lx\n", qc->flags);
- BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
- (qc->flags & ATA_QCFLAG_DMAMAP));
- nv_adma_register_mode(qc->ap);
- return ata_bmdma_qc_issue(qc);
- } else
- nv_adma_mode(qc->ap);
- /* write append register, command tag in lower 8 bits
- and (number of cpbs to append -1) in top 8 bits */
- wmb();
- if (curr_ncq != pp->last_issue_ncq) {
- /* Seems to need some delay before switching between NCQ and
- non-NCQ commands, else we get command timeouts and such. */
- udelay(20);
- pp->last_issue_ncq = curr_ncq;
- }
- writew(qc->tag, mmio + NV_ADMA_APPEND);
- DPRINTK("Issued tag %u\n", qc->tag);
- return 0;
- }
- static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- unsigned int i;
- unsigned int handled = 0;
- unsigned long flags;
- spin_lock_irqsave(&host->lock, flags);
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- struct ata_queued_cmd *qc;
- qc = ata_qc_from_tag(ap, ap->link.active_tag);
- if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
- handled += ata_bmdma_port_intr(ap, qc);
- } else {
- /*
- * No request pending? Clear interrupt status
- * anyway, in case there's one pending.
- */
- ap->ops->sff_check_status(ap);
- }
- }
- spin_unlock_irqrestore(&host->lock, flags);
- return IRQ_RETVAL(handled);
- }
- static irqreturn_t nv_do_interrupt(struct ata_host *host, u8 irq_stat)
- {
- int i, handled = 0;
- for (i = 0; i < host->n_ports; i++) {
- handled += nv_host_intr(host->ports[i], irq_stat);
- irq_stat >>= NV_INT_PORT_SHIFT;
- }
- return IRQ_RETVAL(handled);
- }
- static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- u8 irq_stat;
- irqreturn_t ret;
- spin_lock(&host->lock);
- irq_stat = ioread8(host->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
- ret = nv_do_interrupt(host, irq_stat);
- spin_unlock(&host->lock);
- return ret;
- }
- static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- u8 irq_stat;
- irqreturn_t ret;
- spin_lock(&host->lock);
- irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
- ret = nv_do_interrupt(host, irq_stat);
- spin_unlock(&host->lock);
- return ret;
- }
- static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
- {
- if (sc_reg > SCR_CONTROL)
- return -EINVAL;
- *val = ioread32(link->ap->ioaddr.scr_addr + (sc_reg * 4));
- return 0;
- }
- static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
- {
- if (sc_reg > SCR_CONTROL)
- return -EINVAL;
- iowrite32(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
- return 0;
- }
- static int nv_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
- {
- struct ata_eh_context *ehc = &link->eh_context;
- /* Do hardreset iff it's post-boot probing, please read the
- * comment above port ops for details.
- */
- if (!(link->ap->pflags & ATA_PFLAG_LOADING) &&
- !ata_dev_enabled(link->device))
- sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
- NULL, NULL);
- else {
- const unsigned long *timing = sata_ehc_deb_timing(ehc);
- int rc;
- if (!(ehc->i.flags & ATA_EHI_QUIET))
- ata_link_info(link,
- "nv: skipping hardreset on occupied port\n");
- /* make sure the link is online */
- rc = sata_link_resume(link, timing, deadline);
- /* whine about phy resume failure but proceed */
- if (rc && rc != -EOPNOTSUPP)
- ata_link_warn(link, "failed to resume link (errno=%d)\n",
- rc);
- }
- /* device signature acquisition is unreliable */
- return -EAGAIN;
- }
- static void nv_nf2_freeze(struct ata_port *ap)
- {
- void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
- int shift = ap->port_no * NV_INT_PORT_SHIFT;
- u8 mask;
- mask = ioread8(scr_addr + NV_INT_ENABLE);
- mask &= ~(NV_INT_ALL << shift);
- iowrite8(mask, scr_addr + NV_INT_ENABLE);
- }
- static void nv_nf2_thaw(struct ata_port *ap)
- {
- void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
- int shift = ap->port_no * NV_INT_PORT_SHIFT;
- u8 mask;
- iowrite8(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS);
- mask = ioread8(scr_addr + NV_INT_ENABLE);
- mask |= (NV_INT_MASK << shift);
- iowrite8(mask, scr_addr + NV_INT_ENABLE);
- }
- static void nv_ck804_freeze(struct ata_port *ap)
- {
- void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
- int shift = ap->port_no * NV_INT_PORT_SHIFT;
- u8 mask;
- mask = readb(mmio_base + NV_INT_ENABLE_CK804);
- mask &= ~(NV_INT_ALL << shift);
- writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
- }
- static void nv_ck804_thaw(struct ata_port *ap)
- {
- void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
- int shift = ap->port_no * NV_INT_PORT_SHIFT;
- u8 mask;
- writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804);
- mask = readb(mmio_base + NV_INT_ENABLE_CK804);
- mask |= (NV_INT_MASK << shift);
- writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
- }
- static void nv_mcp55_freeze(struct ata_port *ap)
- {
- void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
- int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55;
- u32 mask;
- writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55);
- mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
- mask &= ~(NV_INT_ALL_MCP55 << shift);
- writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
- }
- static void nv_mcp55_thaw(struct ata_port *ap)
- {
- void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
- int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55;
- u32 mask;
- writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55);
- mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
- mask |= (NV_INT_MASK_MCP55 << shift);
- writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
- }
- static void nv_adma_error_handler(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
- void __iomem *mmio = pp->ctl_block;
- int i;
- u16 tmp;
- if (ata_tag_valid(ap->link.active_tag) || ap->link.sactive) {
- u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
- u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
- u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
- u32 status = readw(mmio + NV_ADMA_STAT);
- u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT);
- u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX);
- ata_port_err(ap,
- "EH in ADMA mode, notifier 0x%X "
- "notifier_error 0x%X gen_ctl 0x%X status 0x%X "
- "next cpb count 0x%X next cpb idx 0x%x\n",
- notifier, notifier_error, gen_ctl, status,
- cpb_count, next_cpb_idx);
- for (i = 0; i < NV_ADMA_MAX_CPBS; i++) {
- struct nv_adma_cpb *cpb = &pp->cpb[i];
- if ((ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||
- ap->link.sactive & (1 << i))
- ata_port_err(ap,
- "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
- i, cpb->ctl_flags, cpb->resp_flags);
- }
- }
- /* Push us back into port register mode for error handling. */
- nv_adma_register_mode(ap);
- /* Mark all of the CPBs as invalid to prevent them from
- being executed */
- for (i = 0; i < NV_ADMA_MAX_CPBS; i++)
- pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID;
- /* clear CPB fetch count */
- writew(0, mmio + NV_ADMA_CPB_COUNT);
- /* Reset channel */
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw(mmio + NV_ADMA_CTL); /* flush posted write */
- udelay(1);
- writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw(mmio + NV_ADMA_CTL); /* flush posted write */
- }
- ata_bmdma_error_handler(ap);
- }
- static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc)
- {
- struct nv_swncq_port_priv *pp = ap->private_data;
- struct defer_queue *dq = &pp->defer_queue;
- /* queue is full */
- WARN_ON(dq->tail - dq->head == ATA_MAX_QUEUE);
- dq->defer_bits |= (1 << qc->tag);
- dq->tag[dq->tail++ & (ATA_MAX_QUEUE - 1)] = qc->tag;
- }
- static struct ata_queued_cmd *nv_swncq_qc_from_dq(struct ata_port *ap)
- {
- struct nv_swncq_port_priv *pp = ap->private_data;
- struct defer_queue *dq = &pp->defer_queue;
- unsigned int tag;
- if (dq->head == dq->tail) /* null queue */
- return NULL;
- tag = dq->tag[dq->head & (ATA_MAX_QUEUE - 1)];
- dq->tag[dq->head++ & (ATA_MAX_QUEUE - 1)] = ATA_TAG_POISON;
- WARN_ON(!(dq->defer_bits & (1 << tag)));
- dq->defer_bits &= ~(1 << tag);
- return ata_qc_from_tag(ap, tag);
- }
- static void nv_swncq_fis_reinit(struct ata_port *ap)
- {
- struct nv_swncq_port_priv *pp = ap->private_data;
- pp->dhfis_bits = 0;
- pp->dmafis_bits = 0;
- pp->sdbfis_bits = 0;
- pp->ncq_flags = 0;
- }
- static void nv_swncq_pp_reinit(struct ata_port *ap)
- {
- struct nv_swncq_port_priv *pp = ap->private_data;
- struct defer_queue *dq = &pp->defer_queue;
- dq->head = 0;
- dq->tail = 0;
- dq->defer_bits = 0;
- pp->qc_active = 0;
- pp->last_issue_tag = ATA_TAG_POISON;
- nv_swncq_fis_reinit(ap);
- }
- static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis)
- {
- struct nv_swncq_port_priv *pp = ap->private_data;
- writew(fis, pp->irq_block);
- }
- static void __ata_bmdma_stop(struct ata_port *ap)
- {
- struct ata_queued_cmd qc;
- qc.ap = ap;
- ata_bmdma_stop(&qc);
- }
- static void nv_swncq_ncq_stop(struct ata_port *ap)
- {
- struct nv_swncq_port_priv *pp = ap->private_data;
- unsigned int i;
- u32 sactive;
- u32 done_mask;
- ata_port_err(ap, "EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n",
- ap->qc_active, ap->link.sactive);
- ata_port_err(ap,
- "SWNCQ:qc_active 0x%X defer_bits 0x%X last_issue_tag 0x%x\n "
- "dhfis 0x%X dmafis 0x%X sdbfis 0x%X\n",
- pp->qc_active, pp->defer_queue.defer_bits, pp->last_issue_tag,
- pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits);
- ata_port_err(ap, "ATA_REG 0x%X ERR_REG 0x%X\n",
- ap->ops->sff_check_status(ap),
- ioread8(ap->ioaddr.error_addr));
- sactive = readl(pp->sactive_block);
- done_mask = pp->qc_active ^ sactive;
- ata_port_err(ap, "tag : dhfis dmafis sdbfis sactive\n");
- for (i = 0; i < ATA_MAX_QUEUE; i++) {
- u8 err = 0;
- if (pp->qc_active & (1 << i))
- err = 0;
- else if (done_mask & (1 << i))
- err = 1;
- else
- continue;
- ata_port_err(ap,
- "tag 0x%x: %01x %01x %01x %01x %s\n", i,
- (pp->dhfis_bits >> i) & 0x1,
- (pp->dmafis_bits >> i) & 0x1,
- (pp->sdbfis_bits >> i) & 0x1,
- (sactive >> i) & 0x1,
- (err ? "error! tag doesn't exit" : " "));
- }
- nv_swncq_pp_reinit(ap);
- ap->ops->sff_irq_clear(ap);
- __ata_bmdma_stop(ap);
- nv_swncq_irq_clear(ap, 0xffff);
- }
- static void nv_swncq_error_handler(struct ata_port *ap)
- {
- struct ata_eh_context *ehc = &ap->link.eh_context;
- if (ap->link.sactive) {
- nv_swncq_ncq_stop(ap);
- ehc->i.action |= ATA_EH_RESET;
- }
- ata_bmdma_error_handler(ap);
- }
- #ifdef CONFIG_PM
- static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg)
- {
- void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
- u32 tmp;
- /* clear irq */
- writel(~0, mmio + NV_INT_STATUS_MCP55);
- /* disable irq */
- writel(0, mmio + NV_INT_ENABLE_MCP55);
- /* disable swncq */
- tmp = readl(mmio + NV_CTL_MCP55);
- tmp &= ~(NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ);
- writel(tmp, mmio + NV_CTL_MCP55);
- return 0;
- }
- static int nv_swncq_port_resume(struct ata_port *ap)
- {
- void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
- u32 tmp;
- /* clear irq */
- writel(~0, mmio + NV_INT_STATUS_MCP55);
- /* enable irq */
- writel(0x00fd00fd, mmio + NV_INT_ENABLE_MCP55);
- /* enable swncq */
- tmp = readl(mmio + NV_CTL_MCP55);
- writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55);
- return 0;
- }
- #endif
- static void nv_swncq_host_init(struct ata_host *host)
- {
- u32 tmp;
- void __iomem *mmio = host->iomap[NV_MMIO_BAR];
- struct pci_dev *pdev = to_pci_dev(host->dev);
- u8 regval;
- /* disable ECO 398 */
- pci_read_config_byte(pdev, 0x7f, ®val);
- regval &= ~(1 << 7);
- pci_write_config_byte(pdev, 0x7f, regval);
- /* enable swncq */
- tmp = readl(mmio + NV_CTL_MCP55);
- VPRINTK("HOST_CTL:0x%X\n", tmp);
- writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55);
- /* enable irq intr */
- tmp = readl(mmio + NV_INT_ENABLE_MCP55);
- VPRINTK("HOST_ENABLE:0x%X\n", tmp);
- writel(tmp | 0x00fd00fd, mmio + NV_INT_ENABLE_MCP55);
- /* clear port irq */
- writel(~0x0, mmio + NV_INT_STATUS_MCP55);
- }
- static int nv_swncq_slave_config(struct scsi_device *sdev)
- {
- struct ata_port *ap = ata_shost_to_port(sdev->host);
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- struct ata_device *dev;
- int rc;
- u8 rev;
- u8 check_maxtor = 0;
- unsigned char model_num[ATA_ID_PROD_LEN + 1];
- rc = ata_scsi_slave_config(sdev);
- if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun)
- /* Not a proper libata device, ignore */
- return rc;
- dev = &ap->link.device[sdev->id];
- if (!(ap->flags & ATA_FLAG_NCQ) || dev->class == ATA_DEV_ATAPI)
- return rc;
- /* if MCP51 and Maxtor, then disable ncq */
- if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA ||
- pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2)
- check_maxtor = 1;
- /* if MCP55 and rev <= a2 and Maxtor, then disable ncq */
- if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA ||
- pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2) {
- pci_read_config_byte(pdev, 0x8, &rev);
- if (rev <= 0xa2)
- check_maxtor = 1;
- }
- if (!check_maxtor)
- return rc;
- ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
- if (strncmp(model_num, "Maxtor", 6) == 0) {
- ata_scsi_change_queue_depth(sdev, 1);
- ata_dev_notice(dev, "Disabling SWNCQ mode (depth %x)\n",
- sdev->queue_depth);
- }
- return rc;
- }
- static int nv_swncq_port_start(struct ata_port *ap)
- {
- struct device *dev = ap->host->dev;
- void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
- struct nv_swncq_port_priv *pp;
- int rc;
- /* we might fallback to bmdma, allocate bmdma resources */
- rc = ata_bmdma_port_start(ap);
- if (rc)
- return rc;
- pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
- if (!pp)
- return -ENOMEM;
- pp->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE,
- &pp->prd_dma, GFP_KERNEL);
- if (!pp->prd)
- return -ENOMEM;
- memset(pp->prd, 0, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE);
- ap->private_data = pp;
- pp->sactive_block = ap->ioaddr.scr_addr + 4 * SCR_ACTIVE;
- pp->irq_block = mmio + NV_INT_STATUS_MCP55 + ap->port_no * 2;
- pp->tag_block = mmio + NV_NCQ_REG_MCP55 + ap->port_no * 2;
- return 0;
- }
- static void nv_swncq_qc_prep(struct ata_queued_cmd *qc)
- {
- if (qc->tf.protocol != ATA_PROT_NCQ) {
- ata_bmdma_qc_prep(qc);
- return;
- }
- if (!(qc->flags & ATA_QCFLAG_DMAMAP))
- return;
- nv_swncq_fill_sg(qc);
- }
- static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- struct scatterlist *sg;
- struct nv_swncq_port_priv *pp = ap->private_data;
- struct ata_bmdma_prd *prd;
- unsigned int si, idx;
- prd = pp->prd + ATA_MAX_PRD * qc->tag;
- idx = 0;
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
- u32 addr, offset;
- u32 sg_len, len;
- addr = (u32)sg_dma_address(sg);
- sg_len = sg_dma_len(sg);
- while (sg_len) {
- offset = addr & 0xffff;
- len = sg_len;
- if ((offset + sg_len) > 0x10000)
- len = 0x10000 - offset;
- prd[idx].addr = cpu_to_le32(addr);
- prd[idx].flags_len = cpu_to_le32(len & 0xffff);
- idx++;
- sg_len -= len;
- addr += len;
- }
- }
- prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
- }
- static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
- struct ata_queued_cmd *qc)
- {
- struct nv_swncq_port_priv *pp = ap->private_data;
- if (qc == NULL)
- return 0;
- DPRINTK("Enter\n");
- writel((1 << qc->tag), pp->sactive_block);
- pp->last_issue_tag = qc->tag;
- pp->dhfis_bits &= ~(1 << qc->tag);
- pp->dmafis_bits &= ~(1 << qc->tag);
- pp->qc_active |= (0x1 << qc->tag);
- ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
- ap->ops->sff_exec_command(ap, &qc->tf);
- DPRINTK("Issued tag %u\n", qc->tag);
- return 0;
- }
- static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- struct nv_swncq_port_priv *pp = ap->private_data;
- if (qc->tf.protocol != ATA_PROT_NCQ)
- return ata_bmdma_qc_issue(qc);
- DPRINTK("Enter\n");
- if (!pp->qc_active)
- nv_swncq_issue_atacmd(ap, qc);
- else
- nv_swncq_qc_to_dq(ap, qc); /* add qc to defer queue */
- return 0;
- }
- static void nv_swncq_hotplug(struct ata_port *ap, u32 fis)
- {
- u32 serror;
- struct ata_eh_info *ehi = &ap->link.eh_info;
- ata_ehi_clear_desc(ehi);
- /* AHCI needs SError cleared; otherwise, it might lock up */
- sata_scr_read(&ap->link, SCR_ERROR, &serror);
- sata_scr_write(&ap->link, SCR_ERROR, serror);
- /* analyze @irq_stat */
- if (fis & NV_SWNCQ_IRQ_ADDED)
- ata_ehi_push_desc(ehi, "hot plug");
- else if (fis & NV_SWNCQ_IRQ_REMOVED)
- ata_ehi_push_desc(ehi, "hot unplug");
- ata_ehi_hotplugged(ehi);
- /* okay, let's hand over to EH */
- ehi->serror |= serror;
- ata_port_freeze(ap);
- }
- static int nv_swncq_sdbfis(struct ata_port *ap)
- {
- struct ata_queued_cmd *qc;
- struct nv_swncq_port_priv *pp = ap->private_data;
- struct ata_eh_info *ehi = &ap->link.eh_info;
- u32 sactive;
- u32 done_mask;
- u8 host_stat;
- u8 lack_dhfis = 0;
- host_stat = ap->ops->bmdma_status(ap);
- if (unlikely(host_stat & ATA_DMA_ERR)) {
- /* error when transferring data to/from memory */
- ata_ehi_clear_desc(ehi);
- ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
- ehi->err_mask |= AC_ERR_HOST_BUS;
- ehi->action |= ATA_EH_RESET;
- return -EINVAL;
- }
- ap->ops->sff_irq_clear(ap);
- __ata_bmdma_stop(ap);
- sactive = readl(pp->sactive_block);
- done_mask = pp->qc_active ^ sactive;
- pp->qc_active &= ~done_mask;
- pp->dhfis_bits &= ~done_mask;
- pp->dmafis_bits &= ~done_mask;
- pp->sdbfis_bits |= done_mask;
- ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
- if (!ap->qc_active) {
- DPRINTK("over\n");
- nv_swncq_pp_reinit(ap);
- return 0;
- }
- if (pp->qc_active & pp->dhfis_bits)
- return 0;
- if ((pp->ncq_flags & ncq_saw_backout) ||
- (pp->qc_active ^ pp->dhfis_bits))
- /* if the controller can't get a device to host register FIS,
- * The driver needs to reissue the new command.
- */
- lack_dhfis = 1;
- DPRINTK("id 0x%x QC: qc_active 0x%x,"
- "SWNCQ:qc_active 0x%X defer_bits %X "
- "dhfis 0x%X dmafis 0x%X last_issue_tag %x\n",
- ap->print_id, ap->qc_active, pp->qc_active,
- pp->defer_queue.defer_bits, pp->dhfis_bits,
- pp->dmafis_bits, pp->last_issue_tag);
- nv_swncq_fis_reinit(ap);
- if (lack_dhfis) {
- qc = ata_qc_from_tag(ap, pp->last_issue_tag);
- nv_swncq_issue_atacmd(ap, qc);
- return 0;
- }
- if (pp->defer_queue.defer_bits) {
- /* send deferral queue command */
- qc = nv_swncq_qc_from_dq(ap);
- WARN_ON(qc == NULL);
- nv_swncq_issue_atacmd(ap, qc);
- }
- return 0;
- }
- static inline u32 nv_swncq_tag(struct ata_port *ap)
- {
- struct nv_swncq_port_priv *pp = ap->private_data;
- u32 tag;
- tag = readb(pp->tag_block) >> 2;
- return (tag & 0x1f);
- }
- static void nv_swncq_dmafis(struct ata_port *ap)
- {
- struct ata_queued_cmd *qc;
- unsigned int rw;
- u8 dmactl;
- u32 tag;
- struct nv_swncq_port_priv *pp = ap->private_data;
- __ata_bmdma_stop(ap);
- tag = nv_swncq_tag(ap);
- DPRINTK("dma setup tag 0x%x\n", tag);
- qc = ata_qc_from_tag(ap, tag);
- if (unlikely(!qc))
- return;
- rw = qc->tf.flags & ATA_TFLAG_WRITE;
- /* load PRD table addr. */
- iowrite32(pp->prd_dma + ATA_PRD_TBL_SZ * qc->tag,
- ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
- /* specify data direction, triple-check start bit is clear */
- dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- dmactl &= ~ATA_DMA_WR;
- if (!rw)
- dmactl |= ATA_DMA_WR;
- iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- }
- static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
- {
- struct nv_swncq_port_priv *pp = ap->private_data;
- struct ata_queued_cmd *qc;
- struct ata_eh_info *ehi = &ap->link.eh_info;
- u32 serror;
- u8 ata_stat;
- ata_stat = ap->ops->sff_check_status(ap);
- nv_swncq_irq_clear(ap, fis);
- if (!fis)
- return;
- if (ap->pflags & ATA_PFLAG_FROZEN)
- return;
- if (fis & NV_SWNCQ_IRQ_HOTPLUG) {
- nv_swncq_hotplug(ap, fis);
- return;
- }
- if (!pp->qc_active)
- return;
- if (ap->ops->scr_read(&ap->link, SCR_ERROR, &serror))
- return;
- ap->ops->scr_write(&ap->link, SCR_ERROR, serror);
- if (ata_stat & ATA_ERR) {
- ata_ehi_clear_desc(ehi);
- ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis);
- ehi->err_mask |= AC_ERR_DEV;
- ehi->serror |= serror;
- ehi->action |= ATA_EH_RESET;
- ata_port_freeze(ap);
- return;
- }
- if (fis & NV_SWNCQ_IRQ_BACKOUT) {
- /* If the IRQ is backout, driver must issue
- * the new command again some time later.
- */
- pp->ncq_flags |= ncq_saw_backout;
- }
- if (fis & NV_SWNCQ_IRQ_SDBFIS) {
- pp->ncq_flags |= ncq_saw_sdb;
- DPRINTK("id 0x%x SWNCQ: qc_active 0x%X "
- "dhfis 0x%X dmafis 0x%X sactive 0x%X\n",
- ap->print_id, pp->qc_active, pp->dhfis_bits,
- pp->dmafis_bits, readl(pp->sactive_block));
- if (nv_swncq_sdbfis(ap) < 0)
- goto irq_error;
- }
- if (fis & NV_SWNCQ_IRQ_DHREGFIS) {
- /* The interrupt indicates the new command
- * was transmitted correctly to the drive.
- */
- pp->dhfis_bits |= (0x1 << pp->last_issue_tag);
- pp->ncq_flags |= ncq_saw_d2h;
- if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) {
- ata_ehi_push_desc(ehi, "illegal fis transaction");
- ehi->err_mask |= AC_ERR_HSM;
- ehi->action |= ATA_EH_RESET;
- goto irq_error;
- }
- if (!(fis & NV_SWNCQ_IRQ_DMASETUP) &&
- !(pp->ncq_flags & ncq_saw_dmas)) {
- ata_stat = ap->ops->sff_check_status(ap);
- if (ata_stat & ATA_BUSY)
- goto irq_exit;
- if (pp->defer_queue.defer_bits) {
- DPRINTK("send next command\n");
- qc = nv_swncq_qc_from_dq(ap);
- nv_swncq_issue_atacmd(ap, qc);
- }
- }
- }
- if (fis & NV_SWNCQ_IRQ_DMASETUP) {
- /* program the dma controller with appropriate PRD buffers
- * and start the DMA transfer for requested command.
- */
- pp->dmafis_bits |= (0x1 << nv_swncq_tag(ap));
- pp->ncq_flags |= ncq_saw_dmas;
- nv_swncq_dmafis(ap);
- }
- irq_exit:
- return;
- irq_error:
- ata_ehi_push_desc(ehi, "fis:0x%x", fis);
- ata_port_freeze(ap);
- return;
- }
- static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- unsigned int i;
- unsigned int handled = 0;
- unsigned long flags;
- u32 irq_stat;
- spin_lock_irqsave(&host->lock, flags);
- irq_stat = readl(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_MCP55);
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- if (ap->link.sactive) {
- nv_swncq_host_interrupt(ap, (u16)irq_stat);
- handled = 1;
- } else {
- if (irq_stat) /* reserve Hotplug */
- nv_swncq_irq_clear(ap, 0xfff0);
- handled += nv_host_intr(ap, (u8)irq_stat);
- }
- irq_stat >>= NV_INT_PORT_SHIFT_MCP55;
- }
- spin_unlock_irqrestore(&host->lock, flags);
- return IRQ_RETVAL(handled);
- }
- static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
- {
- const struct ata_port_info *ppi[] = { NULL, NULL };
- struct nv_pi_priv *ipriv;
- struct ata_host *host;
- struct nv_host_priv *hpriv;
- int rc;
- u32 bar;
- void __iomem *base;
- unsigned long type = ent->driver_data;
- // Make sure this is a SATA controller by counting the number of bars
- // (NVIDIA SATA controllers will always have six bars). Otherwise,
- // it's an IDE controller and we ignore it.
- for (bar = 0; bar < 6; bar++)
- if (pci_resource_start(pdev, bar) == 0)
- return -ENODEV;
- ata_print_version_once(&pdev->dev, DRV_VERSION);
- rc = pcim_enable_device(pdev);
- if (rc)
- return rc;
- /* determine type and allocate host */
- if (type == CK804 && adma_enabled) {
- dev_notice(&pdev->dev, "Using ADMA mode\n");
- type = ADMA;
- } else if (type == MCP5x && swncq_enabled) {
- dev_notice(&pdev->dev, "Using SWNCQ mode\n");
- type = SWNCQ;
- }
- ppi[0] = &nv_port_info[type];
- ipriv = ppi[0]->private_data;
- rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
- if (rc)
- return rc;
- hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
- if (!hpriv)
- return -ENOMEM;
- hpriv->type = type;
- host->private_data = hpriv;
- /* request and iomap NV_MMIO_BAR */
- rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME);
- if (rc)
- return rc;
- /* configure SCR access */
- base = host->iomap[NV_MMIO_BAR];
- host->ports[0]->ioaddr.scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
- host->ports[1]->ioaddr.scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
- /* enable SATA space for CK804 */
- if (type >= CK804) {
- u8 regval;
- pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val);
- regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
- pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
- }
- /* init ADMA */
- if (type == ADMA) {
- rc = nv_adma_host_init(host);
- if (rc)
- return rc;
- } else if (type == SWNCQ)
- nv_swncq_host_init(host);
- if (msi_enabled) {
- dev_notice(&pdev->dev, "Using MSI\n");
- pci_enable_msi(pdev);
- }
- pci_set_master(pdev);
- return ata_pci_sff_activate_host(host, ipriv->irq_handler, ipriv->sht);
- }
- #ifdef CONFIG_PM_SLEEP
- static int nv_pci_device_resume(struct pci_dev *pdev)
- {
- struct ata_host *host = pci_get_drvdata(pdev);
- struct nv_host_priv *hpriv = host->private_data;
- int rc;
- rc = ata_pci_device_do_resume(pdev);
- if (rc)
- return rc;
- if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
- if (hpriv->type >= CK804) {
- u8 regval;
- pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val);
- regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
- pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
- }
- if (hpriv->type == ADMA) {
- u32 tmp32;
- struct nv_adma_port_priv *pp;
- /* enable/disable ADMA on the ports appropriately */
- pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
- pp = host->ports[0]->private_data;
- if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
- tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
- else
- tmp32 |= (NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
- pp = host->ports[1]->private_data;
- if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
- tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
- else
- tmp32 |= (NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
- pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
- }
- }
- ata_host_resume(host);
- return 0;
- }
- #endif
- static void nv_ck804_host_stop(struct ata_host *host)
- {
- struct pci_dev *pdev = to_pci_dev(host->dev);
- u8 regval;
- /* disable SATA space for CK804 */
- pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val);
- regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
- pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
- }
- static void nv_adma_host_stop(struct ata_host *host)
- {
- struct pci_dev *pdev = to_pci_dev(host->dev);
- u32 tmp32;
- /* disable ADMA on the ports */
- pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
- tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN |
- NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
- pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
- nv_ck804_host_stop(host);
- }
- module_pci_driver(nv_pci_driver);
- module_param_named(adma, adma_enabled, bool, 0444);
- MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");
- module_param_named(swncq, swncq_enabled, bool, 0444);
- MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
- module_param_named(msi, msi_enabled, bool, 0444);
- MODULE_PARM_DESC(msi, "Enable use of MSI (Default: false)");
|