diff options
Diffstat (limited to 'drivers/scsi/mvsas.c')
-rwxr-xr-x | drivers/scsi/mvsas.c | 2981 |
1 files changed, 2981 insertions, 0 deletions
diff --git a/drivers/scsi/mvsas.c b/drivers/scsi/mvsas.c new file mode 100755 index 000000000000..30e20e69715a --- /dev/null +++ b/drivers/scsi/mvsas.c | |||
@@ -0,0 +1,2981 @@ | |||
1 | /* | ||
2 | mvsas.c - Marvell 88SE6440 SAS/SATA support | ||
3 | |||
4 | Copyright 2007 Red Hat, Inc. | ||
5 | Copyright 2008 Marvell. <kewei@marvell.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or | ||
8 | modify it under the terms of the GNU General Public License as | ||
9 | published by the Free Software Foundation; either version 2, | ||
10 | or (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty | ||
14 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
15 | See the GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public | ||
18 | License along with this program; see the file COPYING. If not, | ||
19 | write to the Free Software Foundation, 675 Mass Ave, Cambridge, | ||
20 | MA 02139, USA. | ||
21 | |||
22 | --------------------------------------------------------------- | ||
23 | |||
24 | Random notes: | ||
25 | * hardware supports controlling the endian-ness of data | ||
26 | structures. this permits elimination of all the le32_to_cpu() | ||
27 | and cpu_to_le32() conversions. | ||
28 | |||
29 | */ | ||
30 | |||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/dma-mapping.h> | ||
38 | #include <scsi/libsas.h> | ||
39 | #include <asm/io.h> | ||
40 | |||
41 | #define DRV_NAME "mvsas" | ||
42 | #define DRV_VERSION "0.5" | ||
43 | #define _MV_DUMP 0 | ||
44 | #define MVS_DISABLE_NVRAM | ||
45 | #define MVS_DISABLE_MSI | ||
46 | |||
47 | #define mr32(reg) readl(regs + MVS_##reg) | ||
48 | #define mw32(reg,val) writel((val), regs + MVS_##reg) | ||
49 | #define mw32_f(reg,val) do { \ | ||
50 | writel((val), regs + MVS_##reg); \ | ||
51 | readl(regs + MVS_##reg); \ | ||
52 | } while (0) | ||
53 | |||
54 | #define MVS_ID_NOT_MAPPED 0xff | ||
55 | #define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width) | ||
56 | |||
57 | /* offset for D2H FIS in the Received FIS List Structure */ | ||
58 | #define SATA_RECEIVED_D2H_FIS(reg_set) \ | ||
59 | ((void *) mvi->rx_fis + 0x400 + 0x100 * reg_set + 0x40) | ||
60 | #define SATA_RECEIVED_PIO_FIS(reg_set) \ | ||
61 | ((void *) mvi->rx_fis + 0x400 + 0x100 * reg_set + 0x20) | ||
62 | #define UNASSOC_D2H_FIS(id) \ | ||
63 | ((void *) mvi->rx_fis + 0x100 * id) | ||
64 | |||
65 | #define for_each_phy(__lseq_mask, __mc, __lseq, __rest) \ | ||
66 | for ((__mc) = (__lseq_mask), (__lseq) = 0; \ | ||
67 | (__mc) != 0 && __rest; \ | ||
68 | (++__lseq), (__mc) >>= 1) | ||
69 | |||
70 | /* driver compile-time configuration */ | ||
71 | enum driver_configuration { | ||
72 | MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */ | ||
73 | MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */ | ||
74 | /* software requires power-of-2 | ||
75 | ring size */ | ||
76 | |||
77 | MVS_SLOTS = 512, /* command slots */ | ||
78 | MVS_SLOT_BUF_SZ = 8192, /* cmd tbl + IU + status + PRD */ | ||
79 | MVS_SSP_CMD_SZ = 64, /* SSP command table buffer size */ | ||
80 | MVS_ATA_CMD_SZ = 96, /* SATA command table buffer size */ | ||
81 | MVS_OAF_SZ = 64, /* Open address frame buffer size */ | ||
82 | |||
83 | MVS_RX_FIS_COUNT = 17, /* Optional rx'd FISs (max 17) */ | ||
84 | |||
85 | MVS_QUEUE_SIZE = 30, /* Support Queue depth */ | ||
86 | }; | ||
87 | |||
88 | /* unchangeable hardware details */ | ||
89 | enum hardware_details { | ||
90 | MVS_MAX_PHYS = 8, /* max. possible phys */ | ||
91 | MVS_MAX_PORTS = 8, /* max. possible ports */ | ||
92 | MVS_RX_FISL_SZ = 0x400 + (MVS_RX_FIS_COUNT * 0x100), | ||
93 | }; | ||
94 | |||
95 | /* peripheral registers (BAR2) */ | ||
96 | enum peripheral_registers { | ||
97 | SPI_CTL = 0x10, /* EEPROM control */ | ||
98 | SPI_CMD = 0x14, /* EEPROM command */ | ||
99 | SPI_DATA = 0x18, /* EEPROM data */ | ||
100 | }; | ||
101 | |||
102 | enum peripheral_register_bits { | ||
103 | TWSI_RDY = (1U << 7), /* EEPROM interface ready */ | ||
104 | TWSI_RD = (1U << 4), /* EEPROM read access */ | ||
105 | |||
106 | SPI_ADDR_MASK = 0x3ffff, /* bits 17:0 */ | ||
107 | }; | ||
108 | |||
109 | /* enhanced mode registers (BAR4) */ | ||
110 | enum hw_registers { | ||
111 | MVS_GBL_CTL = 0x04, /* global control */ | ||
112 | MVS_GBL_INT_STAT = 0x08, /* global irq status */ | ||
113 | MVS_GBL_PI = 0x0C, /* ports implemented bitmask */ | ||
114 | MVS_GBL_PORT_TYPE = 0xa0, /* port type */ | ||
115 | |||
116 | MVS_CTL = 0x100, /* SAS/SATA port configuration */ | ||
117 | MVS_PCS = 0x104, /* SAS/SATA port control/status */ | ||
118 | MVS_CMD_LIST_LO = 0x108, /* cmd list addr */ | ||
119 | MVS_CMD_LIST_HI = 0x10C, | ||
120 | MVS_RX_FIS_LO = 0x110, /* RX FIS list addr */ | ||
121 | MVS_RX_FIS_HI = 0x114, | ||
122 | |||
123 | MVS_TX_CFG = 0x120, /* TX configuration */ | ||
124 | MVS_TX_LO = 0x124, /* TX (delivery) ring addr */ | ||
125 | MVS_TX_HI = 0x128, | ||
126 | |||
127 | MVS_TX_PROD_IDX = 0x12C, /* TX producer pointer */ | ||
128 | MVS_TX_CONS_IDX = 0x130, /* TX consumer pointer (RO) */ | ||
129 | MVS_RX_CFG = 0x134, /* RX configuration */ | ||
130 | MVS_RX_LO = 0x138, /* RX (completion) ring addr */ | ||
131 | MVS_RX_HI = 0x13C, | ||
132 | MVS_RX_CONS_IDX = 0x140, /* RX consumer pointer (RO) */ | ||
133 | |||
134 | MVS_INT_COAL = 0x148, /* Int coalescing config */ | ||
135 | MVS_INT_COAL_TMOUT = 0x14C, /* Int coalescing timeout */ | ||
136 | MVS_INT_STAT = 0x150, /* Central int status */ | ||
137 | MVS_INT_MASK = 0x154, /* Central int enable */ | ||
138 | MVS_INT_STAT_SRS = 0x158, /* SATA register set status */ | ||
139 | MVS_INT_MASK_SRS = 0x15C, | ||
140 | |||
141 | /* ports 1-3 follow after this */ | ||
142 | MVS_P0_INT_STAT = 0x160, /* port0 interrupt status */ | ||
143 | MVS_P0_INT_MASK = 0x164, /* port0 interrupt mask */ | ||
144 | MVS_P4_INT_STAT = 0x200, /* Port 4 interrupt status */ | ||
145 | MVS_P4_INT_MASK = 0x204, /* Port 4 interrupt enable mask */ | ||
146 | |||
147 | /* ports 1-3 follow after this */ | ||
148 | MVS_P0_SER_CTLSTAT = 0x180, /* port0 serial control/status */ | ||
149 | MVS_P4_SER_CTLSTAT = 0x220, /* port4 serial control/status */ | ||
150 | |||
151 | MVS_CMD_ADDR = 0x1B8, /* Command register port (addr) */ | ||
152 | MVS_CMD_DATA = 0x1BC, /* Command register port (data) */ | ||
153 | |||
154 | /* ports 1-3 follow after this */ | ||
155 | MVS_P0_CFG_ADDR = 0x1C0, /* port0 phy register address */ | ||
156 | MVS_P0_CFG_DATA = 0x1C4, /* port0 phy register data */ | ||
157 | MVS_P4_CFG_ADDR = 0x230, /* Port 4 config address */ | ||
158 | MVS_P4_CFG_DATA = 0x234, /* Port 4 config data */ | ||
159 | |||
160 | /* ports 1-3 follow after this */ | ||
161 | MVS_P0_VSR_ADDR = 0x1E0, /* port0 VSR address */ | ||
162 | MVS_P0_VSR_DATA = 0x1E4, /* port0 VSR data */ | ||
163 | MVS_P4_VSR_ADDR = 0x250, /* port 4 VSR addr */ | ||
164 | MVS_P4_VSR_DATA = 0x254, /* port 4 VSR data */ | ||
165 | }; | ||
166 | |||
167 | enum hw_register_bits { | ||
168 | /* MVS_GBL_CTL */ | ||
169 | INT_EN = (1U << 1), /* Global int enable */ | ||
170 | HBA_RST = (1U << 0), /* HBA reset */ | ||
171 | |||
172 | /* MVS_GBL_INT_STAT */ | ||
173 | INT_XOR = (1U << 4), /* XOR engine event */ | ||
174 | INT_SAS_SATA = (1U << 0), /* SAS/SATA event */ | ||
175 | |||
176 | /* MVS_GBL_PORT_TYPE */ /* shl for ports 1-3 */ | ||
177 | SATA_TARGET = (1U << 16), /* port0 SATA target enable */ | ||
178 | MODE_AUTO_DET_PORT7 = (1U << 15), /* port0 SAS/SATA autodetect */ | ||
179 | MODE_AUTO_DET_PORT6 = (1U << 14), | ||
180 | MODE_AUTO_DET_PORT5 = (1U << 13), | ||
181 | MODE_AUTO_DET_PORT4 = (1U << 12), | ||
182 | MODE_AUTO_DET_PORT3 = (1U << 11), | ||
183 | MODE_AUTO_DET_PORT2 = (1U << 10), | ||
184 | MODE_AUTO_DET_PORT1 = (1U << 9), | ||
185 | MODE_AUTO_DET_PORT0 = (1U << 8), | ||
186 | MODE_AUTO_DET_EN = MODE_AUTO_DET_PORT0 | MODE_AUTO_DET_PORT1 | | ||
187 | MODE_AUTO_DET_PORT2 | MODE_AUTO_DET_PORT3 | | ||
188 | MODE_AUTO_DET_PORT4 | MODE_AUTO_DET_PORT5 | | ||
189 | MODE_AUTO_DET_PORT6 | MODE_AUTO_DET_PORT7, | ||
190 | MODE_SAS_PORT7_MASK = (1U << 7), /* port0 SAS(1), SATA(0) mode */ | ||
191 | MODE_SAS_PORT6_MASK = (1U << 6), | ||
192 | MODE_SAS_PORT5_MASK = (1U << 5), | ||
193 | MODE_SAS_PORT4_MASK = (1U << 4), | ||
194 | MODE_SAS_PORT3_MASK = (1U << 3), | ||
195 | MODE_SAS_PORT2_MASK = (1U << 2), | ||
196 | MODE_SAS_PORT1_MASK = (1U << 1), | ||
197 | MODE_SAS_PORT0_MASK = (1U << 0), | ||
198 | MODE_SAS_SATA = MODE_SAS_PORT0_MASK | MODE_SAS_PORT1_MASK | | ||
199 | MODE_SAS_PORT2_MASK | MODE_SAS_PORT3_MASK | | ||
200 | MODE_SAS_PORT4_MASK | MODE_SAS_PORT5_MASK | | ||
201 | MODE_SAS_PORT6_MASK | MODE_SAS_PORT7_MASK, | ||
202 | |||
203 | /* SAS_MODE value may be | ||
204 | * dictated (in hw) by values | ||
205 | * of SATA_TARGET & AUTO_DET | ||
206 | */ | ||
207 | |||
208 | /* MVS_TX_CFG */ | ||
209 | TX_EN = (1U << 16), /* Enable TX */ | ||
210 | TX_RING_SZ_MASK = 0xfff, /* TX ring size, bits 11:0 */ | ||
211 | |||
212 | /* MVS_RX_CFG */ | ||
213 | RX_EN = (1U << 16), /* Enable RX */ | ||
214 | RX_RING_SZ_MASK = 0xfff, /* RX ring size, bits 11:0 */ | ||
215 | |||
216 | /* MVS_INT_COAL */ | ||
217 | COAL_EN = (1U << 16), /* Enable int coalescing */ | ||
218 | |||
219 | /* MVS_INT_STAT, MVS_INT_MASK */ | ||
220 | CINT_I2C = (1U << 31), /* I2C event */ | ||
221 | CINT_SW0 = (1U << 30), /* software event 0 */ | ||
222 | CINT_SW1 = (1U << 29), /* software event 1 */ | ||
223 | CINT_PRD_BC = (1U << 28), /* PRD BC err for read cmd */ | ||
224 | CINT_DMA_PCIE = (1U << 27), /* DMA to PCIE timeout */ | ||
225 | CINT_MEM = (1U << 26), /* int mem parity err */ | ||
226 | CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */ | ||
227 | CINT_SRS = (1U << 3), /* SRS event */ | ||
228 | CINT_CI_STOP = (1U << 1), /* cmd issue stopped */ | ||
229 | CINT_DONE = (1U << 0), /* cmd completion */ | ||
230 | |||
231 | /* shl for ports 1-3 */ | ||
232 | CINT_PORT_STOPPED = (1U << 16), /* port0 stopped */ | ||
233 | CINT_PORT = (1U << 8), /* port0 event */ | ||
234 | CINT_PORT_MASK_OFFSET = 8, | ||
235 | CINT_PORT_MASK = (0xFF << CINT_PORT_MASK_OFFSET), | ||
236 | |||
237 | /* TX (delivery) ring bits */ | ||
238 | TXQ_CMD_SHIFT = 29, | ||
239 | TXQ_CMD_SSP = 1, /* SSP protocol */ | ||
240 | TXQ_CMD_SMP = 2, /* SMP protocol */ | ||
241 | TXQ_CMD_STP = 3, /* STP/SATA protocol */ | ||
242 | TXQ_CMD_SSP_FREE_LIST = 4, /* add to SSP targ free list */ | ||
243 | TXQ_CMD_SLOT_RESET = 7, /* reset command slot */ | ||
244 | TXQ_MODE_I = (1U << 28), /* mode: 0=target,1=initiator */ | ||
245 | TXQ_PRIO_HI = (1U << 27), /* priority: 0=normal, 1=high */ | ||
246 | TXQ_SRS_SHIFT = 20, /* SATA register set */ | ||
247 | TXQ_SRS_MASK = 0x7f, | ||
248 | TXQ_PHY_SHIFT = 12, /* PHY bitmap */ | ||
249 | TXQ_PHY_MASK = 0xff, | ||
250 | TXQ_SLOT_MASK = 0xfff, /* slot number */ | ||
251 | |||
252 | /* RX (completion) ring bits */ | ||
253 | RXQ_GOOD = (1U << 23), /* Response good */ | ||
254 | RXQ_SLOT_RESET = (1U << 21), /* Slot reset complete */ | ||
255 | RXQ_CMD_RX = (1U << 20), /* target cmd received */ | ||
256 | RXQ_ATTN = (1U << 19), /* attention */ | ||
257 | RXQ_RSP = (1U << 18), /* response frame xfer'd */ | ||
258 | RXQ_ERR = (1U << 17), /* err info rec xfer'd */ | ||
259 | RXQ_DONE = (1U << 16), /* cmd complete */ | ||
260 | RXQ_SLOT_MASK = 0xfff, /* slot number */ | ||
261 | |||
262 | /* mvs_cmd_hdr bits */ | ||
263 | MCH_PRD_LEN_SHIFT = 16, /* 16-bit PRD table len */ | ||
264 | MCH_SSP_FR_TYPE_SHIFT = 13, /* SSP frame type */ | ||
265 | |||
266 | /* SSP initiator only */ | ||
267 | MCH_SSP_FR_CMD = 0x0, /* COMMAND frame */ | ||
268 | |||
269 | /* SSP initiator or target */ | ||
270 | MCH_SSP_FR_TASK = 0x1, /* TASK frame */ | ||
271 | |||
272 | /* SSP target only */ | ||
273 | MCH_SSP_FR_XFER_RDY = 0x4, /* XFER_RDY frame */ | ||
274 | MCH_SSP_FR_RESP = 0x5, /* RESPONSE frame */ | ||
275 | MCH_SSP_FR_READ = 0x6, /* Read DATA frame(s) */ | ||
276 | MCH_SSP_FR_READ_RESP = 0x7, /* ditto, plus RESPONSE */ | ||
277 | |||
278 | MCH_PASSTHRU = (1U << 12), /* pass-through (SSP) */ | ||
279 | MCH_FBURST = (1U << 11), /* first burst (SSP) */ | ||
280 | MCH_CHK_LEN = (1U << 10), /* chk xfer len (SSP) */ | ||
281 | MCH_RETRY = (1U << 9), /* tport layer retry (SSP) */ | ||
282 | MCH_PROTECTION = (1U << 8), /* protection info rec (SSP) */ | ||
283 | MCH_RESET = (1U << 7), /* Reset (STP/SATA) */ | ||
284 | MCH_FPDMA = (1U << 6), /* First party DMA (STP/SATA) */ | ||
285 | MCH_ATAPI = (1U << 5), /* ATAPI (STP/SATA) */ | ||
286 | MCH_BIST = (1U << 4), /* BIST activate (STP/SATA) */ | ||
287 | MCH_PMP_MASK = 0xf, /* PMP from cmd FIS (STP/SATA)*/ | ||
288 | |||
289 | CCTL_RST = (1U << 5), /* port logic reset */ | ||
290 | |||
291 | /* 0(LSB first), 1(MSB first) */ | ||
292 | CCTL_ENDIAN_DATA = (1U << 3), /* PRD data */ | ||
293 | CCTL_ENDIAN_RSP = (1U << 2), /* response frame */ | ||
294 | CCTL_ENDIAN_OPEN = (1U << 1), /* open address frame */ | ||
295 | CCTL_ENDIAN_CMD = (1U << 0), /* command table */ | ||
296 | |||
297 | /* MVS_Px_SER_CTLSTAT (per-phy control) */ | ||
298 | PHY_SSP_RST = (1U << 3), /* reset SSP link layer */ | ||
299 | PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */ | ||
300 | PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */ | ||
301 | PHY_RST = (1U << 0), /* phy reset */ | ||
302 | PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0xF << 8), | ||
303 | PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0xF << 12), | ||
304 | PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (16), | ||
305 | PHY_NEG_SPP_PHYS_LINK_RATE_MASK = | ||
306 | (0xF << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET), | ||
307 | PHY_READY_MASK = (1U << 20), | ||
308 | |||
309 | /* MVS_Px_INT_STAT, MVS_Px_INT_MASK (per-phy events) */ | ||
310 | PHYEV_DEC_ERR = (1U << 24), /* Phy Decoding Error */ | ||
311 | PHYEV_UNASSOC_FIS = (1U << 19), /* unassociated FIS rx'd */ | ||
312 | PHYEV_AN = (1U << 18), /* SATA async notification */ | ||
313 | PHYEV_BIST_ACT = (1U << 17), /* BIST activate FIS */ | ||
314 | PHYEV_SIG_FIS = (1U << 16), /* signature FIS */ | ||
315 | PHYEV_POOF = (1U << 12), /* phy ready from 1 -> 0 */ | ||
316 | PHYEV_IU_BIG = (1U << 11), /* IU too long err */ | ||
317 | PHYEV_IU_SMALL = (1U << 10), /* IU too short err */ | ||
318 | PHYEV_UNK_TAG = (1U << 9), /* unknown tag */ | ||
319 | PHYEV_BROAD_CH = (1U << 8), /* broadcast(CHANGE) */ | ||
320 | PHYEV_COMWAKE = (1U << 7), /* COMWAKE rx'd */ | ||
321 | PHYEV_PORT_SEL = (1U << 6), /* port selector present */ | ||
322 | PHYEV_HARD_RST = (1U << 5), /* hard reset rx'd */ | ||
323 | PHYEV_ID_TMOUT = (1U << 4), /* identify timeout */ | ||
324 | PHYEV_ID_FAIL = (1U << 3), /* identify failed */ | ||
325 | PHYEV_ID_DONE = (1U << 2), /* identify done */ | ||
326 | PHYEV_HARD_RST_DONE = (1U << 1), /* hard reset done */ | ||
327 | PHYEV_RDY_CH = (1U << 0), /* phy ready changed state */ | ||
328 | |||
329 | /* MVS_PCS */ | ||
330 | PCS_EN_SATA_REG_SHIFT = (16), /* Enable SATA Register Set */ | ||
331 | PCS_EN_PORT_XMT_SHIFT = (12), /* Enable Port Transmit */ | ||
332 | PCS_EN_PORT_XMT_SHIFT2 = (8), /* For 6480 */ | ||
333 | PCS_SATA_RETRY = (1U << 8), /* retry ctl FIS on R_ERR */ | ||
334 | PCS_RSP_RX_EN = (1U << 7), /* raw response rx */ | ||
335 | PCS_SELF_CLEAR = (1U << 5), /* self-clearing int mode */ | ||
336 | PCS_FIS_RX_EN = (1U << 4), /* FIS rx enable */ | ||
337 | PCS_CMD_STOP_ERR = (1U << 3), /* cmd stop-on-err enable */ | ||
338 | PCS_CMD_RST = (1U << 1), /* reset cmd issue */ | ||
339 | PCS_CMD_EN = (1U << 0), /* enable cmd issue */ | ||
340 | |||
341 | /* Port n Attached Device Info */ | ||
342 | PORT_DEV_SSP_TRGT = (1U << 19), | ||
343 | PORT_DEV_SMP_TRGT = (1U << 18), | ||
344 | PORT_DEV_STP_TRGT = (1U << 17), | ||
345 | PORT_DEV_SSP_INIT = (1U << 11), | ||
346 | PORT_DEV_SMP_INIT = (1U << 10), | ||
347 | PORT_DEV_STP_INIT = (1U << 9), | ||
348 | PORT_PHY_ID_MASK = (0xFFU << 24), | ||
349 | PORT_DEV_TRGT_MASK = (0x7U << 17), | ||
350 | PORT_DEV_INIT_MASK = (0x7U << 9), | ||
351 | PORT_DEV_TYPE_MASK = (0x7U << 0), | ||
352 | |||
353 | /* Port n PHY Status */ | ||
354 | PHY_RDY = (1U << 2), | ||
355 | PHY_DW_SYNC = (1U << 1), | ||
356 | PHY_OOB_DTCTD = (1U << 0), | ||
357 | |||
358 | /* VSR */ | ||
359 | /* PHYMODE 6 (CDB) */ | ||
360 | PHY_MODE6_DTL_SPEED = (1U << 27), | ||
361 | }; | ||
362 | |||
363 | enum mvs_info_flags { | ||
364 | MVF_MSI = (1U << 0), /* MSI is enabled */ | ||
365 | MVF_PHY_PWR_FIX = (1U << 1), /* bug workaround */ | ||
366 | }; | ||
367 | |||
368 | enum sas_cmd_port_registers { | ||
369 | CMD_CMRST_OOB_DET = 0x100, /* COMRESET OOB detect register */ | ||
370 | CMD_CMWK_OOB_DET = 0x104, /* COMWAKE OOB detect register */ | ||
371 | CMD_CMSAS_OOB_DET = 0x108, /* COMSAS OOB detect register */ | ||
372 | CMD_BRST_OOB_DET = 0x10c, /* burst OOB detect register */ | ||
373 | CMD_OOB_SPACE = 0x110, /* OOB space control register */ | ||
374 | CMD_OOB_BURST = 0x114, /* OOB burst control register */ | ||
375 | CMD_PHY_TIMER = 0x118, /* PHY timer control register */ | ||
376 | CMD_PHY_CONFIG0 = 0x11c, /* PHY config register 0 */ | ||
377 | CMD_PHY_CONFIG1 = 0x120, /* PHY config register 1 */ | ||
378 | CMD_SAS_CTL0 = 0x124, /* SAS control register 0 */ | ||
379 | CMD_SAS_CTL1 = 0x128, /* SAS control register 1 */ | ||
380 | CMD_SAS_CTL2 = 0x12c, /* SAS control register 2 */ | ||
381 | CMD_SAS_CTL3 = 0x130, /* SAS control register 3 */ | ||
382 | CMD_ID_TEST = 0x134, /* ID test register */ | ||
383 | CMD_PL_TIMER = 0x138, /* PL timer register */ | ||
384 | CMD_WD_TIMER = 0x13c, /* WD timer register */ | ||
385 | CMD_PORT_SEL_COUNT = 0x140, /* port selector count register */ | ||
386 | CMD_APP_MEM_CTL = 0x144, /* Application Memory Control */ | ||
387 | CMD_XOR_MEM_CTL = 0x148, /* XOR Block Memory Control */ | ||
388 | CMD_DMA_MEM_CTL = 0x14c, /* DMA Block Memory Control */ | ||
389 | CMD_PORT_MEM_CTL0 = 0x150, /* Port Memory Control 0 */ | ||
390 | CMD_PORT_MEM_CTL1 = 0x154, /* Port Memory Control 1 */ | ||
391 | CMD_SATA_PORT_MEM_CTL0 = 0x158, /* SATA Port Memory Control 0 */ | ||
392 | CMD_SATA_PORT_MEM_CTL1 = 0x15c, /* SATA Port Memory Control 1 */ | ||
393 | CMD_XOR_MEM_BIST_CTL = 0x160, /* XOR Memory BIST Control */ | ||
394 | CMD_XOR_MEM_BIST_STAT = 0x164, /* XOR Memroy BIST Status */ | ||
395 | CMD_DMA_MEM_BIST_CTL = 0x168, /* DMA Memory BIST Control */ | ||
396 | CMD_DMA_MEM_BIST_STAT = 0x16c, /* DMA Memory BIST Status */ | ||
397 | CMD_PORT_MEM_BIST_CTL = 0x170, /* Port Memory BIST Control */ | ||
398 | CMD_PORT_MEM_BIST_STAT0 = 0x174, /* Port Memory BIST Status 0 */ | ||
399 | CMD_PORT_MEM_BIST_STAT1 = 0x178, /* Port Memory BIST Status 1 */ | ||
400 | CMD_STP_MEM_BIST_CTL = 0x17c, /* STP Memory BIST Control */ | ||
401 | CMD_STP_MEM_BIST_STAT0 = 0x180, /* STP Memory BIST Status 0 */ | ||
402 | CMD_STP_MEM_BIST_STAT1 = 0x184, /* STP Memory BIST Status 1 */ | ||
403 | CMD_RESET_COUNT = 0x188, /* Reset Count */ | ||
404 | CMD_MONTR_DATA_SEL = 0x18C, /* Monitor Data/Select */ | ||
405 | CMD_PLL_PHY_CONFIG = 0x190, /* PLL/PHY Configuration */ | ||
406 | CMD_PHY_CTL = 0x194, /* PHY Control and Status */ | ||
407 | CMD_PHY_TEST_COUNT0 = 0x198, /* Phy Test Count 0 */ | ||
408 | CMD_PHY_TEST_COUNT1 = 0x19C, /* Phy Test Count 1 */ | ||
409 | CMD_PHY_TEST_COUNT2 = 0x1A0, /* Phy Test Count 2 */ | ||
410 | CMD_APP_ERR_CONFIG = 0x1A4, /* Application Error Configuration */ | ||
411 | CMD_PND_FIFO_CTL0 = 0x1A8, /* Pending FIFO Control 0 */ | ||
412 | CMD_HOST_CTL = 0x1AC, /* Host Control Status */ | ||
413 | CMD_HOST_WR_DATA = 0x1B0, /* Host Write Data */ | ||
414 | CMD_HOST_RD_DATA = 0x1B4, /* Host Read Data */ | ||
415 | CMD_PHY_MODE_21 = 0x1B8, /* Phy Mode 21 */ | ||
416 | CMD_SL_MODE0 = 0x1BC, /* SL Mode 0 */ | ||
417 | CMD_SL_MODE1 = 0x1C0, /* SL Mode 1 */ | ||
418 | CMD_PND_FIFO_CTL1 = 0x1C4, /* Pending FIFO Control 1 */ | ||
419 | }; | ||
420 | |||
421 | /* SAS/SATA configuration port registers, aka phy registers */ | ||
422 | enum sas_sata_config_port_regs { | ||
423 | PHYR_IDENTIFY = 0x00, /* info for IDENTIFY frame */ | ||
424 | PHYR_ADDR_LO = 0x04, /* my SAS address (low) */ | ||
425 | PHYR_ADDR_HI = 0x08, /* my SAS address (high) */ | ||
426 | PHYR_ATT_DEV_INFO = 0x0C, /* attached device info */ | ||
427 | PHYR_ATT_ADDR_LO = 0x10, /* attached dev SAS addr (low) */ | ||
428 | PHYR_ATT_ADDR_HI = 0x14, /* attached dev SAS addr (high) */ | ||
429 | PHYR_SATA_CTL = 0x18, /* SATA control */ | ||
430 | PHYR_PHY_STAT = 0x1C, /* PHY status */ | ||
431 | PHYR_SATA_SIG0 = 0x20, /*port SATA signature FIS(Byte 0-3) */ | ||
432 | PHYR_SATA_SIG1 = 0x24, /*port SATA signature FIS(Byte 4-7) */ | ||
433 | PHYR_SATA_SIG2 = 0x28, /*port SATA signature FIS(Byte 8-11) */ | ||
434 | PHYR_SATA_SIG3 = 0x2c, /*port SATA signature FIS(Byte 12-15) */ | ||
435 | PHYR_R_ERR_COUNT = 0x30, /* port R_ERR count register */ | ||
436 | PHYR_CRC_ERR_COUNT = 0x34, /* port CRC error count register */ | ||
437 | PHYR_WIDE_PORT = 0x38, /* wide port participating */ | ||
438 | PHYR_CURRENT0 = 0x80, /* current connection info 0 */ | ||
439 | PHYR_CURRENT1 = 0x84, /* current connection info 1 */ | ||
440 | PHYR_CURRENT2 = 0x88, /* current connection info 2 */ | ||
441 | }; | ||
442 | |||
443 | /* SAS/SATA Vendor Specific Port Registers */ | ||
444 | enum sas_sata_vsp_regs { | ||
445 | VSR_PHY_STAT = 0x00, /* Phy Status */ | ||
446 | VSR_PHY_MODE1 = 0x01, /* phy tx */ | ||
447 | VSR_PHY_MODE2 = 0x02, /* tx scc */ | ||
448 | VSR_PHY_MODE3 = 0x03, /* pll */ | ||
449 | VSR_PHY_MODE4 = 0x04, /* VCO */ | ||
450 | VSR_PHY_MODE5 = 0x05, /* Rx */ | ||
451 | VSR_PHY_MODE6 = 0x06, /* CDR */ | ||
452 | VSR_PHY_MODE7 = 0x07, /* Impedance */ | ||
453 | VSR_PHY_MODE8 = 0x08, /* Voltage */ | ||
454 | VSR_PHY_MODE9 = 0x09, /* Test */ | ||
455 | VSR_PHY_MODE10 = 0x0A, /* Power */ | ||
456 | VSR_PHY_MODE11 = 0x0B, /* Phy Mode */ | ||
457 | VSR_PHY_VS0 = 0x0C, /* Vednor Specific 0 */ | ||
458 | VSR_PHY_VS1 = 0x0D, /* Vednor Specific 1 */ | ||
459 | }; | ||
460 | |||
461 | enum pci_cfg_registers { | ||
462 | PCR_PHY_CTL = 0x40, | ||
463 | PCR_PHY_CTL2 = 0x90, | ||
464 | PCR_DEV_CTRL = 0xE8, | ||
465 | }; | ||
466 | |||
467 | enum pci_cfg_register_bits { | ||
468 | PCTL_PWR_ON = (0xFU << 24), | ||
469 | PCTL_OFF = (0xFU << 12), | ||
470 | PRD_REQ_SIZE = (0x4000), | ||
471 | PRD_REQ_MASK = (0x00007000), | ||
472 | }; | ||
473 | |||
474 | enum nvram_layout_offsets { | ||
475 | NVR_SIG = 0x00, /* 0xAA, 0x55 */ | ||
476 | NVR_SAS_ADDR = 0x02, /* 8-byte SAS address */ | ||
477 | }; | ||
478 | |||
479 | enum chip_flavors { | ||
480 | chip_6320, | ||
481 | chip_6440, | ||
482 | chip_6480, | ||
483 | }; | ||
484 | |||
485 | enum port_type { | ||
486 | PORT_TYPE_SAS = (1L << 1), | ||
487 | PORT_TYPE_SATA = (1L << 0), | ||
488 | }; | ||
489 | |||
490 | /* Command Table Format */ | ||
491 | enum ct_format { | ||
492 | /* SSP */ | ||
493 | SSP_F_H = 0x00, | ||
494 | SSP_F_IU = 0x18, | ||
495 | SSP_F_MAX = 0x4D, | ||
496 | /* STP */ | ||
497 | STP_CMD_FIS = 0x00, | ||
498 | STP_ATAPI_CMD = 0x40, | ||
499 | STP_F_MAX = 0x10, | ||
500 | /* SMP */ | ||
501 | SMP_F_T = 0x00, | ||
502 | SMP_F_DEP = 0x01, | ||
503 | SMP_F_MAX = 0x101, | ||
504 | }; | ||
505 | |||
506 | enum status_buffer { | ||
507 | SB_EIR_OFF = 0x00, /* Error Information Record */ | ||
508 | SB_RFB_OFF = 0x08, /* Response Frame Buffer */ | ||
509 | SB_RFB_MAX = 0x400, /* RFB size*/ | ||
510 | }; | ||
511 | |||
512 | enum error_info_rec { | ||
513 | CMD_ISS_STPD = (1U << 31), /* Cmd Issue Stopped */ | ||
514 | }; | ||
515 | |||
516 | struct mvs_chip_info { | ||
517 | u32 n_phy; | ||
518 | u32 srs_sz; | ||
519 | u32 slot_width; | ||
520 | }; | ||
521 | |||
522 | struct mvs_err_info { | ||
523 | __le32 flags; | ||
524 | __le32 flags2; | ||
525 | }; | ||
526 | |||
527 | struct mvs_prd { | ||
528 | __le64 addr; /* 64-bit buffer address */ | ||
529 | __le32 reserved; | ||
530 | __le32 len; /* 16-bit length */ | ||
531 | }; | ||
532 | |||
533 | struct mvs_cmd_hdr { | ||
534 | __le32 flags; /* PRD tbl len; SAS, SATA ctl */ | ||
535 | __le32 lens; /* cmd, max resp frame len */ | ||
536 | __le32 tags; /* targ port xfer tag; tag */ | ||
537 | __le32 data_len; /* data xfer len */ | ||
538 | __le64 cmd_tbl; /* command table address */ | ||
539 | __le64 open_frame; /* open addr frame address */ | ||
540 | __le64 status_buf; /* status buffer address */ | ||
541 | __le64 prd_tbl; /* PRD tbl address */ | ||
542 | __le32 reserved[4]; | ||
543 | }; | ||
544 | |||
545 | struct mvs_slot_info { | ||
546 | struct sas_task *task; | ||
547 | u32 n_elem; | ||
548 | u32 tx; | ||
549 | |||
550 | /* DMA buffer for storing cmd tbl, open addr frame, status buffer, | ||
551 | * and PRD table | ||
552 | */ | ||
553 | void *buf; | ||
554 | dma_addr_t buf_dma; | ||
555 | #if _MV_DUMP | ||
556 | u32 cmd_size; | ||
557 | #endif | ||
558 | |||
559 | void *response; | ||
560 | }; | ||
561 | |||
562 | struct mvs_port { | ||
563 | struct asd_sas_port sas_port; | ||
564 | u8 port_attached; | ||
565 | u8 taskfileset; | ||
566 | u8 wide_port_phymap; | ||
567 | }; | ||
568 | |||
569 | struct mvs_phy { | ||
570 | struct mvs_port *port; | ||
571 | struct asd_sas_phy sas_phy; | ||
572 | struct sas_identify identify; | ||
573 | struct scsi_device *sdev; | ||
574 | u64 dev_sas_addr; | ||
575 | u64 att_dev_sas_addr; | ||
576 | u32 att_dev_info; | ||
577 | u32 dev_info; | ||
578 | u32 phy_type; | ||
579 | u32 phy_status; | ||
580 | u32 irq_status; | ||
581 | u32 frame_rcvd_size; | ||
582 | u8 frame_rcvd[32]; | ||
583 | u8 phy_attached; | ||
584 | }; | ||
585 | |||
586 | struct mvs_info { | ||
587 | unsigned long flags; | ||
588 | |||
589 | spinlock_t lock; /* host-wide lock */ | ||
590 | struct pci_dev *pdev; /* our device */ | ||
591 | void __iomem *regs; /* enhanced mode registers */ | ||
592 | void __iomem *peri_regs; /* peripheral registers */ | ||
593 | |||
594 | u8 sas_addr[SAS_ADDR_SIZE]; | ||
595 | struct sas_ha_struct sas; /* SCSI/SAS glue */ | ||
596 | struct Scsi_Host *shost; | ||
597 | |||
598 | __le32 *tx; /* TX (delivery) DMA ring */ | ||
599 | dma_addr_t tx_dma; | ||
600 | u32 tx_prod; /* cached next-producer idx */ | ||
601 | |||
602 | __le32 *rx; /* RX (completion) DMA ring */ | ||
603 | dma_addr_t rx_dma; | ||
604 | u32 rx_cons; /* RX consumer idx */ | ||
605 | |||
606 | __le32 *rx_fis; /* RX'd FIS area */ | ||
607 | dma_addr_t rx_fis_dma; | ||
608 | |||
609 | struct mvs_cmd_hdr *slot; /* DMA command header slots */ | ||
610 | dma_addr_t slot_dma; | ||
611 | |||
612 | const struct mvs_chip_info *chip; | ||
613 | |||
614 | unsigned long tags[MVS_SLOTS]; | ||
615 | struct mvs_slot_info slot_info[MVS_SLOTS]; | ||
616 | /* further per-slot information */ | ||
617 | struct mvs_phy phy[MVS_MAX_PHYS]; | ||
618 | struct mvs_port port[MVS_MAX_PHYS]; | ||
619 | |||
620 | u32 can_queue; /* per adapter */ | ||
621 | u32 tag_out; /*Get*/ | ||
622 | u32 tag_in; /*Give*/ | ||
623 | }; | ||
624 | |||
625 | struct mvs_queue_task { | ||
626 | struct list_head list; | ||
627 | |||
628 | void *uldd_task; | ||
629 | }; | ||
630 | |||
631 | static int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | ||
632 | void *funcdata); | ||
633 | static u32 mvs_read_phy_ctl(struct mvs_info *mvi, u32 port); | ||
634 | static void mvs_write_phy_ctl(struct mvs_info *mvi, u32 port, u32 val); | ||
635 | static u32 mvs_read_port(struct mvs_info *mvi, u32 off, u32 off2, u32 port); | ||
636 | static void mvs_write_port(struct mvs_info *mvi, u32 off, u32 off2, | ||
637 | u32 port, u32 val); | ||
638 | static u32 mvs_read_port_cfg_data(struct mvs_info *mvi, u32 port); | ||
639 | static void mvs_write_port_cfg_data(struct mvs_info *mvi, u32 port, u32 val); | ||
640 | static void mvs_write_port_cfg_addr(struct mvs_info *mvi, u32 port, u32 addr); | ||
641 | static u32 mvs_read_port_vsr_data(struct mvs_info *mvi, u32 port); | ||
642 | static void mvs_write_port_vsr_data(struct mvs_info *mvi, u32 port, u32 val); | ||
643 | static void mvs_write_port_vsr_addr(struct mvs_info *mvi, u32 port, u32 addr); | ||
644 | static u32 mvs_read_port_irq_stat(struct mvs_info *mvi, u32 port); | ||
645 | static void mvs_write_port_irq_stat(struct mvs_info *mvi, u32 port, u32 val); | ||
646 | static void mvs_write_port_irq_mask(struct mvs_info *mvi, u32 port, u32 val); | ||
647 | static u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port); | ||
648 | |||
649 | static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i); | ||
650 | static void mvs_detect_porttype(struct mvs_info *mvi, int i); | ||
651 | static void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st); | ||
652 | static void mvs_free_reg_set(struct mvs_info *mvi, struct mvs_port *port); | ||
653 | static u8 mvs_assign_reg_set(struct mvs_info *mvi, struct mvs_port *port); | ||
654 | static u32 mvs_is_sig_fis_received(u32 irq_status); | ||
655 | |||
656 | static int mvs_scan_finished(struct Scsi_Host *, unsigned long); | ||
657 | static void mvs_scan_start(struct Scsi_Host *); | ||
658 | static int mvs_sas_slave_alloc(struct scsi_device *scsi_dev); | ||
659 | |||
660 | static struct scsi_transport_template *mvs_stt; | ||
661 | |||
662 | static const struct mvs_chip_info mvs_chips[] = { | ||
663 | [chip_6320] = { 2, 16, 9 }, | ||
664 | [chip_6440] = { 4, 16, 9 }, | ||
665 | [chip_6480] = { 8, 32, 10 }, | ||
666 | }; | ||
667 | |||
668 | static struct scsi_host_template mvs_sht = { | ||
669 | .module = THIS_MODULE, | ||
670 | .name = DRV_NAME, | ||
671 | .queuecommand = sas_queuecommand, | ||
672 | .target_alloc = sas_target_alloc, | ||
673 | .slave_configure = sas_slave_configure, | ||
674 | .slave_destroy = sas_slave_destroy, | ||
675 | .scan_finished = mvs_scan_finished, | ||
676 | .scan_start = mvs_scan_start, | ||
677 | .change_queue_depth = sas_change_queue_depth, | ||
678 | .change_queue_type = sas_change_queue_type, | ||
679 | .bios_param = sas_bios_param, | ||
680 | .can_queue = 1, | ||
681 | .cmd_per_lun = 1, | ||
682 | .this_id = -1, | ||
683 | .sg_tablesize = SG_ALL, | ||
684 | .max_sectors = SCSI_DEFAULT_MAX_SECTORS, | ||
685 | .use_clustering = ENABLE_CLUSTERING, | ||
686 | .eh_device_reset_handler = sas_eh_device_reset_handler, | ||
687 | .eh_bus_reset_handler = sas_eh_bus_reset_handler, | ||
688 | .slave_alloc = mvs_sas_slave_alloc, | ||
689 | .target_destroy = sas_target_destroy, | ||
690 | .ioctl = sas_ioctl, | ||
691 | }; | ||
692 | |||
693 | static void mvs_hexdump(u32 size, u8 *data, u32 baseaddr) | ||
694 | { | ||
695 | u32 i; | ||
696 | u32 run; | ||
697 | u32 offset; | ||
698 | |||
699 | offset = 0; | ||
700 | while (size) { | ||
701 | printk("%08X : ", baseaddr + offset); | ||
702 | if (size >= 16) | ||
703 | run = 16; | ||
704 | else | ||
705 | run = size; | ||
706 | size -= run; | ||
707 | for (i = 0; i < 16; i++) { | ||
708 | if (i < run) | ||
709 | printk("%02X ", (u32)data[i]); | ||
710 | else | ||
711 | printk(" "); | ||
712 | } | ||
713 | printk(": "); | ||
714 | for (i = 0; i < run; i++) | ||
715 | printk("%c", isalnum(data[i]) ? data[i] : '.'); | ||
716 | printk("\n"); | ||
717 | data = &data[16]; | ||
718 | offset += run; | ||
719 | } | ||
720 | printk("\n"); | ||
721 | } | ||
722 | |||
723 | static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag, | ||
724 | enum sas_protocol proto) | ||
725 | { | ||
726 | #if _MV_DUMP | ||
727 | u32 offset; | ||
728 | struct pci_dev *pdev = mvi->pdev; | ||
729 | struct mvs_slot_info *slot = &mvi->slot_info[tag]; | ||
730 | |||
731 | offset = slot->cmd_size + MVS_OAF_SZ + | ||
732 | sizeof(struct mvs_prd) * slot->n_elem; | ||
733 | dev_printk(KERN_DEBUG, &pdev->dev, "+---->Status buffer[%d] :\n", | ||
734 | tag); | ||
735 | mvs_hexdump(32, (u8 *) slot->response, | ||
736 | (u32) slot->buf_dma + offset); | ||
737 | #endif | ||
738 | } | ||
739 | |||
740 | static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, | ||
741 | enum sas_protocol proto) | ||
742 | { | ||
743 | #if _MV_DUMP | ||
744 | u32 sz, w_ptr, r_ptr; | ||
745 | u64 addr; | ||
746 | void __iomem *regs = mvi->regs; | ||
747 | struct pci_dev *pdev = mvi->pdev; | ||
748 | struct mvs_slot_info *slot = &mvi->slot_info[tag]; | ||
749 | |||
750 | /*Delivery Queue */ | ||
751 | sz = mr32(TX_CFG) & TX_RING_SZ_MASK; | ||
752 | w_ptr = mr32(TX_PROD_IDX) & TX_RING_SZ_MASK; | ||
753 | r_ptr = mr32(TX_CONS_IDX) & TX_RING_SZ_MASK; | ||
754 | addr = mr32(TX_HI) << 16 << 16 | mr32(TX_LO); | ||
755 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
756 | "Delivery Queue Size=%04d , WRT_PTR=%04X , RD_PTR=%04X\n", | ||
757 | sz, w_ptr, r_ptr); | ||
758 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
759 | "Delivery Queue Base Address=0x%llX (PA)" | ||
760 | "(tx_dma=0x%llX), Entry=%04d\n", | ||
761 | addr, mvi->tx_dma, w_ptr); | ||
762 | mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]), | ||
763 | (u32) mvi->tx_dma + sizeof(u32) * w_ptr); | ||
764 | /*Command List */ | ||
765 | addr = mr32(CMD_LIST_HI) << 16 << 16 | mr32(CMD_LIST_LO); | ||
766 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
767 | "Command List Base Address=0x%llX (PA)" | ||
768 | "(slot_dma=0x%llX), Header=%03d\n", | ||
769 | addr, mvi->slot_dma, tag); | ||
770 | dev_printk(KERN_DEBUG, &pdev->dev, "Command Header[%03d]:\n", tag); | ||
771 | /*mvs_cmd_hdr */ | ||
772 | mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]), | ||
773 | (u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr)); | ||
774 | /*1.command table area */ | ||
775 | dev_printk(KERN_DEBUG, &pdev->dev, "+---->Command Table :\n"); | ||
776 | mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma); | ||
777 | /*2.open address frame area */ | ||
778 | dev_printk(KERN_DEBUG, &pdev->dev, "+---->Open Address Frame :\n"); | ||
779 | mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size, | ||
780 | (u32) slot->buf_dma + slot->cmd_size); | ||
781 | /*3.status buffer */ | ||
782 | mvs_hba_sb_dump(mvi, tag, proto); | ||
783 | /*4.PRD table */ | ||
784 | dev_printk(KERN_DEBUG, &pdev->dev, "+---->PRD table :\n"); | ||
785 | mvs_hexdump(sizeof(struct mvs_prd) * slot->n_elem, | ||
786 | (u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ, | ||
787 | (u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ); | ||
788 | #endif | ||
789 | } | ||
790 | |||
791 | static void mvs_hba_cq_dump(struct mvs_info *mvi) | ||
792 | { | ||
793 | #if _MV_DUMP | ||
794 | u64 addr; | ||
795 | void __iomem *regs = mvi->regs; | ||
796 | struct pci_dev *pdev = mvi->pdev; | ||
797 | u32 entry = mvi->rx_cons + 1; | ||
798 | u32 rx_desc = le32_to_cpu(mvi->rx[entry]); | ||
799 | |||
800 | /*Completion Queue */ | ||
801 | addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO); | ||
802 | dev_printk(KERN_DEBUG, &pdev->dev, "Completion Task = 0x%08X\n", | ||
803 | (u32) mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task); | ||
804 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
805 | "Completion List Base Address=0x%llX (PA), " | ||
806 | "CQ_Entry=%04d, CQ_WP=0x%08X\n", | ||
807 | addr, entry - 1, mvi->rx[0]); | ||
808 | mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc), | ||
809 | mvi->rx_dma + sizeof(u32) * entry); | ||
810 | #endif | ||
811 | } | ||
812 | |||
813 | static void mvs_hba_interrupt_enable(struct mvs_info *mvi) | ||
814 | { | ||
815 | void __iomem *regs = mvi->regs; | ||
816 | u32 tmp; | ||
817 | |||
818 | tmp = mr32(GBL_CTL); | ||
819 | |||
820 | mw32(GBL_CTL, tmp | INT_EN); | ||
821 | } | ||
822 | |||
823 | static void mvs_hba_interrupt_disable(struct mvs_info *mvi) | ||
824 | { | ||
825 | void __iomem *regs = mvi->regs; | ||
826 | u32 tmp; | ||
827 | |||
828 | tmp = mr32(GBL_CTL); | ||
829 | |||
830 | mw32(GBL_CTL, tmp & ~INT_EN); | ||
831 | } | ||
832 | |||
833 | static int mvs_int_rx(struct mvs_info *mvi, bool self_clear); | ||
834 | |||
835 | /* move to PCI layer or libata core? */ | ||
836 | static int pci_go_64(struct pci_dev *pdev) | ||
837 | { | ||
838 | int rc; | ||
839 | |||
840 | if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { | ||
841 | rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); | ||
842 | if (rc) { | ||
843 | rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); | ||
844 | if (rc) { | ||
845 | dev_printk(KERN_ERR, &pdev->dev, | ||
846 | "64-bit DMA enable failed\n"); | ||
847 | return rc; | ||
848 | } | ||
849 | } | ||
850 | } else { | ||
851 | rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | ||
852 | if (rc) { | ||
853 | dev_printk(KERN_ERR, &pdev->dev, | ||
854 | "32-bit DMA enable failed\n"); | ||
855 | return rc; | ||
856 | } | ||
857 | rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); | ||
858 | if (rc) { | ||
859 | dev_printk(KERN_ERR, &pdev->dev, | ||
860 | "32-bit consistent DMA enable failed\n"); | ||
861 | return rc; | ||
862 | } | ||
863 | } | ||
864 | |||
865 | return rc; | ||
866 | } | ||
867 | |||
868 | static void mvs_tag_clear(struct mvs_info *mvi, u32 tag) | ||
869 | { | ||
870 | mvi->tag_in = (mvi->tag_in + 1) & (MVS_SLOTS - 1); | ||
871 | mvi->tags[mvi->tag_in] = tag; | ||
872 | } | ||
873 | |||
874 | static void mvs_tag_free(struct mvs_info *mvi, u32 tag) | ||
875 | { | ||
876 | mvi->tag_out = (mvi->tag_out - 1) & (MVS_SLOTS - 1); | ||
877 | } | ||
878 | |||
879 | static int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out) | ||
880 | { | ||
881 | if (mvi->tag_out != mvi->tag_in) { | ||
882 | *tag_out = mvi->tags[mvi->tag_out]; | ||
883 | mvi->tag_out = (mvi->tag_out + 1) & (MVS_SLOTS - 1); | ||
884 | return 0; | ||
885 | } | ||
886 | return -EBUSY; | ||
887 | } | ||
888 | |||
889 | static void mvs_tag_init(struct mvs_info *mvi) | ||
890 | { | ||
891 | int i; | ||
892 | for (i = 0; i < MVS_SLOTS; ++i) | ||
893 | mvi->tags[i] = i; | ||
894 | mvi->tag_out = 0; | ||
895 | mvi->tag_in = MVS_SLOTS - 1; | ||
896 | } | ||
897 | |||
898 | #ifndef MVS_DISABLE_NVRAM | ||
899 | static int mvs_eep_read(void __iomem *regs, u32 addr, u32 *data) | ||
900 | { | ||
901 | int timeout = 1000; | ||
902 | |||
903 | if (addr & ~SPI_ADDR_MASK) | ||
904 | return -EINVAL; | ||
905 | |||
906 | writel(addr, regs + SPI_CMD); | ||
907 | writel(TWSI_RD, regs + SPI_CTL); | ||
908 | |||
909 | while (timeout-- > 0) { | ||
910 | if (readl(regs + SPI_CTL) & TWSI_RDY) { | ||
911 | *data = readl(regs + SPI_DATA); | ||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | udelay(10); | ||
916 | } | ||
917 | |||
918 | return -EBUSY; | ||
919 | } | ||
920 | |||
921 | static int mvs_eep_read_buf(void __iomem *regs, u32 addr, | ||
922 | void *buf, u32 buflen) | ||
923 | { | ||
924 | u32 addr_end, tmp_addr, i, j; | ||
925 | u32 tmp = 0; | ||
926 | int rc; | ||
927 | u8 *tmp8, *buf8 = buf; | ||
928 | |||
929 | addr_end = addr + buflen; | ||
930 | tmp_addr = ALIGN(addr, 4); | ||
931 | if (addr > 0xff) | ||
932 | return -EINVAL; | ||
933 | |||
934 | j = addr & 0x3; | ||
935 | if (j) { | ||
936 | rc = mvs_eep_read(regs, tmp_addr, &tmp); | ||
937 | if (rc) | ||
938 | return rc; | ||
939 | |||
940 | tmp8 = (u8 *)&tmp; | ||
941 | for (i = j; i < 4; i++) | ||
942 | *buf8++ = tmp8[i]; | ||
943 | |||
944 | tmp_addr += 4; | ||
945 | } | ||
946 | |||
947 | for (j = ALIGN(addr_end, 4); tmp_addr < j; tmp_addr += 4) { | ||
948 | rc = mvs_eep_read(regs, tmp_addr, &tmp); | ||
949 | if (rc) | ||
950 | return rc; | ||
951 | |||
952 | memcpy(buf8, &tmp, 4); | ||
953 | buf8 += 4; | ||
954 | } | ||
955 | |||
956 | if (tmp_addr < addr_end) { | ||
957 | rc = mvs_eep_read(regs, tmp_addr, &tmp); | ||
958 | if (rc) | ||
959 | return rc; | ||
960 | |||
961 | tmp8 = (u8 *)&tmp; | ||
962 | j = addr_end - tmp_addr; | ||
963 | for (i = 0; i < j; i++) | ||
964 | *buf8++ = tmp8[i]; | ||
965 | |||
966 | tmp_addr += 4; | ||
967 | } | ||
968 | |||
969 | return 0; | ||
970 | } | ||
971 | #endif | ||
972 | |||
973 | static int mvs_nvram_read(struct mvs_info *mvi, u32 addr, | ||
974 | void *buf, u32 buflen) | ||
975 | { | ||
976 | #ifndef MVS_DISABLE_NVRAM | ||
977 | void __iomem *regs = mvi->regs; | ||
978 | int rc, i; | ||
979 | u32 sum; | ||
980 | u8 hdr[2], *tmp; | ||
981 | const char *msg; | ||
982 | |||
983 | rc = mvs_eep_read_buf(regs, addr, &hdr, 2); | ||
984 | if (rc) { | ||
985 | msg = "nvram hdr read failed"; | ||
986 | goto err_out; | ||
987 | } | ||
988 | rc = mvs_eep_read_buf(regs, addr + 2, buf, buflen); | ||
989 | if (rc) { | ||
990 | msg = "nvram read failed"; | ||
991 | goto err_out; | ||
992 | } | ||
993 | |||
994 | if (hdr[0] != 0x5A) { | ||
995 | /* entry id */ | ||
996 | msg = "invalid nvram entry id"; | ||
997 | rc = -ENOENT; | ||
998 | goto err_out; | ||
999 | } | ||
1000 | |||
1001 | tmp = buf; | ||
1002 | sum = ((u32)hdr[0]) + ((u32)hdr[1]); | ||
1003 | for (i = 0; i < buflen; i++) | ||
1004 | sum += ((u32)tmp[i]); | ||
1005 | |||
1006 | if (sum) { | ||
1007 | msg = "nvram checksum failure"; | ||
1008 | rc = -EILSEQ; | ||
1009 | goto err_out; | ||
1010 | } | ||
1011 | |||
1012 | return 0; | ||
1013 | |||
1014 | err_out: | ||
1015 | dev_printk(KERN_ERR, &mvi->pdev->dev, "%s", msg); | ||
1016 | return rc; | ||
1017 | #else | ||
1018 | /* FIXME , For SAS target mode */ | ||
1019 | memcpy(buf, "\x00\x00\xab\x11\x30\x04\x05\x50", 8); | ||
1020 | return 0; | ||
1021 | #endif | ||
1022 | } | ||
1023 | |||
1024 | static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) | ||
1025 | { | ||
1026 | struct mvs_phy *phy = &mvi->phy[i]; | ||
1027 | |||
1028 | if (!phy->phy_attached) | ||
1029 | return; | ||
1030 | |||
1031 | if (phy->phy_type & PORT_TYPE_SAS) { | ||
1032 | struct sas_identify_frame *id; | ||
1033 | |||
1034 | id = (struct sas_identify_frame *)phy->frame_rcvd; | ||
1035 | id->dev_type = phy->identify.device_type; | ||
1036 | id->initiator_bits = SAS_PROTOCOL_ALL; | ||
1037 | id->target_bits = phy->identify.target_port_protocols; | ||
1038 | } else if (phy->phy_type & PORT_TYPE_SATA) { | ||
1039 | /* TODO */ | ||
1040 | } | ||
1041 | mvi->sas.sas_phy[i]->frame_rcvd_size = phy->frame_rcvd_size; | ||
1042 | mvi->sas.notify_port_event(mvi->sas.sas_phy[i], | ||
1043 | PORTE_BYTES_DMAED); | ||
1044 | } | ||
1045 | |||
1046 | static int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time) | ||
1047 | { | ||
1048 | /* give the phy enabling interrupt event time to come in (1s | ||
1049 | * is empirically about all it takes) */ | ||
1050 | if (time < HZ) | ||
1051 | return 0; | ||
1052 | /* Wait for discovery to finish */ | ||
1053 | scsi_flush_work(shost); | ||
1054 | return 1; | ||
1055 | } | ||
1056 | |||
1057 | static void mvs_scan_start(struct Scsi_Host *shost) | ||
1058 | { | ||
1059 | int i; | ||
1060 | struct mvs_info *mvi = SHOST_TO_SAS_HA(shost)->lldd_ha; | ||
1061 | |||
1062 | for (i = 0; i < mvi->chip->n_phy; ++i) { | ||
1063 | mvs_bytes_dmaed(mvi, i); | ||
1064 | } | ||
1065 | } | ||
1066 | |||
1067 | static int mvs_sas_slave_alloc(struct scsi_device *scsi_dev) | ||
1068 | { | ||
1069 | int rc; | ||
1070 | |||
1071 | rc = sas_slave_alloc(scsi_dev); | ||
1072 | |||
1073 | return rc; | ||
1074 | } | ||
1075 | |||
1076 | static void mvs_int_port(struct mvs_info *mvi, int port_no, u32 events) | ||
1077 | { | ||
1078 | struct pci_dev *pdev = mvi->pdev; | ||
1079 | struct sas_ha_struct *sas_ha = &mvi->sas; | ||
1080 | struct mvs_phy *phy = &mvi->phy[port_no]; | ||
1081 | struct asd_sas_phy *sas_phy = &phy->sas_phy; | ||
1082 | |||
1083 | phy->irq_status = mvs_read_port_irq_stat(mvi, port_no); | ||
1084 | /* | ||
1085 | * events is port event now , | ||
1086 | * we need check the interrupt status which belongs to per port. | ||
1087 | */ | ||
1088 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
1089 | "Port %d Event = %X\n", | ||
1090 | port_no, phy->irq_status); | ||
1091 | |||
1092 | if (phy->irq_status & (PHYEV_POOF | PHYEV_DEC_ERR)) { | ||
1093 | if (!mvs_is_phy_ready(mvi, port_no)) { | ||
1094 | sas_phy_disconnected(sas_phy); | ||
1095 | sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); | ||
1096 | } else | ||
1097 | mvs_phy_control(sas_phy, PHY_FUNC_LINK_RESET, NULL); | ||
1098 | } | ||
1099 | if (!(phy->irq_status & PHYEV_DEC_ERR)) { | ||
1100 | if (phy->irq_status & PHYEV_COMWAKE) { | ||
1101 | u32 tmp = mvs_read_port_irq_mask(mvi, port_no); | ||
1102 | mvs_write_port_irq_mask(mvi, port_no, | ||
1103 | tmp | PHYEV_SIG_FIS); | ||
1104 | } | ||
1105 | if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) { | ||
1106 | phy->phy_status = mvs_is_phy_ready(mvi, port_no); | ||
1107 | if (phy->phy_status) { | ||
1108 | mvs_detect_porttype(mvi, port_no); | ||
1109 | |||
1110 | if (phy->phy_type & PORT_TYPE_SATA) { | ||
1111 | u32 tmp = mvs_read_port_irq_mask(mvi, | ||
1112 | port_no); | ||
1113 | tmp &= ~PHYEV_SIG_FIS; | ||
1114 | mvs_write_port_irq_mask(mvi, | ||
1115 | port_no, tmp); | ||
1116 | } | ||
1117 | |||
1118 | mvs_update_phyinfo(mvi, port_no, 0); | ||
1119 | sas_ha->notify_phy_event(sas_phy, | ||
1120 | PHYE_OOB_DONE); | ||
1121 | mvs_bytes_dmaed(mvi, port_no); | ||
1122 | } else { | ||
1123 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
1124 | "plugin interrupt but phy is gone\n"); | ||
1125 | mvs_phy_control(sas_phy, PHY_FUNC_LINK_RESET, | ||
1126 | NULL); | ||
1127 | } | ||
1128 | } else if (phy->irq_status & PHYEV_BROAD_CH) | ||
1129 | sas_ha->notify_port_event(sas_phy, | ||
1130 | PORTE_BROADCAST_RCVD); | ||
1131 | } | ||
1132 | mvs_write_port_irq_stat(mvi, port_no, phy->irq_status); | ||
1133 | } | ||
1134 | |||
1135 | static void mvs_int_sata(struct mvs_info *mvi) | ||
1136 | { | ||
1137 | /* FIXME */ | ||
1138 | } | ||
1139 | |||
1140 | static void mvs_slot_free(struct mvs_info *mvi, struct sas_task *task, | ||
1141 | struct mvs_slot_info *slot, u32 slot_idx) | ||
1142 | { | ||
1143 | if (!sas_protocol_ata(task->task_proto)) | ||
1144 | if (slot->n_elem) | ||
1145 | pci_unmap_sg(mvi->pdev, task->scatter, | ||
1146 | slot->n_elem, task->data_dir); | ||
1147 | |||
1148 | switch (task->task_proto) { | ||
1149 | case SAS_PROTOCOL_SMP: | ||
1150 | pci_unmap_sg(mvi->pdev, &task->smp_task.smp_resp, 1, | ||
1151 | PCI_DMA_FROMDEVICE); | ||
1152 | pci_unmap_sg(mvi->pdev, &task->smp_task.smp_req, 1, | ||
1153 | PCI_DMA_TODEVICE); | ||
1154 | break; | ||
1155 | |||
1156 | case SAS_PROTOCOL_SATA: | ||
1157 | case SAS_PROTOCOL_STP: | ||
1158 | case SAS_PROTOCOL_SSP: | ||
1159 | default: | ||
1160 | /* do nothing */ | ||
1161 | break; | ||
1162 | } | ||
1163 | |||
1164 | slot->task = NULL; | ||
1165 | mvs_tag_clear(mvi, slot_idx); | ||
1166 | } | ||
1167 | |||
1168 | static void mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, | ||
1169 | u32 slot_idx) | ||
1170 | { | ||
1171 | struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; | ||
1172 | u64 err_dw0 = *(u32 *) slot->response; | ||
1173 | void __iomem *regs = mvi->regs; | ||
1174 | u32 tmp; | ||
1175 | |||
1176 | if (err_dw0 & CMD_ISS_STPD) | ||
1177 | if (sas_protocol_ata(task->task_proto)) { | ||
1178 | tmp = mr32(INT_STAT_SRS); | ||
1179 | mw32(INT_STAT_SRS, tmp & 0xFFFF); | ||
1180 | } | ||
1181 | |||
1182 | mvs_hba_sb_dump(mvi, slot_idx, task->task_proto); | ||
1183 | } | ||
1184 | |||
1185 | static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc) | ||
1186 | { | ||
1187 | u32 slot_idx = rx_desc & RXQ_SLOT_MASK; | ||
1188 | struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; | ||
1189 | struct sas_task *task = slot->task; | ||
1190 | struct task_status_struct *tstat = &task->task_status; | ||
1191 | struct mvs_port *port = &mvi->port[task->dev->port->id]; | ||
1192 | bool aborted; | ||
1193 | void *to; | ||
1194 | |||
1195 | spin_lock(&task->task_state_lock); | ||
1196 | aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED; | ||
1197 | if (!aborted) { | ||
1198 | task->task_state_flags &= | ||
1199 | ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); | ||
1200 | task->task_state_flags |= SAS_TASK_STATE_DONE; | ||
1201 | } | ||
1202 | spin_unlock(&task->task_state_lock); | ||
1203 | |||
1204 | if (aborted) | ||
1205 | return -1; | ||
1206 | |||
1207 | memset(tstat, 0, sizeof(*tstat)); | ||
1208 | tstat->resp = SAS_TASK_COMPLETE; | ||
1209 | |||
1210 | |||
1211 | if (unlikely(!port->port_attached)) { | ||
1212 | tstat->stat = SAS_PHY_DOWN; | ||
1213 | goto out; | ||
1214 | } | ||
1215 | |||
1216 | /* error info record present */ | ||
1217 | if ((rx_desc & RXQ_ERR) && (*(u64 *) slot->response)) { | ||
1218 | tstat->stat = SAM_CHECK_COND; | ||
1219 | mvs_slot_err(mvi, task, slot_idx); | ||
1220 | goto out; | ||
1221 | } | ||
1222 | |||
1223 | switch (task->task_proto) { | ||
1224 | case SAS_PROTOCOL_SSP: | ||
1225 | /* hw says status == 0, datapres == 0 */ | ||
1226 | if (rx_desc & RXQ_GOOD) { | ||
1227 | tstat->stat = SAM_GOOD; | ||
1228 | tstat->resp = SAS_TASK_COMPLETE; | ||
1229 | } | ||
1230 | /* response frame present */ | ||
1231 | else if (rx_desc & RXQ_RSP) { | ||
1232 | struct ssp_response_iu *iu = | ||
1233 | slot->response + sizeof(struct mvs_err_info); | ||
1234 | sas_ssp_task_response(&mvi->pdev->dev, task, iu); | ||
1235 | } | ||
1236 | |||
1237 | /* should never happen? */ | ||
1238 | else | ||
1239 | tstat->stat = SAM_CHECK_COND; | ||
1240 | break; | ||
1241 | |||
1242 | case SAS_PROTOCOL_SMP: { | ||
1243 | struct scatterlist *sg_resp = &task->smp_task.smp_resp; | ||
1244 | tstat->stat = SAM_GOOD; | ||
1245 | to = kmap_atomic(sg_page(sg_resp), KM_IRQ0); | ||
1246 | memcpy(to + sg_resp->offset, | ||
1247 | slot->response + sizeof(struct mvs_err_info), | ||
1248 | sg_dma_len(sg_resp)); | ||
1249 | kunmap_atomic(to, KM_IRQ0); | ||
1250 | break; | ||
1251 | } | ||
1252 | |||
1253 | case SAS_PROTOCOL_SATA: | ||
1254 | case SAS_PROTOCOL_STP: | ||
1255 | case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: { | ||
1256 | struct ata_task_resp *resp = | ||
1257 | (struct ata_task_resp *)tstat->buf; | ||
1258 | |||
1259 | if ((rx_desc & (RXQ_DONE | RXQ_ERR | RXQ_ATTN)) == | ||
1260 | RXQ_DONE) | ||
1261 | tstat->stat = SAM_GOOD; | ||
1262 | else | ||
1263 | tstat->stat = SAM_CHECK_COND; | ||
1264 | |||
1265 | resp->frame_len = sizeof(struct dev_to_host_fis); | ||
1266 | memcpy(&resp->ending_fis[0], | ||
1267 | SATA_RECEIVED_D2H_FIS(port->taskfileset), | ||
1268 | sizeof(struct dev_to_host_fis)); | ||
1269 | if (resp->ending_fis[2] & ATA_ERR) | ||
1270 | mvs_hexdump(16, resp->ending_fis, 0); | ||
1271 | break; | ||
1272 | } | ||
1273 | |||
1274 | default: | ||
1275 | tstat->stat = SAM_CHECK_COND; | ||
1276 | break; | ||
1277 | } | ||
1278 | |||
1279 | out: | ||
1280 | mvs_slot_free(mvi, task, slot, slot_idx); | ||
1281 | task->task_done(task); | ||
1282 | return tstat->stat; | ||
1283 | } | ||
1284 | |||
1285 | static void mvs_int_full(struct mvs_info *mvi) | ||
1286 | { | ||
1287 | void __iomem *regs = mvi->regs; | ||
1288 | u32 tmp, stat; | ||
1289 | int i; | ||
1290 | |||
1291 | stat = mr32(INT_STAT); | ||
1292 | |||
1293 | mvs_int_rx(mvi, false); | ||
1294 | |||
1295 | for (i = 0; i < MVS_MAX_PORTS; i++) { | ||
1296 | tmp = (stat >> i) & (CINT_PORT | CINT_PORT_STOPPED); | ||
1297 | if (tmp) | ||
1298 | mvs_int_port(mvi, i, tmp); | ||
1299 | } | ||
1300 | |||
1301 | if (stat & CINT_SRS) | ||
1302 | mvs_int_sata(mvi); | ||
1303 | |||
1304 | mw32(INT_STAT, stat); | ||
1305 | } | ||
1306 | |||
1307 | static int mvs_int_rx(struct mvs_info *mvi, bool self_clear) | ||
1308 | { | ||
1309 | void __iomem *regs = mvi->regs; | ||
1310 | u32 rx_prod_idx, rx_desc; | ||
1311 | bool attn = false; | ||
1312 | struct pci_dev *pdev = mvi->pdev; | ||
1313 | |||
1314 | /* the first dword in the RX ring is special: it contains | ||
1315 | * a mirror of the hardware's RX producer index, so that | ||
1316 | * we don't have to stall the CPU reading that register. | ||
1317 | * The actual RX ring is offset by one dword, due to this. | ||
1318 | */ | ||
1319 | rx_prod_idx = mr32(RX_CONS_IDX) & RX_RING_SZ_MASK; | ||
1320 | if (rx_prod_idx == 0xfff) { /* h/w hasn't touched RX ring yet */ | ||
1321 | mvi->rx_cons = 0xfff; | ||
1322 | return 0; | ||
1323 | } | ||
1324 | |||
1325 | /* The CMPL_Q may come late, read from register and try again | ||
1326 | * note: if coalescing is enabled, | ||
1327 | * it will need to read from register every time for sure | ||
1328 | */ | ||
1329 | if (mvi->rx_cons == rx_prod_idx) | ||
1330 | return 0; | ||
1331 | |||
1332 | if (mvi->rx_cons == 0xfff) | ||
1333 | mvi->rx_cons = MVS_RX_RING_SZ - 1; | ||
1334 | |||
1335 | while (mvi->rx_cons != rx_prod_idx) { | ||
1336 | |||
1337 | /* increment our internal RX consumer pointer */ | ||
1338 | mvi->rx_cons = (mvi->rx_cons + 1) & (MVS_RX_RING_SZ - 1); | ||
1339 | |||
1340 | rx_desc = le32_to_cpu(mvi->rx[mvi->rx_cons + 1]); | ||
1341 | |||
1342 | mvs_hba_cq_dump(mvi); | ||
1343 | |||
1344 | if (unlikely(rx_desc & RXQ_DONE)) | ||
1345 | mvs_slot_complete(mvi, rx_desc); | ||
1346 | if (rx_desc & RXQ_ATTN) { | ||
1347 | attn = true; | ||
1348 | dev_printk(KERN_DEBUG, &pdev->dev, "ATTN %X\n", | ||
1349 | rx_desc); | ||
1350 | } else if (rx_desc & RXQ_ERR) { | ||
1351 | dev_printk(KERN_DEBUG, &pdev->dev, "RXQ_ERR %X\n", | ||
1352 | rx_desc); | ||
1353 | } | ||
1354 | } | ||
1355 | |||
1356 | if (attn && self_clear) | ||
1357 | mvs_int_full(mvi); | ||
1358 | |||
1359 | return 0; | ||
1360 | } | ||
1361 | |||
1362 | static irqreturn_t mvs_interrupt(int irq, void *opaque) | ||
1363 | { | ||
1364 | struct mvs_info *mvi = opaque; | ||
1365 | void __iomem *regs = mvi->regs; | ||
1366 | u32 stat; | ||
1367 | |||
1368 | stat = mr32(GBL_INT_STAT); | ||
1369 | |||
1370 | /* clear CMD_CMPLT ASAP */ | ||
1371 | mw32_f(INT_STAT, CINT_DONE); | ||
1372 | |||
1373 | if (stat == 0 || stat == 0xffffffff) | ||
1374 | return IRQ_NONE; | ||
1375 | |||
1376 | spin_lock(&mvi->lock); | ||
1377 | |||
1378 | mvs_int_full(mvi); | ||
1379 | |||
1380 | spin_unlock(&mvi->lock); | ||
1381 | |||
1382 | return IRQ_HANDLED; | ||
1383 | } | ||
1384 | |||
1385 | #ifndef MVS_DISABLE_MSI | ||
1386 | static irqreturn_t mvs_msi_interrupt(int irq, void *opaque) | ||
1387 | { | ||
1388 | struct mvs_info *mvi = opaque; | ||
1389 | |||
1390 | spin_lock(&mvi->lock); | ||
1391 | |||
1392 | mvs_int_rx(mvi, true); | ||
1393 | |||
1394 | spin_unlock(&mvi->lock); | ||
1395 | |||
1396 | return IRQ_HANDLED; | ||
1397 | } | ||
1398 | #endif | ||
1399 | |||
1400 | struct mvs_task_exec_info { | ||
1401 | struct sas_task *task; | ||
1402 | struct mvs_cmd_hdr *hdr; | ||
1403 | struct mvs_port *port; | ||
1404 | u32 tag; | ||
1405 | int n_elem; | ||
1406 | }; | ||
1407 | |||
1408 | static int mvs_task_prep_smp(struct mvs_info *mvi, | ||
1409 | struct mvs_task_exec_info *tei) | ||
1410 | { | ||
1411 | int elem, rc, i; | ||
1412 | struct sas_task *task = tei->task; | ||
1413 | struct mvs_cmd_hdr *hdr = tei->hdr; | ||
1414 | struct scatterlist *sg_req, *sg_resp; | ||
1415 | u32 req_len, resp_len, tag = tei->tag; | ||
1416 | void *buf_tmp; | ||
1417 | u8 *buf_oaf; | ||
1418 | dma_addr_t buf_tmp_dma; | ||
1419 | struct mvs_prd *buf_prd; | ||
1420 | struct scatterlist *sg; | ||
1421 | struct mvs_slot_info *slot = &mvi->slot_info[tag]; | ||
1422 | struct asd_sas_port *sas_port = task->dev->port; | ||
1423 | u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); | ||
1424 | #if _MV_DUMP | ||
1425 | u8 *buf_cmd; | ||
1426 | void *from; | ||
1427 | #endif | ||
1428 | /* | ||
1429 | * DMA-map SMP request, response buffers | ||
1430 | */ | ||
1431 | sg_req = &task->smp_task.smp_req; | ||
1432 | elem = pci_map_sg(mvi->pdev, sg_req, 1, PCI_DMA_TODEVICE); | ||
1433 | if (!elem) | ||
1434 | return -ENOMEM; | ||
1435 | req_len = sg_dma_len(sg_req); | ||
1436 | |||
1437 | sg_resp = &task->smp_task.smp_resp; | ||
1438 | elem = pci_map_sg(mvi->pdev, sg_resp, 1, PCI_DMA_FROMDEVICE); | ||
1439 | if (!elem) { | ||
1440 | rc = -ENOMEM; | ||
1441 | goto err_out; | ||
1442 | } | ||
1443 | resp_len = sg_dma_len(sg_resp); | ||
1444 | |||
1445 | /* must be in dwords */ | ||
1446 | if ((req_len & 0x3) || (resp_len & 0x3)) { | ||
1447 | rc = -EINVAL; | ||
1448 | goto err_out_2; | ||
1449 | } | ||
1450 | |||
1451 | /* | ||
1452 | * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs | ||
1453 | */ | ||
1454 | |||
1455 | /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */ | ||
1456 | buf_tmp = slot->buf; | ||
1457 | buf_tmp_dma = slot->buf_dma; | ||
1458 | |||
1459 | #if _MV_DUMP | ||
1460 | buf_cmd = buf_tmp; | ||
1461 | hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); | ||
1462 | buf_tmp += req_len; | ||
1463 | buf_tmp_dma += req_len; | ||
1464 | slot->cmd_size = req_len; | ||
1465 | #else | ||
1466 | hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req)); | ||
1467 | #endif | ||
1468 | |||
1469 | /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ | ||
1470 | buf_oaf = buf_tmp; | ||
1471 | hdr->open_frame = cpu_to_le64(buf_tmp_dma); | ||
1472 | |||
1473 | buf_tmp += MVS_OAF_SZ; | ||
1474 | buf_tmp_dma += MVS_OAF_SZ; | ||
1475 | |||
1476 | /* region 3: PRD table ********************************************* */ | ||
1477 | buf_prd = buf_tmp; | ||
1478 | if (tei->n_elem) | ||
1479 | hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); | ||
1480 | else | ||
1481 | hdr->prd_tbl = 0; | ||
1482 | |||
1483 | i = sizeof(struct mvs_prd) * tei->n_elem; | ||
1484 | buf_tmp += i; | ||
1485 | buf_tmp_dma += i; | ||
1486 | |||
1487 | /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ | ||
1488 | slot->response = buf_tmp; | ||
1489 | hdr->status_buf = cpu_to_le64(buf_tmp_dma); | ||
1490 | |||
1491 | /* | ||
1492 | * Fill in TX ring and command slot header | ||
1493 | */ | ||
1494 | slot->tx = mvi->tx_prod; | ||
1495 | mvi->tx[mvi->tx_prod] = cpu_to_le32((TXQ_CMD_SMP << TXQ_CMD_SHIFT) | | ||
1496 | TXQ_MODE_I | tag | | ||
1497 | (sas_port->phy_mask << TXQ_PHY_SHIFT)); | ||
1498 | |||
1499 | hdr->flags |= flags; | ||
1500 | hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | ((req_len - 4) / 4)); | ||
1501 | hdr->tags = cpu_to_le32(tag); | ||
1502 | hdr->data_len = 0; | ||
1503 | |||
1504 | /* generate open address frame hdr (first 12 bytes) */ | ||
1505 | buf_oaf[0] = (1 << 7) | (0 << 4) | 0x01; /* initiator, SMP, ftype 1h */ | ||
1506 | buf_oaf[1] = task->dev->linkrate & 0xf; | ||
1507 | *(u16 *)(buf_oaf + 2) = 0xFFFF; /* SAS SPEC */ | ||
1508 | memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE); | ||
1509 | |||
1510 | /* fill in PRD (scatter/gather) table, if any */ | ||
1511 | for_each_sg(task->scatter, sg, tei->n_elem, i) { | ||
1512 | buf_prd->addr = cpu_to_le64(sg_dma_address(sg)); | ||
1513 | buf_prd->len = cpu_to_le32(sg_dma_len(sg)); | ||
1514 | buf_prd++; | ||
1515 | } | ||
1516 | |||
1517 | #if _MV_DUMP | ||
1518 | /* copy cmd table */ | ||
1519 | from = kmap_atomic(sg_page(sg_req), KM_IRQ0); | ||
1520 | memcpy(buf_cmd, from + sg_req->offset, req_len); | ||
1521 | kunmap_atomic(from, KM_IRQ0); | ||
1522 | #endif | ||
1523 | return 0; | ||
1524 | |||
1525 | err_out_2: | ||
1526 | pci_unmap_sg(mvi->pdev, &tei->task->smp_task.smp_resp, 1, | ||
1527 | PCI_DMA_FROMDEVICE); | ||
1528 | err_out: | ||
1529 | pci_unmap_sg(mvi->pdev, &tei->task->smp_task.smp_req, 1, | ||
1530 | PCI_DMA_TODEVICE); | ||
1531 | return rc; | ||
1532 | } | ||
1533 | |||
1534 | static void mvs_free_reg_set(struct mvs_info *mvi, struct mvs_port *port) | ||
1535 | { | ||
1536 | void __iomem *regs = mvi->regs; | ||
1537 | u32 tmp, offs; | ||
1538 | u8 *tfs = &port->taskfileset; | ||
1539 | |||
1540 | if (*tfs == MVS_ID_NOT_MAPPED) | ||
1541 | return; | ||
1542 | |||
1543 | offs = 1U << ((*tfs & 0x0f) + PCS_EN_SATA_REG_SHIFT); | ||
1544 | if (*tfs < 16) { | ||
1545 | tmp = mr32(PCS); | ||
1546 | mw32(PCS, tmp & ~offs); | ||
1547 | } else { | ||
1548 | tmp = mr32(CTL); | ||
1549 | mw32(CTL, tmp & ~offs); | ||
1550 | } | ||
1551 | |||
1552 | tmp = mr32(INT_STAT_SRS) & (1U << *tfs); | ||
1553 | if (tmp) | ||
1554 | mw32(INT_STAT_SRS, tmp); | ||
1555 | |||
1556 | *tfs = MVS_ID_NOT_MAPPED; | ||
1557 | } | ||
1558 | |||
1559 | static u8 mvs_assign_reg_set(struct mvs_info *mvi, struct mvs_port *port) | ||
1560 | { | ||
1561 | int i; | ||
1562 | u32 tmp, offs; | ||
1563 | void __iomem *regs = mvi->regs; | ||
1564 | |||
1565 | if (port->taskfileset != MVS_ID_NOT_MAPPED) | ||
1566 | return 0; | ||
1567 | |||
1568 | tmp = mr32(PCS); | ||
1569 | |||
1570 | for (i = 0; i < mvi->chip->srs_sz; i++) { | ||
1571 | if (i == 16) | ||
1572 | tmp = mr32(CTL); | ||
1573 | offs = 1U << ((i & 0x0f) + PCS_EN_SATA_REG_SHIFT); | ||
1574 | if (!(tmp & offs)) { | ||
1575 | port->taskfileset = i; | ||
1576 | |||
1577 | if (i < 16) | ||
1578 | mw32(PCS, tmp | offs); | ||
1579 | else | ||
1580 | mw32(CTL, tmp | offs); | ||
1581 | tmp = mr32(INT_STAT_SRS) & (1U << i); | ||
1582 | if (tmp) | ||
1583 | mw32(INT_STAT_SRS, tmp); | ||
1584 | return 0; | ||
1585 | } | ||
1586 | } | ||
1587 | return MVS_ID_NOT_MAPPED; | ||
1588 | } | ||
1589 | |||
1590 | static u32 mvs_get_ncq_tag(struct sas_task *task) | ||
1591 | { | ||
1592 | u32 tag = 0; | ||
1593 | struct ata_queued_cmd *qc = task->uldd_task; | ||
1594 | |||
1595 | if (qc) | ||
1596 | tag = qc->tag; | ||
1597 | |||
1598 | return tag; | ||
1599 | } | ||
1600 | |||
1601 | static int mvs_task_prep_ata(struct mvs_info *mvi, | ||
1602 | struct mvs_task_exec_info *tei) | ||
1603 | { | ||
1604 | struct sas_task *task = tei->task; | ||
1605 | struct domain_device *dev = task->dev; | ||
1606 | struct mvs_cmd_hdr *hdr = tei->hdr; | ||
1607 | struct asd_sas_port *sas_port = dev->port; | ||
1608 | struct mvs_slot_info *slot; | ||
1609 | struct scatterlist *sg; | ||
1610 | struct mvs_prd *buf_prd; | ||
1611 | struct mvs_port *port = tei->port; | ||
1612 | u32 tag = tei->tag; | ||
1613 | u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); | ||
1614 | void *buf_tmp; | ||
1615 | u8 *buf_cmd, *buf_oaf; | ||
1616 | dma_addr_t buf_tmp_dma; | ||
1617 | u32 i, req_len, resp_len; | ||
1618 | const u32 max_resp_len = SB_RFB_MAX; | ||
1619 | |||
1620 | if (mvs_assign_reg_set(mvi, port) == MVS_ID_NOT_MAPPED) | ||
1621 | return -EBUSY; | ||
1622 | |||
1623 | slot = &mvi->slot_info[tag]; | ||
1624 | slot->tx = mvi->tx_prod; | ||
1625 | mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag | | ||
1626 | (TXQ_CMD_STP << TXQ_CMD_SHIFT) | | ||
1627 | (sas_port->phy_mask << TXQ_PHY_SHIFT) | | ||
1628 | (port->taskfileset << TXQ_SRS_SHIFT)); | ||
1629 | |||
1630 | if (task->ata_task.use_ncq) | ||
1631 | flags |= MCH_FPDMA; | ||
1632 | if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) { | ||
1633 | if (task->ata_task.fis.command != ATA_CMD_ID_ATAPI) | ||
1634 | flags |= MCH_ATAPI; | ||
1635 | } | ||
1636 | |||
1637 | /* FIXME: fill in port multiplier number */ | ||
1638 | |||
1639 | hdr->flags = cpu_to_le32(flags); | ||
1640 | |||
1641 | /* FIXME: the low order order 5 bits for the TAG if enable NCQ */ | ||
1642 | if (task->ata_task.use_ncq) { | ||
1643 | hdr->tags = cpu_to_le32(mvs_get_ncq_tag(task)); | ||
1644 | /*Fill in task file */ | ||
1645 | task->ata_task.fis.sector_count = hdr->tags << 3; | ||
1646 | } else | ||
1647 | hdr->tags = cpu_to_le32(tag); | ||
1648 | hdr->data_len = cpu_to_le32(task->total_xfer_len); | ||
1649 | |||
1650 | /* | ||
1651 | * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs | ||
1652 | */ | ||
1653 | |||
1654 | /* region 1: command table area (MVS_ATA_CMD_SZ bytes) ************** */ | ||
1655 | buf_cmd = buf_tmp = slot->buf; | ||
1656 | buf_tmp_dma = slot->buf_dma; | ||
1657 | |||
1658 | hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); | ||
1659 | |||
1660 | buf_tmp += MVS_ATA_CMD_SZ; | ||
1661 | buf_tmp_dma += MVS_ATA_CMD_SZ; | ||
1662 | #if _MV_DUMP | ||
1663 | slot->cmd_size = MVS_ATA_CMD_SZ; | ||
1664 | #endif | ||
1665 | |||
1666 | /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ | ||
1667 | /* used for STP. unused for SATA? */ | ||
1668 | buf_oaf = buf_tmp; | ||
1669 | hdr->open_frame = cpu_to_le64(buf_tmp_dma); | ||
1670 | |||
1671 | buf_tmp += MVS_OAF_SZ; | ||
1672 | buf_tmp_dma += MVS_OAF_SZ; | ||
1673 | |||
1674 | /* region 3: PRD table ********************************************* */ | ||
1675 | buf_prd = buf_tmp; | ||
1676 | if (tei->n_elem) | ||
1677 | hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); | ||
1678 | else | ||
1679 | hdr->prd_tbl = 0; | ||
1680 | |||
1681 | i = sizeof(struct mvs_prd) * tei->n_elem; | ||
1682 | buf_tmp += i; | ||
1683 | buf_tmp_dma += i; | ||
1684 | |||
1685 | /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ | ||
1686 | /* FIXME: probably unused, for SATA. kept here just in case | ||
1687 | * we get a STP/SATA error information record | ||
1688 | */ | ||
1689 | slot->response = buf_tmp; | ||
1690 | hdr->status_buf = cpu_to_le64(buf_tmp_dma); | ||
1691 | |||
1692 | req_len = sizeof(struct host_to_dev_fis); | ||
1693 | resp_len = MVS_SLOT_BUF_SZ - MVS_ATA_CMD_SZ - | ||
1694 | sizeof(struct mvs_err_info) - i; | ||
1695 | |||
1696 | /* request, response lengths */ | ||
1697 | resp_len = min(resp_len, max_resp_len); | ||
1698 | hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4)); | ||
1699 | |||
1700 | task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */ | ||
1701 | /* fill in command FIS and ATAPI CDB */ | ||
1702 | memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis)); | ||
1703 | if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) | ||
1704 | memcpy(buf_cmd + STP_ATAPI_CMD, | ||
1705 | task->ata_task.atapi_packet, 16); | ||
1706 | |||
1707 | /* generate open address frame hdr (first 12 bytes) */ | ||
1708 | buf_oaf[0] = (1 << 7) | (2 << 4) | 0x1; /* initiator, STP, ftype 1h */ | ||
1709 | buf_oaf[1] = task->dev->linkrate & 0xf; | ||
1710 | *(u16 *)(buf_oaf + 2) = cpu_to_be16(tag); | ||
1711 | memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE); | ||
1712 | |||
1713 | /* fill in PRD (scatter/gather) table, if any */ | ||
1714 | for_each_sg(task->scatter, sg, tei->n_elem, i) { | ||
1715 | buf_prd->addr = cpu_to_le64(sg_dma_address(sg)); | ||
1716 | buf_prd->len = cpu_to_le32(sg_dma_len(sg)); | ||
1717 | buf_prd++; | ||
1718 | } | ||
1719 | |||
1720 | return 0; | ||
1721 | } | ||
1722 | |||
1723 | static int mvs_task_prep_ssp(struct mvs_info *mvi, | ||
1724 | struct mvs_task_exec_info *tei) | ||
1725 | { | ||
1726 | struct sas_task *task = tei->task; | ||
1727 | struct mvs_cmd_hdr *hdr = tei->hdr; | ||
1728 | struct mvs_port *port = tei->port; | ||
1729 | struct mvs_slot_info *slot; | ||
1730 | struct scatterlist *sg; | ||
1731 | struct mvs_prd *buf_prd; | ||
1732 | struct ssp_frame_hdr *ssp_hdr; | ||
1733 | void *buf_tmp; | ||
1734 | u8 *buf_cmd, *buf_oaf, fburst = 0; | ||
1735 | dma_addr_t buf_tmp_dma; | ||
1736 | u32 flags; | ||
1737 | u32 resp_len, req_len, i, tag = tei->tag; | ||
1738 | const u32 max_resp_len = SB_RFB_MAX; | ||
1739 | |||
1740 | slot = &mvi->slot_info[tag]; | ||
1741 | |||
1742 | slot->tx = mvi->tx_prod; | ||
1743 | mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag | | ||
1744 | (TXQ_CMD_SSP << TXQ_CMD_SHIFT) | | ||
1745 | (port->wide_port_phymap << TXQ_PHY_SHIFT)); | ||
1746 | |||
1747 | flags = MCH_RETRY; | ||
1748 | if (task->ssp_task.enable_first_burst) { | ||
1749 | flags |= MCH_FBURST; | ||
1750 | fburst = (1 << 7); | ||
1751 | } | ||
1752 | hdr->flags = cpu_to_le32(flags | | ||
1753 | (tei->n_elem << MCH_PRD_LEN_SHIFT) | | ||
1754 | (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT)); | ||
1755 | |||
1756 | hdr->tags = cpu_to_le32(tag); | ||
1757 | hdr->data_len = cpu_to_le32(task->total_xfer_len); | ||
1758 | |||
1759 | /* | ||
1760 | * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs | ||
1761 | */ | ||
1762 | |||
1763 | /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */ | ||
1764 | buf_cmd = buf_tmp = slot->buf; | ||
1765 | buf_tmp_dma = slot->buf_dma; | ||
1766 | |||
1767 | hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); | ||
1768 | |||
1769 | buf_tmp += MVS_SSP_CMD_SZ; | ||
1770 | buf_tmp_dma += MVS_SSP_CMD_SZ; | ||
1771 | #if _MV_DUMP | ||
1772 | slot->cmd_size = MVS_SSP_CMD_SZ; | ||
1773 | #endif | ||
1774 | |||
1775 | /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ | ||
1776 | buf_oaf = buf_tmp; | ||
1777 | hdr->open_frame = cpu_to_le64(buf_tmp_dma); | ||
1778 | |||
1779 | buf_tmp += MVS_OAF_SZ; | ||
1780 | buf_tmp_dma += MVS_OAF_SZ; | ||
1781 | |||
1782 | /* region 3: PRD table ********************************************* */ | ||
1783 | buf_prd = buf_tmp; | ||
1784 | if (tei->n_elem) | ||
1785 | hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); | ||
1786 | else | ||
1787 | hdr->prd_tbl = 0; | ||
1788 | |||
1789 | i = sizeof(struct mvs_prd) * tei->n_elem; | ||
1790 | buf_tmp += i; | ||
1791 | buf_tmp_dma += i; | ||
1792 | |||
1793 | /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ | ||
1794 | slot->response = buf_tmp; | ||
1795 | hdr->status_buf = cpu_to_le64(buf_tmp_dma); | ||
1796 | |||
1797 | resp_len = MVS_SLOT_BUF_SZ - MVS_SSP_CMD_SZ - MVS_OAF_SZ - | ||
1798 | sizeof(struct mvs_err_info) - i; | ||
1799 | resp_len = min(resp_len, max_resp_len); | ||
1800 | |||
1801 | req_len = sizeof(struct ssp_frame_hdr) + 28; | ||
1802 | |||
1803 | /* request, response lengths */ | ||
1804 | hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4)); | ||
1805 | |||
1806 | /* generate open address frame hdr (first 12 bytes) */ | ||
1807 | buf_oaf[0] = (1 << 7) | (1 << 4) | 0x1; /* initiator, SSP, ftype 1h */ | ||
1808 | buf_oaf[1] = task->dev->linkrate & 0xf; | ||
1809 | *(u16 *)(buf_oaf + 2) = cpu_to_be16(tag); | ||
1810 | memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE); | ||
1811 | |||
1812 | /* fill in SSP frame header (Command Table.SSP frame header) */ | ||
1813 | ssp_hdr = (struct ssp_frame_hdr *)buf_cmd; | ||
1814 | ssp_hdr->frame_type = SSP_COMMAND; | ||
1815 | memcpy(ssp_hdr->hashed_dest_addr, task->dev->hashed_sas_addr, | ||
1816 | HASHED_SAS_ADDR_SIZE); | ||
1817 | memcpy(ssp_hdr->hashed_src_addr, | ||
1818 | task->dev->port->ha->hashed_sas_addr, HASHED_SAS_ADDR_SIZE); | ||
1819 | ssp_hdr->tag = cpu_to_be16(tag); | ||
1820 | |||
1821 | /* fill in command frame IU */ | ||
1822 | buf_cmd += sizeof(*ssp_hdr); | ||
1823 | memcpy(buf_cmd, &task->ssp_task.LUN, 8); | ||
1824 | buf_cmd[9] = fburst | task->ssp_task.task_attr | | ||
1825 | (task->ssp_task.task_prio << 3); | ||
1826 | memcpy(buf_cmd + 12, &task->ssp_task.cdb, 16); | ||
1827 | |||
1828 | /* fill in PRD (scatter/gather) table, if any */ | ||
1829 | for_each_sg(task->scatter, sg, tei->n_elem, i) { | ||
1830 | buf_prd->addr = cpu_to_le64(sg_dma_address(sg)); | ||
1831 | buf_prd->len = cpu_to_le32(sg_dma_len(sg)); | ||
1832 | buf_prd++; | ||
1833 | } | ||
1834 | |||
1835 | return 0; | ||
1836 | } | ||
1837 | |||
1838 | static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags) | ||
1839 | { | ||
1840 | struct domain_device *dev = task->dev; | ||
1841 | struct mvs_info *mvi = dev->port->ha->lldd_ha; | ||
1842 | struct pci_dev *pdev = mvi->pdev; | ||
1843 | void __iomem *regs = mvi->regs; | ||
1844 | struct mvs_task_exec_info tei; | ||
1845 | struct sas_task *t = task; | ||
1846 | u32 tag = 0xdeadbeef, rc, n_elem = 0; | ||
1847 | unsigned long flags; | ||
1848 | u32 n = num, pass = 0; | ||
1849 | |||
1850 | spin_lock_irqsave(&mvi->lock, flags); | ||
1851 | |||
1852 | do { | ||
1853 | tei.port = &mvi->port[dev->port->id]; | ||
1854 | |||
1855 | if (!tei.port->port_attached) { | ||
1856 | struct task_status_struct *ts = &t->task_status; | ||
1857 | ts->stat = SAS_PHY_DOWN; | ||
1858 | t->task_done(t); | ||
1859 | rc = 0; | ||
1860 | goto exec_exit; | ||
1861 | } | ||
1862 | if (!sas_protocol_ata(t->task_proto)) { | ||
1863 | if (t->num_scatter) { | ||
1864 | n_elem = pci_map_sg(mvi->pdev, t->scatter, | ||
1865 | t->num_scatter, | ||
1866 | t->data_dir); | ||
1867 | if (!n_elem) { | ||
1868 | rc = -ENOMEM; | ||
1869 | goto err_out; | ||
1870 | } | ||
1871 | } | ||
1872 | } else { | ||
1873 | n_elem = t->num_scatter; | ||
1874 | } | ||
1875 | |||
1876 | rc = mvs_tag_alloc(mvi, &tag); | ||
1877 | if (rc) | ||
1878 | goto err_out; | ||
1879 | |||
1880 | mvi->slot_info[tag].task = t; | ||
1881 | mvi->slot_info[tag].n_elem = n_elem; | ||
1882 | memset(mvi->slot_info[tag].buf, 0, MVS_SLOT_BUF_SZ); | ||
1883 | tei.task = t; | ||
1884 | tei.hdr = &mvi->slot[tag]; | ||
1885 | tei.tag = tag; | ||
1886 | tei.n_elem = n_elem; | ||
1887 | |||
1888 | switch (t->task_proto) { | ||
1889 | case SAS_PROTOCOL_SMP: | ||
1890 | rc = mvs_task_prep_smp(mvi, &tei); | ||
1891 | break; | ||
1892 | case SAS_PROTOCOL_SSP: | ||
1893 | rc = mvs_task_prep_ssp(mvi, &tei); | ||
1894 | break; | ||
1895 | case SAS_PROTOCOL_SATA: | ||
1896 | case SAS_PROTOCOL_STP: | ||
1897 | case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: | ||
1898 | rc = mvs_task_prep_ata(mvi, &tei); | ||
1899 | break; | ||
1900 | default: | ||
1901 | dev_printk(KERN_ERR, &pdev->dev, | ||
1902 | "unknown sas_task proto: 0x%x\n", | ||
1903 | t->task_proto); | ||
1904 | rc = -EINVAL; | ||
1905 | break; | ||
1906 | } | ||
1907 | |||
1908 | if (rc) | ||
1909 | goto err_out_tag; | ||
1910 | |||
1911 | /* TODO: select normal or high priority */ | ||
1912 | |||
1913 | spin_lock(&t->task_state_lock); | ||
1914 | t->task_state_flags |= SAS_TASK_AT_INITIATOR; | ||
1915 | spin_unlock(&t->task_state_lock); | ||
1916 | |||
1917 | if (n == 1) { | ||
1918 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1919 | mw32(TX_PROD_IDX, mvi->tx_prod); | ||
1920 | } | ||
1921 | mvs_hba_memory_dump(mvi, tag, t->task_proto); | ||
1922 | |||
1923 | ++pass; | ||
1924 | mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); | ||
1925 | |||
1926 | if (n == 1) | ||
1927 | break; | ||
1928 | |||
1929 | t = list_entry(t->list.next, struct sas_task, list); | ||
1930 | } while (--n); | ||
1931 | |||
1932 | return 0; | ||
1933 | |||
1934 | err_out_tag: | ||
1935 | mvs_tag_free(mvi, tag); | ||
1936 | err_out: | ||
1937 | dev_printk(KERN_ERR, &pdev->dev, "mvsas exec failed[%d]!\n", rc); | ||
1938 | if (!sas_protocol_ata(t->task_proto)) | ||
1939 | if (n_elem) | ||
1940 | pci_unmap_sg(mvi->pdev, t->scatter, n_elem, | ||
1941 | t->data_dir); | ||
1942 | exec_exit: | ||
1943 | if (pass) | ||
1944 | mw32(TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); | ||
1945 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1946 | return rc; | ||
1947 | } | ||
1948 | |||
1949 | static int mvs_task_abort(struct sas_task *task) | ||
1950 | { | ||
1951 | int rc = 1; | ||
1952 | unsigned long flags; | ||
1953 | struct mvs_info *mvi = task->dev->port->ha->lldd_ha; | ||
1954 | struct pci_dev *pdev = mvi->pdev; | ||
1955 | |||
1956 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
1957 | if (task->task_state_flags & SAS_TASK_STATE_DONE) { | ||
1958 | rc = TMF_RESP_FUNC_COMPLETE; | ||
1959 | goto out_done; | ||
1960 | } | ||
1961 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
1962 | |||
1963 | /*FIXME*/ | ||
1964 | rc = TMF_RESP_FUNC_COMPLETE; | ||
1965 | |||
1966 | switch (task->task_proto) { | ||
1967 | case SAS_PROTOCOL_SMP: | ||
1968 | dev_printk(KERN_DEBUG, &pdev->dev, "SMP Abort! "); | ||
1969 | break; | ||
1970 | case SAS_PROTOCOL_SSP: | ||
1971 | dev_printk(KERN_DEBUG, &pdev->dev, "SSP Abort! "); | ||
1972 | break; | ||
1973 | case SAS_PROTOCOL_SATA: | ||
1974 | case SAS_PROTOCOL_STP: | ||
1975 | case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:{ | ||
1976 | dev_printk(KERN_DEBUG, &pdev->dev, "STP Abort! " | ||
1977 | "Dump D2H FIS: \n"); | ||
1978 | mvs_hexdump(sizeof(struct host_to_dev_fis), | ||
1979 | (void *)&task->ata_task.fis, 0); | ||
1980 | dev_printk(KERN_DEBUG, &pdev->dev, "Dump ATAPI Cmd : \n"); | ||
1981 | mvs_hexdump(16, task->ata_task.atapi_packet, 0); | ||
1982 | break; | ||
1983 | } | ||
1984 | default: | ||
1985 | break; | ||
1986 | } | ||
1987 | out_done: | ||
1988 | return rc; | ||
1989 | } | ||
1990 | |||
1991 | static void mvs_free(struct mvs_info *mvi) | ||
1992 | { | ||
1993 | int i; | ||
1994 | |||
1995 | if (!mvi) | ||
1996 | return; | ||
1997 | |||
1998 | for (i = 0; i < MVS_SLOTS; i++) { | ||
1999 | struct mvs_slot_info *slot = &mvi->slot_info[i]; | ||
2000 | |||
2001 | if (slot->buf) | ||
2002 | dma_free_coherent(&mvi->pdev->dev, MVS_SLOT_BUF_SZ, | ||
2003 | slot->buf, slot->buf_dma); | ||
2004 | } | ||
2005 | |||
2006 | if (mvi->tx) | ||
2007 | dma_free_coherent(&mvi->pdev->dev, | ||
2008 | sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ, | ||
2009 | mvi->tx, mvi->tx_dma); | ||
2010 | if (mvi->rx_fis) | ||
2011 | dma_free_coherent(&mvi->pdev->dev, MVS_RX_FISL_SZ, | ||
2012 | mvi->rx_fis, mvi->rx_fis_dma); | ||
2013 | if (mvi->rx) | ||
2014 | dma_free_coherent(&mvi->pdev->dev, | ||
2015 | sizeof(*mvi->rx) * MVS_RX_RING_SZ, | ||
2016 | mvi->rx, mvi->rx_dma); | ||
2017 | if (mvi->slot) | ||
2018 | dma_free_coherent(&mvi->pdev->dev, | ||
2019 | sizeof(*mvi->slot) * MVS_SLOTS, | ||
2020 | mvi->slot, mvi->slot_dma); | ||
2021 | #ifdef MVS_ENABLE_PERI | ||
2022 | if (mvi->peri_regs) | ||
2023 | iounmap(mvi->peri_regs); | ||
2024 | #endif | ||
2025 | if (mvi->regs) | ||
2026 | iounmap(mvi->regs); | ||
2027 | if (mvi->shost) | ||
2028 | scsi_host_put(mvi->shost); | ||
2029 | kfree(mvi->sas.sas_port); | ||
2030 | kfree(mvi->sas.sas_phy); | ||
2031 | kfree(mvi); | ||
2032 | } | ||
2033 | |||
2034 | /* FIXME: locking? */ | ||
2035 | static int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | ||
2036 | void *funcdata) | ||
2037 | { | ||
2038 | struct mvs_info *mvi = sas_phy->ha->lldd_ha; | ||
2039 | int rc = 0, phy_id = sas_phy->id; | ||
2040 | u32 tmp; | ||
2041 | |||
2042 | tmp = mvs_read_phy_ctl(mvi, phy_id); | ||
2043 | |||
2044 | switch (func) { | ||
2045 | case PHY_FUNC_SET_LINK_RATE:{ | ||
2046 | struct sas_phy_linkrates *rates = funcdata; | ||
2047 | u32 lrmin = 0, lrmax = 0; | ||
2048 | |||
2049 | lrmin = (rates->minimum_linkrate << 8); | ||
2050 | lrmax = (rates->maximum_linkrate << 12); | ||
2051 | |||
2052 | if (lrmin) { | ||
2053 | tmp &= ~(0xf << 8); | ||
2054 | tmp |= lrmin; | ||
2055 | } | ||
2056 | if (lrmax) { | ||
2057 | tmp &= ~(0xf << 12); | ||
2058 | tmp |= lrmax; | ||
2059 | } | ||
2060 | mvs_write_phy_ctl(mvi, phy_id, tmp); | ||
2061 | break; | ||
2062 | } | ||
2063 | |||
2064 | case PHY_FUNC_HARD_RESET: | ||
2065 | if (tmp & PHY_RST_HARD) | ||
2066 | break; | ||
2067 | mvs_write_phy_ctl(mvi, phy_id, tmp | PHY_RST_HARD); | ||
2068 | break; | ||
2069 | |||
2070 | case PHY_FUNC_LINK_RESET: | ||
2071 | mvs_write_phy_ctl(mvi, phy_id, tmp | PHY_RST); | ||
2072 | break; | ||
2073 | |||
2074 | case PHY_FUNC_DISABLE: | ||
2075 | case PHY_FUNC_RELEASE_SPINUP_HOLD: | ||
2076 | default: | ||
2077 | rc = -EOPNOTSUPP; | ||
2078 | } | ||
2079 | |||
2080 | return rc; | ||
2081 | } | ||
2082 | |||
2083 | static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id) | ||
2084 | { | ||
2085 | struct mvs_phy *phy = &mvi->phy[phy_id]; | ||
2086 | struct asd_sas_phy *sas_phy = &phy->sas_phy; | ||
2087 | |||
2088 | sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0; | ||
2089 | sas_phy->class = SAS; | ||
2090 | sas_phy->iproto = SAS_PROTOCOL_ALL; | ||
2091 | sas_phy->tproto = 0; | ||
2092 | sas_phy->type = PHY_TYPE_PHYSICAL; | ||
2093 | sas_phy->role = PHY_ROLE_INITIATOR; | ||
2094 | sas_phy->oob_mode = OOB_NOT_CONNECTED; | ||
2095 | sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN; | ||
2096 | |||
2097 | sas_phy->id = phy_id; | ||
2098 | sas_phy->sas_addr = &mvi->sas_addr[0]; | ||
2099 | sas_phy->frame_rcvd = &phy->frame_rcvd[0]; | ||
2100 | sas_phy->ha = &mvi->sas; | ||
2101 | sas_phy->lldd_phy = phy; | ||
2102 | } | ||
2103 | |||
2104 | static struct mvs_info *__devinit mvs_alloc(struct pci_dev *pdev, | ||
2105 | const struct pci_device_id *ent) | ||
2106 | { | ||
2107 | struct mvs_info *mvi; | ||
2108 | unsigned long res_start, res_len, res_flag; | ||
2109 | struct asd_sas_phy **arr_phy; | ||
2110 | struct asd_sas_port **arr_port; | ||
2111 | const struct mvs_chip_info *chip = &mvs_chips[ent->driver_data]; | ||
2112 | int i; | ||
2113 | |||
2114 | /* | ||
2115 | * alloc and init our per-HBA mvs_info struct | ||
2116 | */ | ||
2117 | |||
2118 | mvi = kzalloc(sizeof(*mvi), GFP_KERNEL); | ||
2119 | if (!mvi) | ||
2120 | return NULL; | ||
2121 | |||
2122 | spin_lock_init(&mvi->lock); | ||
2123 | mvi->pdev = pdev; | ||
2124 | mvi->chip = chip; | ||
2125 | |||
2126 | if (pdev->device == 0x6440 && pdev->revision == 0) | ||
2127 | mvi->flags |= MVF_PHY_PWR_FIX; | ||
2128 | |||
2129 | /* | ||
2130 | * alloc and init SCSI, SAS glue | ||
2131 | */ | ||
2132 | |||
2133 | mvi->shost = scsi_host_alloc(&mvs_sht, sizeof(void *)); | ||
2134 | if (!mvi->shost) | ||
2135 | goto err_out; | ||
2136 | |||
2137 | arr_phy = kcalloc(MVS_MAX_PHYS, sizeof(void *), GFP_KERNEL); | ||
2138 | arr_port = kcalloc(MVS_MAX_PHYS, sizeof(void *), GFP_KERNEL); | ||
2139 | if (!arr_phy || !arr_port) | ||
2140 | goto err_out; | ||
2141 | |||
2142 | for (i = 0; i < MVS_MAX_PHYS; i++) { | ||
2143 | mvs_phy_init(mvi, i); | ||
2144 | arr_phy[i] = &mvi->phy[i].sas_phy; | ||
2145 | arr_port[i] = &mvi->port[i].sas_port; | ||
2146 | } | ||
2147 | |||
2148 | SHOST_TO_SAS_HA(mvi->shost) = &mvi->sas; | ||
2149 | mvi->shost->transportt = mvs_stt; | ||
2150 | mvi->shost->max_id = 21; | ||
2151 | mvi->shost->max_lun = ~0; | ||
2152 | mvi->shost->max_channel = 0; | ||
2153 | mvi->shost->max_cmd_len = 16; | ||
2154 | |||
2155 | mvi->sas.sas_ha_name = DRV_NAME; | ||
2156 | mvi->sas.dev = &pdev->dev; | ||
2157 | mvi->sas.lldd_module = THIS_MODULE; | ||
2158 | mvi->sas.sas_addr = &mvi->sas_addr[0]; | ||
2159 | mvi->sas.sas_phy = arr_phy; | ||
2160 | mvi->sas.sas_port = arr_port; | ||
2161 | mvi->sas.num_phys = chip->n_phy; | ||
2162 | mvi->sas.lldd_max_execute_num = MVS_CHIP_SLOT_SZ - 1; | ||
2163 | mvi->sas.lldd_queue_size = MVS_QUEUE_SIZE; | ||
2164 | mvi->can_queue = (MVS_CHIP_SLOT_SZ >> 1) - 1; | ||
2165 | mvi->sas.lldd_ha = mvi; | ||
2166 | mvi->sas.core.shost = mvi->shost; | ||
2167 | |||
2168 | mvs_tag_init(mvi); | ||
2169 | |||
2170 | /* | ||
2171 | * ioremap main and peripheral registers | ||
2172 | */ | ||
2173 | |||
2174 | #ifdef MVS_ENABLE_PERI | ||
2175 | res_start = pci_resource_start(pdev, 2); | ||
2176 | res_len = pci_resource_len(pdev, 2); | ||
2177 | if (!res_start || !res_len) | ||
2178 | goto err_out; | ||
2179 | |||
2180 | mvi->peri_regs = ioremap_nocache(res_start, res_len); | ||
2181 | if (!mvi->peri_regs) | ||
2182 | goto err_out; | ||
2183 | #endif | ||
2184 | |||
2185 | res_start = pci_resource_start(pdev, 4); | ||
2186 | res_len = pci_resource_len(pdev, 4); | ||
2187 | if (!res_start || !res_len) | ||
2188 | goto err_out; | ||
2189 | |||
2190 | res_flag = pci_resource_flags(pdev, 4); | ||
2191 | if (res_flag & IORESOURCE_CACHEABLE) | ||
2192 | mvi->regs = ioremap(res_start, res_len); | ||
2193 | else | ||
2194 | mvi->regs = ioremap_nocache(res_start, res_len); | ||
2195 | |||
2196 | if (!mvi->regs) | ||
2197 | goto err_out; | ||
2198 | |||
2199 | /* | ||
2200 | * alloc and init our DMA areas | ||
2201 | */ | ||
2202 | |||
2203 | mvi->tx = dma_alloc_coherent(&pdev->dev, | ||
2204 | sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ, | ||
2205 | &mvi->tx_dma, GFP_KERNEL); | ||
2206 | if (!mvi->tx) | ||
2207 | goto err_out; | ||
2208 | memset(mvi->tx, 0, sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ); | ||
2209 | |||
2210 | mvi->rx_fis = dma_alloc_coherent(&pdev->dev, MVS_RX_FISL_SZ, | ||
2211 | &mvi->rx_fis_dma, GFP_KERNEL); | ||
2212 | if (!mvi->rx_fis) | ||
2213 | goto err_out; | ||
2214 | memset(mvi->rx_fis, 0, MVS_RX_FISL_SZ); | ||
2215 | |||
2216 | mvi->rx = dma_alloc_coherent(&pdev->dev, | ||
2217 | sizeof(*mvi->rx) * MVS_RX_RING_SZ, | ||
2218 | &mvi->rx_dma, GFP_KERNEL); | ||
2219 | if (!mvi->rx) | ||
2220 | goto err_out; | ||
2221 | memset(mvi->rx, 0, sizeof(*mvi->rx) * MVS_RX_RING_SZ); | ||
2222 | |||
2223 | mvi->rx[0] = cpu_to_le32(0xfff); | ||
2224 | mvi->rx_cons = 0xfff; | ||
2225 | |||
2226 | mvi->slot = dma_alloc_coherent(&pdev->dev, | ||
2227 | sizeof(*mvi->slot) * MVS_SLOTS, | ||
2228 | &mvi->slot_dma, GFP_KERNEL); | ||
2229 | if (!mvi->slot) | ||
2230 | goto err_out; | ||
2231 | memset(mvi->slot, 0, sizeof(*mvi->slot) * MVS_SLOTS); | ||
2232 | |||
2233 | for (i = 0; i < MVS_SLOTS; i++) { | ||
2234 | struct mvs_slot_info *slot = &mvi->slot_info[i]; | ||
2235 | |||
2236 | slot->buf = dma_alloc_coherent(&pdev->dev, MVS_SLOT_BUF_SZ, | ||
2237 | &slot->buf_dma, GFP_KERNEL); | ||
2238 | if (!slot->buf) | ||
2239 | goto err_out; | ||
2240 | memset(slot->buf, 0, MVS_SLOT_BUF_SZ); | ||
2241 | } | ||
2242 | |||
2243 | /* finally, read NVRAM to get our SAS address */ | ||
2244 | if (mvs_nvram_read(mvi, NVR_SAS_ADDR, &mvi->sas_addr, 8)) | ||
2245 | goto err_out; | ||
2246 | return mvi; | ||
2247 | |||
2248 | err_out: | ||
2249 | mvs_free(mvi); | ||
2250 | return NULL; | ||
2251 | } | ||
2252 | |||
2253 | static u32 mvs_cr32(void __iomem *regs, u32 addr) | ||
2254 | { | ||
2255 | mw32(CMD_ADDR, addr); | ||
2256 | return mr32(CMD_DATA); | ||
2257 | } | ||
2258 | |||
2259 | static void mvs_cw32(void __iomem *regs, u32 addr, u32 val) | ||
2260 | { | ||
2261 | mw32(CMD_ADDR, addr); | ||
2262 | mw32(CMD_DATA, val); | ||
2263 | } | ||
2264 | |||
2265 | static u32 mvs_read_phy_ctl(struct mvs_info *mvi, u32 port) | ||
2266 | { | ||
2267 | void __iomem *regs = mvi->regs; | ||
2268 | return (port < 4)?mr32(P0_SER_CTLSTAT + port * 4): | ||
2269 | mr32(P4_SER_CTLSTAT + (port - 4) * 4); | ||
2270 | } | ||
2271 | |||
2272 | static void mvs_write_phy_ctl(struct mvs_info *mvi, u32 port, u32 val) | ||
2273 | { | ||
2274 | void __iomem *regs = mvi->regs; | ||
2275 | if (port < 4) | ||
2276 | mw32(P0_SER_CTLSTAT + port * 4, val); | ||
2277 | else | ||
2278 | mw32(P4_SER_CTLSTAT + (port - 4) * 4, val); | ||
2279 | } | ||
2280 | |||
2281 | static u32 mvs_read_port(struct mvs_info *mvi, u32 off, u32 off2, u32 port) | ||
2282 | { | ||
2283 | void __iomem *regs = mvi->regs + off; | ||
2284 | void __iomem *regs2 = mvi->regs + off2; | ||
2285 | return (port < 4)?readl(regs + port * 8): | ||
2286 | readl(regs2 + (port - 4) * 8); | ||
2287 | } | ||
2288 | |||
2289 | static void mvs_write_port(struct mvs_info *mvi, u32 off, u32 off2, | ||
2290 | u32 port, u32 val) | ||
2291 | { | ||
2292 | void __iomem *regs = mvi->regs + off; | ||
2293 | void __iomem *regs2 = mvi->regs + off2; | ||
2294 | if (port < 4) | ||
2295 | writel(val, regs + port * 8); | ||
2296 | else | ||
2297 | writel(val, regs2 + (port - 4) * 8); | ||
2298 | } | ||
2299 | |||
2300 | static u32 mvs_read_port_cfg_data(struct mvs_info *mvi, u32 port) | ||
2301 | { | ||
2302 | return mvs_read_port(mvi, MVS_P0_CFG_DATA, MVS_P4_CFG_DATA, port); | ||
2303 | } | ||
2304 | |||
2305 | static void mvs_write_port_cfg_data(struct mvs_info *mvi, u32 port, u32 val) | ||
2306 | { | ||
2307 | mvs_write_port(mvi, MVS_P0_CFG_DATA, MVS_P4_CFG_DATA, port, val); | ||
2308 | } | ||
2309 | |||
2310 | static void mvs_write_port_cfg_addr(struct mvs_info *mvi, u32 port, u32 addr) | ||
2311 | { | ||
2312 | mvs_write_port(mvi, MVS_P0_CFG_ADDR, MVS_P4_CFG_ADDR, port, addr); | ||
2313 | } | ||
2314 | |||
2315 | static u32 mvs_read_port_vsr_data(struct mvs_info *mvi, u32 port) | ||
2316 | { | ||
2317 | return mvs_read_port(mvi, MVS_P0_VSR_DATA, MVS_P4_VSR_DATA, port); | ||
2318 | } | ||
2319 | |||
2320 | static void mvs_write_port_vsr_data(struct mvs_info *mvi, u32 port, u32 val) | ||
2321 | { | ||
2322 | mvs_write_port(mvi, MVS_P0_VSR_DATA, MVS_P4_VSR_DATA, port, val); | ||
2323 | } | ||
2324 | |||
2325 | static void mvs_write_port_vsr_addr(struct mvs_info *mvi, u32 port, u32 addr) | ||
2326 | { | ||
2327 | mvs_write_port(mvi, MVS_P0_VSR_ADDR, MVS_P4_VSR_ADDR, port, addr); | ||
2328 | } | ||
2329 | |||
2330 | static u32 mvs_read_port_irq_stat(struct mvs_info *mvi, u32 port) | ||
2331 | { | ||
2332 | return mvs_read_port(mvi, MVS_P0_INT_STAT, MVS_P4_INT_STAT, port); | ||
2333 | } | ||
2334 | |||
2335 | static void mvs_write_port_irq_stat(struct mvs_info *mvi, u32 port, u32 val) | ||
2336 | { | ||
2337 | mvs_write_port(mvi, MVS_P0_INT_STAT, MVS_P4_INT_STAT, port, val); | ||
2338 | } | ||
2339 | |||
2340 | static u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port) | ||
2341 | { | ||
2342 | return mvs_read_port(mvi, MVS_P0_INT_MASK, MVS_P4_INT_MASK, port); | ||
2343 | } | ||
2344 | |||
2345 | static void mvs_write_port_irq_mask(struct mvs_info *mvi, u32 port, u32 val) | ||
2346 | { | ||
2347 | mvs_write_port(mvi, MVS_P0_INT_MASK, MVS_P4_INT_MASK, port, val); | ||
2348 | } | ||
2349 | |||
2350 | static void __devinit mvs_phy_hacks(struct mvs_info *mvi) | ||
2351 | { | ||
2352 | void __iomem *regs = mvi->regs; | ||
2353 | u32 tmp; | ||
2354 | |||
2355 | /* workaround for SATA R-ERR, to ignore phy glitch */ | ||
2356 | tmp = mvs_cr32(regs, CMD_PHY_TIMER); | ||
2357 | tmp &= ~(1 << 9); | ||
2358 | tmp |= (1 << 10); | ||
2359 | mvs_cw32(regs, CMD_PHY_TIMER, tmp); | ||
2360 | |||
2361 | /* enable retry 127 times */ | ||
2362 | mvs_cw32(regs, CMD_SAS_CTL1, 0x7f7f); | ||
2363 | |||
2364 | /* extend open frame timeout to max */ | ||
2365 | tmp = mvs_cr32(regs, CMD_SAS_CTL0); | ||
2366 | tmp &= ~0xffff; | ||
2367 | tmp |= 0x3fff; | ||
2368 | mvs_cw32(regs, CMD_SAS_CTL0, tmp); | ||
2369 | |||
2370 | /* workaround for WDTIMEOUT , set to 550 ms */ | ||
2371 | mvs_cw32(regs, CMD_WD_TIMER, 0xffffff); | ||
2372 | |||
2373 | /* not to halt for different port op during wideport link change */ | ||
2374 | mvs_cw32(regs, CMD_APP_ERR_CONFIG, 0xffefbf7d); | ||
2375 | |||
2376 | /* workaround for Seagate disk not-found OOB sequence, recv | ||
2377 | * COMINIT before sending out COMWAKE */ | ||
2378 | tmp = mvs_cr32(regs, CMD_PHY_MODE_21); | ||
2379 | tmp &= 0x0000ffff; | ||
2380 | tmp |= 0x00fa0000; | ||
2381 | mvs_cw32(regs, CMD_PHY_MODE_21, tmp); | ||
2382 | |||
2383 | tmp = mvs_cr32(regs, CMD_PHY_TIMER); | ||
2384 | tmp &= 0x1fffffff; | ||
2385 | tmp |= (2U << 29); /* 8 ms retry */ | ||
2386 | mvs_cw32(regs, CMD_PHY_TIMER, tmp); | ||
2387 | |||
2388 | /* TEST - for phy decoding error, adjust voltage levels */ | ||
2389 | mw32(P0_VSR_ADDR + 0, 0x8); | ||
2390 | mw32(P0_VSR_DATA + 0, 0x2F0); | ||
2391 | |||
2392 | mw32(P0_VSR_ADDR + 8, 0x8); | ||
2393 | mw32(P0_VSR_DATA + 8, 0x2F0); | ||
2394 | |||
2395 | mw32(P0_VSR_ADDR + 16, 0x8); | ||
2396 | mw32(P0_VSR_DATA + 16, 0x2F0); | ||
2397 | |||
2398 | mw32(P0_VSR_ADDR + 24, 0x8); | ||
2399 | mw32(P0_VSR_DATA + 24, 0x2F0); | ||
2400 | |||
2401 | } | ||
2402 | |||
2403 | static void mvs_enable_xmt(struct mvs_info *mvi, int PhyId) | ||
2404 | { | ||
2405 | void __iomem *regs = mvi->regs; | ||
2406 | u32 tmp; | ||
2407 | |||
2408 | tmp = mr32(PCS); | ||
2409 | if (mvi->chip->n_phy <= 4) | ||
2410 | tmp |= 1 << (PhyId + PCS_EN_PORT_XMT_SHIFT); | ||
2411 | else | ||
2412 | tmp |= 1 << (PhyId + PCS_EN_PORT_XMT_SHIFT2); | ||
2413 | mw32(PCS, tmp); | ||
2414 | } | ||
2415 | |||
2416 | static void mvs_detect_porttype(struct mvs_info *mvi, int i) | ||
2417 | { | ||
2418 | void __iomem *regs = mvi->regs; | ||
2419 | u32 reg; | ||
2420 | struct mvs_phy *phy = &mvi->phy[i]; | ||
2421 | |||
2422 | /* TODO check & save device type */ | ||
2423 | reg = mr32(GBL_PORT_TYPE); | ||
2424 | |||
2425 | if (reg & MODE_SAS_SATA & (1 << i)) | ||
2426 | phy->phy_type |= PORT_TYPE_SAS; | ||
2427 | else | ||
2428 | phy->phy_type |= PORT_TYPE_SATA; | ||
2429 | } | ||
2430 | |||
2431 | static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf) | ||
2432 | { | ||
2433 | u32 *s = (u32 *) buf; | ||
2434 | |||
2435 | if (!s) | ||
2436 | return NULL; | ||
2437 | |||
2438 | mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3); | ||
2439 | s[3] = mvs_read_port_cfg_data(mvi, i); | ||
2440 | |||
2441 | mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2); | ||
2442 | s[2] = mvs_read_port_cfg_data(mvi, i); | ||
2443 | |||
2444 | mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1); | ||
2445 | s[1] = mvs_read_port_cfg_data(mvi, i); | ||
2446 | |||
2447 | mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0); | ||
2448 | s[0] = mvs_read_port_cfg_data(mvi, i); | ||
2449 | |||
2450 | return (void *)s; | ||
2451 | } | ||
2452 | |||
2453 | static u32 mvs_is_sig_fis_received(u32 irq_status) | ||
2454 | { | ||
2455 | return irq_status & PHYEV_SIG_FIS; | ||
2456 | } | ||
2457 | |||
2458 | static void mvs_update_wideport(struct mvs_info *mvi, int i) | ||
2459 | { | ||
2460 | struct mvs_phy *phy = &mvi->phy[i]; | ||
2461 | struct mvs_port *port = phy->port; | ||
2462 | int j, no; | ||
2463 | |||
2464 | for_each_phy(port->wide_port_phymap, no, j, mvi->chip->n_phy) | ||
2465 | if (no & 1) { | ||
2466 | mvs_write_port_cfg_addr(mvi, no, PHYR_WIDE_PORT); | ||
2467 | mvs_write_port_cfg_data(mvi, no, | ||
2468 | port->wide_port_phymap); | ||
2469 | } else { | ||
2470 | mvs_write_port_cfg_addr(mvi, no, PHYR_WIDE_PORT); | ||
2471 | mvs_write_port_cfg_data(mvi, no, 0); | ||
2472 | } | ||
2473 | } | ||
2474 | |||
2475 | static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i) | ||
2476 | { | ||
2477 | u32 tmp; | ||
2478 | struct mvs_phy *phy = &mvi->phy[i]; | ||
2479 | struct mvs_port *port; | ||
2480 | |||
2481 | tmp = mvs_read_phy_ctl(mvi, i); | ||
2482 | |||
2483 | if ((tmp & PHY_READY_MASK) && !(phy->irq_status & PHYEV_POOF)) { | ||
2484 | if (!phy->port) | ||
2485 | phy->phy_attached = 1; | ||
2486 | return tmp; | ||
2487 | } | ||
2488 | |||
2489 | port = phy->port; | ||
2490 | if (port) { | ||
2491 | if (phy->phy_type & PORT_TYPE_SAS) { | ||
2492 | port->wide_port_phymap &= ~(1U << i); | ||
2493 | if (!port->wide_port_phymap) | ||
2494 | port->port_attached = 0; | ||
2495 | mvs_update_wideport(mvi, i); | ||
2496 | } else if (phy->phy_type & PORT_TYPE_SATA) | ||
2497 | port->port_attached = 0; | ||
2498 | mvs_free_reg_set(mvi, phy->port); | ||
2499 | phy->port = NULL; | ||
2500 | phy->phy_attached = 0; | ||
2501 | phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); | ||
2502 | } | ||
2503 | return 0; | ||
2504 | } | ||
2505 | |||
2506 | static void mvs_update_phyinfo(struct mvs_info *mvi, int i, | ||
2507 | int get_st) | ||
2508 | { | ||
2509 | struct mvs_phy *phy = &mvi->phy[i]; | ||
2510 | struct pci_dev *pdev = mvi->pdev; | ||
2511 | u32 tmp, j; | ||
2512 | u64 tmp64; | ||
2513 | |||
2514 | mvs_write_port_cfg_addr(mvi, i, PHYR_IDENTIFY); | ||
2515 | phy->dev_info = mvs_read_port_cfg_data(mvi, i); | ||
2516 | |||
2517 | mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_HI); | ||
2518 | phy->dev_sas_addr = (u64) mvs_read_port_cfg_data(mvi, i) << 32; | ||
2519 | |||
2520 | mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_LO); | ||
2521 | phy->dev_sas_addr |= mvs_read_port_cfg_data(mvi, i); | ||
2522 | |||
2523 | if (get_st) { | ||
2524 | phy->irq_status = mvs_read_port_irq_stat(mvi, i); | ||
2525 | phy->phy_status = mvs_is_phy_ready(mvi, i); | ||
2526 | } | ||
2527 | |||
2528 | if (phy->phy_status) { | ||
2529 | u32 phy_st; | ||
2530 | struct asd_sas_phy *sas_phy = mvi->sas.sas_phy[i]; | ||
2531 | |||
2532 | mvs_write_port_cfg_addr(mvi, i, PHYR_PHY_STAT); | ||
2533 | phy_st = mvs_read_port_cfg_data(mvi, i); | ||
2534 | |||
2535 | sas_phy->linkrate = | ||
2536 | (phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >> | ||
2537 | PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET; | ||
2538 | |||
2539 | /* Updated attached_sas_addr */ | ||
2540 | mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_HI); | ||
2541 | phy->att_dev_sas_addr = | ||
2542 | (u64) mvs_read_port_cfg_data(mvi, i) << 32; | ||
2543 | |||
2544 | mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_LO); | ||
2545 | phy->att_dev_sas_addr |= mvs_read_port_cfg_data(mvi, i); | ||
2546 | |||
2547 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
2548 | "phy[%d] Get Attached Address 0x%llX ," | ||
2549 | " SAS Address 0x%llX\n", | ||
2550 | i, phy->att_dev_sas_addr, phy->dev_sas_addr); | ||
2551 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
2552 | "Rate = %x , type = %d\n", | ||
2553 | sas_phy->linkrate, phy->phy_type); | ||
2554 | |||
2555 | #if 1 | ||
2556 | /* | ||
2557 | * If the device is capable of supporting a wide port | ||
2558 | * on its phys, it may configure the phys as a wide port. | ||
2559 | */ | ||
2560 | if (phy->phy_type & PORT_TYPE_SAS) | ||
2561 | for (j = 0; j < mvi->chip->n_phy && j != i; ++j) { | ||
2562 | if ((mvi->phy[j].phy_attached) && | ||
2563 | (mvi->phy[j].phy_type & PORT_TYPE_SAS)) | ||
2564 | if (phy->att_dev_sas_addr == | ||
2565 | mvi->phy[j].att_dev_sas_addr - 1) { | ||
2566 | phy->att_dev_sas_addr = | ||
2567 | mvi->phy[j].att_dev_sas_addr; | ||
2568 | break; | ||
2569 | } | ||
2570 | } | ||
2571 | |||
2572 | #endif | ||
2573 | |||
2574 | tmp64 = cpu_to_be64(phy->att_dev_sas_addr); | ||
2575 | memcpy(sas_phy->attached_sas_addr, &tmp64, SAS_ADDR_SIZE); | ||
2576 | |||
2577 | if (phy->phy_type & PORT_TYPE_SAS) { | ||
2578 | mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_DEV_INFO); | ||
2579 | phy->att_dev_info = mvs_read_port_cfg_data(mvi, i); | ||
2580 | phy->identify.device_type = | ||
2581 | phy->att_dev_info & PORT_DEV_TYPE_MASK; | ||
2582 | |||
2583 | if (phy->identify.device_type == SAS_END_DEV) | ||
2584 | phy->identify.target_port_protocols = | ||
2585 | SAS_PROTOCOL_SSP; | ||
2586 | else if (phy->identify.device_type != NO_DEVICE) | ||
2587 | phy->identify.target_port_protocols = | ||
2588 | SAS_PROTOCOL_SMP; | ||
2589 | if (phy_st & PHY_OOB_DTCTD) | ||
2590 | sas_phy->oob_mode = SAS_OOB_MODE; | ||
2591 | phy->frame_rcvd_size = | ||
2592 | sizeof(struct sas_identify_frame); | ||
2593 | } else if (phy->phy_type & PORT_TYPE_SATA) { | ||
2594 | phy->identify.target_port_protocols = SAS_PROTOCOL_STP; | ||
2595 | if (mvs_is_sig_fis_received(phy->irq_status)) { | ||
2596 | if (phy_st & PHY_OOB_DTCTD) | ||
2597 | sas_phy->oob_mode = SATA_OOB_MODE; | ||
2598 | phy->frame_rcvd_size = | ||
2599 | sizeof(struct dev_to_host_fis); | ||
2600 | mvs_get_d2h_reg(mvi, i, | ||
2601 | (void *)sas_phy->frame_rcvd); | ||
2602 | } else { | ||
2603 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
2604 | "No sig fis\n"); | ||
2605 | } | ||
2606 | } | ||
2607 | /* workaround for HW phy decoding error on 1.5g disk drive */ | ||
2608 | mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE6); | ||
2609 | tmp = mvs_read_port_vsr_data(mvi, i); | ||
2610 | if (((phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >> | ||
2611 | PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET) == | ||
2612 | SAS_LINK_RATE_1_5_GBPS) | ||
2613 | tmp &= ~PHY_MODE6_DTL_SPEED; | ||
2614 | else | ||
2615 | tmp |= PHY_MODE6_DTL_SPEED; | ||
2616 | mvs_write_port_vsr_data(mvi, i, tmp); | ||
2617 | |||
2618 | } | ||
2619 | if (get_st) | ||
2620 | mvs_write_port_irq_stat(mvi, i, phy->irq_status); | ||
2621 | } | ||
2622 | |||
2623 | static void mvs_port_formed(struct asd_sas_phy *sas_phy) | ||
2624 | { | ||
2625 | struct sas_ha_struct *sas_ha = sas_phy->ha; | ||
2626 | struct mvs_info *mvi = sas_ha->lldd_ha; | ||
2627 | struct asd_sas_port *sas_port = sas_phy->port; | ||
2628 | struct mvs_phy *phy = sas_phy->lldd_phy; | ||
2629 | struct mvs_port *port = &mvi->port[sas_port->id]; | ||
2630 | unsigned long flags; | ||
2631 | |||
2632 | spin_lock_irqsave(&mvi->lock, flags); | ||
2633 | port->port_attached = 1; | ||
2634 | phy->port = port; | ||
2635 | port->taskfileset = MVS_ID_NOT_MAPPED; | ||
2636 | if (phy->phy_type & PORT_TYPE_SAS) { | ||
2637 | port->wide_port_phymap = sas_port->phy_mask; | ||
2638 | mvs_update_wideport(mvi, sas_phy->id); | ||
2639 | } | ||
2640 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
2641 | } | ||
2642 | |||
2643 | static int __devinit mvs_hw_init(struct mvs_info *mvi) | ||
2644 | { | ||
2645 | void __iomem *regs = mvi->regs; | ||
2646 | int i; | ||
2647 | u32 tmp, cctl; | ||
2648 | |||
2649 | /* make sure interrupts are masked immediately (paranoia) */ | ||
2650 | mw32(GBL_CTL, 0); | ||
2651 | tmp = mr32(GBL_CTL); | ||
2652 | |||
2653 | /* Reset Controller */ | ||
2654 | if (!(tmp & HBA_RST)) { | ||
2655 | if (mvi->flags & MVF_PHY_PWR_FIX) { | ||
2656 | pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp); | ||
2657 | tmp &= ~PCTL_PWR_ON; | ||
2658 | tmp |= PCTL_OFF; | ||
2659 | pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp); | ||
2660 | |||
2661 | pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp); | ||
2662 | tmp &= ~PCTL_PWR_ON; | ||
2663 | tmp |= PCTL_OFF; | ||
2664 | pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp); | ||
2665 | } | ||
2666 | |||
2667 | /* global reset, incl. COMRESET/H_RESET_N (self-clearing) */ | ||
2668 | mw32_f(GBL_CTL, HBA_RST); | ||
2669 | } | ||
2670 | |||
2671 | /* wait for reset to finish; timeout is just a guess */ | ||
2672 | i = 1000; | ||
2673 | while (i-- > 0) { | ||
2674 | msleep(10); | ||
2675 | |||
2676 | if (!(mr32(GBL_CTL) & HBA_RST)) | ||
2677 | break; | ||
2678 | } | ||
2679 | if (mr32(GBL_CTL) & HBA_RST) { | ||
2680 | dev_printk(KERN_ERR, &mvi->pdev->dev, "HBA reset failed\n"); | ||
2681 | return -EBUSY; | ||
2682 | } | ||
2683 | |||
2684 | /* Init Chip */ | ||
2685 | /* make sure RST is set; HBA_RST /should/ have done that for us */ | ||
2686 | cctl = mr32(CTL); | ||
2687 | if (cctl & CCTL_RST) | ||
2688 | cctl &= ~CCTL_RST; | ||
2689 | else | ||
2690 | mw32_f(CTL, cctl | CCTL_RST); | ||
2691 | |||
2692 | /* write to device control _AND_ device status register? - A.C. */ | ||
2693 | pci_read_config_dword(mvi->pdev, PCR_DEV_CTRL, &tmp); | ||
2694 | tmp &= ~PRD_REQ_MASK; | ||
2695 | tmp |= PRD_REQ_SIZE; | ||
2696 | pci_write_config_dword(mvi->pdev, PCR_DEV_CTRL, tmp); | ||
2697 | |||
2698 | pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp); | ||
2699 | tmp |= PCTL_PWR_ON; | ||
2700 | tmp &= ~PCTL_OFF; | ||
2701 | pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp); | ||
2702 | |||
2703 | pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp); | ||
2704 | tmp |= PCTL_PWR_ON; | ||
2705 | tmp &= ~PCTL_OFF; | ||
2706 | pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp); | ||
2707 | |||
2708 | mw32_f(CTL, cctl); | ||
2709 | |||
2710 | /* reset control */ | ||
2711 | mw32(PCS, 0); /*MVS_PCS */ | ||
2712 | |||
2713 | mvs_phy_hacks(mvi); | ||
2714 | |||
2715 | mw32(CMD_LIST_LO, mvi->slot_dma); | ||
2716 | mw32(CMD_LIST_HI, (mvi->slot_dma >> 16) >> 16); | ||
2717 | |||
2718 | mw32(RX_FIS_LO, mvi->rx_fis_dma); | ||
2719 | mw32(RX_FIS_HI, (mvi->rx_fis_dma >> 16) >> 16); | ||
2720 | |||
2721 | mw32(TX_CFG, MVS_CHIP_SLOT_SZ); | ||
2722 | mw32(TX_LO, mvi->tx_dma); | ||
2723 | mw32(TX_HI, (mvi->tx_dma >> 16) >> 16); | ||
2724 | |||
2725 | mw32(RX_CFG, MVS_RX_RING_SZ); | ||
2726 | mw32(RX_LO, mvi->rx_dma); | ||
2727 | mw32(RX_HI, (mvi->rx_dma >> 16) >> 16); | ||
2728 | |||
2729 | /* enable auto port detection */ | ||
2730 | mw32(GBL_PORT_TYPE, MODE_AUTO_DET_EN); | ||
2731 | msleep(100); | ||
2732 | /* init and reset phys */ | ||
2733 | for (i = 0; i < mvi->chip->n_phy; i++) { | ||
2734 | /* FIXME: is this the correct dword order? */ | ||
2735 | u32 lo = *((u32 *)&mvi->sas_addr[0]); | ||
2736 | u32 hi = *((u32 *)&mvi->sas_addr[4]); | ||
2737 | |||
2738 | mvs_detect_porttype(mvi, i); | ||
2739 | |||
2740 | /* set phy local SAS address */ | ||
2741 | mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_LO); | ||
2742 | mvs_write_port_cfg_data(mvi, i, lo); | ||
2743 | mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_HI); | ||
2744 | mvs_write_port_cfg_data(mvi, i, hi); | ||
2745 | |||
2746 | /* reset phy */ | ||
2747 | tmp = mvs_read_phy_ctl(mvi, i); | ||
2748 | tmp |= PHY_RST; | ||
2749 | mvs_write_phy_ctl(mvi, i, tmp); | ||
2750 | } | ||
2751 | |||
2752 | msleep(100); | ||
2753 | |||
2754 | for (i = 0; i < mvi->chip->n_phy; i++) { | ||
2755 | /* clear phy int status */ | ||
2756 | tmp = mvs_read_port_irq_stat(mvi, i); | ||
2757 | tmp &= ~PHYEV_SIG_FIS; | ||
2758 | mvs_write_port_irq_stat(mvi, i, tmp); | ||
2759 | |||
2760 | /* set phy int mask */ | ||
2761 | tmp = PHYEV_RDY_CH | PHYEV_BROAD_CH | PHYEV_UNASSOC_FIS | | ||
2762 | PHYEV_ID_DONE | PHYEV_DEC_ERR; | ||
2763 | mvs_write_port_irq_mask(mvi, i, tmp); | ||
2764 | |||
2765 | msleep(100); | ||
2766 | mvs_update_phyinfo(mvi, i, 1); | ||
2767 | mvs_enable_xmt(mvi, i); | ||
2768 | } | ||
2769 | |||
2770 | /* FIXME: update wide port bitmaps */ | ||
2771 | |||
2772 | /* little endian for open address and command table, etc. */ | ||
2773 | /* A.C. | ||
2774 | * it seems that ( from the spec ) turning on big-endian won't | ||
2775 | * do us any good on big-endian machines, need further confirmation | ||
2776 | */ | ||
2777 | cctl = mr32(CTL); | ||
2778 | cctl |= CCTL_ENDIAN_CMD; | ||
2779 | cctl |= CCTL_ENDIAN_DATA; | ||
2780 | cctl &= ~CCTL_ENDIAN_OPEN; | ||
2781 | cctl |= CCTL_ENDIAN_RSP; | ||
2782 | mw32_f(CTL, cctl); | ||
2783 | |||
2784 | /* reset CMD queue */ | ||
2785 | tmp = mr32(PCS); | ||
2786 | tmp |= PCS_CMD_RST; | ||
2787 | mw32(PCS, tmp); | ||
2788 | /* interrupt coalescing may cause missing HW interrput in some case, | ||
2789 | * and the max count is 0x1ff, while our max slot is 0x200, | ||
2790 | * it will make count 0. | ||
2791 | */ | ||
2792 | tmp = 0; | ||
2793 | mw32(INT_COAL, tmp); | ||
2794 | |||
2795 | tmp = 0x100; | ||
2796 | mw32(INT_COAL_TMOUT, tmp); | ||
2797 | |||
2798 | /* ladies and gentlemen, start your engines */ | ||
2799 | mw32(TX_CFG, 0); | ||
2800 | mw32(TX_CFG, MVS_CHIP_SLOT_SZ | TX_EN); | ||
2801 | mw32(RX_CFG, MVS_RX_RING_SZ | RX_EN); | ||
2802 | /* enable CMD/CMPL_Q/RESP mode */ | ||
2803 | mw32(PCS, PCS_SATA_RETRY | PCS_FIS_RX_EN | PCS_CMD_EN); | ||
2804 | |||
2805 | /* re-enable interrupts globally */ | ||
2806 | mvs_hba_interrupt_enable(mvi); | ||
2807 | |||
2808 | /* enable completion queue interrupt */ | ||
2809 | tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM); | ||
2810 | mw32(INT_MASK, tmp); | ||
2811 | |||
2812 | return 0; | ||
2813 | } | ||
2814 | |||
2815 | static void __devinit mvs_print_info(struct mvs_info *mvi) | ||
2816 | { | ||
2817 | struct pci_dev *pdev = mvi->pdev; | ||
2818 | static int printed_version; | ||
2819 | |||
2820 | if (!printed_version++) | ||
2821 | dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); | ||
2822 | |||
2823 | dev_printk(KERN_INFO, &pdev->dev, "%u phys, addr %llx\n", | ||
2824 | mvi->chip->n_phy, SAS_ADDR(mvi->sas_addr)); | ||
2825 | } | ||
2826 | |||
2827 | static int __devinit mvs_pci_init(struct pci_dev *pdev, | ||
2828 | const struct pci_device_id *ent) | ||
2829 | { | ||
2830 | int rc; | ||
2831 | struct mvs_info *mvi; | ||
2832 | irq_handler_t irq_handler = mvs_interrupt; | ||
2833 | |||
2834 | rc = pci_enable_device(pdev); | ||
2835 | if (rc) | ||
2836 | return rc; | ||
2837 | |||
2838 | pci_set_master(pdev); | ||
2839 | |||
2840 | rc = pci_request_regions(pdev, DRV_NAME); | ||
2841 | if (rc) | ||
2842 | goto err_out_disable; | ||
2843 | |||
2844 | rc = pci_go_64(pdev); | ||
2845 | if (rc) | ||
2846 | goto err_out_regions; | ||
2847 | |||
2848 | mvi = mvs_alloc(pdev, ent); | ||
2849 | if (!mvi) { | ||
2850 | rc = -ENOMEM; | ||
2851 | goto err_out_regions; | ||
2852 | } | ||
2853 | |||
2854 | rc = mvs_hw_init(mvi); | ||
2855 | if (rc) | ||
2856 | goto err_out_mvi; | ||
2857 | |||
2858 | #ifndef MVS_DISABLE_MSI | ||
2859 | if (!pci_enable_msi(pdev)) { | ||
2860 | u32 tmp; | ||
2861 | void __iomem *regs = mvi->regs; | ||
2862 | mvi->flags |= MVF_MSI; | ||
2863 | irq_handler = mvs_msi_interrupt; | ||
2864 | tmp = mr32(PCS); | ||
2865 | mw32(PCS, tmp | PCS_SELF_CLEAR); | ||
2866 | } | ||
2867 | #endif | ||
2868 | |||
2869 | rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, DRV_NAME, mvi); | ||
2870 | if (rc) | ||
2871 | goto err_out_msi; | ||
2872 | |||
2873 | rc = scsi_add_host(mvi->shost, &pdev->dev); | ||
2874 | if (rc) | ||
2875 | goto err_out_irq; | ||
2876 | |||
2877 | rc = sas_register_ha(&mvi->sas); | ||
2878 | if (rc) | ||
2879 | goto err_out_shost; | ||
2880 | |||
2881 | pci_set_drvdata(pdev, mvi); | ||
2882 | |||
2883 | mvs_print_info(mvi); | ||
2884 | |||
2885 | scsi_scan_host(mvi->shost); | ||
2886 | |||
2887 | return 0; | ||
2888 | |||
2889 | err_out_shost: | ||
2890 | scsi_remove_host(mvi->shost); | ||
2891 | err_out_irq: | ||
2892 | free_irq(pdev->irq, mvi); | ||
2893 | err_out_msi: | ||
2894 | if (mvi->flags |= MVF_MSI) | ||
2895 | pci_disable_msi(pdev); | ||
2896 | err_out_mvi: | ||
2897 | mvs_free(mvi); | ||
2898 | err_out_regions: | ||
2899 | pci_release_regions(pdev); | ||
2900 | err_out_disable: | ||
2901 | pci_disable_device(pdev); | ||
2902 | return rc; | ||
2903 | } | ||
2904 | |||
2905 | static void __devexit mvs_pci_remove(struct pci_dev *pdev) | ||
2906 | { | ||
2907 | struct mvs_info *mvi = pci_get_drvdata(pdev); | ||
2908 | |||
2909 | pci_set_drvdata(pdev, NULL); | ||
2910 | |||
2911 | if (mvi) { | ||
2912 | sas_unregister_ha(&mvi->sas); | ||
2913 | mvs_hba_interrupt_disable(mvi); | ||
2914 | sas_remove_host(mvi->shost); | ||
2915 | scsi_remove_host(mvi->shost); | ||
2916 | |||
2917 | free_irq(pdev->irq, mvi); | ||
2918 | if (mvi->flags & MVF_MSI) | ||
2919 | pci_disable_msi(pdev); | ||
2920 | mvs_free(mvi); | ||
2921 | pci_release_regions(pdev); | ||
2922 | } | ||
2923 | pci_disable_device(pdev); | ||
2924 | } | ||
2925 | |||
2926 | static struct sas_domain_function_template mvs_transport_ops = { | ||
2927 | .lldd_execute_task = mvs_task_exec, | ||
2928 | .lldd_control_phy = mvs_phy_control, | ||
2929 | .lldd_abort_task = mvs_task_abort, | ||
2930 | .lldd_port_formed = mvs_port_formed | ||
2931 | }; | ||
2932 | |||
2933 | static struct pci_device_id __devinitdata mvs_pci_table[] = { | ||
2934 | { PCI_VDEVICE(MARVELL, 0x6320), chip_6320 }, | ||
2935 | { PCI_VDEVICE(MARVELL, 0x6340), chip_6440 }, | ||
2936 | { PCI_VDEVICE(MARVELL, 0x6440), chip_6440 }, | ||
2937 | { PCI_VDEVICE(MARVELL, 0x6480), chip_6480 }, | ||
2938 | |||
2939 | { } /* terminate list */ | ||
2940 | }; | ||
2941 | |||
2942 | static struct pci_driver mvs_pci_driver = { | ||
2943 | .name = DRV_NAME, | ||
2944 | .id_table = mvs_pci_table, | ||
2945 | .probe = mvs_pci_init, | ||
2946 | .remove = __devexit_p(mvs_pci_remove), | ||
2947 | }; | ||
2948 | |||
2949 | static int __init mvs_init(void) | ||
2950 | { | ||
2951 | int rc; | ||
2952 | |||
2953 | mvs_stt = sas_domain_attach_transport(&mvs_transport_ops); | ||
2954 | if (!mvs_stt) | ||
2955 | return -ENOMEM; | ||
2956 | |||
2957 | rc = pci_register_driver(&mvs_pci_driver); | ||
2958 | if (rc) | ||
2959 | goto err_out; | ||
2960 | |||
2961 | return 0; | ||
2962 | |||
2963 | err_out: | ||
2964 | sas_release_transport(mvs_stt); | ||
2965 | return rc; | ||
2966 | } | ||
2967 | |||
2968 | static void __exit mvs_exit(void) | ||
2969 | { | ||
2970 | pci_unregister_driver(&mvs_pci_driver); | ||
2971 | sas_release_transport(mvs_stt); | ||
2972 | } | ||
2973 | |||
2974 | module_init(mvs_init); | ||
2975 | module_exit(mvs_exit); | ||
2976 | |||
2977 | MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>"); | ||
2978 | MODULE_DESCRIPTION("Marvell 88SE6440 SAS/SATA controller driver"); | ||
2979 | MODULE_VERSION(DRV_VERSION); | ||
2980 | MODULE_LICENSE("GPL"); | ||
2981 | MODULE_DEVICE_TABLE(pci, mvs_pci_table); | ||