diff options
Diffstat (limited to 'drivers/scsi/mvsas/mv_sas.c')
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.c | 2154 |
1 files changed, 2154 insertions, 0 deletions
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c new file mode 100644 index 000000000000..0d2138641214 --- /dev/null +++ b/drivers/scsi/mvsas/mv_sas.c | |||
@@ -0,0 +1,2154 @@ | |||
1 | /* | ||
2 | * Marvell 88SE64xx/88SE94xx main function | ||
3 | * | ||
4 | * Copyright 2007 Red Hat, Inc. | ||
5 | * Copyright 2008 Marvell. <kewei@marvell.com> | ||
6 | * | ||
7 | * This file is licensed under GPLv2. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License as | ||
11 | * published by the Free Software Foundation; version 2 of the | ||
12 | * License. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
22 | * USA | ||
23 | */ | ||
24 | |||
25 | #include "mv_sas.h" | ||
26 | |||
27 | static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag) | ||
28 | { | ||
29 | if (task->lldd_task) { | ||
30 | struct mvs_slot_info *slot; | ||
31 | slot = task->lldd_task; | ||
32 | *tag = slot->slot_tag; | ||
33 | return 1; | ||
34 | } | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | void mvs_tag_clear(struct mvs_info *mvi, u32 tag) | ||
39 | { | ||
40 | void *bitmap = &mvi->tags; | ||
41 | clear_bit(tag, bitmap); | ||
42 | } | ||
43 | |||
44 | void mvs_tag_free(struct mvs_info *mvi, u32 tag) | ||
45 | { | ||
46 | mvs_tag_clear(mvi, tag); | ||
47 | } | ||
48 | |||
49 | void mvs_tag_set(struct mvs_info *mvi, unsigned int tag) | ||
50 | { | ||
51 | void *bitmap = &mvi->tags; | ||
52 | set_bit(tag, bitmap); | ||
53 | } | ||
54 | |||
55 | inline int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out) | ||
56 | { | ||
57 | unsigned int index, tag; | ||
58 | void *bitmap = &mvi->tags; | ||
59 | |||
60 | index = find_first_zero_bit(bitmap, mvi->tags_num); | ||
61 | tag = index; | ||
62 | if (tag >= mvi->tags_num) | ||
63 | return -SAS_QUEUE_FULL; | ||
64 | mvs_tag_set(mvi, tag); | ||
65 | *tag_out = tag; | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | void mvs_tag_init(struct mvs_info *mvi) | ||
70 | { | ||
71 | int i; | ||
72 | for (i = 0; i < mvi->tags_num; ++i) | ||
73 | mvs_tag_clear(mvi, i); | ||
74 | } | ||
75 | |||
76 | void mvs_hexdump(u32 size, u8 *data, u32 baseaddr) | ||
77 | { | ||
78 | u32 i; | ||
79 | u32 run; | ||
80 | u32 offset; | ||
81 | |||
82 | offset = 0; | ||
83 | while (size) { | ||
84 | printk(KERN_DEBUG"%08X : ", baseaddr + offset); | ||
85 | if (size >= 16) | ||
86 | run = 16; | ||
87 | else | ||
88 | run = size; | ||
89 | size -= run; | ||
90 | for (i = 0; i < 16; i++) { | ||
91 | if (i < run) | ||
92 | printk(KERN_DEBUG"%02X ", (u32)data[i]); | ||
93 | else | ||
94 | printk(KERN_DEBUG" "); | ||
95 | } | ||
96 | printk(KERN_DEBUG": "); | ||
97 | for (i = 0; i < run; i++) | ||
98 | printk(KERN_DEBUG"%c", | ||
99 | isalnum(data[i]) ? data[i] : '.'); | ||
100 | printk(KERN_DEBUG"\n"); | ||
101 | data = &data[16]; | ||
102 | offset += run; | ||
103 | } | ||
104 | printk(KERN_DEBUG"\n"); | ||
105 | } | ||
106 | |||
107 | #if (_MV_DUMP > 1) | ||
108 | static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag, | ||
109 | enum sas_protocol proto) | ||
110 | { | ||
111 | u32 offset; | ||
112 | struct mvs_slot_info *slot = &mvi->slot_info[tag]; | ||
113 | |||
114 | offset = slot->cmd_size + MVS_OAF_SZ + | ||
115 | MVS_CHIP_DISP->prd_size() * slot->n_elem; | ||
116 | dev_printk(KERN_DEBUG, mvi->dev, "+---->Status buffer[%d] :\n", | ||
117 | tag); | ||
118 | mvs_hexdump(32, (u8 *) slot->response, | ||
119 | (u32) slot->buf_dma + offset); | ||
120 | } | ||
121 | #endif | ||
122 | |||
123 | static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, | ||
124 | enum sas_protocol proto) | ||
125 | { | ||
126 | #if (_MV_DUMP > 1) | ||
127 | u32 sz, w_ptr; | ||
128 | u64 addr; | ||
129 | struct mvs_slot_info *slot = &mvi->slot_info[tag]; | ||
130 | |||
131 | /*Delivery Queue */ | ||
132 | sz = MVS_CHIP_SLOT_SZ; | ||
133 | w_ptr = slot->tx; | ||
134 | addr = mvi->tx_dma; | ||
135 | dev_printk(KERN_DEBUG, mvi->dev, | ||
136 | "Delivery Queue Size=%04d , WRT_PTR=%04X\n", sz, w_ptr); | ||
137 | dev_printk(KERN_DEBUG, mvi->dev, | ||
138 | "Delivery Queue Base Address=0x%llX (PA)" | ||
139 | "(tx_dma=0x%llX), Entry=%04d\n", | ||
140 | addr, (unsigned long long)mvi->tx_dma, w_ptr); | ||
141 | mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]), | ||
142 | (u32) mvi->tx_dma + sizeof(u32) * w_ptr); | ||
143 | /*Command List */ | ||
144 | addr = mvi->slot_dma; | ||
145 | dev_printk(KERN_DEBUG, mvi->dev, | ||
146 | "Command List Base Address=0x%llX (PA)" | ||
147 | "(slot_dma=0x%llX), Header=%03d\n", | ||
148 | addr, (unsigned long long)slot->buf_dma, tag); | ||
149 | dev_printk(KERN_DEBUG, mvi->dev, "Command Header[%03d]:\n", tag); | ||
150 | /*mvs_cmd_hdr */ | ||
151 | mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]), | ||
152 | (u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr)); | ||
153 | /*1.command table area */ | ||
154 | dev_printk(KERN_DEBUG, mvi->dev, "+---->Command Table :\n"); | ||
155 | mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma); | ||
156 | /*2.open address frame area */ | ||
157 | dev_printk(KERN_DEBUG, mvi->dev, "+---->Open Address Frame :\n"); | ||
158 | mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size, | ||
159 | (u32) slot->buf_dma + slot->cmd_size); | ||
160 | /*3.status buffer */ | ||
161 | mvs_hba_sb_dump(mvi, tag, proto); | ||
162 | /*4.PRD table */ | ||
163 | dev_printk(KERN_DEBUG, mvi->dev, "+---->PRD table :\n"); | ||
164 | mvs_hexdump(MVS_CHIP_DISP->prd_size() * slot->n_elem, | ||
165 | (u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ, | ||
166 | (u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ); | ||
167 | #endif | ||
168 | } | ||
169 | |||
170 | static void mvs_hba_cq_dump(struct mvs_info *mvi) | ||
171 | { | ||
172 | #if (_MV_DUMP > 2) | ||
173 | u64 addr; | ||
174 | void __iomem *regs = mvi->regs; | ||
175 | u32 entry = mvi->rx_cons + 1; | ||
176 | u32 rx_desc = le32_to_cpu(mvi->rx[entry]); | ||
177 | |||
178 | /*Completion Queue */ | ||
179 | addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO); | ||
180 | dev_printk(KERN_DEBUG, mvi->dev, "Completion Task = 0x%p\n", | ||
181 | mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task); | ||
182 | dev_printk(KERN_DEBUG, mvi->dev, | ||
183 | "Completion List Base Address=0x%llX (PA), " | ||
184 | "CQ_Entry=%04d, CQ_WP=0x%08X\n", | ||
185 | addr, entry - 1, mvi->rx[0]); | ||
186 | mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc), | ||
187 | mvi->rx_dma + sizeof(u32) * entry); | ||
188 | #endif | ||
189 | } | ||
190 | |||
191 | void mvs_get_sas_addr(void *buf, u32 buflen) | ||
192 | { | ||
193 | /*memcpy(buf, "\x50\x05\x04\x30\x11\xab\x64\x40", 8);*/ | ||
194 | } | ||
195 | |||
196 | struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev) | ||
197 | { | ||
198 | unsigned long i = 0, j = 0, hi = 0; | ||
199 | struct sas_ha_struct *sha = dev->port->ha; | ||
200 | struct mvs_info *mvi = NULL; | ||
201 | struct asd_sas_phy *phy; | ||
202 | |||
203 | while (sha->sas_port[i]) { | ||
204 | if (sha->sas_port[i] == dev->port) { | ||
205 | phy = container_of(sha->sas_port[i]->phy_list.next, | ||
206 | struct asd_sas_phy, port_phy_el); | ||
207 | j = 0; | ||
208 | while (sha->sas_phy[j]) { | ||
209 | if (sha->sas_phy[j] == phy) | ||
210 | break; | ||
211 | j++; | ||
212 | } | ||
213 | break; | ||
214 | } | ||
215 | i++; | ||
216 | } | ||
217 | hi = j/((struct mvs_prv_info *)sha->lldd_ha)->n_phy; | ||
218 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[hi]; | ||
219 | |||
220 | return mvi; | ||
221 | |||
222 | } | ||
223 | |||
224 | /* FIXME */ | ||
225 | int mvs_find_dev_phyno(struct domain_device *dev, int *phyno) | ||
226 | { | ||
227 | unsigned long i = 0, j = 0, n = 0, num = 0; | ||
228 | struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; | ||
229 | struct mvs_info *mvi = mvi_dev->mvi_info; | ||
230 | struct sas_ha_struct *sha = dev->port->ha; | ||
231 | |||
232 | while (sha->sas_port[i]) { | ||
233 | if (sha->sas_port[i] == dev->port) { | ||
234 | struct asd_sas_phy *phy; | ||
235 | list_for_each_entry(phy, | ||
236 | &sha->sas_port[i]->phy_list, port_phy_el) { | ||
237 | j = 0; | ||
238 | while (sha->sas_phy[j]) { | ||
239 | if (sha->sas_phy[j] == phy) | ||
240 | break; | ||
241 | j++; | ||
242 | } | ||
243 | phyno[n] = (j >= mvi->chip->n_phy) ? | ||
244 | (j - mvi->chip->n_phy) : j; | ||
245 | num++; | ||
246 | n++; | ||
247 | } | ||
248 | break; | ||
249 | } | ||
250 | i++; | ||
251 | } | ||
252 | return num; | ||
253 | } | ||
254 | |||
255 | static inline void mvs_free_reg_set(struct mvs_info *mvi, | ||
256 | struct mvs_device *dev) | ||
257 | { | ||
258 | if (!dev) { | ||
259 | mv_printk("device has been free.\n"); | ||
260 | return; | ||
261 | } | ||
262 | if (dev->runing_req != 0) | ||
263 | return; | ||
264 | if (dev->taskfileset == MVS_ID_NOT_MAPPED) | ||
265 | return; | ||
266 | MVS_CHIP_DISP->free_reg_set(mvi, &dev->taskfileset); | ||
267 | } | ||
268 | |||
269 | static inline u8 mvs_assign_reg_set(struct mvs_info *mvi, | ||
270 | struct mvs_device *dev) | ||
271 | { | ||
272 | if (dev->taskfileset != MVS_ID_NOT_MAPPED) | ||
273 | return 0; | ||
274 | return MVS_CHIP_DISP->assign_reg_set(mvi, &dev->taskfileset); | ||
275 | } | ||
276 | |||
277 | void mvs_phys_reset(struct mvs_info *mvi, u32 phy_mask, int hard) | ||
278 | { | ||
279 | u32 no; | ||
280 | for_each_phy(phy_mask, phy_mask, no) { | ||
281 | if (!(phy_mask & 1)) | ||
282 | continue; | ||
283 | MVS_CHIP_DISP->phy_reset(mvi, no, hard); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | /* FIXME: locking? */ | ||
288 | int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | ||
289 | void *funcdata) | ||
290 | { | ||
291 | int rc = 0, phy_id = sas_phy->id; | ||
292 | u32 tmp, i = 0, hi; | ||
293 | struct sas_ha_struct *sha = sas_phy->ha; | ||
294 | struct mvs_info *mvi = NULL; | ||
295 | |||
296 | while (sha->sas_phy[i]) { | ||
297 | if (sha->sas_phy[i] == sas_phy) | ||
298 | break; | ||
299 | i++; | ||
300 | } | ||
301 | hi = i/((struct mvs_prv_info *)sha->lldd_ha)->n_phy; | ||
302 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[hi]; | ||
303 | |||
304 | switch (func) { | ||
305 | case PHY_FUNC_SET_LINK_RATE: | ||
306 | MVS_CHIP_DISP->phy_set_link_rate(mvi, phy_id, funcdata); | ||
307 | break; | ||
308 | |||
309 | case PHY_FUNC_HARD_RESET: | ||
310 | tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id); | ||
311 | if (tmp & PHY_RST_HARD) | ||
312 | break; | ||
313 | MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1); | ||
314 | break; | ||
315 | |||
316 | case PHY_FUNC_LINK_RESET: | ||
317 | MVS_CHIP_DISP->phy_enable(mvi, phy_id); | ||
318 | MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0); | ||
319 | break; | ||
320 | |||
321 | case PHY_FUNC_DISABLE: | ||
322 | MVS_CHIP_DISP->phy_disable(mvi, phy_id); | ||
323 | break; | ||
324 | case PHY_FUNC_RELEASE_SPINUP_HOLD: | ||
325 | default: | ||
326 | rc = -EOPNOTSUPP; | ||
327 | } | ||
328 | msleep(200); | ||
329 | return rc; | ||
330 | } | ||
331 | |||
332 | void __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id, | ||
333 | u32 off_lo, u32 off_hi, u64 sas_addr) | ||
334 | { | ||
335 | u32 lo = (u32)sas_addr; | ||
336 | u32 hi = (u32)(sas_addr>>32); | ||
337 | |||
338 | MVS_CHIP_DISP->write_port_cfg_addr(mvi, port_id, off_lo); | ||
339 | MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, lo); | ||
340 | MVS_CHIP_DISP->write_port_cfg_addr(mvi, port_id, off_hi); | ||
341 | MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, hi); | ||
342 | } | ||
343 | |||
344 | static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) | ||
345 | { | ||
346 | struct mvs_phy *phy = &mvi->phy[i]; | ||
347 | struct asd_sas_phy *sas_phy = &phy->sas_phy; | ||
348 | struct sas_ha_struct *sas_ha; | ||
349 | if (!phy->phy_attached) | ||
350 | return; | ||
351 | |||
352 | if (!(phy->att_dev_info & PORT_DEV_TRGT_MASK) | ||
353 | && phy->phy_type & PORT_TYPE_SAS) { | ||
354 | return; | ||
355 | } | ||
356 | |||
357 | sas_ha = mvi->sas; | ||
358 | sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE); | ||
359 | |||
360 | if (sas_phy->phy) { | ||
361 | struct sas_phy *sphy = sas_phy->phy; | ||
362 | |||
363 | sphy->negotiated_linkrate = sas_phy->linkrate; | ||
364 | sphy->minimum_linkrate = phy->minimum_linkrate; | ||
365 | sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; | ||
366 | sphy->maximum_linkrate = phy->maximum_linkrate; | ||
367 | sphy->maximum_linkrate_hw = MVS_CHIP_DISP->phy_max_link_rate(); | ||
368 | } | ||
369 | |||
370 | if (phy->phy_type & PORT_TYPE_SAS) { | ||
371 | struct sas_identify_frame *id; | ||
372 | |||
373 | id = (struct sas_identify_frame *)phy->frame_rcvd; | ||
374 | id->dev_type = phy->identify.device_type; | ||
375 | id->initiator_bits = SAS_PROTOCOL_ALL; | ||
376 | id->target_bits = phy->identify.target_port_protocols; | ||
377 | } else if (phy->phy_type & PORT_TYPE_SATA) { | ||
378 | /*Nothing*/ | ||
379 | } | ||
380 | mv_dprintk("phy %d byte dmaded.\n", i + mvi->id * mvi->chip->n_phy); | ||
381 | |||
382 | sas_phy->frame_rcvd_size = phy->frame_rcvd_size; | ||
383 | |||
384 | mvi->sas->notify_port_event(sas_phy, | ||
385 | PORTE_BYTES_DMAED); | ||
386 | } | ||
387 | |||
388 | int mvs_slave_alloc(struct scsi_device *scsi_dev) | ||
389 | { | ||
390 | struct domain_device *dev = sdev_to_domain_dev(scsi_dev); | ||
391 | if (dev_is_sata(dev)) { | ||
392 | /* We don't need to rescan targets | ||
393 | * if REPORT_LUNS request is failed | ||
394 | */ | ||
395 | if (scsi_dev->lun > 0) | ||
396 | return -ENXIO; | ||
397 | scsi_dev->tagged_supported = 1; | ||
398 | } | ||
399 | |||
400 | return sas_slave_alloc(scsi_dev); | ||
401 | } | ||
402 | |||
403 | int mvs_slave_configure(struct scsi_device *sdev) | ||
404 | { | ||
405 | struct domain_device *dev = sdev_to_domain_dev(sdev); | ||
406 | int ret = sas_slave_configure(sdev); | ||
407 | |||
408 | if (ret) | ||
409 | return ret; | ||
410 | if (dev_is_sata(dev)) { | ||
411 | /* may set PIO mode */ | ||
412 | #if MV_DISABLE_NCQ | ||
413 | struct ata_port *ap = dev->sata_dev.ap; | ||
414 | struct ata_device *adev = ap->link.device; | ||
415 | adev->flags |= ATA_DFLAG_NCQ_OFF; | ||
416 | scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1); | ||
417 | #endif | ||
418 | } | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | void mvs_scan_start(struct Scsi_Host *shost) | ||
423 | { | ||
424 | int i, j; | ||
425 | unsigned short core_nr; | ||
426 | struct mvs_info *mvi; | ||
427 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
428 | |||
429 | core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; | ||
430 | |||
431 | for (j = 0; j < core_nr; j++) { | ||
432 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j]; | ||
433 | for (i = 0; i < mvi->chip->n_phy; ++i) | ||
434 | mvs_bytes_dmaed(mvi, i); | ||
435 | } | ||
436 | } | ||
437 | |||
438 | int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time) | ||
439 | { | ||
440 | /* give the phy enabling interrupt event time to come in (1s | ||
441 | * is empirically about all it takes) */ | ||
442 | if (time < HZ) | ||
443 | return 0; | ||
444 | /* Wait for discovery to finish */ | ||
445 | scsi_flush_work(shost); | ||
446 | return 1; | ||
447 | } | ||
448 | |||
449 | static int mvs_task_prep_smp(struct mvs_info *mvi, | ||
450 | struct mvs_task_exec_info *tei) | ||
451 | { | ||
452 | int elem, rc, i; | ||
453 | struct sas_task *task = tei->task; | ||
454 | struct mvs_cmd_hdr *hdr = tei->hdr; | ||
455 | struct domain_device *dev = task->dev; | ||
456 | struct asd_sas_port *sas_port = dev->port; | ||
457 | struct scatterlist *sg_req, *sg_resp; | ||
458 | u32 req_len, resp_len, tag = tei->tag; | ||
459 | void *buf_tmp; | ||
460 | u8 *buf_oaf; | ||
461 | dma_addr_t buf_tmp_dma; | ||
462 | void *buf_prd; | ||
463 | struct mvs_slot_info *slot = &mvi->slot_info[tag]; | ||
464 | u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); | ||
465 | #if _MV_DUMP | ||
466 | u8 *buf_cmd; | ||
467 | void *from; | ||
468 | #endif | ||
469 | /* | ||
470 | * DMA-map SMP request, response buffers | ||
471 | */ | ||
472 | sg_req = &task->smp_task.smp_req; | ||
473 | elem = dma_map_sg(mvi->dev, sg_req, 1, PCI_DMA_TODEVICE); | ||
474 | if (!elem) | ||
475 | return -ENOMEM; | ||
476 | req_len = sg_dma_len(sg_req); | ||
477 | |||
478 | sg_resp = &task->smp_task.smp_resp; | ||
479 | elem = dma_map_sg(mvi->dev, sg_resp, 1, PCI_DMA_FROMDEVICE); | ||
480 | if (!elem) { | ||
481 | rc = -ENOMEM; | ||
482 | goto err_out; | ||
483 | } | ||
484 | resp_len = SB_RFB_MAX; | ||
485 | |||
486 | /* must be in dwords */ | ||
487 | if ((req_len & 0x3) || (resp_len & 0x3)) { | ||
488 | rc = -EINVAL; | ||
489 | goto err_out_2; | ||
490 | } | ||
491 | |||
492 | /* | ||
493 | * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs | ||
494 | */ | ||
495 | |||
496 | /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ***** */ | ||
497 | buf_tmp = slot->buf; | ||
498 | buf_tmp_dma = slot->buf_dma; | ||
499 | |||
500 | #if _MV_DUMP | ||
501 | buf_cmd = buf_tmp; | ||
502 | hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); | ||
503 | buf_tmp += req_len; | ||
504 | buf_tmp_dma += req_len; | ||
505 | slot->cmd_size = req_len; | ||
506 | #else | ||
507 | hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req)); | ||
508 | #endif | ||
509 | |||
510 | /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ | ||
511 | buf_oaf = buf_tmp; | ||
512 | hdr->open_frame = cpu_to_le64(buf_tmp_dma); | ||
513 | |||
514 | buf_tmp += MVS_OAF_SZ; | ||
515 | buf_tmp_dma += MVS_OAF_SZ; | ||
516 | |||
517 | /* region 3: PRD table *********************************** */ | ||
518 | buf_prd = buf_tmp; | ||
519 | if (tei->n_elem) | ||
520 | hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); | ||
521 | else | ||
522 | hdr->prd_tbl = 0; | ||
523 | |||
524 | i = MVS_CHIP_DISP->prd_size() * tei->n_elem; | ||
525 | buf_tmp += i; | ||
526 | buf_tmp_dma += i; | ||
527 | |||
528 | /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ | ||
529 | slot->response = buf_tmp; | ||
530 | hdr->status_buf = cpu_to_le64(buf_tmp_dma); | ||
531 | if (mvi->flags & MVF_FLAG_SOC) | ||
532 | hdr->reserved[0] = 0; | ||
533 | |||
534 | /* | ||
535 | * Fill in TX ring and command slot header | ||
536 | */ | ||
537 | slot->tx = mvi->tx_prod; | ||
538 | mvi->tx[mvi->tx_prod] = cpu_to_le32((TXQ_CMD_SMP << TXQ_CMD_SHIFT) | | ||
539 | TXQ_MODE_I | tag | | ||
540 | (sas_port->phy_mask << TXQ_PHY_SHIFT)); | ||
541 | |||
542 | hdr->flags |= flags; | ||
543 | hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | ((req_len - 4) / 4)); | ||
544 | hdr->tags = cpu_to_le32(tag); | ||
545 | hdr->data_len = 0; | ||
546 | |||
547 | /* generate open address frame hdr (first 12 bytes) */ | ||
548 | /* initiator, SMP, ftype 1h */ | ||
549 | buf_oaf[0] = (1 << 7) | (PROTOCOL_SMP << 4) | 0x01; | ||
550 | buf_oaf[1] = dev->linkrate & 0xf; | ||
551 | *(u16 *)(buf_oaf + 2) = 0xFFFF; /* SAS SPEC */ | ||
552 | memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE); | ||
553 | |||
554 | /* fill in PRD (scatter/gather) table, if any */ | ||
555 | MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); | ||
556 | |||
557 | #if _MV_DUMP | ||
558 | /* copy cmd table */ | ||
559 | from = kmap_atomic(sg_page(sg_req), KM_IRQ0); | ||
560 | memcpy(buf_cmd, from + sg_req->offset, req_len); | ||
561 | kunmap_atomic(from, KM_IRQ0); | ||
562 | #endif | ||
563 | return 0; | ||
564 | |||
565 | err_out_2: | ||
566 | dma_unmap_sg(mvi->dev, &tei->task->smp_task.smp_resp, 1, | ||
567 | PCI_DMA_FROMDEVICE); | ||
568 | err_out: | ||
569 | dma_unmap_sg(mvi->dev, &tei->task->smp_task.smp_req, 1, | ||
570 | PCI_DMA_TODEVICE); | ||
571 | return rc; | ||
572 | } | ||
573 | |||
574 | static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag) | ||
575 | { | ||
576 | struct ata_queued_cmd *qc = task->uldd_task; | ||
577 | |||
578 | if (qc) { | ||
579 | if (qc->tf.command == ATA_CMD_FPDMA_WRITE || | ||
580 | qc->tf.command == ATA_CMD_FPDMA_READ) { | ||
581 | *tag = qc->tag; | ||
582 | return 1; | ||
583 | } | ||
584 | } | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static int mvs_task_prep_ata(struct mvs_info *mvi, | ||
590 | struct mvs_task_exec_info *tei) | ||
591 | { | ||
592 | struct sas_task *task = tei->task; | ||
593 | struct domain_device *dev = task->dev; | ||
594 | struct mvs_device *mvi_dev = dev->lldd_dev; | ||
595 | struct mvs_cmd_hdr *hdr = tei->hdr; | ||
596 | struct asd_sas_port *sas_port = dev->port; | ||
597 | struct mvs_slot_info *slot; | ||
598 | void *buf_prd; | ||
599 | u32 tag = tei->tag, hdr_tag; | ||
600 | u32 flags, del_q; | ||
601 | void *buf_tmp; | ||
602 | u8 *buf_cmd, *buf_oaf; | ||
603 | dma_addr_t buf_tmp_dma; | ||
604 | u32 i, req_len, resp_len; | ||
605 | const u32 max_resp_len = SB_RFB_MAX; | ||
606 | |||
607 | if (mvs_assign_reg_set(mvi, mvi_dev) == MVS_ID_NOT_MAPPED) { | ||
608 | mv_dprintk("Have not enough regiset for dev %d.\n", | ||
609 | mvi_dev->device_id); | ||
610 | return -EBUSY; | ||
611 | } | ||
612 | slot = &mvi->slot_info[tag]; | ||
613 | slot->tx = mvi->tx_prod; | ||
614 | del_q = TXQ_MODE_I | tag | | ||
615 | (TXQ_CMD_STP << TXQ_CMD_SHIFT) | | ||
616 | (sas_port->phy_mask << TXQ_PHY_SHIFT) | | ||
617 | (mvi_dev->taskfileset << TXQ_SRS_SHIFT); | ||
618 | mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q); | ||
619 | |||
620 | #ifndef DISABLE_HOTPLUG_DMA_FIX | ||
621 | if (task->data_dir == DMA_FROM_DEVICE) | ||
622 | flags = (MVS_CHIP_DISP->prd_count() << MCH_PRD_LEN_SHIFT); | ||
623 | else | ||
624 | flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); | ||
625 | #else | ||
626 | flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); | ||
627 | #endif | ||
628 | if (task->ata_task.use_ncq) | ||
629 | flags |= MCH_FPDMA; | ||
630 | if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) { | ||
631 | if (task->ata_task.fis.command != ATA_CMD_ID_ATAPI) | ||
632 | flags |= MCH_ATAPI; | ||
633 | } | ||
634 | |||
635 | /* FIXME: fill in port multiplier number */ | ||
636 | |||
637 | hdr->flags = cpu_to_le32(flags); | ||
638 | |||
639 | /* FIXME: the low order order 5 bits for the TAG if enable NCQ */ | ||
640 | if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr_tag)) | ||
641 | task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3); | ||
642 | else | ||
643 | hdr_tag = tag; | ||
644 | |||
645 | hdr->tags = cpu_to_le32(hdr_tag); | ||
646 | |||
647 | hdr->data_len = cpu_to_le32(task->total_xfer_len); | ||
648 | |||
649 | /* | ||
650 | * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs | ||
651 | */ | ||
652 | |||
653 | /* region 1: command table area (MVS_ATA_CMD_SZ bytes) ************** */ | ||
654 | buf_cmd = buf_tmp = slot->buf; | ||
655 | buf_tmp_dma = slot->buf_dma; | ||
656 | |||
657 | hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); | ||
658 | |||
659 | buf_tmp += MVS_ATA_CMD_SZ; | ||
660 | buf_tmp_dma += MVS_ATA_CMD_SZ; | ||
661 | #if _MV_DUMP | ||
662 | slot->cmd_size = MVS_ATA_CMD_SZ; | ||
663 | #endif | ||
664 | |||
665 | /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ | ||
666 | /* used for STP. unused for SATA? */ | ||
667 | buf_oaf = buf_tmp; | ||
668 | hdr->open_frame = cpu_to_le64(buf_tmp_dma); | ||
669 | |||
670 | buf_tmp += MVS_OAF_SZ; | ||
671 | buf_tmp_dma += MVS_OAF_SZ; | ||
672 | |||
673 | /* region 3: PRD table ********************************************* */ | ||
674 | buf_prd = buf_tmp; | ||
675 | |||
676 | if (tei->n_elem) | ||
677 | hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); | ||
678 | else | ||
679 | hdr->prd_tbl = 0; | ||
680 | i = MVS_CHIP_DISP->prd_size() * MVS_CHIP_DISP->prd_count(); | ||
681 | |||
682 | buf_tmp += i; | ||
683 | buf_tmp_dma += i; | ||
684 | |||
685 | /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ | ||
686 | /* FIXME: probably unused, for SATA. kept here just in case | ||
687 | * we get a STP/SATA error information record | ||
688 | */ | ||
689 | slot->response = buf_tmp; | ||
690 | hdr->status_buf = cpu_to_le64(buf_tmp_dma); | ||
691 | if (mvi->flags & MVF_FLAG_SOC) | ||
692 | hdr->reserved[0] = 0; | ||
693 | |||
694 | req_len = sizeof(struct host_to_dev_fis); | ||
695 | resp_len = MVS_SLOT_BUF_SZ - MVS_ATA_CMD_SZ - | ||
696 | sizeof(struct mvs_err_info) - i; | ||
697 | |||
698 | /* request, response lengths */ | ||
699 | resp_len = min(resp_len, max_resp_len); | ||
700 | hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4)); | ||
701 | |||
702 | if (likely(!task->ata_task.device_control_reg_update)) | ||
703 | task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */ | ||
704 | /* fill in command FIS and ATAPI CDB */ | ||
705 | memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis)); | ||
706 | if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) | ||
707 | memcpy(buf_cmd + STP_ATAPI_CMD, | ||
708 | task->ata_task.atapi_packet, 16); | ||
709 | |||
710 | /* generate open address frame hdr (first 12 bytes) */ | ||
711 | /* initiator, STP, ftype 1h */ | ||
712 | buf_oaf[0] = (1 << 7) | (PROTOCOL_STP << 4) | 0x1; | ||
713 | buf_oaf[1] = dev->linkrate & 0xf; | ||
714 | *(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1); | ||
715 | memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE); | ||
716 | |||
717 | /* fill in PRD (scatter/gather) table, if any */ | ||
718 | MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); | ||
719 | #ifndef DISABLE_HOTPLUG_DMA_FIX | ||
720 | if (task->data_dir == DMA_FROM_DEVICE) | ||
721 | MVS_CHIP_DISP->dma_fix(mvi->bulk_buffer_dma, | ||
722 | TRASH_BUCKET_SIZE, tei->n_elem, buf_prd); | ||
723 | #endif | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | static int mvs_task_prep_ssp(struct mvs_info *mvi, | ||
728 | struct mvs_task_exec_info *tei, int is_tmf, | ||
729 | struct mvs_tmf_task *tmf) | ||
730 | { | ||
731 | struct sas_task *task = tei->task; | ||
732 | struct mvs_cmd_hdr *hdr = tei->hdr; | ||
733 | struct mvs_port *port = tei->port; | ||
734 | struct domain_device *dev = task->dev; | ||
735 | struct mvs_device *mvi_dev = dev->lldd_dev; | ||
736 | struct asd_sas_port *sas_port = dev->port; | ||
737 | struct mvs_slot_info *slot; | ||
738 | void *buf_prd; | ||
739 | struct ssp_frame_hdr *ssp_hdr; | ||
740 | void *buf_tmp; | ||
741 | u8 *buf_cmd, *buf_oaf, fburst = 0; | ||
742 | dma_addr_t buf_tmp_dma; | ||
743 | u32 flags; | ||
744 | u32 resp_len, req_len, i, tag = tei->tag; | ||
745 | const u32 max_resp_len = SB_RFB_MAX; | ||
746 | u32 phy_mask; | ||
747 | |||
748 | slot = &mvi->slot_info[tag]; | ||
749 | |||
750 | phy_mask = ((port->wide_port_phymap) ? port->wide_port_phymap : | ||
751 | sas_port->phy_mask) & TXQ_PHY_MASK; | ||
752 | |||
753 | slot->tx = mvi->tx_prod; | ||
754 | mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag | | ||
755 | (TXQ_CMD_SSP << TXQ_CMD_SHIFT) | | ||
756 | (phy_mask << TXQ_PHY_SHIFT)); | ||
757 | |||
758 | flags = MCH_RETRY; | ||
759 | if (task->ssp_task.enable_first_burst) { | ||
760 | flags |= MCH_FBURST; | ||
761 | fburst = (1 << 7); | ||
762 | } | ||
763 | if (is_tmf) | ||
764 | flags |= (MCH_SSP_FR_TASK << MCH_SSP_FR_TYPE_SHIFT); | ||
765 | else | ||
766 | flags |= (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT); | ||
767 | hdr->flags = cpu_to_le32(flags | (tei->n_elem << MCH_PRD_LEN_SHIFT)); | ||
768 | hdr->tags = cpu_to_le32(tag); | ||
769 | hdr->data_len = cpu_to_le32(task->total_xfer_len); | ||
770 | |||
771 | /* | ||
772 | * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs | ||
773 | */ | ||
774 | |||
775 | /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */ | ||
776 | buf_cmd = buf_tmp = slot->buf; | ||
777 | buf_tmp_dma = slot->buf_dma; | ||
778 | |||
779 | hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); | ||
780 | |||
781 | buf_tmp += MVS_SSP_CMD_SZ; | ||
782 | buf_tmp_dma += MVS_SSP_CMD_SZ; | ||
783 | #if _MV_DUMP | ||
784 | slot->cmd_size = MVS_SSP_CMD_SZ; | ||
785 | #endif | ||
786 | |||
787 | /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ | ||
788 | buf_oaf = buf_tmp; | ||
789 | hdr->open_frame = cpu_to_le64(buf_tmp_dma); | ||
790 | |||
791 | buf_tmp += MVS_OAF_SZ; | ||
792 | buf_tmp_dma += MVS_OAF_SZ; | ||
793 | |||
794 | /* region 3: PRD table ********************************************* */ | ||
795 | buf_prd = buf_tmp; | ||
796 | if (tei->n_elem) | ||
797 | hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); | ||
798 | else | ||
799 | hdr->prd_tbl = 0; | ||
800 | |||
801 | i = MVS_CHIP_DISP->prd_size() * tei->n_elem; | ||
802 | buf_tmp += i; | ||
803 | buf_tmp_dma += i; | ||
804 | |||
805 | /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ | ||
806 | slot->response = buf_tmp; | ||
807 | hdr->status_buf = cpu_to_le64(buf_tmp_dma); | ||
808 | if (mvi->flags & MVF_FLAG_SOC) | ||
809 | hdr->reserved[0] = 0; | ||
810 | |||
811 | resp_len = MVS_SLOT_BUF_SZ - MVS_SSP_CMD_SZ - MVS_OAF_SZ - | ||
812 | sizeof(struct mvs_err_info) - i; | ||
813 | resp_len = min(resp_len, max_resp_len); | ||
814 | |||
815 | req_len = sizeof(struct ssp_frame_hdr) + 28; | ||
816 | |||
817 | /* request, response lengths */ | ||
818 | hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4)); | ||
819 | |||
820 | /* generate open address frame hdr (first 12 bytes) */ | ||
821 | /* initiator, SSP, ftype 1h */ | ||
822 | buf_oaf[0] = (1 << 7) | (PROTOCOL_SSP << 4) | 0x1; | ||
823 | buf_oaf[1] = dev->linkrate & 0xf; | ||
824 | *(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1); | ||
825 | memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE); | ||
826 | |||
827 | /* fill in SSP frame header (Command Table.SSP frame header) */ | ||
828 | ssp_hdr = (struct ssp_frame_hdr *)buf_cmd; | ||
829 | |||
830 | if (is_tmf) | ||
831 | ssp_hdr->frame_type = SSP_TASK; | ||
832 | else | ||
833 | ssp_hdr->frame_type = SSP_COMMAND; | ||
834 | |||
835 | memcpy(ssp_hdr->hashed_dest_addr, dev->hashed_sas_addr, | ||
836 | HASHED_SAS_ADDR_SIZE); | ||
837 | memcpy(ssp_hdr->hashed_src_addr, | ||
838 | dev->hashed_sas_addr, HASHED_SAS_ADDR_SIZE); | ||
839 | ssp_hdr->tag = cpu_to_be16(tag); | ||
840 | |||
841 | /* fill in IU for TASK and Command Frame */ | ||
842 | buf_cmd += sizeof(*ssp_hdr); | ||
843 | memcpy(buf_cmd, &task->ssp_task.LUN, 8); | ||
844 | |||
845 | if (ssp_hdr->frame_type != SSP_TASK) { | ||
846 | buf_cmd[9] = fburst | task->ssp_task.task_attr | | ||
847 | (task->ssp_task.task_prio << 3); | ||
848 | memcpy(buf_cmd + 12, &task->ssp_task.cdb, 16); | ||
849 | } else{ | ||
850 | buf_cmd[10] = tmf->tmf; | ||
851 | switch (tmf->tmf) { | ||
852 | case TMF_ABORT_TASK: | ||
853 | case TMF_QUERY_TASK: | ||
854 | buf_cmd[12] = | ||
855 | (tmf->tag_of_task_to_be_managed >> 8) & 0xff; | ||
856 | buf_cmd[13] = | ||
857 | tmf->tag_of_task_to_be_managed & 0xff; | ||
858 | break; | ||
859 | default: | ||
860 | break; | ||
861 | } | ||
862 | } | ||
863 | /* fill in PRD (scatter/gather) table, if any */ | ||
864 | MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); | ||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | #define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == NO_DEVICE))) | ||
869 | static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, | ||
870 | struct completion *completion,int is_tmf, | ||
871 | struct mvs_tmf_task *tmf) | ||
872 | { | ||
873 | struct domain_device *dev = task->dev; | ||
874 | struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; | ||
875 | struct mvs_info *mvi = mvi_dev->mvi_info; | ||
876 | struct mvs_task_exec_info tei; | ||
877 | struct sas_task *t = task; | ||
878 | struct mvs_slot_info *slot; | ||
879 | u32 tag = 0xdeadbeef, rc, n_elem = 0; | ||
880 | u32 n = num, pass = 0; | ||
881 | unsigned long flags = 0; | ||
882 | |||
883 | if (!dev->port) { | ||
884 | struct task_status_struct *tsm = &t->task_status; | ||
885 | |||
886 | tsm->resp = SAS_TASK_UNDELIVERED; | ||
887 | tsm->stat = SAS_PHY_DOWN; | ||
888 | t->task_done(t); | ||
889 | return 0; | ||
890 | } | ||
891 | |||
892 | spin_lock_irqsave(&mvi->lock, flags); | ||
893 | do { | ||
894 | dev = t->dev; | ||
895 | mvi_dev = dev->lldd_dev; | ||
896 | if (DEV_IS_GONE(mvi_dev)) { | ||
897 | if (mvi_dev) | ||
898 | mv_dprintk("device %d not ready.\n", | ||
899 | mvi_dev->device_id); | ||
900 | else | ||
901 | mv_dprintk("device %016llx not ready.\n", | ||
902 | SAS_ADDR(dev->sas_addr)); | ||
903 | |||
904 | rc = SAS_PHY_DOWN; | ||
905 | goto out_done; | ||
906 | } | ||
907 | |||
908 | if (dev->port->id >= mvi->chip->n_phy) | ||
909 | tei.port = &mvi->port[dev->port->id - mvi->chip->n_phy]; | ||
910 | else | ||
911 | tei.port = &mvi->port[dev->port->id]; | ||
912 | |||
913 | if (!tei.port->port_attached) { | ||
914 | if (sas_protocol_ata(t->task_proto)) { | ||
915 | mv_dprintk("port %d does not" | ||
916 | "attached device.\n", dev->port->id); | ||
917 | rc = SAS_PHY_DOWN; | ||
918 | goto out_done; | ||
919 | } else { | ||
920 | struct task_status_struct *ts = &t->task_status; | ||
921 | ts->resp = SAS_TASK_UNDELIVERED; | ||
922 | ts->stat = SAS_PHY_DOWN; | ||
923 | t->task_done(t); | ||
924 | if (n > 1) | ||
925 | t = list_entry(t->list.next, | ||
926 | struct sas_task, list); | ||
927 | continue; | ||
928 | } | ||
929 | } | ||
930 | |||
931 | if (!sas_protocol_ata(t->task_proto)) { | ||
932 | if (t->num_scatter) { | ||
933 | n_elem = dma_map_sg(mvi->dev, | ||
934 | t->scatter, | ||
935 | t->num_scatter, | ||
936 | t->data_dir); | ||
937 | if (!n_elem) { | ||
938 | rc = -ENOMEM; | ||
939 | goto err_out; | ||
940 | } | ||
941 | } | ||
942 | } else { | ||
943 | n_elem = t->num_scatter; | ||
944 | } | ||
945 | |||
946 | rc = mvs_tag_alloc(mvi, &tag); | ||
947 | if (rc) | ||
948 | goto err_out; | ||
949 | |||
950 | slot = &mvi->slot_info[tag]; | ||
951 | |||
952 | |||
953 | t->lldd_task = NULL; | ||
954 | slot->n_elem = n_elem; | ||
955 | slot->slot_tag = tag; | ||
956 | memset(slot->buf, 0, MVS_SLOT_BUF_SZ); | ||
957 | |||
958 | tei.task = t; | ||
959 | tei.hdr = &mvi->slot[tag]; | ||
960 | tei.tag = tag; | ||
961 | tei.n_elem = n_elem; | ||
962 | switch (t->task_proto) { | ||
963 | case SAS_PROTOCOL_SMP: | ||
964 | rc = mvs_task_prep_smp(mvi, &tei); | ||
965 | break; | ||
966 | case SAS_PROTOCOL_SSP: | ||
967 | rc = mvs_task_prep_ssp(mvi, &tei, is_tmf, tmf); | ||
968 | break; | ||
969 | case SAS_PROTOCOL_SATA: | ||
970 | case SAS_PROTOCOL_STP: | ||
971 | case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: | ||
972 | rc = mvs_task_prep_ata(mvi, &tei); | ||
973 | break; | ||
974 | default: | ||
975 | dev_printk(KERN_ERR, mvi->dev, | ||
976 | "unknown sas_task proto: 0x%x\n", | ||
977 | t->task_proto); | ||
978 | rc = -EINVAL; | ||
979 | break; | ||
980 | } | ||
981 | |||
982 | if (rc) { | ||
983 | mv_dprintk("rc is %x\n", rc); | ||
984 | goto err_out_tag; | ||
985 | } | ||
986 | slot->task = t; | ||
987 | slot->port = tei.port; | ||
988 | t->lldd_task = slot; | ||
989 | list_add_tail(&slot->entry, &tei.port->list); | ||
990 | /* TODO: select normal or high priority */ | ||
991 | spin_lock(&t->task_state_lock); | ||
992 | t->task_state_flags |= SAS_TASK_AT_INITIATOR; | ||
993 | spin_unlock(&t->task_state_lock); | ||
994 | |||
995 | mvs_hba_memory_dump(mvi, tag, t->task_proto); | ||
996 | mvi_dev->runing_req++; | ||
997 | ++pass; | ||
998 | mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); | ||
999 | if (n > 1) | ||
1000 | t = list_entry(t->list.next, struct sas_task, list); | ||
1001 | } while (--n); | ||
1002 | rc = 0; | ||
1003 | goto out_done; | ||
1004 | |||
1005 | err_out_tag: | ||
1006 | mvs_tag_free(mvi, tag); | ||
1007 | err_out: | ||
1008 | |||
1009 | dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc); | ||
1010 | if (!sas_protocol_ata(t->task_proto)) | ||
1011 | if (n_elem) | ||
1012 | dma_unmap_sg(mvi->dev, t->scatter, n_elem, | ||
1013 | t->data_dir); | ||
1014 | out_done: | ||
1015 | if (likely(pass)) { | ||
1016 | MVS_CHIP_DISP->start_delivery(mvi, | ||
1017 | (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); | ||
1018 | } | ||
1019 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1020 | return rc; | ||
1021 | } | ||
1022 | |||
1023 | int mvs_queue_command(struct sas_task *task, const int num, | ||
1024 | gfp_t gfp_flags) | ||
1025 | { | ||
1026 | return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL); | ||
1027 | } | ||
1028 | |||
1029 | static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc) | ||
1030 | { | ||
1031 | u32 slot_idx = rx_desc & RXQ_SLOT_MASK; | ||
1032 | mvs_tag_clear(mvi, slot_idx); | ||
1033 | } | ||
1034 | |||
1035 | static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task, | ||
1036 | struct mvs_slot_info *slot, u32 slot_idx) | ||
1037 | { | ||
1038 | if (!slot->task) | ||
1039 | return; | ||
1040 | if (!sas_protocol_ata(task->task_proto)) | ||
1041 | if (slot->n_elem) | ||
1042 | dma_unmap_sg(mvi->dev, task->scatter, | ||
1043 | slot->n_elem, task->data_dir); | ||
1044 | |||
1045 | switch (task->task_proto) { | ||
1046 | case SAS_PROTOCOL_SMP: | ||
1047 | dma_unmap_sg(mvi->dev, &task->smp_task.smp_resp, 1, | ||
1048 | PCI_DMA_FROMDEVICE); | ||
1049 | dma_unmap_sg(mvi->dev, &task->smp_task.smp_req, 1, | ||
1050 | PCI_DMA_TODEVICE); | ||
1051 | break; | ||
1052 | |||
1053 | case SAS_PROTOCOL_SATA: | ||
1054 | case SAS_PROTOCOL_STP: | ||
1055 | case SAS_PROTOCOL_SSP: | ||
1056 | default: | ||
1057 | /* do nothing */ | ||
1058 | break; | ||
1059 | } | ||
1060 | list_del_init(&slot->entry); | ||
1061 | task->lldd_task = NULL; | ||
1062 | slot->task = NULL; | ||
1063 | slot->port = NULL; | ||
1064 | slot->slot_tag = 0xFFFFFFFF; | ||
1065 | mvs_slot_free(mvi, slot_idx); | ||
1066 | } | ||
1067 | |||
1068 | static void mvs_update_wideport(struct mvs_info *mvi, int i) | ||
1069 | { | ||
1070 | struct mvs_phy *phy = &mvi->phy[i]; | ||
1071 | struct mvs_port *port = phy->port; | ||
1072 | int j, no; | ||
1073 | |||
1074 | for_each_phy(port->wide_port_phymap, j, no) { | ||
1075 | if (j & 1) { | ||
1076 | MVS_CHIP_DISP->write_port_cfg_addr(mvi, no, | ||
1077 | PHYR_WIDE_PORT); | ||
1078 | MVS_CHIP_DISP->write_port_cfg_data(mvi, no, | ||
1079 | port->wide_port_phymap); | ||
1080 | } else { | ||
1081 | MVS_CHIP_DISP->write_port_cfg_addr(mvi, no, | ||
1082 | PHYR_WIDE_PORT); | ||
1083 | MVS_CHIP_DISP->write_port_cfg_data(mvi, no, | ||
1084 | 0); | ||
1085 | } | ||
1086 | } | ||
1087 | } | ||
1088 | |||
1089 | static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i) | ||
1090 | { | ||
1091 | u32 tmp; | ||
1092 | struct mvs_phy *phy = &mvi->phy[i]; | ||
1093 | struct mvs_port *port = phy->port; | ||
1094 | |||
1095 | tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, i); | ||
1096 | if ((tmp & PHY_READY_MASK) && !(phy->irq_status & PHYEV_POOF)) { | ||
1097 | if (!port) | ||
1098 | phy->phy_attached = 1; | ||
1099 | return tmp; | ||
1100 | } | ||
1101 | |||
1102 | if (port) { | ||
1103 | if (phy->phy_type & PORT_TYPE_SAS) { | ||
1104 | port->wide_port_phymap &= ~(1U << i); | ||
1105 | if (!port->wide_port_phymap) | ||
1106 | port->port_attached = 0; | ||
1107 | mvs_update_wideport(mvi, i); | ||
1108 | } else if (phy->phy_type & PORT_TYPE_SATA) | ||
1109 | port->port_attached = 0; | ||
1110 | phy->port = NULL; | ||
1111 | phy->phy_attached = 0; | ||
1112 | phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); | ||
1113 | } | ||
1114 | return 0; | ||
1115 | } | ||
1116 | |||
1117 | static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf) | ||
1118 | { | ||
1119 | u32 *s = (u32 *) buf; | ||
1120 | |||
1121 | if (!s) | ||
1122 | return NULL; | ||
1123 | |||
1124 | MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3); | ||
1125 | s[3] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); | ||
1126 | |||
1127 | MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2); | ||
1128 | s[2] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); | ||
1129 | |||
1130 | MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1); | ||
1131 | s[1] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); | ||
1132 | |||
1133 | MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0); | ||
1134 | s[0] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); | ||
1135 | |||
1136 | /* Workaround: take some ATAPI devices for ATA */ | ||
1137 | if (((s[1] & 0x00FFFFFF) == 0x00EB1401) && (*(u8 *)&s[3] == 0x01)) | ||
1138 | s[1] = 0x00EB1401 | (*((u8 *)&s[1] + 3) & 0x10); | ||
1139 | |||
1140 | return s; | ||
1141 | } | ||
1142 | |||
1143 | static u32 mvs_is_sig_fis_received(u32 irq_status) | ||
1144 | { | ||
1145 | return irq_status & PHYEV_SIG_FIS; | ||
1146 | } | ||
1147 | |||
1148 | void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st) | ||
1149 | { | ||
1150 | struct mvs_phy *phy = &mvi->phy[i]; | ||
1151 | struct sas_identify_frame *id; | ||
1152 | |||
1153 | id = (struct sas_identify_frame *)phy->frame_rcvd; | ||
1154 | |||
1155 | if (get_st) { | ||
1156 | phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, i); | ||
1157 | phy->phy_status = mvs_is_phy_ready(mvi, i); | ||
1158 | } | ||
1159 | |||
1160 | if (phy->phy_status) { | ||
1161 | int oob_done = 0; | ||
1162 | struct asd_sas_phy *sas_phy = &mvi->phy[i].sas_phy; | ||
1163 | |||
1164 | oob_done = MVS_CHIP_DISP->oob_done(mvi, i); | ||
1165 | |||
1166 | MVS_CHIP_DISP->fix_phy_info(mvi, i, id); | ||
1167 | if (phy->phy_type & PORT_TYPE_SATA) { | ||
1168 | phy->identify.target_port_protocols = SAS_PROTOCOL_STP; | ||
1169 | if (mvs_is_sig_fis_received(phy->irq_status)) { | ||
1170 | phy->phy_attached = 1; | ||
1171 | phy->att_dev_sas_addr = | ||
1172 | i + mvi->id * mvi->chip->n_phy; | ||
1173 | if (oob_done) | ||
1174 | sas_phy->oob_mode = SATA_OOB_MODE; | ||
1175 | phy->frame_rcvd_size = | ||
1176 | sizeof(struct dev_to_host_fis); | ||
1177 | mvs_get_d2h_reg(mvi, i, id); | ||
1178 | } else { | ||
1179 | u32 tmp; | ||
1180 | dev_printk(KERN_DEBUG, mvi->dev, | ||
1181 | "Phy%d : No sig fis\n", i); | ||
1182 | tmp = MVS_CHIP_DISP->read_port_irq_mask(mvi, i); | ||
1183 | MVS_CHIP_DISP->write_port_irq_mask(mvi, i, | ||
1184 | tmp | PHYEV_SIG_FIS); | ||
1185 | phy->phy_attached = 0; | ||
1186 | phy->phy_type &= ~PORT_TYPE_SATA; | ||
1187 | MVS_CHIP_DISP->phy_reset(mvi, i, 0); | ||
1188 | goto out_done; | ||
1189 | } | ||
1190 | } else if (phy->phy_type & PORT_TYPE_SAS | ||
1191 | || phy->att_dev_info & PORT_SSP_INIT_MASK) { | ||
1192 | phy->phy_attached = 1; | ||
1193 | phy->identify.device_type = | ||
1194 | phy->att_dev_info & PORT_DEV_TYPE_MASK; | ||
1195 | |||
1196 | if (phy->identify.device_type == SAS_END_DEV) | ||
1197 | phy->identify.target_port_protocols = | ||
1198 | SAS_PROTOCOL_SSP; | ||
1199 | else if (phy->identify.device_type != NO_DEVICE) | ||
1200 | phy->identify.target_port_protocols = | ||
1201 | SAS_PROTOCOL_SMP; | ||
1202 | if (oob_done) | ||
1203 | sas_phy->oob_mode = SAS_OOB_MODE; | ||
1204 | phy->frame_rcvd_size = | ||
1205 | sizeof(struct sas_identify_frame); | ||
1206 | } | ||
1207 | memcpy(sas_phy->attached_sas_addr, | ||
1208 | &phy->att_dev_sas_addr, SAS_ADDR_SIZE); | ||
1209 | |||
1210 | if (MVS_CHIP_DISP->phy_work_around) | ||
1211 | MVS_CHIP_DISP->phy_work_around(mvi, i); | ||
1212 | } | ||
1213 | mv_dprintk("port %d attach dev info is %x\n", | ||
1214 | i + mvi->id * mvi->chip->n_phy, phy->att_dev_info); | ||
1215 | mv_dprintk("port %d attach sas addr is %llx\n", | ||
1216 | i + mvi->id * mvi->chip->n_phy, phy->att_dev_sas_addr); | ||
1217 | out_done: | ||
1218 | if (get_st) | ||
1219 | MVS_CHIP_DISP->write_port_irq_stat(mvi, i, phy->irq_status); | ||
1220 | } | ||
1221 | |||
1222 | static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock) | ||
1223 | { | ||
1224 | struct sas_ha_struct *sas_ha = sas_phy->ha; | ||
1225 | struct mvs_info *mvi = NULL; int i = 0, hi; | ||
1226 | struct mvs_phy *phy = sas_phy->lldd_phy; | ||
1227 | struct asd_sas_port *sas_port = sas_phy->port; | ||
1228 | struct mvs_port *port; | ||
1229 | unsigned long flags = 0; | ||
1230 | if (!sas_port) | ||
1231 | return; | ||
1232 | |||
1233 | while (sas_ha->sas_phy[i]) { | ||
1234 | if (sas_ha->sas_phy[i] == sas_phy) | ||
1235 | break; | ||
1236 | i++; | ||
1237 | } | ||
1238 | hi = i/((struct mvs_prv_info *)sas_ha->lldd_ha)->n_phy; | ||
1239 | mvi = ((struct mvs_prv_info *)sas_ha->lldd_ha)->mvi[hi]; | ||
1240 | if (sas_port->id >= mvi->chip->n_phy) | ||
1241 | port = &mvi->port[sas_port->id - mvi->chip->n_phy]; | ||
1242 | else | ||
1243 | port = &mvi->port[sas_port->id]; | ||
1244 | if (lock) | ||
1245 | spin_lock_irqsave(&mvi->lock, flags); | ||
1246 | port->port_attached = 1; | ||
1247 | phy->port = port; | ||
1248 | if (phy->phy_type & PORT_TYPE_SAS) { | ||
1249 | port->wide_port_phymap = sas_port->phy_mask; | ||
1250 | mv_printk("set wide port phy map %x\n", sas_port->phy_mask); | ||
1251 | mvs_update_wideport(mvi, sas_phy->id); | ||
1252 | } | ||
1253 | if (lock) | ||
1254 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1255 | } | ||
1256 | |||
1257 | static void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock) | ||
1258 | { | ||
1259 | /*Nothing*/ | ||
1260 | } | ||
1261 | |||
1262 | |||
1263 | void mvs_port_formed(struct asd_sas_phy *sas_phy) | ||
1264 | { | ||
1265 | mvs_port_notify_formed(sas_phy, 1); | ||
1266 | } | ||
1267 | |||
1268 | void mvs_port_deformed(struct asd_sas_phy *sas_phy) | ||
1269 | { | ||
1270 | mvs_port_notify_deformed(sas_phy, 1); | ||
1271 | } | ||
1272 | |||
1273 | struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi) | ||
1274 | { | ||
1275 | u32 dev; | ||
1276 | for (dev = 0; dev < MVS_MAX_DEVICES; dev++) { | ||
1277 | if (mvi->devices[dev].dev_type == NO_DEVICE) { | ||
1278 | mvi->devices[dev].device_id = dev; | ||
1279 | return &mvi->devices[dev]; | ||
1280 | } | ||
1281 | } | ||
1282 | |||
1283 | if (dev == MVS_MAX_DEVICES) | ||
1284 | mv_printk("max support %d devices, ignore ..\n", | ||
1285 | MVS_MAX_DEVICES); | ||
1286 | |||
1287 | return NULL; | ||
1288 | } | ||
1289 | |||
1290 | void mvs_free_dev(struct mvs_device *mvi_dev) | ||
1291 | { | ||
1292 | u32 id = mvi_dev->device_id; | ||
1293 | memset(mvi_dev, 0, sizeof(*mvi_dev)); | ||
1294 | mvi_dev->device_id = id; | ||
1295 | mvi_dev->dev_type = NO_DEVICE; | ||
1296 | mvi_dev->dev_status = MVS_DEV_NORMAL; | ||
1297 | mvi_dev->taskfileset = MVS_ID_NOT_MAPPED; | ||
1298 | } | ||
1299 | |||
1300 | int mvs_dev_found_notify(struct domain_device *dev, int lock) | ||
1301 | { | ||
1302 | unsigned long flags = 0; | ||
1303 | int res = 0; | ||
1304 | struct mvs_info *mvi = NULL; | ||
1305 | struct domain_device *parent_dev = dev->parent; | ||
1306 | struct mvs_device *mvi_device; | ||
1307 | |||
1308 | mvi = mvs_find_dev_mvi(dev); | ||
1309 | |||
1310 | if (lock) | ||
1311 | spin_lock_irqsave(&mvi->lock, flags); | ||
1312 | |||
1313 | mvi_device = mvs_alloc_dev(mvi); | ||
1314 | if (!mvi_device) { | ||
1315 | res = -1; | ||
1316 | goto found_out; | ||
1317 | } | ||
1318 | dev->lldd_dev = mvi_device; | ||
1319 | mvi_device->dev_type = dev->dev_type; | ||
1320 | mvi_device->mvi_info = mvi; | ||
1321 | if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { | ||
1322 | int phy_id; | ||
1323 | u8 phy_num = parent_dev->ex_dev.num_phys; | ||
1324 | struct ex_phy *phy; | ||
1325 | for (phy_id = 0; phy_id < phy_num; phy_id++) { | ||
1326 | phy = &parent_dev->ex_dev.ex_phy[phy_id]; | ||
1327 | if (SAS_ADDR(phy->attached_sas_addr) == | ||
1328 | SAS_ADDR(dev->sas_addr)) { | ||
1329 | mvi_device->attached_phy = phy_id; | ||
1330 | break; | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | if (phy_id == phy_num) { | ||
1335 | mv_printk("Error: no attached dev:%016llx" | ||
1336 | "at ex:%016llx.\n", | ||
1337 | SAS_ADDR(dev->sas_addr), | ||
1338 | SAS_ADDR(parent_dev->sas_addr)); | ||
1339 | res = -1; | ||
1340 | } | ||
1341 | } | ||
1342 | |||
1343 | found_out: | ||
1344 | if (lock) | ||
1345 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1346 | return res; | ||
1347 | } | ||
1348 | |||
1349 | int mvs_dev_found(struct domain_device *dev) | ||
1350 | { | ||
1351 | return mvs_dev_found_notify(dev, 1); | ||
1352 | } | ||
1353 | |||
1354 | void mvs_dev_gone_notify(struct domain_device *dev, int lock) | ||
1355 | { | ||
1356 | unsigned long flags = 0; | ||
1357 | struct mvs_device *mvi_dev = dev->lldd_dev; | ||
1358 | struct mvs_info *mvi = mvi_dev->mvi_info; | ||
1359 | |||
1360 | if (lock) | ||
1361 | spin_lock_irqsave(&mvi->lock, flags); | ||
1362 | |||
1363 | if (mvi_dev) { | ||
1364 | mv_dprintk("found dev[%d:%x] is gone.\n", | ||
1365 | mvi_dev->device_id, mvi_dev->dev_type); | ||
1366 | mvs_free_reg_set(mvi, mvi_dev); | ||
1367 | mvs_free_dev(mvi_dev); | ||
1368 | } else { | ||
1369 | mv_dprintk("found dev has gone.\n"); | ||
1370 | } | ||
1371 | dev->lldd_dev = NULL; | ||
1372 | |||
1373 | if (lock) | ||
1374 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1375 | } | ||
1376 | |||
1377 | |||
1378 | void mvs_dev_gone(struct domain_device *dev) | ||
1379 | { | ||
1380 | mvs_dev_gone_notify(dev, 1); | ||
1381 | } | ||
1382 | |||
1383 | static struct sas_task *mvs_alloc_task(void) | ||
1384 | { | ||
1385 | struct sas_task *task = kzalloc(sizeof(struct sas_task), GFP_KERNEL); | ||
1386 | |||
1387 | if (task) { | ||
1388 | INIT_LIST_HEAD(&task->list); | ||
1389 | spin_lock_init(&task->task_state_lock); | ||
1390 | task->task_state_flags = SAS_TASK_STATE_PENDING; | ||
1391 | init_timer(&task->timer); | ||
1392 | init_completion(&task->completion); | ||
1393 | } | ||
1394 | return task; | ||
1395 | } | ||
1396 | |||
1397 | static void mvs_free_task(struct sas_task *task) | ||
1398 | { | ||
1399 | if (task) { | ||
1400 | BUG_ON(!list_empty(&task->list)); | ||
1401 | kfree(task); | ||
1402 | } | ||
1403 | } | ||
1404 | |||
1405 | static void mvs_task_done(struct sas_task *task) | ||
1406 | { | ||
1407 | if (!del_timer(&task->timer)) | ||
1408 | return; | ||
1409 | complete(&task->completion); | ||
1410 | } | ||
1411 | |||
1412 | static void mvs_tmf_timedout(unsigned long data) | ||
1413 | { | ||
1414 | struct sas_task *task = (struct sas_task *)data; | ||
1415 | |||
1416 | task->task_state_flags |= SAS_TASK_STATE_ABORTED; | ||
1417 | complete(&task->completion); | ||
1418 | } | ||
1419 | |||
1420 | /* XXX */ | ||
1421 | #define MVS_TASK_TIMEOUT 20 | ||
1422 | static int mvs_exec_internal_tmf_task(struct domain_device *dev, | ||
1423 | void *parameter, u32 para_len, struct mvs_tmf_task *tmf) | ||
1424 | { | ||
1425 | int res, retry; | ||
1426 | struct sas_task *task = NULL; | ||
1427 | |||
1428 | for (retry = 0; retry < 3; retry++) { | ||
1429 | task = mvs_alloc_task(); | ||
1430 | if (!task) | ||
1431 | return -ENOMEM; | ||
1432 | |||
1433 | task->dev = dev; | ||
1434 | task->task_proto = dev->tproto; | ||
1435 | |||
1436 | memcpy(&task->ssp_task, parameter, para_len); | ||
1437 | task->task_done = mvs_task_done; | ||
1438 | |||
1439 | task->timer.data = (unsigned long) task; | ||
1440 | task->timer.function = mvs_tmf_timedout; | ||
1441 | task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ; | ||
1442 | add_timer(&task->timer); | ||
1443 | |||
1444 | res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, tmf); | ||
1445 | |||
1446 | if (res) { | ||
1447 | del_timer(&task->timer); | ||
1448 | mv_printk("executing internel task failed:%d\n", res); | ||
1449 | goto ex_err; | ||
1450 | } | ||
1451 | |||
1452 | wait_for_completion(&task->completion); | ||
1453 | res = -TMF_RESP_FUNC_FAILED; | ||
1454 | /* Even TMF timed out, return direct. */ | ||
1455 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | ||
1456 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | ||
1457 | mv_printk("TMF task[%x] timeout.\n", tmf->tmf); | ||
1458 | goto ex_err; | ||
1459 | } | ||
1460 | } | ||
1461 | |||
1462 | if (task->task_status.resp == SAS_TASK_COMPLETE && | ||
1463 | task->task_status.stat == SAM_GOOD) { | ||
1464 | res = TMF_RESP_FUNC_COMPLETE; | ||
1465 | break; | ||
1466 | } | ||
1467 | |||
1468 | if (task->task_status.resp == SAS_TASK_COMPLETE && | ||
1469 | task->task_status.stat == SAS_DATA_UNDERRUN) { | ||
1470 | /* no error, but return the number of bytes of | ||
1471 | * underrun */ | ||
1472 | res = task->task_status.residual; | ||
1473 | break; | ||
1474 | } | ||
1475 | |||
1476 | if (task->task_status.resp == SAS_TASK_COMPLETE && | ||
1477 | task->task_status.stat == SAS_DATA_OVERRUN) { | ||
1478 | mv_dprintk("blocked task error.\n"); | ||
1479 | res = -EMSGSIZE; | ||
1480 | break; | ||
1481 | } else { | ||
1482 | mv_dprintk(" task to dev %016llx response: 0x%x " | ||
1483 | "status 0x%x\n", | ||
1484 | SAS_ADDR(dev->sas_addr), | ||
1485 | task->task_status.resp, | ||
1486 | task->task_status.stat); | ||
1487 | mvs_free_task(task); | ||
1488 | task = NULL; | ||
1489 | |||
1490 | } | ||
1491 | } | ||
1492 | ex_err: | ||
1493 | BUG_ON(retry == 3 && task != NULL); | ||
1494 | if (task != NULL) | ||
1495 | mvs_free_task(task); | ||
1496 | return res; | ||
1497 | } | ||
1498 | |||
1499 | static int mvs_debug_issue_ssp_tmf(struct domain_device *dev, | ||
1500 | u8 *lun, struct mvs_tmf_task *tmf) | ||
1501 | { | ||
1502 | struct sas_ssp_task ssp_task; | ||
1503 | DECLARE_COMPLETION_ONSTACK(completion); | ||
1504 | if (!(dev->tproto & SAS_PROTOCOL_SSP)) | ||
1505 | return TMF_RESP_FUNC_ESUPP; | ||
1506 | |||
1507 | strncpy((u8 *)&ssp_task.LUN, lun, 8); | ||
1508 | |||
1509 | return mvs_exec_internal_tmf_task(dev, &ssp_task, | ||
1510 | sizeof(ssp_task), tmf); | ||
1511 | } | ||
1512 | |||
1513 | |||
1514 | /* Standard mandates link reset for ATA (type 0) | ||
1515 | and hard reset for SSP (type 1) , only for RECOVERY */ | ||
1516 | static int mvs_debug_I_T_nexus_reset(struct domain_device *dev) | ||
1517 | { | ||
1518 | int rc; | ||
1519 | struct sas_phy *phy = sas_find_local_phy(dev); | ||
1520 | int reset_type = (dev->dev_type == SATA_DEV || | ||
1521 | (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; | ||
1522 | rc = sas_phy_reset(phy, reset_type); | ||
1523 | msleep(2000); | ||
1524 | return rc; | ||
1525 | } | ||
1526 | |||
1527 | /* mandatory SAM-3 */ | ||
1528 | int mvs_lu_reset(struct domain_device *dev, u8 *lun) | ||
1529 | { | ||
1530 | unsigned long flags; | ||
1531 | int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED; | ||
1532 | struct mvs_tmf_task tmf_task; | ||
1533 | struct mvs_device * mvi_dev = dev->lldd_dev; | ||
1534 | struct mvs_info *mvi = mvi_dev->mvi_info; | ||
1535 | |||
1536 | tmf_task.tmf = TMF_LU_RESET; | ||
1537 | mvi_dev->dev_status = MVS_DEV_EH; | ||
1538 | rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); | ||
1539 | if (rc == TMF_RESP_FUNC_COMPLETE) { | ||
1540 | num = mvs_find_dev_phyno(dev, phyno); | ||
1541 | spin_lock_irqsave(&mvi->lock, flags); | ||
1542 | for (i = 0; i < num; i++) | ||
1543 | mvs_release_task(mvi, phyno[i], dev); | ||
1544 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1545 | } | ||
1546 | /* If failed, fall-through I_T_Nexus reset */ | ||
1547 | mv_printk("%s for device[%x]:rc= %d\n", __func__, | ||
1548 | mvi_dev->device_id, rc); | ||
1549 | return rc; | ||
1550 | } | ||
1551 | |||
1552 | int mvs_I_T_nexus_reset(struct domain_device *dev) | ||
1553 | { | ||
1554 | unsigned long flags; | ||
1555 | int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED; | ||
1556 | struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev; | ||
1557 | struct mvs_info *mvi = mvi_dev->mvi_info; | ||
1558 | |||
1559 | if (mvi_dev->dev_status != MVS_DEV_EH) | ||
1560 | return TMF_RESP_FUNC_COMPLETE; | ||
1561 | rc = mvs_debug_I_T_nexus_reset(dev); | ||
1562 | mv_printk("%s for device[%x]:rc= %d\n", | ||
1563 | __func__, mvi_dev->device_id, rc); | ||
1564 | |||
1565 | /* housekeeper */ | ||
1566 | num = mvs_find_dev_phyno(dev, phyno); | ||
1567 | spin_lock_irqsave(&mvi->lock, flags); | ||
1568 | for (i = 0; i < num; i++) | ||
1569 | mvs_release_task(mvi, phyno[i], dev); | ||
1570 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1571 | |||
1572 | return rc; | ||
1573 | } | ||
1574 | /* optional SAM-3 */ | ||
1575 | int mvs_query_task(struct sas_task *task) | ||
1576 | { | ||
1577 | u32 tag; | ||
1578 | struct scsi_lun lun; | ||
1579 | struct mvs_tmf_task tmf_task; | ||
1580 | int rc = TMF_RESP_FUNC_FAILED; | ||
1581 | |||
1582 | if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { | ||
1583 | struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task; | ||
1584 | struct domain_device *dev = task->dev; | ||
1585 | struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; | ||
1586 | struct mvs_info *mvi = mvi_dev->mvi_info; | ||
1587 | |||
1588 | int_to_scsilun(cmnd->device->lun, &lun); | ||
1589 | rc = mvs_find_tag(mvi, task, &tag); | ||
1590 | if (rc == 0) { | ||
1591 | rc = TMF_RESP_FUNC_FAILED; | ||
1592 | return rc; | ||
1593 | } | ||
1594 | |||
1595 | tmf_task.tmf = TMF_QUERY_TASK; | ||
1596 | tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); | ||
1597 | |||
1598 | rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task); | ||
1599 | switch (rc) { | ||
1600 | /* The task is still in Lun, release it then */ | ||
1601 | case TMF_RESP_FUNC_SUCC: | ||
1602 | /* The task is not in Lun or failed, reset the phy */ | ||
1603 | case TMF_RESP_FUNC_FAILED: | ||
1604 | case TMF_RESP_FUNC_COMPLETE: | ||
1605 | break; | ||
1606 | } | ||
1607 | } | ||
1608 | mv_printk("%s:rc= %d\n", __func__, rc); | ||
1609 | return rc; | ||
1610 | } | ||
1611 | |||
1612 | /* mandatory SAM-3, still need free task/slot info */ | ||
1613 | int mvs_abort_task(struct sas_task *task) | ||
1614 | { | ||
1615 | struct scsi_lun lun; | ||
1616 | struct mvs_tmf_task tmf_task; | ||
1617 | struct domain_device *dev = task->dev; | ||
1618 | struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; | ||
1619 | struct mvs_info *mvi = mvi_dev->mvi_info; | ||
1620 | int rc = TMF_RESP_FUNC_FAILED; | ||
1621 | unsigned long flags; | ||
1622 | u32 tag; | ||
1623 | |||
1624 | if (mvi->exp_req) | ||
1625 | mvi->exp_req--; | ||
1626 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
1627 | if (task->task_state_flags & SAS_TASK_STATE_DONE) { | ||
1628 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
1629 | rc = TMF_RESP_FUNC_COMPLETE; | ||
1630 | goto out; | ||
1631 | } | ||
1632 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
1633 | if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { | ||
1634 | struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task; | ||
1635 | |||
1636 | int_to_scsilun(cmnd->device->lun, &lun); | ||
1637 | rc = mvs_find_tag(mvi, task, &tag); | ||
1638 | if (rc == 0) { | ||
1639 | mv_printk("No such tag in %s\n", __func__); | ||
1640 | rc = TMF_RESP_FUNC_FAILED; | ||
1641 | return rc; | ||
1642 | } | ||
1643 | |||
1644 | tmf_task.tmf = TMF_ABORT_TASK; | ||
1645 | tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); | ||
1646 | |||
1647 | rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task); | ||
1648 | |||
1649 | /* if successful, clear the task and callback forwards.*/ | ||
1650 | if (rc == TMF_RESP_FUNC_COMPLETE) { | ||
1651 | u32 slot_no; | ||
1652 | struct mvs_slot_info *slot; | ||
1653 | |||
1654 | if (task->lldd_task) { | ||
1655 | slot = task->lldd_task; | ||
1656 | slot_no = (u32) (slot - mvi->slot_info); | ||
1657 | mvs_slot_complete(mvi, slot_no, 1); | ||
1658 | } | ||
1659 | } | ||
1660 | } else if (task->task_proto & SAS_PROTOCOL_SATA || | ||
1661 | task->task_proto & SAS_PROTOCOL_STP) { | ||
1662 | /* to do free register_set */ | ||
1663 | } else { | ||
1664 | /* SMP */ | ||
1665 | |||
1666 | } | ||
1667 | out: | ||
1668 | if (rc != TMF_RESP_FUNC_COMPLETE) | ||
1669 | mv_printk("%s:rc= %d\n", __func__, rc); | ||
1670 | return rc; | ||
1671 | } | ||
1672 | |||
1673 | int mvs_abort_task_set(struct domain_device *dev, u8 *lun) | ||
1674 | { | ||
1675 | int rc = TMF_RESP_FUNC_FAILED; | ||
1676 | struct mvs_tmf_task tmf_task; | ||
1677 | |||
1678 | tmf_task.tmf = TMF_ABORT_TASK_SET; | ||
1679 | rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); | ||
1680 | |||
1681 | return rc; | ||
1682 | } | ||
1683 | |||
1684 | int mvs_clear_aca(struct domain_device *dev, u8 *lun) | ||
1685 | { | ||
1686 | int rc = TMF_RESP_FUNC_FAILED; | ||
1687 | struct mvs_tmf_task tmf_task; | ||
1688 | |||
1689 | tmf_task.tmf = TMF_CLEAR_ACA; | ||
1690 | rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); | ||
1691 | |||
1692 | return rc; | ||
1693 | } | ||
1694 | |||
1695 | int mvs_clear_task_set(struct domain_device *dev, u8 *lun) | ||
1696 | { | ||
1697 | int rc = TMF_RESP_FUNC_FAILED; | ||
1698 | struct mvs_tmf_task tmf_task; | ||
1699 | |||
1700 | tmf_task.tmf = TMF_CLEAR_TASK_SET; | ||
1701 | rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); | ||
1702 | |||
1703 | return rc; | ||
1704 | } | ||
1705 | |||
1706 | static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task, | ||
1707 | u32 slot_idx, int err) | ||
1708 | { | ||
1709 | struct mvs_device *mvi_dev = task->dev->lldd_dev; | ||
1710 | struct task_status_struct *tstat = &task->task_status; | ||
1711 | struct ata_task_resp *resp = (struct ata_task_resp *)tstat->buf; | ||
1712 | int stat = SAM_GOOD; | ||
1713 | |||
1714 | |||
1715 | resp->frame_len = sizeof(struct dev_to_host_fis); | ||
1716 | memcpy(&resp->ending_fis[0], | ||
1717 | SATA_RECEIVED_D2H_FIS(mvi_dev->taskfileset), | ||
1718 | sizeof(struct dev_to_host_fis)); | ||
1719 | tstat->buf_valid_size = sizeof(*resp); | ||
1720 | if (unlikely(err)) | ||
1721 | stat = SAS_PROTO_RESPONSE; | ||
1722 | return stat; | ||
1723 | } | ||
1724 | |||
1725 | static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, | ||
1726 | u32 slot_idx) | ||
1727 | { | ||
1728 | struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; | ||
1729 | int stat; | ||
1730 | u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response)); | ||
1731 | u32 tfs = 0; | ||
1732 | enum mvs_port_type type = PORT_TYPE_SAS; | ||
1733 | |||
1734 | if (err_dw0 & CMD_ISS_STPD) | ||
1735 | MVS_CHIP_DISP->issue_stop(mvi, type, tfs); | ||
1736 | |||
1737 | MVS_CHIP_DISP->command_active(mvi, slot_idx); | ||
1738 | |||
1739 | stat = SAM_CHECK_COND; | ||
1740 | switch (task->task_proto) { | ||
1741 | case SAS_PROTOCOL_SSP: | ||
1742 | stat = SAS_ABORTED_TASK; | ||
1743 | break; | ||
1744 | case SAS_PROTOCOL_SMP: | ||
1745 | stat = SAM_CHECK_COND; | ||
1746 | break; | ||
1747 | |||
1748 | case SAS_PROTOCOL_SATA: | ||
1749 | case SAS_PROTOCOL_STP: | ||
1750 | case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: | ||
1751 | { | ||
1752 | if (err_dw0 == 0x80400002) | ||
1753 | mv_printk("find reserved error, why?\n"); | ||
1754 | |||
1755 | task->ata_task.use_ncq = 0; | ||
1756 | stat = SAS_PROTO_RESPONSE; | ||
1757 | mvs_sata_done(mvi, task, slot_idx, 1); | ||
1758 | |||
1759 | } | ||
1760 | break; | ||
1761 | default: | ||
1762 | break; | ||
1763 | } | ||
1764 | |||
1765 | return stat; | ||
1766 | } | ||
1767 | |||
1768 | int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) | ||
1769 | { | ||
1770 | u32 slot_idx = rx_desc & RXQ_SLOT_MASK; | ||
1771 | struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; | ||
1772 | struct sas_task *task = slot->task; | ||
1773 | struct mvs_device *mvi_dev = NULL; | ||
1774 | struct task_status_struct *tstat; | ||
1775 | |||
1776 | bool aborted; | ||
1777 | void *to; | ||
1778 | enum exec_status sts; | ||
1779 | |||
1780 | if (mvi->exp_req) | ||
1781 | mvi->exp_req--; | ||
1782 | if (unlikely(!task || !task->lldd_task)) | ||
1783 | return -1; | ||
1784 | |||
1785 | tstat = &task->task_status; | ||
1786 | mvi_dev = task->dev->lldd_dev; | ||
1787 | |||
1788 | mvs_hba_cq_dump(mvi); | ||
1789 | |||
1790 | spin_lock(&task->task_state_lock); | ||
1791 | task->task_state_flags &= | ||
1792 | ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); | ||
1793 | task->task_state_flags |= SAS_TASK_STATE_DONE; | ||
1794 | /* race condition*/ | ||
1795 | aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED; | ||
1796 | spin_unlock(&task->task_state_lock); | ||
1797 | |||
1798 | memset(tstat, 0, sizeof(*tstat)); | ||
1799 | tstat->resp = SAS_TASK_COMPLETE; | ||
1800 | |||
1801 | if (unlikely(aborted)) { | ||
1802 | tstat->stat = SAS_ABORTED_TASK; | ||
1803 | if (mvi_dev) | ||
1804 | mvi_dev->runing_req--; | ||
1805 | if (sas_protocol_ata(task->task_proto)) | ||
1806 | mvs_free_reg_set(mvi, mvi_dev); | ||
1807 | |||
1808 | mvs_slot_task_free(mvi, task, slot, slot_idx); | ||
1809 | return -1; | ||
1810 | } | ||
1811 | |||
1812 | if (unlikely(!mvi_dev || !slot->port->port_attached || flags)) { | ||
1813 | mv_dprintk("port has not device.\n"); | ||
1814 | tstat->stat = SAS_PHY_DOWN; | ||
1815 | goto out; | ||
1816 | } | ||
1817 | |||
1818 | /* | ||
1819 | if (unlikely((rx_desc & RXQ_ERR) || (*(u64 *) slot->response))) { | ||
1820 | mv_dprintk("Find device[%016llx] RXQ_ERR %X, | ||
1821 | err info:%016llx\n", | ||
1822 | SAS_ADDR(task->dev->sas_addr), | ||
1823 | rx_desc, (u64)(*(u64 *) slot->response)); | ||
1824 | } | ||
1825 | */ | ||
1826 | |||
1827 | /* error info record present */ | ||
1828 | if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) { | ||
1829 | tstat->stat = mvs_slot_err(mvi, task, slot_idx); | ||
1830 | goto out; | ||
1831 | } | ||
1832 | |||
1833 | switch (task->task_proto) { | ||
1834 | case SAS_PROTOCOL_SSP: | ||
1835 | /* hw says status == 0, datapres == 0 */ | ||
1836 | if (rx_desc & RXQ_GOOD) { | ||
1837 | tstat->stat = SAM_GOOD; | ||
1838 | tstat->resp = SAS_TASK_COMPLETE; | ||
1839 | } | ||
1840 | /* response frame present */ | ||
1841 | else if (rx_desc & RXQ_RSP) { | ||
1842 | struct ssp_response_iu *iu = slot->response + | ||
1843 | sizeof(struct mvs_err_info); | ||
1844 | sas_ssp_task_response(mvi->dev, task, iu); | ||
1845 | } else | ||
1846 | tstat->stat = SAM_CHECK_COND; | ||
1847 | break; | ||
1848 | |||
1849 | case SAS_PROTOCOL_SMP: { | ||
1850 | struct scatterlist *sg_resp = &task->smp_task.smp_resp; | ||
1851 | tstat->stat = SAM_GOOD; | ||
1852 | to = kmap_atomic(sg_page(sg_resp), KM_IRQ0); | ||
1853 | memcpy(to + sg_resp->offset, | ||
1854 | slot->response + sizeof(struct mvs_err_info), | ||
1855 | sg_dma_len(sg_resp)); | ||
1856 | kunmap_atomic(to, KM_IRQ0); | ||
1857 | break; | ||
1858 | } | ||
1859 | |||
1860 | case SAS_PROTOCOL_SATA: | ||
1861 | case SAS_PROTOCOL_STP: | ||
1862 | case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: { | ||
1863 | tstat->stat = mvs_sata_done(mvi, task, slot_idx, 0); | ||
1864 | break; | ||
1865 | } | ||
1866 | |||
1867 | default: | ||
1868 | tstat->stat = SAM_CHECK_COND; | ||
1869 | break; | ||
1870 | } | ||
1871 | |||
1872 | out: | ||
1873 | if (mvi_dev) { | ||
1874 | mvi_dev->runing_req--; | ||
1875 | if (sas_protocol_ata(task->task_proto)) | ||
1876 | mvs_free_reg_set(mvi, mvi_dev); | ||
1877 | } | ||
1878 | mvs_slot_task_free(mvi, task, slot, slot_idx); | ||
1879 | sts = tstat->stat; | ||
1880 | |||
1881 | spin_unlock(&mvi->lock); | ||
1882 | if (task->task_done) | ||
1883 | task->task_done(task); | ||
1884 | else | ||
1885 | mv_dprintk("why has not task_done.\n"); | ||
1886 | spin_lock(&mvi->lock); | ||
1887 | |||
1888 | return sts; | ||
1889 | } | ||
1890 | |||
1891 | void mvs_release_task(struct mvs_info *mvi, | ||
1892 | int phy_no, struct domain_device *dev) | ||
1893 | { | ||
1894 | int i = 0; u32 slot_idx; | ||
1895 | struct mvs_phy *phy; | ||
1896 | struct mvs_port *port; | ||
1897 | struct mvs_slot_info *slot, *slot2; | ||
1898 | |||
1899 | phy = &mvi->phy[phy_no]; | ||
1900 | port = phy->port; | ||
1901 | if (!port) | ||
1902 | return; | ||
1903 | |||
1904 | list_for_each_entry_safe(slot, slot2, &port->list, entry) { | ||
1905 | struct sas_task *task; | ||
1906 | slot_idx = (u32) (slot - mvi->slot_info); | ||
1907 | task = slot->task; | ||
1908 | |||
1909 | if (dev && task->dev != dev) | ||
1910 | continue; | ||
1911 | |||
1912 | mv_printk("Release slot [%x] tag[%x], task [%p]:\n", | ||
1913 | slot_idx, slot->slot_tag, task); | ||
1914 | |||
1915 | if (task->task_proto & SAS_PROTOCOL_SSP) { | ||
1916 | mv_printk("attached with SSP task CDB["); | ||
1917 | for (i = 0; i < 16; i++) | ||
1918 | mv_printk(" %02x", task->ssp_task.cdb[i]); | ||
1919 | mv_printk(" ]\n"); | ||
1920 | } | ||
1921 | |||
1922 | mvs_slot_complete(mvi, slot_idx, 1); | ||
1923 | } | ||
1924 | } | ||
1925 | |||
1926 | static void mvs_phy_disconnected(struct mvs_phy *phy) | ||
1927 | { | ||
1928 | phy->phy_attached = 0; | ||
1929 | phy->att_dev_info = 0; | ||
1930 | phy->att_dev_sas_addr = 0; | ||
1931 | } | ||
1932 | |||
1933 | static void mvs_work_queue(struct work_struct *work) | ||
1934 | { | ||
1935 | struct delayed_work *dw = container_of(work, struct delayed_work, work); | ||
1936 | struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q); | ||
1937 | struct mvs_info *mvi = mwq->mvi; | ||
1938 | unsigned long flags; | ||
1939 | |||
1940 | spin_lock_irqsave(&mvi->lock, flags); | ||
1941 | if (mwq->handler & PHY_PLUG_EVENT) { | ||
1942 | u32 phy_no = (unsigned long) mwq->data; | ||
1943 | struct sas_ha_struct *sas_ha = mvi->sas; | ||
1944 | struct mvs_phy *phy = &mvi->phy[phy_no]; | ||
1945 | struct asd_sas_phy *sas_phy = &phy->sas_phy; | ||
1946 | |||
1947 | if (phy->phy_event & PHY_PLUG_OUT) { | ||
1948 | u32 tmp; | ||
1949 | struct sas_identify_frame *id; | ||
1950 | id = (struct sas_identify_frame *)phy->frame_rcvd; | ||
1951 | tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no); | ||
1952 | phy->phy_event &= ~PHY_PLUG_OUT; | ||
1953 | if (!(tmp & PHY_READY_MASK)) { | ||
1954 | sas_phy_disconnected(sas_phy); | ||
1955 | mvs_phy_disconnected(phy); | ||
1956 | sas_ha->notify_phy_event(sas_phy, | ||
1957 | PHYE_LOSS_OF_SIGNAL); | ||
1958 | mv_dprintk("phy%d Removed Device\n", phy_no); | ||
1959 | } else { | ||
1960 | MVS_CHIP_DISP->detect_porttype(mvi, phy_no); | ||
1961 | mvs_update_phyinfo(mvi, phy_no, 1); | ||
1962 | mvs_bytes_dmaed(mvi, phy_no); | ||
1963 | mvs_port_notify_formed(sas_phy, 0); | ||
1964 | mv_dprintk("phy%d Attached Device\n", phy_no); | ||
1965 | } | ||
1966 | } | ||
1967 | } | ||
1968 | list_del(&mwq->entry); | ||
1969 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1970 | kfree(mwq); | ||
1971 | } | ||
1972 | |||
1973 | static int mvs_handle_event(struct mvs_info *mvi, void *data, int handler) | ||
1974 | { | ||
1975 | struct mvs_wq *mwq; | ||
1976 | int ret = 0; | ||
1977 | |||
1978 | mwq = kmalloc(sizeof(struct mvs_wq), GFP_ATOMIC); | ||
1979 | if (mwq) { | ||
1980 | mwq->mvi = mvi; | ||
1981 | mwq->data = data; | ||
1982 | mwq->handler = handler; | ||
1983 | MV_INIT_DELAYED_WORK(&mwq->work_q, mvs_work_queue, mwq); | ||
1984 | list_add_tail(&mwq->entry, &mvi->wq_list); | ||
1985 | schedule_delayed_work(&mwq->work_q, HZ * 2); | ||
1986 | } else | ||
1987 | ret = -ENOMEM; | ||
1988 | |||
1989 | return ret; | ||
1990 | } | ||
1991 | |||
1992 | static void mvs_sig_time_out(unsigned long tphy) | ||
1993 | { | ||
1994 | struct mvs_phy *phy = (struct mvs_phy *)tphy; | ||
1995 | struct mvs_info *mvi = phy->mvi; | ||
1996 | u8 phy_no; | ||
1997 | |||
1998 | for (phy_no = 0; phy_no < mvi->chip->n_phy; phy_no++) { | ||
1999 | if (&mvi->phy[phy_no] == phy) { | ||
2000 | mv_dprintk("Get signature time out, reset phy %d\n", | ||
2001 | phy_no+mvi->id*mvi->chip->n_phy); | ||
2002 | MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1); | ||
2003 | } | ||
2004 | } | ||
2005 | } | ||
2006 | |||
2007 | static void mvs_sig_remove_timer(struct mvs_phy *phy) | ||
2008 | { | ||
2009 | if (phy->timer.function) | ||
2010 | del_timer(&phy->timer); | ||
2011 | phy->timer.function = NULL; | ||
2012 | } | ||
2013 | |||
2014 | void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) | ||
2015 | { | ||
2016 | u32 tmp; | ||
2017 | struct sas_ha_struct *sas_ha = mvi->sas; | ||
2018 | struct mvs_phy *phy = &mvi->phy[phy_no]; | ||
2019 | struct asd_sas_phy *sas_phy = &phy->sas_phy; | ||
2020 | |||
2021 | phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no); | ||
2022 | mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy, | ||
2023 | MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no)); | ||
2024 | mv_dprintk("Port %d irq sts = 0x%X\n", phy_no+mvi->id*mvi->chip->n_phy, | ||
2025 | phy->irq_status); | ||
2026 | |||
2027 | /* | ||
2028 | * events is port event now , | ||
2029 | * we need check the interrupt status which belongs to per port. | ||
2030 | */ | ||
2031 | |||
2032 | if (phy->irq_status & PHYEV_DCDR_ERR) | ||
2033 | mv_dprintk("port %d STP decoding error.\n", | ||
2034 | phy_no+mvi->id*mvi->chip->n_phy); | ||
2035 | |||
2036 | if (phy->irq_status & PHYEV_POOF) { | ||
2037 | if (!(phy->phy_event & PHY_PLUG_OUT)) { | ||
2038 | int dev_sata = phy->phy_type & PORT_TYPE_SATA; | ||
2039 | int ready; | ||
2040 | mvs_release_task(mvi, phy_no, NULL); | ||
2041 | phy->phy_event |= PHY_PLUG_OUT; | ||
2042 | mvs_handle_event(mvi, | ||
2043 | (void *)(unsigned long)phy_no, | ||
2044 | PHY_PLUG_EVENT); | ||
2045 | ready = mvs_is_phy_ready(mvi, phy_no); | ||
2046 | if (!ready) | ||
2047 | mv_dprintk("phy%d Unplug Notice\n", | ||
2048 | phy_no + | ||
2049 | mvi->id * mvi->chip->n_phy); | ||
2050 | if (ready || dev_sata) { | ||
2051 | if (MVS_CHIP_DISP->stp_reset) | ||
2052 | MVS_CHIP_DISP->stp_reset(mvi, | ||
2053 | phy_no); | ||
2054 | else | ||
2055 | MVS_CHIP_DISP->phy_reset(mvi, | ||
2056 | phy_no, 0); | ||
2057 | return; | ||
2058 | } | ||
2059 | } | ||
2060 | } | ||
2061 | |||
2062 | if (phy->irq_status & PHYEV_COMWAKE) { | ||
2063 | tmp = MVS_CHIP_DISP->read_port_irq_mask(mvi, phy_no); | ||
2064 | MVS_CHIP_DISP->write_port_irq_mask(mvi, phy_no, | ||
2065 | tmp | PHYEV_SIG_FIS); | ||
2066 | if (phy->timer.function == NULL) { | ||
2067 | phy->timer.data = (unsigned long)phy; | ||
2068 | phy->timer.function = mvs_sig_time_out; | ||
2069 | phy->timer.expires = jiffies + 10*HZ; | ||
2070 | add_timer(&phy->timer); | ||
2071 | } | ||
2072 | } | ||
2073 | if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) { | ||
2074 | phy->phy_status = mvs_is_phy_ready(mvi, phy_no); | ||
2075 | mvs_sig_remove_timer(phy); | ||
2076 | mv_dprintk("notify plug in on phy[%d]\n", phy_no); | ||
2077 | if (phy->phy_status) { | ||
2078 | mdelay(10); | ||
2079 | MVS_CHIP_DISP->detect_porttype(mvi, phy_no); | ||
2080 | if (phy->phy_type & PORT_TYPE_SATA) { | ||
2081 | tmp = MVS_CHIP_DISP->read_port_irq_mask( | ||
2082 | mvi, phy_no); | ||
2083 | tmp &= ~PHYEV_SIG_FIS; | ||
2084 | MVS_CHIP_DISP->write_port_irq_mask(mvi, | ||
2085 | phy_no, tmp); | ||
2086 | } | ||
2087 | mvs_update_phyinfo(mvi, phy_no, 0); | ||
2088 | mvs_bytes_dmaed(mvi, phy_no); | ||
2089 | /* whether driver is going to handle hot plug */ | ||
2090 | if (phy->phy_event & PHY_PLUG_OUT) { | ||
2091 | mvs_port_notify_formed(sas_phy, 0); | ||
2092 | phy->phy_event &= ~PHY_PLUG_OUT; | ||
2093 | } | ||
2094 | } else { | ||
2095 | mv_dprintk("plugin interrupt but phy%d is gone\n", | ||
2096 | phy_no + mvi->id*mvi->chip->n_phy); | ||
2097 | } | ||
2098 | } else if (phy->irq_status & PHYEV_BROAD_CH) { | ||
2099 | mv_dprintk("port %d broadcast change.\n", | ||
2100 | phy_no + mvi->id*mvi->chip->n_phy); | ||
2101 | /* exception for Samsung disk drive*/ | ||
2102 | mdelay(1000); | ||
2103 | sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); | ||
2104 | } | ||
2105 | MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status); | ||
2106 | } | ||
2107 | |||
2108 | int mvs_int_rx(struct mvs_info *mvi, bool self_clear) | ||
2109 | { | ||
2110 | u32 rx_prod_idx, rx_desc; | ||
2111 | bool attn = false; | ||
2112 | |||
2113 | /* the first dword in the RX ring is special: it contains | ||
2114 | * a mirror of the hardware's RX producer index, so that | ||
2115 | * we don't have to stall the CPU reading that register. | ||
2116 | * The actual RX ring is offset by one dword, due to this. | ||
2117 | */ | ||
2118 | rx_prod_idx = mvi->rx_cons; | ||
2119 | mvi->rx_cons = le32_to_cpu(mvi->rx[0]); | ||
2120 | if (mvi->rx_cons == 0xfff) /* h/w hasn't touched RX ring yet */ | ||
2121 | return 0; | ||
2122 | |||
2123 | /* The CMPL_Q may come late, read from register and try again | ||
2124 | * note: if coalescing is enabled, | ||
2125 | * it will need to read from register every time for sure | ||
2126 | */ | ||
2127 | if (unlikely(mvi->rx_cons == rx_prod_idx)) | ||
2128 | mvi->rx_cons = MVS_CHIP_DISP->rx_update(mvi) & RX_RING_SZ_MASK; | ||
2129 | |||
2130 | if (mvi->rx_cons == rx_prod_idx) | ||
2131 | return 0; | ||
2132 | |||
2133 | while (mvi->rx_cons != rx_prod_idx) { | ||
2134 | /* increment our internal RX consumer pointer */ | ||
2135 | rx_prod_idx = (rx_prod_idx + 1) & (MVS_RX_RING_SZ - 1); | ||
2136 | rx_desc = le32_to_cpu(mvi->rx[rx_prod_idx + 1]); | ||
2137 | |||
2138 | if (likely(rx_desc & RXQ_DONE)) | ||
2139 | mvs_slot_complete(mvi, rx_desc, 0); | ||
2140 | if (rx_desc & RXQ_ATTN) { | ||
2141 | attn = true; | ||
2142 | } else if (rx_desc & RXQ_ERR) { | ||
2143 | if (!(rx_desc & RXQ_DONE)) | ||
2144 | mvs_slot_complete(mvi, rx_desc, 0); | ||
2145 | } else if (rx_desc & RXQ_SLOT_RESET) { | ||
2146 | mvs_slot_free(mvi, rx_desc); | ||
2147 | } | ||
2148 | } | ||
2149 | |||
2150 | if (attn && self_clear) | ||
2151 | MVS_CHIP_DISP->int_full(mvi); | ||
2152 | return 0; | ||
2153 | } | ||
2154 | |||