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