Blame view
drivers/ata/sata_sil24.c
37.9 KB
edb336670 [PATCH] SATA: rew... |
1 2 3 4 5 6 7 |
/* * sata_sil24.c - Driver for Silicon Image 3124/3132 SATA-2 controllers * * Copyright 2005 Tejun Heo * * Based on preview driver from Silicon Image. * |
edb336670 [PATCH] SATA: rew... |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
* 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. * */ #include <linux/kernel.h> #include <linux/module.h> |
5a0e3ad6a include cleanup: ... |
22 |
#include <linux/gfp.h> |
edb336670 [PATCH] SATA: rew... |
23 24 25 26 27 |
#include <linux/pci.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> |
a9524a76f [libata] use dev_... |
28 |
#include <linux/device.h> |
edb336670 [PATCH] SATA: rew... |
29 |
#include <scsi/scsi_host.h> |
193515d51 [libata] eliminat... |
30 |
#include <scsi/scsi_cmnd.h> |
edb336670 [PATCH] SATA: rew... |
31 |
#include <linux/libata.h> |
edb336670 [PATCH] SATA: rew... |
32 33 |
#define DRV_NAME "sata_sil24" |
3454dc692 sata_sil24: imple... |
34 |
#define DRV_VERSION "1.1" |
edb336670 [PATCH] SATA: rew... |
35 |
|
edb336670 [PATCH] SATA: rew... |
36 37 38 39 |
/* * Port request block (PRB) 32 bytes */ struct sil24_prb { |
b47725743 [PATCH] sata_sil2... |
40 41 42 |
__le16 ctrl; __le16 prot; __le32 rx_cnt; |
edb336670 [PATCH] SATA: rew... |
43 44 45 46 47 48 49 |
u8 fis[6 * 4]; }; /* * Scatter gather entry (SGE) 16 bytes */ struct sil24_sge { |
b47725743 [PATCH] sata_sil2... |
50 51 52 |
__le64 addr; __le32 cnt; __le32 flags; |
edb336670 [PATCH] SATA: rew... |
53 |
}; |
edb336670 [PATCH] SATA: rew... |
54 55 |
enum { |
0d5ff5667 libata: convert t... |
56 57 |
SIL24_HOST_BAR = 0, SIL24_PORT_BAR = 2, |
93e2618e0 sata_sil24: fix s... |
58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
/* sil24 fetches in chunks of 64bytes. The first block * contains the PRB and two SGEs. From the second block, it's * consisted of four SGEs and called SGT. Calculate the * number of SGTs that fit into one page. */ SIL24_PRB_SZ = sizeof(struct sil24_prb) + 2 * sizeof(struct sil24_sge), SIL24_MAX_SGT = (PAGE_SIZE - SIL24_PRB_SZ) / (4 * sizeof(struct sil24_sge)), /* This will give us one unused SGEs for ATA. This extra SGE * will be used to store CDB for ATAPI devices. */ SIL24_MAX_SGE = 4 * SIL24_MAX_SGT + 1, |
edb336670 [PATCH] SATA: rew... |
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
/* * Global controller registers (128 bytes @ BAR0) */ /* 32 bit regs */ HOST_SLOT_STAT = 0x00, /* 32 bit slot stat * 4 */ HOST_CTRL = 0x40, HOST_IRQ_STAT = 0x44, HOST_PHY_CFG = 0x48, HOST_BIST_CTRL = 0x50, HOST_BIST_PTRN = 0x54, HOST_BIST_STAT = 0x58, HOST_MEM_BIST_STAT = 0x5c, HOST_FLASH_CMD = 0x70, /* 8 bit regs */ HOST_FLASH_DATA = 0x74, HOST_TRANSITION_DETECT = 0x75, HOST_GPIO_CTRL = 0x76, HOST_I2C_ADDR = 0x78, /* 32 bit */ HOST_I2C_DATA = 0x7c, HOST_I2C_XFER_CNT = 0x7e, HOST_I2C_CTRL = 0x7f, /* HOST_SLOT_STAT bits */ HOST_SSTAT_ATTN = (1 << 31), |
7dafc3fd9 [PATCH] sata_sil2... |
96 97 98 99 100 101 |
/* HOST_CTRL bits */ HOST_CTRL_M66EN = (1 << 16), /* M66EN PCI bus signal */ HOST_CTRL_TRDY = (1 << 17), /* latched PCI TRDY */ HOST_CTRL_STOP = (1 << 18), /* latched PCI STOP */ HOST_CTRL_DEVSEL = (1 << 19), /* latched PCI DEVSEL */ HOST_CTRL_REQ64 = (1 << 20), /* latched PCI REQ64 */ |
d2298dca9 [PATCH] sata_sil2... |
102 |
HOST_CTRL_GLOBAL_RST = (1 << 31), /* global reset */ |
7dafc3fd9 [PATCH] sata_sil2... |
103 |
|
edb336670 [PATCH] SATA: rew... |
104 105 106 107 108 |
/* * Port registers * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2) */ PORT_REGS_SIZE = 0x2000, |
135da3457 [PATCH] sata_sil2... |
109 |
|
28c8f3b4f [PATCH] sata_sil2... |
110 |
PORT_LRAM = 0x0000, /* 31 LRAM slots and PMP regs */ |
135da3457 [PATCH] sata_sil2... |
111 |
PORT_LRAM_SLOT_SZ = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */ |
edb336670 [PATCH] SATA: rew... |
112 |
|
28c8f3b4f [PATCH] sata_sil2... |
113 |
PORT_PMP = 0x0f80, /* 8 bytes PMP * 16 (128 bytes) */ |
c0c559083 [PATCH] sata_sil2... |
114 115 116 |
PORT_PMP_STATUS = 0x0000, /* port device status offset */ PORT_PMP_QACTIVE = 0x0004, /* port device QActive offset */ PORT_PMP_SIZE = 0x0008, /* 8 bytes per PMP */ |
edb336670 [PATCH] SATA: rew... |
117 |
/* 32 bit regs */ |
83bbecc90 [PATCH] sil24: ad... |
118 119 120 121 122 |
PORT_CTRL_STAT = 0x1000, /* write: ctrl-set, read: stat */ PORT_CTRL_CLR = 0x1004, /* write: ctrl-clear */ PORT_IRQ_STAT = 0x1008, /* high: status, low: interrupt */ PORT_IRQ_ENABLE_SET = 0x1010, /* write: enable-set */ PORT_IRQ_ENABLE_CLR = 0x1014, /* write: enable-clear */ |
edb336670 [PATCH] SATA: rew... |
123 |
PORT_ACTIVATE_UPPER_ADDR= 0x101c, |
83bbecc90 [PATCH] sil24: ad... |
124 125 |
PORT_EXEC_FIFO = 0x1020, /* command execution fifo */ PORT_CMD_ERR = 0x1024, /* command error number */ |
edb336670 [PATCH] SATA: rew... |
126 127 128 129 130 131 132 133 134 135 136 137 138 |
PORT_FIS_CFG = 0x1028, PORT_FIFO_THRES = 0x102c, /* 16 bit regs */ PORT_DECODE_ERR_CNT = 0x1040, PORT_DECODE_ERR_THRESH = 0x1042, PORT_CRC_ERR_CNT = 0x1044, PORT_CRC_ERR_THRESH = 0x1046, PORT_HSHK_ERR_CNT = 0x1048, PORT_HSHK_ERR_THRESH = 0x104a, /* 32 bit regs */ PORT_PHY_CFG = 0x1050, PORT_SLOT_STAT = 0x1800, PORT_CMD_ACTIVATE = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */ |
c0c559083 [PATCH] sata_sil2... |
139 |
PORT_CONTEXT = 0x1e04, |
edb336670 [PATCH] SATA: rew... |
140 141 142 143 144 145 146 147 148 149 150 151 |
PORT_EXEC_DIAG = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */ PORT_PSD_DIAG = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */ PORT_SCONTROL = 0x1f00, PORT_SSTATUS = 0x1f04, PORT_SERROR = 0x1f08, PORT_SACTIVE = 0x1f0c, /* PORT_CTRL_STAT bits */ PORT_CS_PORT_RST = (1 << 0), /* port reset */ PORT_CS_DEV_RST = (1 << 1), /* device reset */ PORT_CS_INIT = (1 << 2), /* port initialize */ PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */ |
d10cb35a8 [PATCH] sil24: ad... |
152 |
PORT_CS_CDB16 = (1 << 5), /* 0=12b cdb, 1=16b cdb */ |
28c8f3b4f [PATCH] sata_sil2... |
153 |
PORT_CS_PMP_RESUME = (1 << 6), /* PMP resume */ |
e382eb1db [PATCH] sil24: fi... |
154 |
PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */ |
28c8f3b4f [PATCH] sata_sil2... |
155 |
PORT_CS_PMP_EN = (1 << 13), /* port multiplier enable */ |
e382eb1db [PATCH] sil24: fi... |
156 |
PORT_CS_RDY = (1 << 31), /* port ready to accept commands */ |
edb336670 [PATCH] SATA: rew... |
157 158 159 160 161 162 163 164 165 |
/* PORT_IRQ_STAT/ENABLE_SET/CLR */ /* bits[11:0] are masked */ PORT_IRQ_COMPLETE = (1 << 0), /* command(s) completed */ PORT_IRQ_ERROR = (1 << 1), /* command execution error */ PORT_IRQ_PORTRDY_CHG = (1 << 2), /* port ready change */ PORT_IRQ_PWR_CHG = (1 << 3), /* power management change */ PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */ PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */ |
7dafc3fd9 [PATCH] sata_sil2... |
166 167 168 169 170 |
PORT_IRQ_UNK_FIS = (1 << 6), /* unknown FIS received */ PORT_IRQ_DEV_XCHG = (1 << 7), /* device exchanged */ PORT_IRQ_8B10B = (1 << 8), /* 8b/10b decode error threshold */ PORT_IRQ_CRC = (1 << 9), /* CRC error threshold */ PORT_IRQ_HANDSHAKE = (1 << 10), /* handshake error threshold */ |
3b9f1d0fb [PATCH] sata_sil2... |
171 |
PORT_IRQ_SDB_NOTIFY = (1 << 11), /* SDB notify received */ |
edb336670 [PATCH] SATA: rew... |
172 |
|
88ce7550c [PATCH] sata_sil2... |
173 |
DEF_PORT_IRQ = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | |
0542925b2 [PATCH] sata_sil2... |
174 |
PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG | |
854c73a2f libata: misc upda... |
175 |
PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_NOTIFY, |
88ce7550c [PATCH] sata_sil2... |
176 |
|
edb336670 [PATCH] SATA: rew... |
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
/* bits[27:16] are unmasked (raw) */ PORT_IRQ_RAW_SHIFT = 16, PORT_IRQ_MASKED_MASK = 0x7ff, PORT_IRQ_RAW_MASK = (0x7ff << PORT_IRQ_RAW_SHIFT), /* ENABLE_SET/CLR specific, intr steering - 2 bit field */ PORT_IRQ_STEER_SHIFT = 30, PORT_IRQ_STEER_MASK = (3 << PORT_IRQ_STEER_SHIFT), /* PORT_CMD_ERR constants */ PORT_CERR_DEV = 1, /* Error bit in D2H Register FIS */ PORT_CERR_SDB = 2, /* Error bit in SDB FIS */ PORT_CERR_DATA = 3, /* Error in data FIS not detected by dev */ PORT_CERR_SEND = 4, /* Initial cmd FIS transmission failure */ PORT_CERR_INCONSISTENT = 5, /* Protocol mismatch */ PORT_CERR_DIRECTION = 6, /* Data direction mismatch */ PORT_CERR_UNDERRUN = 7, /* Ran out of SGEs while writing */ PORT_CERR_OVERRUN = 8, /* Ran out of SGEs while reading */ PORT_CERR_PKT_PROT = 11, /* DIR invalid in 1st PIO setup of ATAPI */ PORT_CERR_SGT_BOUNDARY = 16, /* PLD ecode 00 - SGT not on qword boundary */ PORT_CERR_SGT_TGTABRT = 17, /* PLD ecode 01 - target abort */ PORT_CERR_SGT_MSTABRT = 18, /* PLD ecode 10 - master abort */ PORT_CERR_SGT_PCIPERR = 19, /* PLD ecode 11 - PCI parity err while fetching SGT */ PORT_CERR_CMD_BOUNDARY = 24, /* ctrl[15:13] 001 - PRB not on qword boundary */ PORT_CERR_CMD_TGTABRT = 25, /* ctrl[15:13] 010 - target abort */ PORT_CERR_CMD_MSTABRT = 26, /* ctrl[15:13] 100 - master abort */ PORT_CERR_CMD_PCIPERR = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */ PORT_CERR_XFR_UNDEF = 32, /* PSD ecode 00 - undefined */ PORT_CERR_XFR_TGTABRT = 33, /* PSD ecode 01 - target abort */ |
640088024 [PATCH] sata_sil2... |
206 |
PORT_CERR_XFR_MSTABRT = 34, /* PSD ecode 10 - master abort */ |
edb336670 [PATCH] SATA: rew... |
207 |
PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */ |
83bbecc90 [PATCH] sil24: ad... |
208 |
PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */ |
edb336670 [PATCH] SATA: rew... |
209 |
|
d10cb35a8 [PATCH] sil24: ad... |
210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
/* bits of PRB control field */ PRB_CTRL_PROTOCOL = (1 << 0), /* override def. ATA protocol */ PRB_CTRL_PACKET_READ = (1 << 4), /* PACKET cmd read */ PRB_CTRL_PACKET_WRITE = (1 << 5), /* PACKET cmd write */ PRB_CTRL_NIEN = (1 << 6), /* Mask completion irq */ PRB_CTRL_SRST = (1 << 7), /* Soft reset request (ign BSY?) */ /* PRB protocol field */ PRB_PROT_PACKET = (1 << 0), PRB_PROT_TCQ = (1 << 1), PRB_PROT_NCQ = (1 << 2), PRB_PROT_READ = (1 << 3), PRB_PROT_WRITE = (1 << 4), PRB_PROT_TRANSPARENT = (1 << 5), |
edb336670 [PATCH] SATA: rew... |
224 225 226 227 |
/* * Other constants */ SGE_TRM = (1 << 31), /* Last SGE in chain */ |
d10cb35a8 [PATCH] sil24: ad... |
228 229 230 231 |
SGE_LNK = (1 << 30), /* linked list Points to SGT, not SGE */ SGE_DRD = (1 << 29), /* discard data read (/dev/null) data address ignored */ |
edb336670 [PATCH] SATA: rew... |
232 |
|
aee10a03e [PATCH] sata_sil2... |
233 |
SIL24_MAX_CMDS = 31, |
edb336670 [PATCH] SATA: rew... |
234 235 236 |
/* board id */ BID_SIL3124 = 0, BID_SIL3132 = 1, |
042c21fd2 [libata sata_sil2... |
237 |
BID_SIL3131 = 2, |
edb336670 [PATCH] SATA: rew... |
238 |
|
9466d85bb [PATCH] sata_sil2... |
239 |
/* host flags */ |
9cbe056f6 libata: remove AT... |
240 241 242 |
SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | ATA_FLAG_AN | ATA_FLAG_PMP, |
37024e8ee [PATCH] sata_sil2... |
243 |
SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ |
9466d85bb [PATCH] sata_sil2... |
244 |
|
edb336670 [PATCH] SATA: rew... |
245 246 |
IRQ_STAT_4PORTS = 0xf, }; |
69ad185fa [PATCH] sil24: ad... |
247 |
struct sil24_ata_block { |
edb336670 [PATCH] SATA: rew... |
248 |
struct sil24_prb prb; |
93e2618e0 sata_sil24: fix s... |
249 |
struct sil24_sge sge[SIL24_MAX_SGE]; |
edb336670 [PATCH] SATA: rew... |
250 |
}; |
69ad185fa [PATCH] sil24: ad... |
251 252 253 |
struct sil24_atapi_block { struct sil24_prb prb; u8 cdb[16]; |
93e2618e0 sata_sil24: fix s... |
254 |
struct sil24_sge sge[SIL24_MAX_SGE]; |
69ad185fa [PATCH] sil24: ad... |
255 256 257 258 259 260 |
}; union sil24_cmd_block { struct sil24_ata_block ata; struct sil24_atapi_block atapi; }; |
fc8cc1d5b sata_sil24: Use c... |
261 |
static const struct sil24_cerr_info { |
88ce7550c [PATCH] sata_sil2... |
262 263 264 |
unsigned int err_mask, action; const char *desc; } sil24_cerr_db[] = { |
f90f0828e libata: stop bein... |
265 |
[0] = { AC_ERR_DEV, 0, |
88ce7550c [PATCH] sata_sil2... |
266 |
"device error" }, |
f90f0828e libata: stop bein... |
267 |
[PORT_CERR_DEV] = { AC_ERR_DEV, 0, |
88ce7550c [PATCH] sata_sil2... |
268 |
"device error via D2H FIS" }, |
f90f0828e libata: stop bein... |
269 |
[PORT_CERR_SDB] = { AC_ERR_DEV, 0, |
88ce7550c [PATCH] sata_sil2... |
270 |
"device error via SDB FIS" }, |
cf4806265 libata: prefer ha... |
271 |
[PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
272 |
"error in data FIS" }, |
cf4806265 libata: prefer ha... |
273 |
[PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
274 |
"failed to transmit command FIS" }, |
cf4806265 libata: prefer ha... |
275 |
[PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
276 |
"protocol mismatch" }, |
cf4806265 libata: prefer ha... |
277 |
[PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
278 |
"data directon mismatch" }, |
cf4806265 libata: prefer ha... |
279 |
[PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
280 |
"ran out of SGEs while writing" }, |
cf4806265 libata: prefer ha... |
281 |
[PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
282 |
"ran out of SGEs while reading" }, |
cf4806265 libata: prefer ha... |
283 |
[PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
284 |
"invalid data directon for ATAPI CDB" }, |
cf4806265 libata: prefer ha... |
285 |
[PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET, |
7293fa8fb sata_sil24: fix s... |
286 |
"SGT not on qword boundary" }, |
cf4806265 libata: prefer ha... |
287 |
[PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
288 |
"PCI target abort while fetching SGT" }, |
cf4806265 libata: prefer ha... |
289 |
[PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
290 |
"PCI master abort while fetching SGT" }, |
cf4806265 libata: prefer ha... |
291 |
[PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
292 |
"PCI parity error while fetching SGT" }, |
cf4806265 libata: prefer ha... |
293 |
[PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
294 |
"PRB not on qword boundary" }, |
cf4806265 libata: prefer ha... |
295 |
[PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
296 |
"PCI target abort while fetching PRB" }, |
cf4806265 libata: prefer ha... |
297 |
[PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
298 |
"PCI master abort while fetching PRB" }, |
cf4806265 libata: prefer ha... |
299 |
[PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
300 |
"PCI parity error while fetching PRB" }, |
cf4806265 libata: prefer ha... |
301 |
[PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
302 |
"undefined error while transferring data" }, |
cf4806265 libata: prefer ha... |
303 |
[PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
304 |
"PCI target abort while transferring data" }, |
cf4806265 libata: prefer ha... |
305 |
[PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
306 |
"PCI master abort while transferring data" }, |
cf4806265 libata: prefer ha... |
307 |
[PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
308 |
"PCI parity error while transferring data" }, |
cf4806265 libata: prefer ha... |
309 |
[PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_RESET, |
88ce7550c [PATCH] sata_sil2... |
310 311 |
"FIS received while sending service FIS" }, }; |
edb336670 [PATCH] SATA: rew... |
312 313 314 315 316 317 318 |
/* * ap->private_data * * The preview driver always returned 0 for status. We emulate it * here from the previous interrupt. */ struct sil24_port_priv { |
69ad185fa [PATCH] sil24: ad... |
319 |
union sil24_cmd_block *cmd_block; /* 32 cmd blocks */ |
edb336670 [PATCH] SATA: rew... |
320 |
dma_addr_t cmd_block_dma; /* DMA base addr for them */ |
238180343 sata_sil24: imple... |
321 |
int do_port_rst; |
edb336670 [PATCH] SATA: rew... |
322 |
}; |
cd0d3bbcd libata: dev_confi... |
323 |
static void sil24_dev_config(struct ata_device *dev); |
82ef04fb4 libata: make SCR ... |
324 325 |
static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val); static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val); |
3454dc692 sata_sil24: imple... |
326 |
static int sil24_qc_defer(struct ata_queued_cmd *qc); |
edb336670 [PATCH] SATA: rew... |
327 |
static void sil24_qc_prep(struct ata_queued_cmd *qc); |
9a3d9eb01 [PATCH] libata: r... |
328 |
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); |
79f97dadf libata: drop @fin... |
329 |
static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc); |
3454dc692 sata_sil24: imple... |
330 331 |
static void sil24_pmp_attach(struct ata_port *ap); static void sil24_pmp_detach(struct ata_port *ap); |
88ce7550c [PATCH] sata_sil2... |
332 333 |
static void sil24_freeze(struct ata_port *ap); static void sil24_thaw(struct ata_port *ap); |
a1efdaba2 libata: make rese... |
334 335 336 337 |
static int sil24_softreset(struct ata_link *link, unsigned int *class, unsigned long deadline); static int sil24_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); |
a1efdaba2 libata: make rese... |
338 339 |
static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); |
88ce7550c [PATCH] sata_sil2... |
340 341 |
static void sil24_error_handler(struct ata_port *ap); static void sil24_post_internal_cmd(struct ata_queued_cmd *qc); |
edb336670 [PATCH] SATA: rew... |
342 |
static int sil24_port_start(struct ata_port *ap); |
edb336670 [PATCH] SATA: rew... |
343 |
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
281d426c7 [PATCH] CONFIG_PM... |
344 |
#ifdef CONFIG_PM |
d2298dca9 [PATCH] sata_sil2... |
345 |
static int sil24_pci_device_resume(struct pci_dev *pdev); |
3454dc692 sata_sil24: imple... |
346 |
static int sil24_port_resume(struct ata_port *ap); |
281d426c7 [PATCH] CONFIG_PM... |
347 |
#endif |
edb336670 [PATCH] SATA: rew... |
348 |
|
3b7d697df [libata] constify... |
349 |
static const struct pci_device_id sil24_pci_tbl[] = { |
54bb3a94b [libata] Use new ... |
350 351 352 |
{ PCI_VDEVICE(CMD, 0x3124), BID_SIL3124 }, { PCI_VDEVICE(INTEL, 0x3124), BID_SIL3124 }, { PCI_VDEVICE(CMD, 0x3132), BID_SIL3132 }, |
722d67b62 sata_sil24: Add A... |
353 |
{ PCI_VDEVICE(CMD, 0x0242), BID_SIL3132 }, |
464b3286b sata_sil24: add D... |
354 |
{ PCI_VDEVICE(CMD, 0x0244), BID_SIL3132 }, |
54bb3a94b [libata] Use new ... |
355 356 |
{ PCI_VDEVICE(CMD, 0x3131), BID_SIL3131 }, { PCI_VDEVICE(CMD, 0x3531), BID_SIL3131 }, |
1fcce839a [libata sata_sil2... |
357 |
{ } /* terminate list */ |
edb336670 [PATCH] SATA: rew... |
358 359 360 361 362 363 |
}; static struct pci_driver sil24_pci_driver = { .name = DRV_NAME, .id_table = sil24_pci_tbl, .probe = sil24_init_one, |
24dc5f33e libata: update li... |
364 |
.remove = ata_pci_remove_one, |
281d426c7 [PATCH] CONFIG_PM... |
365 |
#ifdef CONFIG_PM |
d2298dca9 [PATCH] sata_sil2... |
366 367 |
.suspend = ata_pci_device_suspend, .resume = sil24_pci_device_resume, |
281d426c7 [PATCH] CONFIG_PM... |
368 |
#endif |
edb336670 [PATCH] SATA: rew... |
369 |
}; |
193515d51 [libata] eliminat... |
370 |
static struct scsi_host_template sil24_sht = { |
68d1d07b5 libata: implement... |
371 |
ATA_NCQ_SHT(DRV_NAME), |
aee10a03e [PATCH] sata_sil2... |
372 |
.can_queue = SIL24_MAX_CMDS, |
93e2618e0 sata_sil24: fix s... |
373 |
.sg_tablesize = SIL24_MAX_SGE, |
edb336670 [PATCH] SATA: rew... |
374 |
.dma_boundary = ATA_DMA_BOUNDARY, |
edb336670 [PATCH] SATA: rew... |
375 |
}; |
029cfd6b7 libata: implement... |
376 377 |
static struct ata_port_operations sil24_ops = { .inherits = &sata_pmp_port_ops, |
69ad185fa [PATCH] sil24: ad... |
378 |
|
3454dc692 sata_sil24: imple... |
379 |
.qc_defer = sil24_qc_defer, |
edb336670 [PATCH] SATA: rew... |
380 381 |
.qc_prep = sil24_qc_prep, .qc_issue = sil24_qc_issue, |
79f97dadf libata: drop @fin... |
382 |
.qc_fill_rtf = sil24_qc_fill_rtf, |
edb336670 [PATCH] SATA: rew... |
383 |
|
029cfd6b7 libata: implement... |
384 385 |
.freeze = sil24_freeze, .thaw = sil24_thaw, |
a1efdaba2 libata: make rese... |
386 387 |
.softreset = sil24_softreset, .hardreset = sil24_hardreset, |
071f44b1d libata: implement... |
388 |
.pmp_softreset = sil24_softreset, |
a1efdaba2 libata: make rese... |
389 |
.pmp_hardreset = sil24_pmp_hardreset, |
029cfd6b7 libata: implement... |
390 391 392 |
.error_handler = sil24_error_handler, .post_internal_cmd = sil24_post_internal_cmd, .dev_config = sil24_dev_config, |
edb336670 [PATCH] SATA: rew... |
393 394 395 |
.scr_read = sil24_scr_read, .scr_write = sil24_scr_write, |
3454dc692 sata_sil24: imple... |
396 397 |
.pmp_attach = sil24_pmp_attach, .pmp_detach = sil24_pmp_detach, |
3454dc692 sata_sil24: imple... |
398 |
|
edb336670 [PATCH] SATA: rew... |
399 |
.port_start = sil24_port_start, |
3454dc692 sata_sil24: imple... |
400 401 402 |
#ifdef CONFIG_PM .port_resume = sil24_port_resume, #endif |
edb336670 [PATCH] SATA: rew... |
403 |
}; |
90ab5ee94 module_param: mak... |
404 |
static bool sata_sil24_msi; /* Disable MSI */ |
dae77214f sata_sil24: MSI s... |
405 406 |
module_param_named(msi, sata_sil24_msi, bool, S_IRUGO); MODULE_PARM_DESC(msi, "Enable MSI (Default: false)"); |
042c21fd2 [libata sata_sil2... |
407 |
/* |
cca3974e4 libata: Grand ren... |
408 |
* Use bits 30-31 of port_flags to encode available port numbers. |
042c21fd2 [libata sata_sil2... |
409 410 411 412 |
* Current maxium is 4. */ #define SIL24_NPORTS2FLAG(nports) ((((unsigned)(nports) - 1) & 0x3) << 30) #define SIL24_FLAG2NPORTS(flag) ((((flag) >> 30) & 0x3) + 1) |
4447d3515 libata: convert t... |
413 |
static const struct ata_port_info sil24_port_info[] = { |
edb336670 [PATCH] SATA: rew... |
414 415 |
/* sil_3124 */ { |
cca3974e4 libata: Grand ren... |
416 |
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | |
37024e8ee [PATCH] sata_sil2... |
417 |
SIL24_FLAG_PCIX_IRQ_WOC, |
14bdef982 [libata] convert ... |
418 419 420 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, |
edb336670 [PATCH] SATA: rew... |
421 422 |
.port_ops = &sil24_ops, }, |
2e9edbf81 [libata] export a... |
423 |
/* sil_3132 */ |
edb336670 [PATCH] SATA: rew... |
424 |
{ |
cca3974e4 libata: Grand ren... |
425 |
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), |
14bdef982 [libata] convert ... |
426 427 428 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, |
042c21fd2 [libata sata_sil2... |
429 430 431 432 |
.port_ops = &sil24_ops, }, /* sil_3131/sil_3531 */ { |
cca3974e4 libata: Grand ren... |
433 |
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), |
14bdef982 [libata] convert ... |
434 435 436 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, |
edb336670 [PATCH] SATA: rew... |
437 438 439 |
.port_ops = &sil24_ops, }, }; |
aee10a03e [PATCH] sata_sil2... |
440 441 442 443 444 445 |
static int sil24_tag(int tag) { if (unlikely(ata_tag_internal(tag))) return 0; return tag; } |
350756f6d libata: don't use... |
446 447 448 449 450 451 452 453 454 |
static unsigned long sil24_port_offset(struct ata_port *ap) { return ap->port_no * PORT_REGS_SIZE; } static void __iomem *sil24_port_base(struct ata_port *ap) { return ap->host->iomap[SIL24_PORT_BAR] + sil24_port_offset(ap); } |
cd0d3bbcd libata: dev_confi... |
455 |
static void sil24_dev_config(struct ata_device *dev) |
69ad185fa [PATCH] sil24: ad... |
456 |
{ |
350756f6d libata: don't use... |
457 |
void __iomem *port = sil24_port_base(dev->link->ap); |
69ad185fa [PATCH] sil24: ad... |
458 |
|
6e7846e9c [PATCH] libata: m... |
459 |
if (dev->cdb_len == 16) |
69ad185fa [PATCH] sil24: ad... |
460 461 462 463 |
writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); else writel(PORT_CS_CDB16, port + PORT_CTRL_CLR); } |
e59f0dad3 sata_sil24: repla... |
464 |
static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf) |
6a575fa96 [PATCH] sil24: im... |
465 |
{ |
350756f6d libata: don't use... |
466 |
void __iomem *port = sil24_port_base(ap); |
e59f0dad3 sata_sil24: repla... |
467 |
struct sil24_prb __iomem *prb; |
4b4a5eaed [PATCH] sata_sil2... |
468 |
u8 fis[6 * 4]; |
6a575fa96 [PATCH] sil24: im... |
469 |
|
e59f0dad3 sata_sil24: repla... |
470 471 472 |
prb = port + PORT_LRAM + sil24_tag(tag) * PORT_LRAM_SLOT_SZ; memcpy_fromio(fis, prb->fis, sizeof(fis)); ata_tf_from_fis(fis, tf); |
6a575fa96 [PATCH] sil24: im... |
473 |
} |
edb336670 [PATCH] SATA: rew... |
474 475 476 477 478 479 |
static int sil24_scr_map[] = { [SCR_CONTROL] = 0, [SCR_STATUS] = 1, [SCR_ERROR] = 2, [SCR_ACTIVE] = 3, }; |
82ef04fb4 libata: make SCR ... |
480 |
static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val) |
edb336670 [PATCH] SATA: rew... |
481 |
{ |
82ef04fb4 libata: make SCR ... |
482 |
void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL; |
da3dbb17a libata: make ->sc... |
483 |
|
edb336670 [PATCH] SATA: rew... |
484 |
if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { |
4b4a5eaed [PATCH] sata_sil2... |
485 |
void __iomem *addr; |
edb336670 [PATCH] SATA: rew... |
486 |
addr = scr_addr + sil24_scr_map[sc_reg] * 4; |
da3dbb17a libata: make ->sc... |
487 488 |
*val = readl(scr_addr + sil24_scr_map[sc_reg] * 4); return 0; |
edb336670 [PATCH] SATA: rew... |
489 |
} |
da3dbb17a libata: make ->sc... |
490 |
return -EINVAL; |
edb336670 [PATCH] SATA: rew... |
491 |
} |
82ef04fb4 libata: make SCR ... |
492 |
static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val) |
edb336670 [PATCH] SATA: rew... |
493 |
{ |
82ef04fb4 libata: make SCR ... |
494 |
void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL; |
da3dbb17a libata: make ->sc... |
495 |
|
edb336670 [PATCH] SATA: rew... |
496 |
if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { |
4b4a5eaed [PATCH] sata_sil2... |
497 |
void __iomem *addr; |
edb336670 [PATCH] SATA: rew... |
498 499 |
addr = scr_addr + sil24_scr_map[sc_reg] * 4; writel(val, scr_addr + sil24_scr_map[sc_reg] * 4); |
da3dbb17a libata: make ->sc... |
500 |
return 0; |
edb336670 [PATCH] SATA: rew... |
501 |
} |
da3dbb17a libata: make ->sc... |
502 |
return -EINVAL; |
edb336670 [PATCH] SATA: rew... |
503 |
} |
238180343 sata_sil24: imple... |
504 505 |
static void sil24_config_port(struct ata_port *ap) { |
350756f6d libata: don't use... |
506 |
void __iomem *port = sil24_port_base(ap); |
238180343 sata_sil24: imple... |
507 508 509 510 511 512 513 514 |
/* configure IRQ WoC */ if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT); else writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); /* zero error counters. */ |
7a4f876b8 sata_sil24: fix k... |
515 516 517 518 519 520 |
writew(0x8000, port + PORT_DECODE_ERR_THRESH); writew(0x8000, port + PORT_CRC_ERR_THRESH); writew(0x8000, port + PORT_HSHK_ERR_THRESH); writew(0x0000, port + PORT_DECODE_ERR_CNT); writew(0x0000, port + PORT_CRC_ERR_CNT); writew(0x0000, port + PORT_HSHK_ERR_CNT); |
238180343 sata_sil24: imple... |
521 522 523 524 525 526 527 |
/* always use 64bit activation */ writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); /* clear port multiplier enable and resume bits */ writel(PORT_CS_PMP_EN | PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR); } |
3454dc692 sata_sil24: imple... |
528 529 |
static void sil24_config_pmp(struct ata_port *ap, int attached) { |
350756f6d libata: don't use... |
530 |
void __iomem *port = sil24_port_base(ap); |
3454dc692 sata_sil24: imple... |
531 532 533 534 535 536 537 538 539 |
if (attached) writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT); else writel(PORT_CS_PMP_EN, port + PORT_CTRL_CLR); } static void sil24_clear_pmp(struct ata_port *ap) { |
350756f6d libata: don't use... |
540 |
void __iomem *port = sil24_port_base(ap); |
3454dc692 sata_sil24: imple... |
541 542 543 544 545 546 547 548 549 550 551 |
int i; writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR); for (i = 0; i < SATA_PMP_MAX_PORTS; i++) { void __iomem *pmp_base = port + PORT_PMP + i * PORT_PMP_SIZE; writel(0, pmp_base + PORT_PMP_STATUS); writel(0, pmp_base + PORT_PMP_QACTIVE); } } |
b5bc421c9 [PATCH] sata_sil2... |
552 553 |
static int sil24_init_port(struct ata_port *ap) { |
350756f6d libata: don't use... |
554 |
void __iomem *port = sil24_port_base(ap); |
238180343 sata_sil24: imple... |
555 |
struct sil24_port_priv *pp = ap->private_data; |
b5bc421c9 [PATCH] sata_sil2... |
556 |
u32 tmp; |
3454dc692 sata_sil24: imple... |
557 |
/* clear PMP error status */ |
071f44b1d libata: implement... |
558 |
if (sata_pmp_attached(ap)) |
3454dc692 sata_sil24: imple... |
559 |
sil24_clear_pmp(ap); |
b5bc421c9 [PATCH] sata_sil2... |
560 |
writel(PORT_CS_INIT, port + PORT_CTRL_STAT); |
97750cebb libata: add @ap t... |
561 |
ata_wait_register(ap, port + PORT_CTRL_STAT, |
b5bc421c9 [PATCH] sata_sil2... |
562 |
PORT_CS_INIT, PORT_CS_INIT, 10, 100); |
97750cebb libata: add @ap t... |
563 |
tmp = ata_wait_register(ap, port + PORT_CTRL_STAT, |
b5bc421c9 [PATCH] sata_sil2... |
564 |
PORT_CS_RDY, 0, 10, 100); |
238180343 sata_sil24: imple... |
565 566 |
if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) { pp->do_port_rst = 1; |
cf4806265 libata: prefer ha... |
567 |
ap->link.eh_context.i.action |= ATA_EH_RESET; |
b5bc421c9 [PATCH] sata_sil2... |
568 |
return -EIO; |
238180343 sata_sil24: imple... |
569 |
} |
b5bc421c9 [PATCH] sata_sil2... |
570 571 |
return 0; } |
37b99cba8 sata_sil24: separ... |
572 573 574 575 |
static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp, const struct ata_taskfile *tf, int is_cmd, u32 ctrl, unsigned long timeout_msec) |
edb336670 [PATCH] SATA: rew... |
576 |
{ |
350756f6d libata: don't use... |
577 |
void __iomem *port = sil24_port_base(ap); |
ca45160db [PATCH] sil24: us... |
578 |
struct sil24_port_priv *pp = ap->private_data; |
69ad185fa [PATCH] sil24: ad... |
579 |
struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; |
ca45160db [PATCH] sil24: us... |
580 |
dma_addr_t paddr = pp->cmd_block_dma; |
37b99cba8 sata_sil24: separ... |
581 582 583 584 585 586 587 588 589 |
u32 irq_enabled, irq_mask, irq_stat; int rc; prb->ctrl = cpu_to_le16(ctrl); ata_tf_to_fis(tf, pmp, is_cmd, prb->fis); /* temporarily plug completion and error interrupts */ irq_enabled = readl(port + PORT_IRQ_ENABLE_SET); writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR, port + PORT_IRQ_ENABLE_CLR); |
108234529 sata_sil24: Use m... |
590 591 592 593 594 |
/* * The barrier is required to ensure that writes to cmd_block reach * the memory before the write to PORT_CMD_ACTIVATE. */ wmb(); |
37b99cba8 sata_sil24: separ... |
595 596 597 598 |
writel((u32)paddr, port + PORT_CMD_ACTIVATE); writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); irq_mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT; |
97750cebb libata: add @ap t... |
599 |
irq_stat = ata_wait_register(ap, port + PORT_IRQ_STAT, irq_mask, 0x0, |
37b99cba8 sata_sil24: separ... |
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 |
10, timeout_msec); writel(irq_mask, port + PORT_IRQ_STAT); /* clear IRQs */ irq_stat >>= PORT_IRQ_RAW_SHIFT; if (irq_stat & PORT_IRQ_COMPLETE) rc = 0; else { /* force port into known state */ sil24_init_port(ap); if (irq_stat & PORT_IRQ_ERROR) rc = -EIO; else rc = -EBUSY; } /* restore IRQ enabled */ writel(irq_enabled, port + PORT_IRQ_ENABLE_SET); return rc; } |
071f44b1d libata: implement... |
622 623 |
static int sil24_softreset(struct ata_link *link, unsigned int *class, unsigned long deadline) |
37b99cba8 sata_sil24: separ... |
624 |
{ |
cc0680a58 libata-link: link... |
625 |
struct ata_port *ap = link->ap; |
071f44b1d libata: implement... |
626 |
int pmp = sata_srst_pmp(link); |
37b99cba8 sata_sil24: separ... |
627 |
unsigned long timeout_msec = 0; |
e59f0dad3 sata_sil24: repla... |
628 |
struct ata_taskfile tf; |
643be977f [PATCH] sata_sil2... |
629 |
const char *reason; |
37b99cba8 sata_sil24: separ... |
630 |
int rc; |
ca45160db [PATCH] sil24: us... |
631 |
|
07b734702 [PATCH] sata_sil2... |
632 633 |
DPRINTK("ENTER "); |
2555d6c26 [PATCH] sata_sil2... |
634 635 |
/* put the port into known state */ if (sil24_init_port(ap)) { |
5796d1c4c [libata] Address ... |
636 |
reason = "port not ready"; |
2555d6c26 [PATCH] sata_sil2... |
637 638 |
goto err; } |
0eaa6058a [PATCH] sata_sil2... |
639 |
/* do SRST */ |
37b99cba8 sata_sil24: separ... |
640 641 |
if (time_after(deadline, jiffies)) timeout_msec = jiffies_to_msecs(deadline - jiffies); |
ca45160db [PATCH] sil24: us... |
642 |
|
cc0680a58 libata-link: link... |
643 |
ata_tf_init(link->device, &tf); /* doesn't really matter */ |
975530e8a sata_sil24: separ... |
644 645 |
rc = sil24_exec_polled_cmd(ap, pmp, &tf, 0, PRB_CTRL_SRST, timeout_msec); |
37b99cba8 sata_sil24: separ... |
646 647 648 649 650 |
if (rc == -EBUSY) { reason = "timeout"; goto err; } else if (rc) { reason = "SRST command error"; |
643be977f [PATCH] sata_sil2... |
651 |
goto err; |
07b734702 [PATCH] sata_sil2... |
652 |
} |
10d996ad1 [PATCH] sata_sil2... |
653 |
|
e59f0dad3 sata_sil24: repla... |
654 655 |
sil24_read_tf(ap, 0, &tf); *class = ata_dev_classify(&tf); |
10d996ad1 [PATCH] sata_sil2... |
656 |
|
07b734702 [PATCH] sata_sil2... |
657 658 |
DPRINTK("EXIT, class=%u ", *class); |
ca45160db [PATCH] sil24: us... |
659 |
return 0; |
643be977f [PATCH] sata_sil2... |
660 661 |
err: |
a9a79dfec ata: Convert ata_... |
662 663 |
ata_link_err(link, "softreset failed (%s) ", reason); |
643be977f [PATCH] sata_sil2... |
664 |
return -EIO; |
ca45160db [PATCH] sil24: us... |
665 |
} |
cc0680a58 libata-link: link... |
666 |
static int sil24_hardreset(struct ata_link *link, unsigned int *class, |
d4b2bab4f libata: add deadl... |
667 |
unsigned long deadline) |
489ff4c7d [PATCH] sata_sil2... |
668 |
{ |
cc0680a58 libata-link: link... |
669 |
struct ata_port *ap = link->ap; |
350756f6d libata: don't use... |
670 |
void __iomem *port = sil24_port_base(ap); |
238180343 sata_sil24: imple... |
671 672 |
struct sil24_port_priv *pp = ap->private_data; int did_port_rst = 0; |
ecc2e2b9c [PATCH] sata_sil2... |
673 |
const char *reason; |
e8e008e7b [PATCH] sata_sil2... |
674 |
int tout_msec, rc; |
ecc2e2b9c [PATCH] sata_sil2... |
675 |
u32 tmp; |
238180343 sata_sil24: imple... |
676 677 678 679 680 |
retry: /* Sometimes, DEV_RST is not enough to recover the controller. * This happens often after PM DMA CS errata. */ if (pp->do_port_rst) { |
a9a79dfec ata: Convert ata_... |
681 682 683 |
ata_port_warn(ap, "controller in dubious state, performing PORT_RST "); |
238180343 sata_sil24: imple... |
684 685 |
writel(PORT_CS_PORT_RST, port + PORT_CTRL_STAT); |
97750cebb libata: add @ap t... |
686 |
ata_msleep(ap, 10); |
238180343 sata_sil24: imple... |
687 |
writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR); |
97750cebb libata: add @ap t... |
688 |
ata_wait_register(ap, port + PORT_CTRL_STAT, PORT_CS_RDY, 0, |
238180343 sata_sil24: imple... |
689 690 691 692 693 694 695 696 697 |
10, 5000); /* restore port configuration */ sil24_config_port(ap); sil24_config_pmp(ap, ap->nr_pmp_links); pp->do_port_rst = 0; did_port_rst = 1; } |
ecc2e2b9c [PATCH] sata_sil2... |
698 |
/* sil24 does the right thing(tm) without any protection */ |
cc0680a58 libata-link: link... |
699 |
sata_set_spd(link); |
ecc2e2b9c [PATCH] sata_sil2... |
700 701 |
tout_msec = 100; |
cc0680a58 libata-link: link... |
702 |
if (ata_link_online(link)) |
ecc2e2b9c [PATCH] sata_sil2... |
703 704 705 |
tout_msec = 5000; writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); |
97750cebb libata: add @ap t... |
706 |
tmp = ata_wait_register(ap, port + PORT_CTRL_STAT, |
5796d1c4c [libata] Address ... |
707 708 |
PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec); |
ecc2e2b9c [PATCH] sata_sil2... |
709 |
|
e8e008e7b [PATCH] sata_sil2... |
710 711 |
/* SStatus oscillates between zero and valid status after * DEV_RST, debounce it. |
ecc2e2b9c [PATCH] sata_sil2... |
712 |
*/ |
cc0680a58 libata-link: link... |
713 |
rc = sata_link_debounce(link, sata_deb_timing_long, deadline); |
e8e008e7b [PATCH] sata_sil2... |
714 715 716 717 |
if (rc) { reason = "PHY debouncing failed"; goto err; } |
ecc2e2b9c [PATCH] sata_sil2... |
718 719 |
if (tmp & PORT_CS_DEV_RST) { |
cc0680a58 libata-link: link... |
720 |
if (ata_link_offline(link)) |
ecc2e2b9c [PATCH] sata_sil2... |
721 722 723 724 |
return 0; reason = "link not ready"; goto err; } |
e8e008e7b [PATCH] sata_sil2... |
725 726 727 728 729 |
/* Sil24 doesn't store signature FIS after hardreset, so we * can't wait for BSY to clear. Some devices take a long time * to get ready and those devices will choke if we don't wait * for BSY clearance here. Tell libata to perform follow-up * softreset. |
ecc2e2b9c [PATCH] sata_sil2... |
730 |
*/ |
e8e008e7b [PATCH] sata_sil2... |
731 |
return -EAGAIN; |
ecc2e2b9c [PATCH] sata_sil2... |
732 733 |
err: |
238180343 sata_sil24: imple... |
734 735 736 737 |
if (!did_port_rst) { pp->do_port_rst = 1; goto retry; } |
a9a79dfec ata: Convert ata_... |
738 739 |
ata_link_err(link, "hardreset failed (%s) ", reason); |
ecc2e2b9c [PATCH] sata_sil2... |
740 |
return -EIO; |
489ff4c7d [PATCH] sata_sil2... |
741 |
} |
edb336670 [PATCH] SATA: rew... |
742 |
static inline void sil24_fill_sg(struct ata_queued_cmd *qc, |
69ad185fa [PATCH] sil24: ad... |
743 |
struct sil24_sge *sge) |
edb336670 [PATCH] SATA: rew... |
744 |
{ |
972c26bdd libata: add ata_s... |
745 |
struct scatterlist *sg; |
3be6cbd73 [libata] kill ata... |
746 |
struct sil24_sge *last_sge = NULL; |
ff2aeb1eb libata: convert t... |
747 |
unsigned int si; |
edb336670 [PATCH] SATA: rew... |
748 |
|
ff2aeb1eb libata: convert t... |
749 |
for_each_sg(qc->sg, sg, qc->n_elem, si) { |
edb336670 [PATCH] SATA: rew... |
750 751 |
sge->addr = cpu_to_le64(sg_dma_address(sg)); sge->cnt = cpu_to_le32(sg_dma_len(sg)); |
3be6cbd73 [libata] kill ata... |
752 753 754 |
sge->flags = 0; last_sge = sge; |
972c26bdd libata: add ata_s... |
755 |
sge++; |
edb336670 [PATCH] SATA: rew... |
756 |
} |
3be6cbd73 [libata] kill ata... |
757 |
|
ff2aeb1eb libata: convert t... |
758 |
last_sge->flags = cpu_to_le32(SGE_TRM); |
edb336670 [PATCH] SATA: rew... |
759 |
} |
3454dc692 sata_sil24: imple... |
760 761 762 763 764 |
static int sil24_qc_defer(struct ata_queued_cmd *qc) { struct ata_link *link = qc->dev->link; struct ata_port *ap = link->ap; u8 prot = qc->tf.protocol; |
13cc546be sata_sil24: preve... |
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 |
/* * There is a bug in the chip: * Port LRAM Causes the PRB/SGT Data to be Corrupted * If the host issues a read request for LRAM and SActive registers * while active commands are available in the port, PRB/SGT data in * the LRAM can become corrupted. This issue applies only when * reading from, but not writing to, the LRAM. * * Therefore, reading LRAM when there is no particular error [and * other commands may be outstanding] is prohibited. * * To avoid this bug there are two situations where a command must run * exclusive of any other commands on the port: * * - ATAPI commands which check the sense data * - Passthrough ATA commands which always have ATA_QCFLAG_RESULT_TF * set. * */ |
405e66b38 libata: implement... |
785 |
int is_excl = (ata_is_atapi(prot) || |
13cc546be sata_sil24: preve... |
786 |
(qc->flags & ATA_QCFLAG_RESULT_TF)); |
3454dc692 sata_sil24: imple... |
787 788 789 790 791 792 793 |
if (unlikely(ap->excl_link)) { if (link == ap->excl_link) { if (ap->nr_active_links) return ATA_DEFER_PORT; qc->flags |= ATA_QCFLAG_CLEAR_EXCL; } else return ATA_DEFER_PORT; |
13cc546be sata_sil24: preve... |
794 |
} else if (unlikely(is_excl)) { |
3454dc692 sata_sil24: imple... |
795 796 797 798 799 800 801 802 |
ap->excl_link = link; if (ap->nr_active_links) return ATA_DEFER_PORT; qc->flags |= ATA_QCFLAG_CLEAR_EXCL; } return ata_std_qc_defer(qc); } |
edb336670 [PATCH] SATA: rew... |
803 804 805 806 |
static void sil24_qc_prep(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct sil24_port_priv *pp = ap->private_data; |
aee10a03e [PATCH] sata_sil2... |
807 |
union sil24_cmd_block *cb; |
69ad185fa [PATCH] sil24: ad... |
808 809 |
struct sil24_prb *prb; struct sil24_sge *sge; |
bad28a37f [PATCH] sata_sil2... |
810 |
u16 ctrl = 0; |
edb336670 [PATCH] SATA: rew... |
811 |
|
aee10a03e [PATCH] sata_sil2... |
812 |
cb = &pp->cmd_block[sil24_tag(qc->tag)]; |
405e66b38 libata: implement... |
813 |
if (!ata_is_atapi(qc->tf.protocol)) { |
69ad185fa [PATCH] sil24: ad... |
814 815 |
prb = &cb->ata.prb; sge = cb->ata.sge; |
4f1a0ee11 sata_sil24: alway... |
816 817 818 819 820 821 822 823 824 825 826 |
if (ata_is_data(qc->tf.protocol)) { u16 prot = 0; ctrl = PRB_CTRL_PROTOCOL; if (ata_is_ncq(qc->tf.protocol)) prot |= PRB_PROT_NCQ; if (qc->tf.flags & ATA_TFLAG_WRITE) prot |= PRB_PROT_WRITE; else prot |= PRB_PROT_READ; prb->prot = cpu_to_le16(prot); } |
405e66b38 libata: implement... |
827 |
} else { |
69ad185fa [PATCH] sil24: ad... |
828 829 |
prb = &cb->atapi.prb; sge = cb->atapi.sge; |
14e45c15e sata_sil24: memse... |
830 |
memset(cb->atapi.cdb, 0, sizeof(cb->atapi.cdb)); |
6e7846e9c [PATCH] libata: m... |
831 |
memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); |
69ad185fa [PATCH] sil24: ad... |
832 |
|
405e66b38 libata: implement... |
833 |
if (ata_is_data(qc->tf.protocol)) { |
69ad185fa [PATCH] sil24: ad... |
834 |
if (qc->tf.flags & ATA_TFLAG_WRITE) |
bad28a37f [PATCH] sata_sil2... |
835 |
ctrl = PRB_CTRL_PACKET_WRITE; |
69ad185fa [PATCH] sil24: ad... |
836 |
else |
bad28a37f [PATCH] sata_sil2... |
837 838 |
ctrl = PRB_CTRL_PACKET_READ; } |
edb336670 [PATCH] SATA: rew... |
839 |
} |
bad28a37f [PATCH] sata_sil2... |
840 |
prb->ctrl = cpu_to_le16(ctrl); |
3454dc692 sata_sil24: imple... |
841 |
ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, prb->fis); |
edb336670 [PATCH] SATA: rew... |
842 843 |
if (qc->flags & ATA_QCFLAG_DMAMAP) |
69ad185fa [PATCH] sil24: ad... |
844 |
sil24_fill_sg(qc, sge); |
edb336670 [PATCH] SATA: rew... |
845 |
} |
9a3d9eb01 [PATCH] libata: r... |
846 |
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) |
edb336670 [PATCH] SATA: rew... |
847 848 849 |
{ struct ata_port *ap = qc->ap; struct sil24_port_priv *pp = ap->private_data; |
350756f6d libata: don't use... |
850 |
void __iomem *port = sil24_port_base(ap); |
aee10a03e [PATCH] sata_sil2... |
851 852 853 |
unsigned int tag = sil24_tag(qc->tag); dma_addr_t paddr; void __iomem *activate; |
edb336670 [PATCH] SATA: rew... |
854 |
|
aee10a03e [PATCH] sata_sil2... |
855 856 |
paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block); activate = port + PORT_CMD_ACTIVATE + tag * 8; |
108234529 sata_sil24: Use m... |
857 858 859 860 861 |
/* * The barrier is required to ensure that writes to cmd_block reach * the memory before the write to PORT_CMD_ACTIVATE. */ wmb(); |
aee10a03e [PATCH] sata_sil2... |
862 863 |
writel((u32)paddr, activate); writel((u64)paddr >> 32, activate + 4); |
26ec634c3 [PATCH] sata_sil2... |
864 |
|
edb336670 [PATCH] SATA: rew... |
865 866 |
return 0; } |
79f97dadf libata: drop @fin... |
867 868 869 870 871 |
static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc) { sil24_read_tf(qc->ap, qc->tag, &qc->result_tf); return true; } |
3454dc692 sata_sil24: imple... |
872 873 |
static void sil24_pmp_attach(struct ata_port *ap) { |
906c1ff44 sata_sil24: don't... |
874 |
u32 *gscr = ap->link.device->gscr; |
3454dc692 sata_sil24: imple... |
875 876 |
sil24_config_pmp(ap, 1); sil24_init_port(ap); |
906c1ff44 sata_sil24: don't... |
877 878 879 |
if (sata_pmp_gscr_vendor(gscr) == 0x11ab && sata_pmp_gscr_devid(gscr) == 0x4140) { |
a9a79dfec ata: Convert ata_... |
880 |
ata_port_info(ap, |
906c1ff44 sata_sil24: don't... |
881 882 883 884 |
"disabling NCQ support due to sil24-mv4140 quirk "); ap->flags &= ~ATA_FLAG_NCQ; } |
3454dc692 sata_sil24: imple... |
885 886 887 888 889 890 |
} static void sil24_pmp_detach(struct ata_port *ap) { sil24_init_port(ap); sil24_config_pmp(ap, 0); |
906c1ff44 sata_sil24: don't... |
891 892 |
ap->flags |= ATA_FLAG_NCQ; |
3454dc692 sata_sil24: imple... |
893 |
} |
3454dc692 sata_sil24: imple... |
894 895 896 897 898 899 900 |
static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { int rc; rc = sil24_init_port(link->ap); if (rc) { |
a9a79dfec ata: Convert ata_... |
901 902 |
ata_link_err(link, "hardreset failed (port not ready) "); |
3454dc692 sata_sil24: imple... |
903 904 |
return rc; } |
5958e3025 libata: move PMP ... |
905 |
return sata_std_hardreset(link, class, deadline); |
3454dc692 sata_sil24: imple... |
906 |
} |
88ce7550c [PATCH] sata_sil2... |
907 |
static void sil24_freeze(struct ata_port *ap) |
7d1ce682d [PATCH] sil24: ad... |
908 |
{ |
350756f6d libata: don't use... |
909 |
void __iomem *port = sil24_port_base(ap); |
7d1ce682d [PATCH] sil24: ad... |
910 |
|
88ce7550c [PATCH] sata_sil2... |
911 912 913 914 |
/* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear * PORT_IRQ_ENABLE instead. */ writel(0xffff, port + PORT_IRQ_ENABLE_CLR); |
7d1ce682d [PATCH] sil24: ad... |
915 |
} |
88ce7550c [PATCH] sata_sil2... |
916 |
static void sil24_thaw(struct ata_port *ap) |
edb336670 [PATCH] SATA: rew... |
917 |
{ |
350756f6d libata: don't use... |
918 |
void __iomem *port = sil24_port_base(ap); |
edb336670 [PATCH] SATA: rew... |
919 |
u32 tmp; |
88ce7550c [PATCH] sata_sil2... |
920 921 922 |
/* clear IRQ */ tmp = readl(port + PORT_IRQ_STAT); writel(tmp, port + PORT_IRQ_STAT); |
edb336670 [PATCH] SATA: rew... |
923 |
|
88ce7550c [PATCH] sata_sil2... |
924 925 |
/* turn IRQ back on */ writel(DEF_PORT_IRQ, port + PORT_IRQ_ENABLE_SET); |
edb336670 [PATCH] SATA: rew... |
926 |
} |
88ce7550c [PATCH] sata_sil2... |
927 |
static void sil24_error_intr(struct ata_port *ap) |
8746618d4 [PATCH] sil24: mo... |
928 |
{ |
350756f6d libata: don't use... |
929 |
void __iomem *port = sil24_port_base(ap); |
e59f0dad3 sata_sil24: repla... |
930 |
struct sil24_port_priv *pp = ap->private_data; |
3454dc692 sata_sil24: imple... |
931 932 933 934 |
struct ata_queued_cmd *qc = NULL; struct ata_link *link; struct ata_eh_info *ehi; int abort = 0, freeze = 0; |
88ce7550c [PATCH] sata_sil2... |
935 |
u32 irq_stat; |
8746618d4 [PATCH] sil24: mo... |
936 |
|
88ce7550c [PATCH] sata_sil2... |
937 |
/* on error, we need to clear IRQ explicitly */ |
8746618d4 [PATCH] sil24: mo... |
938 |
irq_stat = readl(port + PORT_IRQ_STAT); |
88ce7550c [PATCH] sata_sil2... |
939 |
writel(irq_stat, port + PORT_IRQ_STAT); |
ad6e90f6d [PATCH] sil24: ig... |
940 |
|
88ce7550c [PATCH] sata_sil2... |
941 |
/* first, analyze and record host port events */ |
3454dc692 sata_sil24: imple... |
942 943 |
link = &ap->link; ehi = &link->eh_info; |
88ce7550c [PATCH] sata_sil2... |
944 |
ata_ehi_clear_desc(ehi); |
ad6e90f6d [PATCH] sil24: ig... |
945 |
|
88ce7550c [PATCH] sata_sil2... |
946 |
ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); |
8746618d4 [PATCH] sil24: mo... |
947 |
|
854c73a2f libata: misc upda... |
948 |
if (irq_stat & PORT_IRQ_SDB_NOTIFY) { |
854c73a2f libata: misc upda... |
949 |
ata_ehi_push_desc(ehi, "SDB notify"); |
7d77b2470 libata-pmp-prep: ... |
950 |
sata_async_notification(ap); |
854c73a2f libata: misc upda... |
951 |
} |
0542925b2 [PATCH] sata_sil2... |
952 953 |
if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) { ata_ehi_hotplugged(ehi); |
b64bbc39f libata: improve E... |
954 955 956 |
ata_ehi_push_desc(ehi, "%s", irq_stat & PORT_IRQ_PHYRDY_CHG ? "PHY RDY changed" : "device exchanged"); |
88ce7550c [PATCH] sata_sil2... |
957 |
freeze = 1; |
6a575fa96 [PATCH] sil24: im... |
958 |
} |
88ce7550c [PATCH] sata_sil2... |
959 960 |
if (irq_stat & PORT_IRQ_UNK_FIS) { ehi->err_mask |= AC_ERR_HSM; |
cf4806265 libata: prefer ha... |
961 |
ehi->action |= ATA_EH_RESET; |
b64bbc39f libata: improve E... |
962 |
ata_ehi_push_desc(ehi, "unknown FIS"); |
88ce7550c [PATCH] sata_sil2... |
963 964 965 966 967 |
freeze = 1; } /* deal with command error */ if (irq_stat & PORT_IRQ_ERROR) { |
fc8cc1d5b sata_sil24: Use c... |
968 |
const struct sil24_cerr_info *ci = NULL; |
88ce7550c [PATCH] sata_sil2... |
969 |
unsigned int err_mask = 0, action = 0; |
3454dc692 sata_sil24: imple... |
970 971 972 973 974 975 976 977 978 979 980 981 |
u32 context, cerr; int pmp; abort = 1; /* DMA Context Switch Failure in Port Multiplier Mode * errata. If we have active commands to 3 or more * devices, any error condition on active devices can * corrupt DMA context switching. */ if (ap->nr_active_links >= 3) { ehi->err_mask |= AC_ERR_OTHER; |
cf4806265 libata: prefer ha... |
982 |
ehi->action |= ATA_EH_RESET; |
3454dc692 sata_sil24: imple... |
983 |
ata_ehi_push_desc(ehi, "PMP DMA CS errata"); |
238180343 sata_sil24: imple... |
984 |
pp->do_port_rst = 1; |
3454dc692 sata_sil24: imple... |
985 986 987 988 |
freeze = 1; } /* find out the offending link and qc */ |
071f44b1d libata: implement... |
989 |
if (sata_pmp_attached(ap)) { |
3454dc692 sata_sil24: imple... |
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 |
context = readl(port + PORT_CONTEXT); pmp = (context >> 5) & 0xf; if (pmp < ap->nr_pmp_links) { link = &ap->pmp_link[pmp]; ehi = &link->eh_info; qc = ata_qc_from_tag(ap, link->active_tag); ata_ehi_clear_desc(ehi); ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); } else { err_mask |= AC_ERR_HSM; |
cf4806265 libata: prefer ha... |
1003 |
action |= ATA_EH_RESET; |
3454dc692 sata_sil24: imple... |
1004 1005 1006 1007 |
freeze = 1; } } else qc = ata_qc_from_tag(ap, link->active_tag); |
88ce7550c [PATCH] sata_sil2... |
1008 1009 1010 1011 1012 1013 1014 1015 1016 |
/* analyze CMD_ERR */ cerr = readl(port + PORT_CMD_ERR); if (cerr < ARRAY_SIZE(sil24_cerr_db)) ci = &sil24_cerr_db[cerr]; if (ci && ci->desc) { err_mask |= ci->err_mask; action |= ci->action; |
cf4806265 libata: prefer ha... |
1017 |
if (action & ATA_EH_RESET) |
c2e14f111 sata_sil24: freez... |
1018 |
freeze = 1; |
b64bbc39f libata: improve E... |
1019 |
ata_ehi_push_desc(ehi, "%s", ci->desc); |
88ce7550c [PATCH] sata_sil2... |
1020 1021 |
} else { err_mask |= AC_ERR_OTHER; |
cf4806265 libata: prefer ha... |
1022 |
action |= ATA_EH_RESET; |
c2e14f111 sata_sil24: freez... |
1023 |
freeze = 1; |
b64bbc39f libata: improve E... |
1024 |
ata_ehi_push_desc(ehi, "unknown command error %d", |
88ce7550c [PATCH] sata_sil2... |
1025 1026 1027 1028 |
cerr); } /* record error info */ |
520d06f92 libata: remove ch... |
1029 |
if (qc) |
88ce7550c [PATCH] sata_sil2... |
1030 |
qc->err_mask |= err_mask; |
520d06f92 libata: remove ch... |
1031 |
else |
88ce7550c [PATCH] sata_sil2... |
1032 1033 1034 |
ehi->err_mask |= err_mask; ehi->action |= action; |
3454dc692 sata_sil24: imple... |
1035 1036 |
/* if PMP, resume */ |
071f44b1d libata: implement... |
1037 |
if (sata_pmp_attached(ap)) |
3454dc692 sata_sil24: imple... |
1038 |
writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT); |
a22e2eb07 [PATCH] libata: m... |
1039 |
} |
88ce7550c [PATCH] sata_sil2... |
1040 1041 1042 1043 |
/* freeze or abort */ if (freeze) ata_port_freeze(ap); |
3454dc692 sata_sil24: imple... |
1044 1045 1046 1047 1048 1049 |
else if (abort) { if (qc) ata_link_abort(qc->dev->link); else ata_port_abort(ap); } |
8746618d4 [PATCH] sil24: mo... |
1050 |
} |
edb336670 [PATCH] SATA: rew... |
1051 1052 |
static inline void sil24_host_intr(struct ata_port *ap) { |
350756f6d libata: don't use... |
1053 |
void __iomem *port = sil24_port_base(ap); |
aee10a03e [PATCH] sata_sil2... |
1054 1055 |
u32 slot_stat, qc_active; int rc; |
edb336670 [PATCH] SATA: rew... |
1056 |
|
228f47b95 sata_sil24: fix I... |
1057 1058 1059 1060 1061 1062 1063 1064 1065 |
/* If PCIX_IRQ_WOC, there's an inherent race window between * clearing IRQ pending status and reading PORT_SLOT_STAT * which may cause spurious interrupts afterwards. This is * unavoidable and much better than losing interrupts which * happens if IRQ pending is cleared after reading * PORT_SLOT_STAT. */ if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); |
edb336670 [PATCH] SATA: rew... |
1066 |
slot_stat = readl(port + PORT_SLOT_STAT); |
37024e8ee [PATCH] sata_sil2... |
1067 |
|
88ce7550c [PATCH] sata_sil2... |
1068 1069 1070 1071 |
if (unlikely(slot_stat & HOST_SSTAT_ATTN)) { sil24_error_intr(ap); return; } |
aee10a03e [PATCH] sata_sil2... |
1072 |
qc_active = slot_stat & ~HOST_SSTAT_ATTN; |
79f97dadf libata: drop @fin... |
1073 |
rc = ata_qc_complete_multiple(ap, qc_active); |
aee10a03e [PATCH] sata_sil2... |
1074 1075 1076 |
if (rc > 0) return; if (rc < 0) { |
9af5c9c97 libata-link: intr... |
1077 |
struct ata_eh_info *ehi = &ap->link.eh_info; |
aee10a03e [PATCH] sata_sil2... |
1078 |
ehi->err_mask |= AC_ERR_HSM; |
cf4806265 libata: prefer ha... |
1079 |
ehi->action |= ATA_EH_RESET; |
aee10a03e [PATCH] sata_sil2... |
1080 |
ata_port_freeze(ap); |
88ce7550c [PATCH] sata_sil2... |
1081 1082 |
return; } |
228f47b95 sata_sil24: fix I... |
1083 1084 |
/* spurious interrupts are expected if PCIX_IRQ_WOC */ if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit()) |
a9a79dfec ata: Convert ata_... |
1085 1086 1087 |
ata_port_info(ap, "spurious interrupt (slot_stat 0x%x active_tag %d sactive 0x%x) ", |
9af5c9c97 libata-link: intr... |
1088 |
slot_stat, ap->link.active_tag, ap->link.sactive); |
edb336670 [PATCH] SATA: rew... |
1089 |
} |
7d12e780e IRQ: Maintain reg... |
1090 |
static irqreturn_t sil24_interrupt(int irq, void *dev_instance) |
edb336670 [PATCH] SATA: rew... |
1091 |
{ |
cca3974e4 libata: Grand ren... |
1092 |
struct ata_host *host = dev_instance; |
0d5ff5667 libata: convert t... |
1093 |
void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; |
edb336670 [PATCH] SATA: rew... |
1094 1095 1096 |
unsigned handled = 0; u32 status; int i; |
0d5ff5667 libata: convert t... |
1097 |
status = readl(host_base + HOST_IRQ_STAT); |
edb336670 [PATCH] SATA: rew... |
1098 |
|
06460aeaa [PATCH] sil24: ad... |
1099 1100 1101 1102 1103 1104 |
if (status == 0xffffffff) { printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, " "PCI fault or device removal? "); goto out; } |
edb336670 [PATCH] SATA: rew... |
1105 1106 |
if (!(status & IRQ_STAT_4PORTS)) goto out; |
cca3974e4 libata: Grand ren... |
1107 |
spin_lock(&host->lock); |
edb336670 [PATCH] SATA: rew... |
1108 |
|
cca3974e4 libata: Grand ren... |
1109 |
for (i = 0; i < host->n_ports; i++) |
edb336670 [PATCH] SATA: rew... |
1110 |
if (status & (1 << i)) { |
3e4ec3443 libata: kill ATA_... |
1111 1112 |
sil24_host_intr(host->ports[i]); handled++; |
edb336670 [PATCH] SATA: rew... |
1113 |
} |
cca3974e4 libata: Grand ren... |
1114 |
spin_unlock(&host->lock); |
edb336670 [PATCH] SATA: rew... |
1115 1116 1117 |
out: return IRQ_RETVAL(handled); } |
88ce7550c [PATCH] sata_sil2... |
1118 1119 |
static void sil24_error_handler(struct ata_port *ap) { |
238180343 sata_sil24: imple... |
1120 |
struct sil24_port_priv *pp = ap->private_data; |
3454dc692 sata_sil24: imple... |
1121 |
if (sil24_init_port(ap)) |
88ce7550c [PATCH] sata_sil2... |
1122 |
ata_eh_freeze_port(ap); |
88ce7550c [PATCH] sata_sil2... |
1123 |
|
a1efdaba2 libata: make rese... |
1124 |
sata_pmp_error_handler(ap); |
238180343 sata_sil24: imple... |
1125 1126 |
pp->do_port_rst = 0; |
88ce7550c [PATCH] sata_sil2... |
1127 1128 1129 1130 1131 |
} static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; |
88ce7550c [PATCH] sata_sil2... |
1132 |
/* make DMA engine forget about the failed command */ |
3454dc692 sata_sil24: imple... |
1133 1134 |
if ((qc->flags & ATA_QCFLAG_FAILED) && sil24_init_port(ap)) ata_eh_freeze_port(ap); |
88ce7550c [PATCH] sata_sil2... |
1135 |
} |
edb336670 [PATCH] SATA: rew... |
1136 1137 |
static int sil24_port_start(struct ata_port *ap) { |
cca3974e4 libata: Grand ren... |
1138 |
struct device *dev = ap->host->dev; |
edb336670 [PATCH] SATA: rew... |
1139 |
struct sil24_port_priv *pp; |
69ad185fa [PATCH] sil24: ad... |
1140 |
union sil24_cmd_block *cb; |
aee10a03e [PATCH] sata_sil2... |
1141 |
size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS; |
edb336670 [PATCH] SATA: rew... |
1142 |
dma_addr_t cb_dma; |
24dc5f33e libata: update li... |
1143 |
pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); |
edb336670 [PATCH] SATA: rew... |
1144 |
if (!pp) |
24dc5f33e libata: update li... |
1145 |
return -ENOMEM; |
edb336670 [PATCH] SATA: rew... |
1146 |
|
24dc5f33e libata: update li... |
1147 |
cb = dmam_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL); |
6037d6bbd [libata] ATAPI pa... |
1148 |
if (!cb) |
24dc5f33e libata: update li... |
1149 |
return -ENOMEM; |
edb336670 [PATCH] SATA: rew... |
1150 |
memset(cb, 0, cb_size); |
edb336670 [PATCH] SATA: rew... |
1151 1152 1153 1154 |
pp->cmd_block = cb; pp->cmd_block_dma = cb_dma; ap->private_data = pp; |
350756f6d libata: don't use... |
1155 1156 |
ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host"); ata_port_pbar_desc(ap, SIL24_PORT_BAR, sil24_port_offset(ap), "port"); |
edb336670 [PATCH] SATA: rew... |
1157 |
return 0; |
edb336670 [PATCH] SATA: rew... |
1158 |
} |
4447d3515 libata: convert t... |
1159 |
static void sil24_init_controller(struct ata_host *host) |
2a41a6108 [PATCH] sata_sil2... |
1160 |
{ |
4447d3515 libata: convert t... |
1161 |
void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; |
2a41a6108 [PATCH] sata_sil2... |
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 |
u32 tmp; int i; /* GPIO off */ writel(0, host_base + HOST_FLASH_CMD); /* clear global reset & mask interrupts during initialization */ writel(0, host_base + HOST_CTRL); /* init ports */ |
4447d3515 libata: convert t... |
1172 |
for (i = 0; i < host->n_ports; i++) { |
238180343 sata_sil24: imple... |
1173 |
struct ata_port *ap = host->ports[i]; |
350756f6d libata: don't use... |
1174 |
void __iomem *port = sil24_port_base(ap); |
2a41a6108 [PATCH] sata_sil2... |
1175 1176 1177 1178 1179 1180 1181 1182 |
/* Initial PHY setting */ writel(0x20c, port + PORT_PHY_CFG); /* Clear port RST */ tmp = readl(port + PORT_CTRL_STAT); if (tmp & PORT_CS_PORT_RST) { writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR); |
97750cebb libata: add @ap t... |
1183 |
tmp = ata_wait_register(NULL, port + PORT_CTRL_STAT, |
2a41a6108 [PATCH] sata_sil2... |
1184 1185 1186 |
PORT_CS_PORT_RST, PORT_CS_PORT_RST, 10, 100); if (tmp & PORT_CS_PORT_RST) |
a44fec1fc ata: Convert dev_... |
1187 1188 1189 |
dev_err(host->dev, "failed to clear port RST "); |
2a41a6108 [PATCH] sata_sil2... |
1190 |
} |
238180343 sata_sil24: imple... |
1191 1192 |
/* configure port */ sil24_config_port(ap); |
2a41a6108 [PATCH] sata_sil2... |
1193 1194 1195 1196 1197 |
} /* Turn on interrupts */ writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL); } |
edb336670 [PATCH] SATA: rew... |
1198 1199 |
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { |
93e2618e0 sata_sil24: fix s... |
1200 |
extern int __MARKER__sil24_cmd_block_is_sized_wrongly; |
4447d3515 libata: convert t... |
1201 1202 1203 1204 |
struct ata_port_info pi = sil24_port_info[ent->driver_data]; const struct ata_port_info *ppi[] = { &pi, NULL }; void __iomem * const *iomap; struct ata_host *host; |
350756f6d libata: don't use... |
1205 |
int rc; |
37024e8ee [PATCH] sata_sil2... |
1206 |
u32 tmp; |
edb336670 [PATCH] SATA: rew... |
1207 |
|
93e2618e0 sata_sil24: fix s... |
1208 1209 1210 |
/* cause link error if sil24_cmd_block is sized wrongly */ if (sizeof(union sil24_cmd_block) != PAGE_SIZE) __MARKER__sil24_cmd_block_is_sized_wrongly = 1; |
06296a1e6 ata: Add and use ... |
1211 |
ata_print_version_once(&pdev->dev, DRV_VERSION); |
edb336670 [PATCH] SATA: rew... |
1212 |
|
4447d3515 libata: convert t... |
1213 |
/* acquire resources */ |
24dc5f33e libata: update li... |
1214 |
rc = pcim_enable_device(pdev); |
edb336670 [PATCH] SATA: rew... |
1215 1216 |
if (rc) return rc; |
0d5ff5667 libata: convert t... |
1217 1218 1219 |
rc = pcim_iomap_regions(pdev, (1 << SIL24_HOST_BAR) | (1 << SIL24_PORT_BAR), DRV_NAME); |
edb336670 [PATCH] SATA: rew... |
1220 |
if (rc) |
24dc5f33e libata: update li... |
1221 |
return rc; |
4447d3515 libata: convert t... |
1222 |
iomap = pcim_iomap_table(pdev); |
edb336670 [PATCH] SATA: rew... |
1223 |
|
4447d3515 libata: convert t... |
1224 1225 1226 1227 |
/* apply workaround for completion IRQ loss on PCI-X errata */ if (pi.flags & SIL24_FLAG_PCIX_IRQ_WOC) { tmp = readl(iomap[SIL24_HOST_BAR] + HOST_CTRL); if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL)) |
a44fec1fc ata: Convert dev_... |
1228 1229 1230 |
dev_info(&pdev->dev, "Applying completion IRQ loss on PCI-X errata fix "); |
4447d3515 libata: convert t... |
1231 1232 1233 |
else pi.flags &= ~SIL24_FLAG_PCIX_IRQ_WOC; } |
edb336670 [PATCH] SATA: rew... |
1234 |
|
4447d3515 libata: convert t... |
1235 1236 1237 1238 1239 1240 |
/* allocate and fill host */ host = ata_host_alloc_pinfo(&pdev->dev, ppi, SIL24_FLAG2NPORTS(ppi[0]->flags)); if (!host) return -ENOMEM; host->iomap = iomap; |
edb336670 [PATCH] SATA: rew... |
1241 |
|
4447d3515 libata: convert t... |
1242 |
/* configure and activate the device */ |
6a35528a8 dma-mapping: repl... |
1243 1244 |
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); |
26ec634c3 [PATCH] sata_sil2... |
1245 |
if (rc) { |
284901a90 dma-mapping: repl... |
1246 |
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
26ec634c3 [PATCH] sata_sil2... |
1247 |
if (rc) { |
a44fec1fc ata: Convert dev_... |
1248 1249 1250 |
dev_err(&pdev->dev, "64-bit DMA enable failed "); |
24dc5f33e libata: update li... |
1251 |
return rc; |
26ec634c3 [PATCH] sata_sil2... |
1252 1253 1254 |
} } } else { |
284901a90 dma-mapping: repl... |
1255 |
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
26ec634c3 [PATCH] sata_sil2... |
1256 |
if (rc) { |
a44fec1fc ata: Convert dev_... |
1257 1258 |
dev_err(&pdev->dev, "32-bit DMA enable failed "); |
24dc5f33e libata: update li... |
1259 |
return rc; |
26ec634c3 [PATCH] sata_sil2... |
1260 |
} |
284901a90 dma-mapping: repl... |
1261 |
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
26ec634c3 [PATCH] sata_sil2... |
1262 |
if (rc) { |
a44fec1fc ata: Convert dev_... |
1263 1264 1265 |
dev_err(&pdev->dev, "32-bit consistent DMA enable failed "); |
24dc5f33e libata: update li... |
1266 |
return rc; |
26ec634c3 [PATCH] sata_sil2... |
1267 |
} |
edb336670 [PATCH] SATA: rew... |
1268 |
} |
e8b3b5e9f sata_sil24: confi... |
1269 1270 1271 1272 |
/* Set max read request size to 4096. This slightly increases * write throughput for pci-e variants. */ pcie_set_readrq(pdev, 4096); |
4447d3515 libata: convert t... |
1273 |
sil24_init_controller(host); |
edb336670 [PATCH] SATA: rew... |
1274 |
|
dae77214f sata_sil24: MSI s... |
1275 |
if (sata_sil24_msi && !pci_enable_msi(pdev)) { |
a44fec1fc ata: Convert dev_... |
1276 1277 |
dev_info(&pdev->dev, "Using MSI "); |
dae77214f sata_sil24: MSI s... |
1278 1279 |
pci_intx(pdev, 0); } |
edb336670 [PATCH] SATA: rew... |
1280 |
pci_set_master(pdev); |
4447d3515 libata: convert t... |
1281 1282 |
return ata_host_activate(host, pdev->irq, sil24_interrupt, IRQF_SHARED, &sil24_sht); |
edb336670 [PATCH] SATA: rew... |
1283 |
} |
281d426c7 [PATCH] CONFIG_PM... |
1284 |
#ifdef CONFIG_PM |
d2298dca9 [PATCH] sata_sil2... |
1285 1286 |
static int sil24_pci_device_resume(struct pci_dev *pdev) { |
cca3974e4 libata: Grand ren... |
1287 |
struct ata_host *host = dev_get_drvdata(&pdev->dev); |
0d5ff5667 libata: convert t... |
1288 |
void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; |
553c4aa63 libata: handle pc... |
1289 |
int rc; |
d2298dca9 [PATCH] sata_sil2... |
1290 |
|
553c4aa63 libata: handle pc... |
1291 1292 1293 |
rc = ata_pci_device_do_resume(pdev); if (rc) return rc; |
d2298dca9 [PATCH] sata_sil2... |
1294 1295 |
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) |
0d5ff5667 libata: convert t... |
1296 |
writel(HOST_CTRL_GLOBAL_RST, host_base + HOST_CTRL); |
d2298dca9 [PATCH] sata_sil2... |
1297 |
|
4447d3515 libata: convert t... |
1298 |
sil24_init_controller(host); |
d2298dca9 [PATCH] sata_sil2... |
1299 |
|
cca3974e4 libata: Grand ren... |
1300 |
ata_host_resume(host); |
d2298dca9 [PATCH] sata_sil2... |
1301 1302 1303 |
return 0; } |
3454dc692 sata_sil24: imple... |
1304 1305 1306 1307 1308 1309 |
static int sil24_port_resume(struct ata_port *ap) { sil24_config_pmp(ap, ap->nr_pmp_links); return 0; } |
281d426c7 [PATCH] CONFIG_PM... |
1310 |
#endif |
d2298dca9 [PATCH] sata_sil2... |
1311 |
|
edb336670 [PATCH] SATA: rew... |
1312 1313 |
static int __init sil24_init(void) { |
b7887196e [PATCH] libata: r... |
1314 |
return pci_register_driver(&sil24_pci_driver); |
edb336670 [PATCH] SATA: rew... |
1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 |
} static void __exit sil24_exit(void) { pci_unregister_driver(&sil24_pci_driver); } MODULE_AUTHOR("Tejun Heo"); MODULE_DESCRIPTION("Silicon Image 3124/3132 SATA low-level driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sil24_pci_tbl); module_init(sil24_init); module_exit(sil24_exit); |