Patch from andy yan <andyysj@gmail.com>:
[mirror/scst/.git] / mvsas_tgt / mv_tgt.c
1 #ifdef SUPPORT_TARGET
2 #include <linux/module.h>
3 #include <linux/init.h>
4 #include <linux/types.h>
5 #include <linux/version.h>
6 #include <linux/blkdev.h>
7 #include <linux/interrupt.h>
8 #include <scsi/scsi.h>
9 #include <scsi/scsi_host.h>
10 #include <linux/pci.h>
11 #include <linux/delay.h>
12 #include <linux/seq_file.h>
13 #include <linux/list.h>
14 #include <linux/kthread.h>
15 #include <asm/byteorder.h>
16 #include <scst.h>
17 #include <scst_debug.h>
18 #include "mv_sas.h"
19 #include "mv_defs.h"
20 #include "mv_64xx.h"
21 #include "mv_chips.h"
22
23 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
24 unsigned long mvst_trace_flag = MVST_DEFAULT_LOG_FLAGS;
25 #endif
26
27
28 #ifndef SUPPORT_TARGET
29 #error "SUPPORT_TARGET is NOT DEFINED"
30 #endif
31
32 static int mvst_target_detect(struct scst_tgt_template *templ);
33 static int mvst_target_release(struct scst_tgt *scst_tgt);
34 static int mvst_xmit_response(struct scst_cmd *scst_cmd);
35 static int mvst_rdy_to_xfer(struct scst_cmd *scst_cmd);
36 static void mvst_on_free_cmd(struct scst_cmd *scst_cmd);
37 static void mvst_task_mgmt_fn_done(struct scst_mgmt_cmd *mcmd);
38 static int mvst_report_event(struct scst_aen *aen);
39 /* Predefs for callbacks handed to mvst(target) */
40 static u8 mvst_response_ssp_command(struct mvs_info *mvi, u32 rx_desc);
41 static void mvst_async_event(uint16_t code, struct mvs_info *mvi,
42         uint16_t *mailbox);
43 static void mvst_cmd_completion(struct mvs_info *mvi, u32 rx_desc);
44 static void mvst_host_action(struct mvs_info *mvi,
45         enum mvst_tgt_host_action_t action, u8 phyid);
46 static int mvst_send_cmd(struct mvs_info *mvi);
47 static int mvst_start_sas_target(struct mvs_info *mvi, u8 id);
48 static int mvst_restart_free_list(struct mvs_info *mvi, u8 slot_id);
49
50
51 struct kmem_cache *mvst_cmd_cachep;
52 struct mvst_msg_queue tgt_msg_queue;
53
54 struct scst_tgt_template tgt_template = {
55         .name = MVST_NAME,
56         .sg_tablesize = 0,
57         .use_clustering = 1,
58 #ifdef DEBUG_WORK_IN_THREAD
59         .xmit_response_atomic = 0,
60         .rdy_to_xfer_atomic = 0,
61 #else
62         .xmit_response_atomic = 1,
63         .rdy_to_xfer_atomic = 1,
64 #endif
65         .detect = mvst_target_detect,
66         .release = mvst_target_release,
67         .xmit_response = mvst_xmit_response,
68         .rdy_to_xfer = mvst_rdy_to_xfer,
69         .on_free_cmd = mvst_on_free_cmd,
70         .task_mgmt_fn_done = mvst_task_mgmt_fn_done,
71         .report_aen = mvst_report_event,
72 };
73
74 /*
75  * Functions
76  */
77
78 static u64 mvst_get_be_sas_addr(u8 *sas_addr)
79 {
80         u64 lo = cpu_to_be32((u32)(*(u32 *)&sas_addr[0]));
81         u64 hi = cpu_to_be32((u32)(*(u32 *)&sas_addr[4]));
82         return  (hi << 32) | lo;
83 }
84
85 static u64 mvst_get_le_sas_addr(u8 *sas_addr)
86 {
87         u64 lo = ((u32)(*(u32 *)&sas_addr[4]));
88         u64 hi = ((u32)(*(u32 *)&sas_addr[0]));
89         return  (hi << 32) | lo;
90 }
91
92 /* FIXME
93  *
94  * use_sg can not bigger than MAX_SG_COUNT
95  *
96  */
97 static inline void
98 mvst_prep_prd(struct mvst_prm *prm, struct mvs_prd *buf_prd)
99 {
100         struct mvs_info *mvi = prm->tgt->mvi;
101
102         TRACE_ENTRY();
103         TRACE_DBG("bufflen 0x%x, %p", prm->bufflen, prm->sg);
104         sBUG_ON(prm->sg_cnt == 0);
105         prm->seg_cnt = pci_map_sg(prm->tgt->mvi->pdev, prm->sg, prm->sg_cnt,
106                                    scst_to_tgt_dma_dir(prm->data_direction));
107         MVS_CHIP_DISP->make_prd(prm->sg, prm->sg_cnt, buf_prd);
108 }
109
110
111 void
112 mvst_fixup_payload(u32 *payload, u32 nr_pl_dwords)
113 {
114         u32 tmp;
115
116         while (nr_pl_dwords--) {
117                 tmp = *payload;
118                 tmp = ((tmp & 0x000000FF) << 24)        |
119                                 ((tmp & 0x0000FF00) << 8)       |
120                                 ((tmp & 0x00FF0000) >> 8)       |
121                                 ((tmp & 0xFF000000) >> 24);
122         *payload = tmp;
123         payload++;
124     }
125 }
126
127 void
128 memory_dword_copy(u32 *dst, u32 *src, u32 nr_bytes)
129 {
130         nr_bytes /= sizeof(u32);
131         while (nr_bytes--)
132                 *dst++ = *src++;
133 }
134
135 static inline int test_tgt_sess_count(struct mvst_tgt *tgt,
136                                 struct mvs_info *mvi)
137 {
138         unsigned long flags;
139         int res;
140
141         /*
142          * We need to protect against race, when tgt is freed before or
143          * inside wake_up()
144          */
145         spin_lock_irqsave(&tgt->mvi->lock, flags);
146         TRACE_DBG("tgt %p, empty(sess_list)=%d sess_count=%d",
147               tgt, list_empty(&tgt->sess_list), tgt->sess_count);
148         res = (tgt->sess_count == 0);
149         spin_unlock_irqrestore(&tgt->mvi->lock, flags);
150
151         return res;
152 }
153
154 /* mvi->lock supposed to be held on entry */
155 static inline void mvst_exec_queue(struct mvs_info *mvi)
156 {
157         void __iomem *regs = mvi->regs;
158         mw32(MVS_TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
159 }
160
161 /* mvi->lock supposed to be held on entry */
162 static inline void mvst_send_notify_ack(struct mvs_info *mvi,
163         struct mvst_mgmt_cmd *mcmd, int status)
164 {
165
166 }
167
168 /*
169  * register with initiator driver (but target mode isn't enabled till
170  * it's turned on via sysfs)
171  */
172 static int mvst_target_detect(struct scst_tgt_template *templ)
173 {
174         int res;
175         struct mvs_tgt_initiator itd = {
176                 .magic = MVST_TARGET_MAGIC,
177                 .tgt_rsp_ssp_cmd = mvst_response_ssp_command,
178                 .tgt_cmd_cmpl = mvst_cmd_completion,
179                 .tgt_async_event = mvst_async_event,
180                 .tgt_host_action = mvst_host_action,
181                 .tgt_send_cmd = mvst_send_cmd
182         };
183
184         TRACE_ENTRY();
185
186         res = mvs_tgt_register_driver(&itd);
187         if (res != 0) {
188                 PRINT_ERROR("Unable to register driver: %d", res);
189                 goto out;
190         }
191
192 out:
193         TRACE_EXIT();
194         return res;
195 }
196
197 /* no lock held */
198 static void mvst_free_session_done(struct scst_session *scst_sess)
199 {
200         struct mvst_sess *sess;
201         struct mvst_tgt *tgt;
202         struct mvs_info *mvi;
203         unsigned long flags;
204
205         TRACE_ENTRY();
206
207         sBUG_ON(scst_sess == NULL);
208         sess = (struct mvst_sess *)scst_sess_get_tgt_priv(scst_sess);
209         sBUG_ON(sess == NULL);
210         tgt = sess->tgt;
211
212         kfree(sess);
213
214         if (tgt == NULL)
215                 goto out;
216
217         TRACE_MGMT_DBG("tgt %p, empty(sess_list) %d, sess_count %d",
218               tgt, list_empty(&tgt->sess_list), tgt->sess_count);
219
220         mvi = tgt->mvi;
221
222         /*
223          * We need to protect against race, when tgt is freed before or
224          * inside wake_up()
225          */
226         spin_lock_irqsave(&mvi->lock, flags);
227         tgt->sess_count--;
228         if (tgt->sess_count == 0)
229                 wake_up_all(&tgt->waitQ);
230         spin_unlock_irqrestore(&mvi->lock, flags);
231
232 out:
233         TRACE_EXIT();
234         return;
235 }
236
237 /* mvi->lock supposed to be held on entry */
238 static void mvst_unreg_sess(struct mvst_sess *sess)
239 {
240         TRACE_ENTRY();
241
242         if (sess == NULL)
243                 goto out;
244
245         list_del(&sess->sess_entry);
246
247         TRACE_DBG("mvst tgt(%ld): session for initiator %016llx deleted",
248                 sess->tgt->mvi->instance,
249                 mvst_get_le_sas_addr((u8 *)&sess->initiator_sas_addr));
250
251         /*
252          * Any commands for this session will be finished regularly,
253          * because we must not drop SCSI commands on transport level,
254          * at least without any response to the initiator.
255          */
256
257         scst_unregister_session(sess->scst_sess, 0, mvst_free_session_done);
258
259 out:
260         TRACE_EXIT();
261         return;
262 }
263
264 /* mvi->lock supposed to be held on entry */
265 static void mvst_clear_tgt_db(struct mvst_tgt *tgt)
266 {
267         struct mvst_sess *sess, *sess_tmp;
268
269         TRACE_ENTRY();
270
271         TRACE_MGMT_DBG("Clearing targets DB %p", tgt);
272
273         list_for_each_entry_safe(sess, sess_tmp, &tgt->sess_list, sess_entry)
274                 mvst_unreg_sess(sess);
275
276         /* At this point tgt could be already dead */
277
278         TRACE_MGMT_DBG("Finished clearing Target DB %p", tgt);
279
280         TRACE_EXIT();
281         return;
282 }
283
284 /* should be called w/out lock, but tgt should be
285  * unfindable at this point */
286 static int mvst_target_release(struct scst_tgt *scst_tgt)
287 {
288         int res = 0;
289         struct mvst_tgt *tgt =
290                 (struct mvst_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
291         struct mvs_info *mvi = tgt->mvi;
292         unsigned long flags = 0;
293
294         TRACE_ENTRY();
295
296         spin_lock_irqsave(&mvi->lock, flags);
297         tgt->tgt_shutdown = 1;
298         mvst_clear_tgt_db(tgt);
299         spin_unlock_irqrestore(&mvi->lock, flags);
300
301         wait_event(tgt->waitQ, test_tgt_sess_count(tgt, mvi));
302
303         /* big hammer */
304         if (!mvi->flags & MVF_HOST_SHUTTING_DOWN)
305                 mvi->flags |= MVF_TARGET_MODE_ENABLE;
306
307         /* wait for sessions to clear out (just in case) */
308         wait_event(tgt->waitQ, test_tgt_sess_count(tgt, mvi));
309
310         TRACE_MGMT_DBG("Finished waiting for tgt %p: empty(sess_list)=%d "
311                 "sess_count=%d", tgt, list_empty(&tgt->sess_list),
312                 tgt->sess_count);
313
314         /* The lock is needed, because we still can get an incoming packet */
315         spin_lock_irqsave(&mvi->lock, flags);
316         scst_tgt_set_tgt_priv(scst_tgt, NULL);
317         mvi->tgt = NULL;
318         spin_unlock_irqrestore(&mvi->lock, flags);
319
320         kfree(tgt);
321
322         TRACE_EXIT_RES(res);
323         return res;
324 }
325
326 static inline int mvst_has_data(struct scst_cmd *scst_cmd)
327 {
328         return scst_cmd_get_resp_data_len(scst_cmd) > 0;
329 }
330
331
332 static void
333 mvst_put_slot(struct mvs_info *mvi, struct mvs_slot_info *slot)
334 {
335         u32 slot_idx = slot->target_cmd_tag;
336         /* reset field used by target driver */
337         slot->target_cmd_tag = 0xdeadbeef;
338         slot->tx = 0xdeadbeef;
339         slot->slot_scst_cmd = NULL;
340         slot->response = NULL;
341         slot->open_frame = NULL;
342         slot->slot_tgt_port = NULL;
343         list_del(&slot->entry);
344         mvs_tag_clear(mvi, slot_idx);
345 }
346
347
348 static struct mvs_slot_info*
349 mvst_get_slot(struct mvs_info *mvi, struct mvst_port *tgt_port)
350 {
351         u8 rc = 0;
352         u32 tag;
353         struct mvs_slot_info *slot = NULL;
354         rc = mvs_tag_alloc(mvi, &tag);
355         if (rc)
356                 return  NULL;
357         slot = &mvi->slot_info[tag];
358         memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
359         /* used by initiator driver, reserved  for target driver */
360         slot->n_elem = 0;
361         slot->task = NULL;
362         slot->port = NULL;
363
364         /* save free tag */
365         slot->target_cmd_tag = tag;
366         slot->slot_tgt_port = tgt_port;
367         slot->slot_scst_cmd = NULL;
368         slot->open_frame = NULL;
369         slot->tx = mvi->tx_prod;
370         list_add_tail(&slot->entry, &slot->slot_tgt_port->slot_list);
371         return  slot;
372
373 }
374
375 static int mvst_prep_resp_frame(struct mvst_prm *prm,
376                         struct mvs_slot_info *slot, u8 sense_data)
377 {
378         u8 has_data = 0;
379         u16 tag;
380         void *buf_tmp, *buf_cmd;
381         dma_addr_t buf_tmp_dma;
382         u32 resp_len = 0, req_len = 0, prd_len = 0;
383         const u32 max_resp_len = SB_RFB_MAX;
384         struct mvs_info *mvi = prm->tgt->mvi;
385         struct mvst_cmd *cmd = prm->cmd;
386         struct mvs_cmd_header *cmd_hdr;
387         struct mvs_delivery_queue *delivery_q;
388         struct mvs_prd *buf_prd;
389         struct open_address_frame *open_frame;
390         struct mv_ssp_response_iu *response_iu;
391         TRACE_ENTRY();
392         tag = slot->target_cmd_tag;
393         cmd_hdr = (struct mvs_cmd_header *)&mvi->slot[tag];
394         /* get free delivery queue */
395         delivery_q = (struct mvs_delivery_queue *)&mvi->tx[mvi->tx_prod];
396
397         /* SSP protocol, Target mode, Normal priority */
398         delivery_q->cmd = TXQ_CMD_SSP;
399         delivery_q->mode = TXQ_MODE_TARGET;
400         delivery_q->priority = TXQ_PRI_NORMAL;
401         delivery_q->sata_reg_set = 0;
402         delivery_q->phy = cmd->cmd_tgt_port->wide_port_phymap;
403         delivery_q->slot_nm = tag;
404
405         if (sense_data) {
406                 if ((prm->rq_result) && (SCST_SENSE_VALID(prm->sense_buffer))) {
407                         req_len = 24 + prm->sense_buffer_len;
408                         has_data = 1;
409                 } else {
410                         req_len = 24;
411                         has_data = 0;
412                 }
413         } else {
414                 if (prm->rq_result) {
415                         req_len = 24 + 4;
416                         has_data = 1;
417                 } else {
418                         req_len = 24;
419                         has_data = 0;
420                 }
421         }
422         req_len += sizeof(struct ssp_frame_header);
423
424         cmd_hdr->ssp_frame_type = MCH_SSP_FR_RESP;
425         cmd_hdr->ssp_passthru = MCH_SSP_MODE_NORMAL;
426
427         /* command header dword 1 */
428         /* configure in below */
429
430         /* command header dword 2 */
431         /* copy the tag from received command frame */
432         cmd_hdr->target_tag = cpu_to_le16(tag);
433         cmd_hdr->tag = be16_to_cpu(prm->cmd->ssp_hdr->tag);
434
435         /*
436          * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs
437          */
438         /* command header dword 4 -5 */
439         /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */
440         buf_tmp = buf_cmd = slot->buf;
441         buf_tmp_dma = slot->buf_dma;
442         cmd_hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
443
444         /* command header dword 6 -7 */
445         buf_tmp += req_len;
446         buf_tmp_dma += req_len;
447         /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
448         slot->open_frame = buf_tmp;
449         cmd_hdr->open_frame = cpu_to_le64(buf_tmp_dma);
450
451         /* command header dword 10 -11 */
452         buf_tmp += MVS_OAF_SZ;
453         buf_tmp_dma += MVS_OAF_SZ;
454         /* region 3: PRD table ******************************* */
455         buf_prd = buf_tmp;
456         cmd_hdr->prd_tbl = 0;
457
458         /* command header dword 8 -9 */
459         /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
460         slot->response = buf_tmp;
461         cmd_hdr->status_buf = cpu_to_le64(buf_tmp_dma);
462
463         /* command header dword 1 */
464         resp_len = MVS_SLOT_BUF_SZ - req_len - MVS_OAF_SZ -
465             sizeof(struct mvs_err_info) - prd_len;
466         resp_len = min(resp_len, max_resp_len);
467
468         cmd_hdr->max_rsp_frame_len = resp_len / 4;
469         cmd_hdr->frame_len =
470                 req_len / 4 < MVS_MAX_SSP_FRAME ? req_len/4 : MVS_MAX_SSP_FRAME;
471
472         /* generate open address frame hdr (first 12 bytes) */
473         open_frame = (struct open_address_frame *)slot->open_frame;
474         open_frame->initiator = 0;      /* target mode */
475         open_frame->protocol = PROTOCOL_SSP;
476         open_frame->frame_type = ADDRESS_OPEN_FRAME;
477         open_frame->connect_rate = (prm->cmd->open_frame->received_rate);
478         open_frame->connect_tag =
479                 be16_to_cpu(prm->cmd->open_frame->received_tag);
480         open_frame->dest_sas_addr =
481                 mvst_get_be_sas_addr((u8 *)&prm->cmd->open_frame->src_sas_addr);
482
483         /*  for passthru mode */
484         /* fill in SSP frame header (Command Table.SSP frame header) */
485         if (cmd_hdr->ssp_passthru == MCH_SSP_MODE_PASSTHRU) {
486                 struct ssp_frame_header *ssp_hdr;
487                 /* command table */
488                 ssp_hdr = (struct ssp_frame_header *)slot->buf;
489                 ssp_hdr->frame_type = SSP_RESPONSE;
490                 memcpy(ssp_hdr->hashed_dest_sas_addr,
491                         prm->cmd->ssp_hdr->hashed_src_sas_addr,
492                         HASHED_SAS_ADDR_SIZE);
493                 memcpy(ssp_hdr->hashed_src_sas_addr,
494                        prm->cmd->ssp_hdr->hashed_dest_sas_addr,
495                        HASHED_SAS_ADDR_SIZE);
496                 /* copy the tag from received command frame */
497                 ssp_hdr->tag = be16_to_cpu(prm->cmd->ssp_hdr->tag);
498         }
499
500         /* fill in xfer ready frame IU */
501         buf_cmd += sizeof(struct ssp_frame_header);
502         response_iu = (struct mv_ssp_response_iu *)buf_cmd;
503
504         if (has_data == 0) {
505                 response_iu->datapres = NO_DATA;
506         } else if (sense_data) {
507                 response_iu->status = prm->rq_result;
508                 response_iu->datapres = SENSE_DATA;
509                 response_iu->sense_data_len =
510                         cpu_to_be32(prm->sense_buffer_len);
511                 memcpy(response_iu->data,
512                         prm->sense_buffer, prm->sense_buffer_len);
513         } else {
514         /* response data */
515                 response_iu->datapres = RESPONSE_DATA;
516                 response_iu->response_data_len = cpu_to_be32((int)4);
517                 response_iu->data[3] = INVALID_FRAME;
518         }
519
520         TRACE_EXIT();
521         return 0;
522 }
523
524 static int
525 mvst_send_resp_deferred(struct mvs_info *mvi,
526                                 struct mvst_cmd *cmd)
527 {
528         struct mvst_prm prm = { 0 };
529         struct scst_cmd *scst_cmd = cmd->scst_cmd;
530         u16 pass = 0;
531         struct mvs_slot_info *slot;
532         u32 res = SCST_TGT_RES_SUCCESS;
533
534         TRACE_ENTRY();
535         prm.cmd = (struct mvst_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
536         prm.sg = scst_cmd_get_sg(scst_cmd);
537         prm.bufflen = scst_cmd_get_resp_data_len(scst_cmd);
538         prm.sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
539         prm.data_direction = scst_cmd_get_data_direction(scst_cmd);
540         prm.rq_result = scst_cmd_get_status(scst_cmd);
541         prm.sense_buffer = scst_cmd_get_sense_buffer(scst_cmd);
542         prm.sense_buffer_len = scst_cmd_get_sense_buffer_len(scst_cmd);
543         prm.tgt = mvi->tgt;
544         prm.seg_cnt = 0;
545         prm.req_cnt = 1;
546
547         {
548                 /* prepare response frame */
549                 slot = mvst_get_slot(mvi, cmd->cmd_tgt_port);
550                 if (!slot) {
551                         res = SCST_TGT_RES_QUEUE_FULL;
552                         goto err_out;
553                 }
554                 /* save scst cmd */
555                 slot->slot_scst_cmd = scst_cmd;
556                 mvst_prep_resp_frame(&prm, slot, 1);
557
558                 pass++;
559                 mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
560
561         }
562         /* Mid-level is done processing */
563         cmd->cmd_state = MVST_STATE_PROCESSED;
564         goto out_done;
565
566 err_out:
567         TRACE_DBG("send_resp failed[%d]!\n", res);
568 out_done:
569         if (pass)
570                 MVS_CHIP_DISP->start_delivery(mvi,
571                         (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
572         TRACE_EXIT_RES(res);
573         return res;
574 }
575
576
577 static int  mvst_prep_data_frame_sg(struct mvst_prm *prm,
578                         struct mvs_slot_info *slot, u8 no_response)
579 {
580         u16 tag;
581         u8 *buf_tmp, sense_data;
582         dma_addr_t buf_tmp_dma;
583         u32 resp_len, prd_len = 0;
584         const u32 max_resp_len = SB_RFB_MAX;
585         u16 cmd_tbl_len = MVS_MAX_SSP_FRAME * 4;
586         struct mvs_info *mvi = prm->tgt->mvi;
587         struct mvs_cmd_header *cmd_hdr;
588         struct mvs_delivery_queue *delivery_q;
589         struct mvs_prd *buf_prd;
590         struct open_address_frame *open_frame;
591         struct mv_ssp_response_iu *response_iu;
592
593         TRACE_ENTRY();
594         tag = slot->target_cmd_tag;
595         cmd_hdr = (struct mvs_cmd_header *)&mvi->slot[tag];
596         /* get free delivery queue */
597         delivery_q = (struct mvs_delivery_queue *)&mvi->tx[mvi->tx_prod];
598
599         /* SSP protocol, Target mode, Normal priority */
600         delivery_q->cmd = TXQ_CMD_SSP;
601         delivery_q->mode = TXQ_MODE_TARGET;
602         delivery_q->priority = TXQ_PRI_NORMAL;
603         delivery_q->sata_reg_set = 0;
604         delivery_q->phy = prm->cmd->cmd_tgt_port->wide_port_phymap;
605         delivery_q->slot_nm = tag;
606
607         if ((prm->rq_result) && (SCST_SENSE_VALID(prm->sense_buffer)))
608                 sense_data = 1;
609         else
610                 sense_data = 0;
611
612         /* command header dword 0 */
613         cmd_hdr->prd_entry_count = prm->sg_cnt;
614
615         cmd_hdr->ssp_frame_type = MCH_SSP_FR_READ_RESP;
616
617         cmd_hdr->ssp_passthru = MCH_SSP_MODE_NORMAL;
618
619         /* command header dword 1 */
620         /* configure in below */
621
622         /* command header dword 2 */
623         cmd_hdr->target_tag = cpu_to_le16(tag);
624
625         /* copy the tag from received command frame */
626         cmd_hdr->tag = be16_to_cpu(prm->cmd->ssp_hdr->tag);
627
628         /* command header dword 3 */
629         cmd_hdr->data_len = cpu_to_le32(prm->bufflen);
630
631         /*
632          * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs
633          */
634
635         /* command header dword 4 -5 */
636         /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */
637         buf_tmp  = slot->buf;
638         buf_tmp_dma = slot->buf_dma;
639         cmd_hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
640
641         /* prepare response frame following data */
642         buf_tmp += sizeof(struct ssp_frame_header);
643         response_iu = (struct mv_ssp_response_iu *)buf_tmp;
644         if (sense_data == 0) {
645                 response_iu->datapres = NO_DATA;
646         } else if (!no_response) {
647                 response_iu->status = prm->rq_result;
648                 response_iu->datapres = SENSE_DATA;
649                 response_iu->sense_data_len =
650                         cpu_to_le32(prm->sense_buffer_len);
651                 memcpy(response_iu->data,
652                         prm->sense_buffer, prm->sense_buffer_len);
653         }
654         buf_tmp -= sizeof(struct ssp_frame_header);
655
656         /* command header dword 6 -7 */
657         buf_tmp += cmd_tbl_len;
658         buf_tmp_dma += cmd_tbl_len;
659         /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
660         slot->open_frame = buf_tmp;
661         cmd_hdr->open_frame = cpu_to_le64(buf_tmp_dma);
662
663         /* command header dword 10 -11 */
664         buf_tmp += MVS_OAF_SZ;
665         buf_tmp_dma += MVS_OAF_SZ;
666
667         /* region 3: PRD table *********************************** */
668         buf_prd = (struct mvs_prd *)buf_tmp;
669         if (prm->sg_cnt != 0)
670                 cmd_hdr->prd_tbl = cpu_to_le64(buf_tmp_dma);
671         else
672                 cmd_hdr->prd_tbl = 0;
673
674         prd_len = MVS_CHIP_DISP->prd_size() * prm->sg_cnt;
675         buf_tmp += prd_len;
676         buf_tmp_dma += prd_len;
677
678         /* command header dword 8 -9 */
679         /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
680         slot->response = buf_tmp;
681         cmd_hdr->status_buf = cpu_to_le64(buf_tmp_dma);
682
683         /* command header dword 1 */
684         resp_len = MVS_SLOT_BUF_SZ - cmd_tbl_len - MVS_OAF_SZ -
685             sizeof(struct mvs_err_info) - prd_len;
686         resp_len = min(resp_len, max_resp_len);
687
688         cmd_hdr->max_rsp_frame_len = resp_len / 4;
689         cmd_hdr->frame_len = cmd_tbl_len;
690
691         /* generate open address frame hdr (first 12 bytes) */
692         open_frame = (struct open_address_frame *)slot->open_frame;
693         open_frame->initiator = 0;      /* target mode */
694         open_frame->protocol = PROTOCOL_SSP;
695         open_frame->frame_type = ADDRESS_OPEN_FRAME;
696         open_frame->connect_rate = (prm->cmd->open_frame->received_rate);
697         open_frame->connect_tag =
698                 be16_to_cpu(prm->cmd->open_frame->received_tag);
699         open_frame->dest_sas_addr =
700                 mvst_get_be_sas_addr((u8 *)&prm->cmd->open_frame->src_sas_addr);
701
702         /*  for passthru mode */
703         /* fill in SSP frame header (Command Table.SSP frame header) */
704         if (cmd_hdr->ssp_passthru == MCH_SSP_MODE_PASSTHRU) {
705                 struct ssp_frame_header *ssp_hdr;
706                 /* command table */
707                 ssp_hdr = (struct ssp_frame_header *)slot->buf;
708                 ssp_hdr->frame_type = SSP_DATA;
709                 memcpy(ssp_hdr->hashed_dest_sas_addr,
710                         prm->cmd->ssp_hdr->hashed_src_sas_addr,
711                         HASHED_SAS_ADDR_SIZE);
712                 memcpy(ssp_hdr->hashed_src_sas_addr,
713                        prm->cmd->ssp_hdr->hashed_dest_sas_addr,
714                        HASHED_SAS_ADDR_SIZE);
715                 /* copy the tag from received command frame */
716                 ssp_hdr->tag = be16_to_cpu(prm->cmd->ssp_hdr->tag);
717         }
718
719         /* fill in PRD (scatter/gather) table, if any */
720         mvst_prep_prd(prm, buf_prd);
721         TRACE_EXIT();
722         return 0;
723 }
724
725 static int
726 mvst_send_data_frame_sg(struct mvs_info *mvi,
727                                 struct mvst_prm *prm)
728 {
729         u16 pass = 0;
730         struct mvs_slot_info *slot;
731         u32 res = SCST_TGT_RES_SUCCESS;
732         struct mvst_cmd *cmd = prm->cmd;
733         TRACE_ENTRY();
734         /* prepare response frame */
735         slot = mvst_get_slot(mvi, cmd->cmd_tgt_port);
736         if (!slot) {
737                 res = SCST_TGT_RES_QUEUE_FULL;
738                 goto err_out;
739         }
740         /* save scst cmd */
741         slot->slot_scst_cmd = cmd->scst_cmd;
742         mvst_prep_data_frame_sg(prm, slot, prm->rq_result);
743         pass++;
744         mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
745         /* Mid-level is done processing */
746         cmd->cmd_state = MVST_STATE_PROCESSED;
747         goto out_done;
748 err_out:
749         TRACE_DBG("send_data_frame failed[%d]!\n", res);
750 out_done:
751         if (pass) {
752                 MVS_CHIP_DISP->start_delivery(mvi,
753                         (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
754         }
755         TRACE_EXIT_RES(res);
756         return res;
757 }
758
759
760 /* Be called from irq contex */
761 static int
762 mvst_send_cmd(struct mvs_info *mvi)
763 {
764         u32 res = SCST_TGT_RES_SUCCESS;
765         u8 pass = 0;
766         struct list_head *pos, *n;
767         struct mvst_cmd *cmd;
768
769         BUG_ON(!in_irq());
770         list_for_each_safe(pos, n, &mvi->data_cmd_list) {
771                 cmd = container_of(pos, struct mvst_cmd, cmd_entry);
772                 if (cmd->cmd_state == MVST_STATE_PROCESSED)
773                         continue;       /* has sent command */
774                 res = mvst_send_resp_deferred(mvi, cmd);
775                 if (res == SCST_TGT_RES_QUEUE_FULL) {
776                         /* no resource */
777                         goto out_cmd;
778                 }
779                 pass++;
780         }
781 out_cmd:
782         return res;
783 }
784 static int mvst_xmit_response(struct scst_cmd *scst_cmd)
785 {
786         int res = SCST_TGT_RES_SUCCESS;
787         struct mvst_sess *sess;
788         int is_send_status;
789         unsigned long flags = 0;
790         struct mvst_prm prm = { 0 };
791         struct mvs_info *mvi;
792
793         TRACE_ENTRY();
794         TRACE(TRACE_SCSI, "xmit_respons scmd[0x%p] tag=%ld, sg_cnt=%d",
795                 scst_cmd, scst_cmd_get_tag(scst_cmd), scst_cmd->sg_cnt);
796
797 #ifdef DEBUG_WORK_IN_THREAD
798         if (scst_cmd_atomic(scst_cmd))
799                 return SCST_TGT_RES_NEED_THREAD_CTX;
800 #endif
801         memset(&prm, 0, sizeof(struct mvst_prm));
802         prm.cmd = (struct mvst_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
803         TRACE_DBG("xmit_response cmd[0x%p]", prm.cmd);
804         sess = (struct mvst_sess *)
805                 scst_sess_get_tgt_priv(scst_cmd_get_session(scst_cmd));
806
807         if (unlikely(scst_cmd_aborted(scst_cmd))) {
808                 TRACE(TRACE_MGMT_MINOR, "mvst tgt(%ld): terminating exchange "
809                         "for aborted scst_cmd=%p (tag=%ld)",
810                         mvi->instance, scst_cmd, scst_cmd_get_tag(scst_cmd));
811
812                 scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED);
813
814                 prm.cmd->cmd_state = MVST_STATE_ABORTED;
815
816                 /* !! At this point cmd could be already freed !! */
817                 goto out;
818         }
819
820         prm.sg = scst_cmd_get_sg(scst_cmd);
821         prm.bufflen = scst_cmd_get_resp_data_len(scst_cmd);
822         prm.sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
823         prm.data_direction = scst_cmd_get_data_direction(scst_cmd);
824         prm.rq_result = scst_cmd_get_status(scst_cmd);
825         prm.sense_buffer = scst_cmd_get_sense_buffer(scst_cmd);
826         prm.sense_buffer_len = scst_cmd_get_sense_buffer_len(scst_cmd);
827         prm.tgt = sess->tgt;
828         prm.seg_cnt = 0;
829         prm.req_cnt = 1;
830         is_send_status = scst_cmd_get_is_send_status(scst_cmd);
831
832         TRACE_DBG("rq_result=%x, is_send_status=%x,"
833                 "bufflen=0x%x, sense_buffer_len=0x%x", prm.rq_result,
834                 is_send_status, prm.bufflen, prm.sense_buffer_len);
835
836         mvi = prm.tgt->mvi;
837
838         if (prm.rq_result != 0)
839                 TRACE_BUFFER("Sense", prm.sense_buffer, prm.sense_buffer_len);
840
841         if (!is_send_status) {
842                 /* ToDo, after it's done in SCST */
843                 PRINT_ERROR("mvst tgt(%ld): is_send_status not set: "
844                      "feature not implemented", prm.tgt->mvi->instance);
845                 res = SCST_TGT_RES_FATAL_ERROR;
846                 goto out_tgt_free;
847         }
848
849         /* Acquire ring specific lock */
850         spin_lock_irqsave(&prm.tgt->mvi->lock, flags);
851
852         /*
853          * We need send read left data/response frame to HBA in later,
854          * so save the cmd to mvi->data_cmd_list.
855          */
856         list_add_tail(&prm.cmd->cmd_entry, &mvi->data_cmd_list);
857         if (mvst_has_data(scst_cmd)) {
858                 /* prepare send data frame */
859                 res = mvst_send_data_frame_sg(mvi, &prm);
860                 if (res)
861                         TRACE_DBG("xmit_response"
862                         "mvst_send_data_frame failed[%d]!\n",
863                         res);
864                 goto out_done;
865         } else {
866                 /* prepare response frame */
867                 res = mvst_send_resp_deferred(mvi, prm.cmd);
868                 if (res)
869                         TRACE_DBG("xmit_response"
870                         "mvst_send_resp_deferred failed[%d]!\n",
871                         res);
872         }
873
874 out_done:
875         /* Release ring specific lock */
876         spin_unlock_irqrestore(&prm.tgt->mvi->lock, flags);
877
878 out:
879         TRACE_EXIT_RES(res);
880         return res;
881
882 out_tgt_free:
883         /*ToDo: check and set scst_set_delivery_status(), if necessary */
884         if (!in_interrupt()) {
885                 msleep(250);
886                 scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_DIRECT);
887         } else
888                 scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_TASKLET);
889         /* !! At this point cmd could be already freed !! */
890         goto out;
891 }
892
893
894
895 static int mvst_prep_xfer_frame(struct mvst_prm *prm,
896                         struct mvs_slot_info *slot, u8 first_xfer)
897 {
898         u16 tag;
899         void *buf_tmp, *buf_cmd;
900         dma_addr_t buf_tmp_dma;
901         u32 resp_len, req_len, prd_len;
902         const u32 max_resp_len = SB_RFB_MAX;
903         struct mvs_info *mvi = prm->tgt->mvi;
904         struct mvs_cmd_header *cmd_hdr;
905         struct mvs_delivery_queue *delivery_q;
906         struct mvs_prd *buf_prd;
907         struct open_address_frame *open_frame;
908         struct ssp_xfrd_iu *xfrd_iu;
909
910         TRACE_ENTRY();
911         tag = slot->target_cmd_tag;
912
913         cmd_hdr = (struct mvs_cmd_header *)&mvi->slot[tag];
914         /* get free delivery queue */
915         delivery_q = (struct mvs_delivery_queue *)&mvi->tx[mvi->tx_prod];
916         req_len = sizeof(struct ssp_frame_header) + sizeof(struct ssp_xfrd_iu);
917
918         /* SSP protocol, Target mode, Normal priority */
919         delivery_q->cmd = TXQ_CMD_SSP;
920         delivery_q->mode = TXQ_MODE_TARGET;
921         delivery_q->priority = TXQ_PRI_NORMAL;
922         delivery_q->sata_reg_set = 0;
923         delivery_q->phy = prm->cmd->cmd_tgt_port->wide_port_phymap;
924         delivery_q->slot_nm = tag;
925
926         TRACE_DBG("delivery_q=0x%x.\n", mvi->tx[mvi->tx_prod]);
927         /* command header dword 0 */
928         cmd_hdr->prd_entry_count = prm->sg_cnt;
929         cmd_hdr->ssp_frame_type = MCH_SSP_FR_XFER_RDY;
930         cmd_hdr->ssp_passthru = MCH_SSP_MODE_NORMAL;
931
932         /* command header dword 1 */
933         /* configure in below */
934
935         /* command header dword 2 */
936         /* copy the tag from received command frame */
937         cmd_hdr->target_tag = cpu_to_le16(tag);
938         cmd_hdr->tag = be16_to_cpu(prm->cmd->ssp_hdr->tag);
939
940
941         /* command header dword 3 */
942         cmd_hdr->data_len = cpu_to_le32(prm->bufflen);
943
944         /*
945          * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs
946          */
947         /* command header dword 4 -5 */
948         /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ***** */
949         buf_tmp = buf_cmd = slot->buf;
950         buf_tmp_dma = slot->buf_dma;
951         cmd_hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
952
953
954         /* command header dword 6 -7 */
955         buf_tmp += req_len;
956         buf_tmp_dma += req_len;
957         /* region 2: open address frame area (MVS_OAF_SZ bytes) ***** */
958         slot->open_frame = buf_tmp;
959         cmd_hdr->open_frame = cpu_to_le64(buf_tmp_dma);
960
961         /* command header dword 10 -11 */
962         buf_tmp += MVS_OAF_SZ;
963         buf_tmp_dma += MVS_OAF_SZ;
964         /* region 3: PRD table ************************ */
965         buf_prd = buf_tmp;
966         if (prm->sg_cnt)
967                 cmd_hdr->prd_tbl = cpu_to_le64(buf_tmp_dma);
968         else
969                 cmd_hdr->prd_tbl = 0;
970
971         prd_len = sizeof(struct mvs_prd) * prm->sg_cnt;
972         buf_tmp += prd_len;
973         buf_tmp_dma += prd_len;
974
975         /* command header dword 8 -9 */
976         /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
977         slot->response = buf_tmp;
978         cmd_hdr->status_buf = cpu_to_le64(buf_tmp_dma);
979
980         /* command header dword 1 */
981         resp_len = MVS_SLOT_BUF_SZ - req_len - MVS_OAF_SZ -
982             sizeof(struct mvs_err_info) - prd_len;
983         resp_len = min(resp_len, max_resp_len);
984
985         cmd_hdr->max_rsp_frame_len = resp_len / 4;
986         cmd_hdr->frame_len =
987                 req_len / 4 < MVS_MAX_SSP_FRAME ?
988                 req_len/4 : MVS_MAX_SSP_FRAME;
989
990         TRACE_BUFFER("command header:", cmd_hdr, sizeof(*cmd_hdr));
991         /* generate open address frame hdr (first 12 bytes) */
992         open_frame = (struct open_address_frame *)slot->open_frame;
993         /* target mode */
994         open_frame->initiator = 0;
995         open_frame->protocol = PROTOCOL_SSP;
996         open_frame->frame_type = ADDRESS_OPEN_FRAME;
997         open_frame->connect_rate = (prm->cmd->open_frame->received_rate);
998         open_frame->connect_tag =
999                 be16_to_cpu(prm->cmd->open_frame->received_tag);
1000         open_frame->dest_sas_addr =
1001                 mvst_get_be_sas_addr((u8 *)&prm->cmd->open_frame->src_sas_addr);
1002
1003         TRACE_BUFFER("open frame:", open_frame, sizeof(*open_frame));
1004 /*  for passthru mode */
1005         /* fill in SSP frame header (Command Table.SSP frame header) */
1006         if (cmd_hdr->ssp_passthru == MCH_SSP_MODE_PASSTHRU) {
1007                 struct ssp_frame_header *ssp_hdr;
1008                 ssp_hdr = (struct ssp_frame_header *)slot->buf;
1009                 ssp_hdr->frame_type = SSP_XFER_RDY;
1010                 memcpy(ssp_hdr->hashed_dest_sas_addr,
1011                         prm->cmd->ssp_hdr->hashed_src_sas_addr,
1012                        HASHED_SAS_ADDR_SIZE);
1013                 memcpy(ssp_hdr->hashed_src_sas_addr,
1014                        prm->cmd->ssp_hdr->hashed_dest_sas_addr,
1015                        HASHED_SAS_ADDR_SIZE);
1016                 /* copy the tag from received command frame */
1017                 ssp_hdr->tag = be16_to_cpu(prm->cmd->ssp_hdr->tag);
1018         }
1019
1020         /* fill in xfer ready frame IU */
1021         buf_cmd += sizeof(struct ssp_frame_header);
1022         xfrd_iu = (struct ssp_xfrd_iu *)buf_cmd;
1023         xfrd_iu->data_len = cpu_to_be32(prm->bufflen);
1024         if ((!prm->cmd->command_iu->first_burst) ||
1025                 (!prm->cmd->open_frame->first_burst_size))
1026                 xfrd_iu->requested_offset = 0;
1027         else
1028                 xfrd_iu->requested_offset =
1029                         prm->cmd->open_frame->first_burst_size;
1030         TRACE_BUFFER("xfrd_iu:", xfrd_iu, sizeof(*xfrd_iu));
1031
1032         /* fill in PRD (scatter/gather) table, if any */
1033         mvst_prep_prd(prm, buf_prd);
1034
1035         TRACE_EXIT();
1036         return 0;
1037 }
1038
1039 static int mvst_pci_map_calc_cnt(struct mvst_prm *prm)
1040 {
1041         int res = 0;
1042
1043         sBUG_ON(prm->sg_cnt == 0);
1044
1045         /* 32 bit S/G Data Transfer */
1046         prm->seg_cnt = pci_map_sg(prm->tgt->mvi->pdev, prm->sg, prm->sg_cnt,
1047                                scst_to_tgt_dma_dir(prm->data_direction));
1048         if (unlikely(prm->seg_cnt == 0))
1049                 goto out_err;
1050         /*
1051          * If greater than four sg entries then we need to allocate
1052          * the continuation entries, but bug on now
1053          */
1054
1055         sBUG_ON(prm->seg_cnt > SG_ALL);
1056
1057 out:
1058         TRACE_DBG("seg_cnt=%d, req_cnt=%d, res=%d", prm->seg_cnt,
1059                 prm->req_cnt, res);
1060         return res;
1061
1062 out_err:
1063         PRINT_ERROR("mvs_tgt PCI mapping failed: sg_cnt=%d", prm->sg_cnt);
1064         res = -1;
1065         goto out;
1066 }
1067
1068 static int mvst_rdy_to_xfer(struct scst_cmd *scst_cmd)
1069 {
1070         int res = SCST_TGT_RES_SUCCESS;
1071         struct mvst_sess *sess;
1072         unsigned long flags = 0;
1073         struct mvst_prm prm = { 0 };
1074         struct mvs_slot_info *slot;
1075         u32 rc = 0, pass = 0;
1076         struct mvs_info *mvi;
1077         TRACE_ENTRY();
1078         TRACE(TRACE_SCSI, "tag=%lld", scst_cmd_get_tag(scst_cmd));
1079
1080 #ifdef DEBUG_WORK_IN_THREAD
1081         if (scst_cmd_atomic(scst_cmd))
1082                 return SCST_TGT_RES_NEED_THREAD_CTX;
1083 #endif
1084         prm.cmd = (struct mvst_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
1085         sess = (struct mvst_sess *)
1086                 scst_sess_get_tgt_priv(scst_cmd_get_session(scst_cmd));
1087         prm.sg = scst_cmd_get_sg(scst_cmd);
1088         prm.bufflen = scst_cmd_get_bufflen(scst_cmd);
1089         prm.sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
1090         prm.data_direction = scst_cmd_get_data_direction(scst_cmd);
1091         prm.tgt = sess->tgt;
1092         prm.req_cnt = 1;
1093         prm.cmd->cmd_state = MVST_STATE_NEED_DATA;
1094
1095         mvi = prm.tgt->mvi;
1096
1097         /* Acquire ring specific lock */
1098         spin_lock_irqsave(&mvi->lock, flags);
1099
1100         /* Calculate number of entries and segments required */
1101         if (mvst_pci_map_calc_cnt(&prm) != 0) {
1102                 res = SCST_TGT_RES_QUEUE_FULL;
1103                 goto err_out;
1104         }
1105
1106         slot = mvst_get_slot(mvi, prm.cmd->cmd_tgt_port);
1107         if (!slot) {
1108                 res = SCST_TGT_RES_QUEUE_FULL;
1109                 goto err_out;
1110         }
1111         slot->slot_scst_cmd = scst_cmd;
1112
1113         TRACE_DBG("start rdy_to_xfer: mvi(%d)", (int) prm.tgt->mvi->instance);
1114
1115         rc = mvst_prep_xfer_frame(&prm, slot, 1);
1116         if (rc) {
1117                 res = SCST_TGT_RES_FATAL_ERROR;
1118                 goto err_out_tag;
1119         }
1120         ++pass;
1121         mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
1122
1123         goto out_done;
1124
1125 err_out_tag:
1126         PRINT_ERROR("%s:prepare xfer frame failed.", __func__);
1127         mvst_put_slot(mvi, slot);
1128 err_out:
1129         PRINT_ERROR("%s:No sufficient tag for xfer frame", __func__);
1130 out_done:
1131         if (pass)
1132                 MVS_CHIP_DISP->start_delivery(mvi,
1133                         (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
1134
1135         /* Release ring specific lock */
1136         spin_unlock_irqrestore(&mvi->lock, flags);
1137
1138         TRACE_EXIT_RES(res);
1139         return res;
1140 }
1141
1142
1143
1144 static inline void mvst_free_cmd(struct mvst_cmd *cmd)
1145 {
1146         kmem_cache_free(mvst_cmd_cachep, cmd);
1147 }
1148
1149 static void mvst_on_free_cmd(struct scst_cmd *scst_cmd)
1150 {
1151         struct mvst_cmd *cmd =
1152                 (struct mvst_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
1153
1154         TRACE_ENTRY();
1155         TRACE(TRACE_SCSI, "END Command tag %lld", scst_cmd_get_tag(scst_cmd));
1156         scst_cmd_set_tgt_priv(scst_cmd, NULL);
1157         memset(cmd->ssp_hdr, 0, sizeof(*cmd->ssp_hdr));
1158         memset(cmd->command_iu, 0, sizeof(*cmd->command_iu));
1159         memset(cmd->open_frame, 0, sizeof(*cmd->open_frame));
1160         memset(cmd, 0, sizeof(*cmd));
1161
1162         mvst_free_cmd(cmd);
1163
1164         TRACE_EXIT();
1165         return;
1166 }
1167
1168
1169 static int mvst_slot_tgt_err(struct mvs_info *mvi,       u32 slot_idx)
1170 {
1171         struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
1172         u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
1173         u32 err_dw1 = le32_to_cpu(*(u32 *) (slot->response + 4));
1174         int stat = 0;
1175         TRACE_ENTRY();
1176         if (err_dw0 & CMD_ISS_STPD)
1177                 mv_dprintk("slot[%d] command issue stopped.\n", slot_idx);
1178
1179         if (err_dw1 & SLOT_BSY_ERR)
1180                 mv_dprintk("slot[%d] busy error.\n", slot_idx);
1181         mv_dprintk("slot[%d] get error Dw0:0x%x, Dw1:0x%x\n",
1182                 slot_idx, err_dw0, err_dw1);
1183         TRACE_BUFFER("status buffer:", (u8 *) slot->response, 16);
1184         TRACE_EXIT_HRES(stat);
1185         return stat;
1186 }
1187
1188
1189 /* mvi->lock supposed to be held on entry */
1190 static void mvst_do_cmd_completion(struct mvs_info *mvi,
1191                                   uint32_t rx_desc)
1192 {
1193         u32 slot_idx = rx_desc & RXQ_SLOT_MASK;
1194         struct mvs_slot_info *slot =
1195                 (struct mvs_slot_info *)&mvi->slot_info[slot_idx];
1196         struct mvs_cmd_header  *cmd_hdr =
1197                 (struct mvs_cmd_header  *)&mvi->slot[slot_idx];
1198         struct scst_cmd *scst_cmd;
1199         struct mvst_cmd *cmd;
1200         int err = 0;
1201         u8 frame_type;
1202         u64 dest_sas_addr;
1203         TRACE_ENTRY();
1204
1205         frame_type = cmd_hdr->ssp_frame_type;
1206         TRACE(TRACE_DEBUG|TRACE_SCSI, "frame[0x%x] complete, rx_desc=0x%x",
1207               frame_type, rx_desc);
1208
1209         /* error info record present */
1210         if (unlikely((rx_desc & RXQ_ERR) && (slot->response))) {
1211                 mvst_slot_tgt_err(mvi, slot_idx);
1212                 TRACE_DBG("Found by failed  frame_type[0x%x]", frame_type);
1213                 err = 1;
1214         }
1215
1216          if (slot->slot_scst_cmd) {
1217                 if (!slot->open_frame) {
1218                         TRACE_DBG("Found recevied command[%p]"
1219                                 "but no open frame.", slot->slot_scst_cmd);
1220                         sBUG_ON(!slot->open_frame);
1221                         goto out;
1222                 }
1223          }
1224
1225          if (slot->slot_scst_cmd) {
1226                 struct open_address_frame *open_frame =
1227                         (struct open_address_frame *)slot->open_frame;
1228                 struct ssp_frame_header *ssp_hdr;
1229                 struct mvst_sess *sess;
1230                 TRACE_BUFFER("SSP Header", ssp_hdr, sizeof(*ssp_hdr));
1231                 TRACE_BUFFER("SSP open_frame", open_frame, sizeof(*open_frame));
1232                 dest_sas_addr = (open_frame->dest_sas_addr);
1233                 sess = mvst_find_sess_by_lid(mvi->tgt,
1234                         mvst_get_le_sas_addr((u8 *)&dest_sas_addr));
1235                 TRACE(TRACE_DEBUG, "dest_sas_addr=%016llx", dest_sas_addr);
1236                 if (sess == NULL) {
1237                         ssp_hdr = (struct ssp_frame_header *)slot->buf;
1238                         TRACE_DBG("mvst tgt(%ld): Suspicious: "
1239                                    "command completion for non-existing"
1240                                    "session " "(sas addr[%016llx], tag %d)",
1241                                    mvi->instance,
1242                                    mvst_get_le_sas_addr((u8 *)&dest_sas_addr),
1243                                    be16_to_cpu(ssp_hdr->tag));
1244                         goto out;
1245                 }
1246                 scst_cmd = slot->slot_scst_cmd;
1247                 TRACE_DBG("Found scst_cmd %p", scst_cmd);
1248
1249                 cmd = (struct mvst_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
1250
1251                 if (cmd->cmd_state == MVST_STATE_PROCESSED) {
1252                         TRACE_DBG("Command %p finished", cmd);
1253                         if (err)
1254                                 goto out;
1255                         list_del(&cmd->cmd_entry);
1256                         goto out_free;
1257                 } else if (cmd->cmd_state == MVST_STATE_NEED_DATA) {
1258                         int context = SCST_CONTEXT_TASKLET;
1259                         int rx_status = SCST_RX_STATUS_SUCCESS;
1260
1261                         cmd->cmd_state = MVST_STATE_DATA_IN;
1262
1263                         if (err)
1264                                 rx_status = SCST_RX_STATUS_ERROR;
1265
1266 #ifdef DEBUG_WORK_IN_THREAD
1267                         context = SCST_CONTEXT_THREAD;
1268 #endif
1269
1270                         TRACE_DBG("Data received, context %x, rx_status %d",
1271                               context, rx_status);
1272
1273                         pci_unmap_sg(mvi->pdev, scst_cmd_get_sg(scst_cmd),
1274                                 scst_cmd_get_sg_cnt(scst_cmd),
1275                                 scst_to_tgt_dma_dir(
1276                                 scst_cmd_get_data_direction(scst_cmd)));
1277
1278                         scst_rx_data(scst_cmd, rx_status, context);
1279                 } else if (cmd->cmd_state == MVST_STATE_SEND_DATA) {
1280                         TRACE_DBG("Read data command %p finished", cmd);
1281                         if (err) {
1282                                 cmd->cmd_state = MVST_STATE_SEND_DATA_RETRY;
1283                                 sBUG_ON(1);
1284                         }
1285                         goto out;
1286                 } else if (cmd->cmd_state == MVST_STATE_ABORTED) {
1287                         TRACE_DBG("Aborted command %p finished", cmd);
1288                         goto out_free;
1289                 } else {
1290                         PRINT_ERROR("mvst tgt(%ld): A command in state"
1291                                 "(%d) should " "not return a complete",
1292                                 mvi->instance, cmd->cmd_state);
1293                         goto out_free;
1294                 }
1295         } else {
1296                 TRACE_DBG("Found internal target frame[0x%x] complete",
1297                         cmd_hdr->ssp_frame_type);
1298                 goto out;
1299         }
1300 out:
1301         mvst_put_slot(mvi, slot);
1302         TRACE_EXIT();
1303         return;
1304
1305 out_free:
1306         if (unlikely(err)) {
1307                 TRACE_MGMT_DBG("%s", "Finishing failed CTIO");
1308                 scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED);
1309         }
1310         if (!in_interrupt()) {
1311                 msleep(250);
1312                 scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_DIRECT);
1313         } else
1314                 scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_TASKLET);
1315         goto out;
1316 }
1317
1318 /* mvi->lock supposed to be held on entry */
1319 /* called via callback from mvst */
1320 static void mvst_cmd_completion(struct mvs_info *mvi, uint32_t rx_desc)
1321 {
1322         u32 slot_idx = rx_desc & RXQ_SLOT_MASK;
1323         struct mvs_cmd_header  *cmd_hdr = NULL;
1324
1325         TRACE_ENTRY();
1326         sBUG_ON(mvi == NULL);
1327
1328         if ((mvi->tgt != NULL) && MVST_IN_TARGET_MODE(mvi))
1329                 mvst_do_cmd_completion(mvi, rx_desc);
1330         else {
1331                 cmd_hdr = (struct mvs_cmd_header  *)&mvi->slot[slot_idx];
1332                 TRACE_DBG("command complete, but target mode not enabled."
1333                         "mvi %p complete frame 0x%x",
1334                         mvi, cmd_hdr->ssp_frame_type);
1335         }
1336         TRACE_EXIT();
1337         return;
1338 }
1339
1340
1341
1342 /* mvi->lock is supposed to be held on entry */
1343 static int mvst_do_send_cmd_to_scst(struct mvs_info *mvi, struct mvst_cmd *cmd)
1344 {
1345         int res = 0;
1346         struct mvst_sess *sess = cmd->sess;
1347         u8 lun[8];
1348         scst_data_direction dir = SCST_DATA_NONE;
1349         int context;
1350
1351         TRACE_ENTRY();
1352
1353         memcpy(lun, cmd->command_iu->lun, 8);
1354         cmd->scst_cmd = scst_rx_cmd(sess->scst_sess, (uint8_t *)&lun,
1355                                     sizeof(lun), cmd->command_iu->cdb,
1356                                     MVST_MAX_CDB_LEN,
1357                                     SCST_ATOMIC);
1358
1359         if (cmd->scst_cmd == NULL) {
1360                 PRINT_ERROR("mvst tgt(%ld): scst_rx_cmd() failed for "
1361                      "host %ld(%p)", mvi->instance, mvi->host_no, mvi);
1362                 res = -EFAULT;
1363                 goto out;
1364         }
1365
1366         TRACE_DBG("Get new scst_cmd %p", cmd->scst_cmd);
1367         TRACE_BUFFER("Get command header:",
1368                 cmd->ssp_hdr, sizeof(struct ssp_frame_header));
1369         TRACE_BUFFER("Get command open frame:",
1370                 cmd->open_frame, sizeof(struct open_address_frame));
1371         scst_cmd_set_tag(cmd->scst_cmd, be16_to_cpu(cmd->ssp_hdr->tag));
1372         scst_cmd_set_tgt_priv(cmd->scst_cmd, cmd);
1373         if (cmd->command_iu->cdb[0] & MVST_EXEC_READ)
1374                 dir = SCST_DATA_READ;
1375         else if (cmd->command_iu->cdb[0] & MVST_EXEC_WRITE)
1376                 dir = SCST_DATA_WRITE;
1377
1378         switch (cmd->command_iu->task_attr) {
1379         case TASK_ATTR_SIMPLE:
1380                 cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_SIMPLE;
1381                 break;
1382         case TASK_ATTR_HOQ:
1383                 cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
1384                 break;
1385         case TASK_ATTR_ORDERED:
1386                 cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
1387                 break;
1388         case TASK_ATTR_ACA:
1389                 cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_ACA;
1390                 break;
1391         default:
1392                 PRINT_ERROR("mvst tgt(%ld): Unknown task code %x, use "
1393                         "ORDERED instead", mvi->instance,
1394                         cmd->command_iu->task_attr);
1395                 cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
1396                 break;
1397         }
1398
1399 #ifdef DEBUG_WORK_IN_THREAD
1400         context = SCST_CONTEXT_THREAD;
1401 #else
1402         context = SCST_CONTEXT_TASKLET;
1403 #endif
1404
1405         TRACE_DBG("Context %x", context);
1406         TRACE(TRACE_SCSI, "START Command (tag %ld)",
1407                 scst_cmd_get_tag(cmd->scst_cmd));
1408         scst_cmd_init_done(cmd->scst_cmd, context);
1409 out:
1410         TRACE_EXIT_RES(res);
1411         return res;
1412 }
1413
1414 /* Called in SCST's thread context */
1415 static void mvst_alloc_session_done(struct scst_session *scst_sess,
1416                                    void *data, int result)
1417 {
1418         TRACE_ENTRY();
1419
1420         if (result != 0) {
1421                 struct mvst_sess *sess = (struct mvst_sess *)data;
1422                 struct mvst_tgt *tgt = sess->tgt;
1423                 struct mvs_info *mvi = tgt->mvi;
1424                 unsigned long flags;
1425
1426                 TRACE_DBG("mvst tgt(%ld): Session initialization failed",
1427                            mvi->instance);
1428
1429                 spin_lock_irqsave(&mvi->lock, flags);
1430                 mvst_unreg_sess(sess);
1431                 spin_unlock_irqrestore(&mvi->lock, flags);
1432         }
1433
1434         TRACE_EXIT();
1435         return;
1436 }
1437
1438
1439
1440 static char *mvst_make_name(struct mvs_info *mvi)
1441 {
1442         char *wwn_str;
1443         u8 name[16];
1444         strcpy(name,  MVST_NAME);
1445
1446         wwn_str = kmalloc(3*SAS_ADDR_SIZE, GFP_ATOMIC);
1447         if (wwn_str == NULL) {
1448                 TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of wwn_str failed");
1449                 goto out;
1450         }
1451         sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1452                 name[1], name[0], name[3], name[2], name[5], name[4],
1453                 name[7], name[6]);
1454
1455 out:
1456         return wwn_str;
1457
1458
1459 }
1460
1461 struct mvst_port *mvst_get_port_by_sasaddr(struct mvs_info *mvi,
1462                                 u64 dst_sas_addr, u64 src_sas_addr)
1463 {
1464         int n = 0;
1465         for (n = 0; n < mvi->chip->n_phy; n++) {
1466                 if ((SAS_ADDR(&mvi->phy[n].dev_sas_addr) == dst_sas_addr)
1467                         && mvi->tgt_port[n].port_attached)
1468                         break;
1469         }
1470 #if 0
1471         /*check if direct initiator cmd*/
1472         if (n == mvi->chip->n_phy) {
1473                 for (n = 0; n < mvi->chip->n_phy; n++) {
1474                         if ((mvi->tgt_port[n].sas_addr == dst_sas_addr)
1475                                 && mvi->tgt_port[n].port_attached)
1476                                 break;
1477                 }
1478                 if (n == mvi->chip->n_phy)
1479                         return NULL;
1480         } else {
1481                 for (n = 0; n < mvi->chip->n_phy; n++) {
1482                         if ((mvi->tgt_port[n].att_sas_addr == src_sas_addr)
1483                                 && mvi->tgt_port[n].port_attached)
1484                                 break;
1485                 }
1486                 if (n == mvi->chip->n_phy)
1487                         mv_dprintk("Port attatch sas address error\n");
1488         }
1489 #endif
1490
1491         if (n == mvi->chip->n_phy) {
1492                 mv_dprintk("Port attatch sas address error\n");
1493                 return NULL;
1494         }
1495
1496         return &mvi->tgt_port[n];
1497 }
1498
1499 int mvst_alloc_session(struct mvst_sess *sess, struct mvst_tgt *tgt, u64 sas_addr)
1500 {
1501         int res = 0;
1502         struct mvs_info *mvi = tgt->mvi;
1503
1504         TRACE_ENTRY();
1505         sess = mvst_find_sess_by_lid(tgt, sas_addr);
1506         if (unlikely(sess == NULL)) {
1507                 sess = kzalloc(sizeof(*sess), GFP_ATOMIC);
1508                 if (sess == NULL) {
1509                         TRACE(TRACE_OUT_OF_MEM, "%s",
1510                               "Allocation of sess failed");
1511                         res = -ENOMEM;
1512                         goto out;
1513                 }
1514
1515                 sess->tgt = tgt;
1516                 sess->initiator_sas_addr = sas_addr;
1517                 INIT_LIST_HEAD(&sess->sess_entry);
1518
1519                 /* register session (remote initiator) */
1520                 {
1521                         char *name;
1522                         name = mvst_make_name(mvi);
1523                         if (name == NULL) {
1524                                 PRINT_ERROR("can not make name"
1525                                         "for session %p", sess);
1526                                 res = -ESRCH;
1527                                 goto out;
1528                         }
1529
1530                         sess->scst_sess = scst_register_session(
1531                                 tgt->scst_tgt, SCST_ATOMIC, name, sess,
1532                                 mvst_alloc_session_done);
1533                         kfree(name);
1534                 }
1535
1536                 if (sess->scst_sess == NULL) {
1537                         PRINT_ERROR("mvst tgt(%ld): scst_register_session()"
1538                                 "failed for host %ld(%p)",
1539                                 mvi->instance,
1540                                 mvi->host_no, mvi);
1541                         res = -EFAULT;
1542                         goto out;
1543                 }
1544                 scst_sess_set_tgt_priv(sess->scst_sess, sess);
1545
1546                 /* add session data to host data structure */
1547                 list_add(&sess->sess_entry, &tgt->sess_list);
1548                 tgt->sess_count++;
1549         }
1550 out:
1551         TRACE_EXIT();
1552         return res;
1553 }
1554
1555 /* mvi->lock supposed to be held on entry */
1556
1557 static int mvst_send_cmd_to_scst(struct mvs_info *mvi,
1558                                 struct mvs_slot_info *slot)
1559 {
1560         int res = 0;
1561         u64 initiator_sas_addr, src_sas_addr, dst_sas_addr;
1562         struct mvst_tgt *tgt;
1563         struct mvst_sess *sess = NULL;
1564         struct mvst_cmd *cmd;
1565         struct open_address_frame *open_frame =
1566                 (struct open_address_frame *)slot->open_frame;
1567         struct ssp_frame_header *ssp_hdr =
1568                 (struct ssp_frame_header *)((u8 *)slot->response+8);
1569         struct ssp_command_iu *ssp_cmd_iu =
1570                 (struct ssp_command_iu *)((u8 *)ssp_hdr +
1571                 sizeof(struct ssp_frame_header));
1572         struct mvst_port        *tgt_port;
1573         TRACE_ENTRY();
1574
1575         initiator_sas_addr = be64_to_cpu(open_frame->src_sas_addr);
1576         dst_sas_addr = mvst_get_le_sas_addr((u8 *)&open_frame->dest_sas_addr);
1577         src_sas_addr = mvst_get_le_sas_addr((u8 *)&open_frame->src_sas_addr);
1578
1579         tgt = mvi->tgt;
1580         tgt_port = mvst_get_port_by_sasaddr(mvi, dst_sas_addr, src_sas_addr);
1581         if (tgt_port == NULL) {
1582                 res = -EFAULT;
1583                 mv_dprintk("can not find tgt port for dst sas:%016llx,"
1584                         "src sas:%016llx\n",
1585                         dst_sas_addr, src_sas_addr);
1586                 goto out;
1587         }
1588
1589         TRACE_DBG("To SCST instance=%ld  tag=0x%x src_sas_addr=0x%0llx",
1590                   mvi->instance,  be16_to_cpu(ssp_hdr->tag),
1591                   mvst_get_le_sas_addr((u8 *)&initiator_sas_addr));
1592
1593         if (tgt->tgt_shutdown) {
1594                 TRACE_DBG("New command while device %p is shutting "
1595                         "down", tgt);
1596                 res = -EFAULT;
1597                 goto out;
1598         }
1599
1600 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
1601         cmd =  kmem_cache_alloc(mvst_cmd_cachep, GFP_ATOMIC);
1602 #else
1603         cmd =  kmem_cache_zalloc(mvst_cmd_cachep, GFP_ATOMIC);
1604 #endif
1605         if (cmd == NULL) {
1606                 TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of cmd failed");
1607                 res = -ENOMEM;
1608                 goto out;
1609         }
1610 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
1611         memset(cmd, 0, sizeof(*cmd));
1612 #endif
1613         /* set cmd private data for later use */
1614         memcpy(&cmd->save_command_iu, ssp_cmd_iu, sizeof(*ssp_cmd_iu));
1615         memcpy(&cmd->save_open_frame, open_frame, sizeof(*open_frame));
1616         memcpy(&cmd->save_ssp_hdr, ssp_hdr, sizeof(*ssp_hdr));
1617         memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
1618         cmd->command_iu = &cmd->save_command_iu;
1619         cmd->open_frame = &cmd->save_open_frame;
1620         cmd->ssp_hdr = &cmd->save_ssp_hdr;
1621         cmd->cmd_tgt_port =  tgt_port;  /* save  SSP Target port */
1622         cmd->cmd_state = MVST_STATE_NEW;
1623         cmd->transfer_len = 0;
1624         cmd->finished_len = 0;
1625         cmd->transfer_buf = NULL;
1626 #if 0
1627         res = mvst_alloc_session(sess, tgt, initiator_sas_addr);
1628         if (res) {
1629                 if (-ENOMEM == res)
1630                         goto out_free_cmd;
1631                 if (-ESRCH == res || -EFAULT == res)
1632                         goto out_free_sess;
1633         }
1634 #else
1635         sess = mvst_find_sess_by_lid(tgt, initiator_sas_addr);
1636         if (unlikely(sess == NULL)) {
1637                 sess = kzalloc(sizeof(*sess), GFP_ATOMIC);
1638                 if (sess == NULL) {
1639                         TRACE(TRACE_OUT_OF_MEM, "%s",
1640                               "Allocation of sess failed");
1641                         res = -ENOMEM;
1642                         goto out_free_cmd;
1643                 }
1644
1645                 sess->tgt = tgt;
1646                 sess->initiator_sas_addr = initiator_sas_addr;
1647                 INIT_LIST_HEAD(&sess->sess_entry);
1648
1649                 /* register session (remote initiator) */
1650                 {
1651                         char *name;
1652                         name = mvst_make_name(mvi);
1653                         if (name == NULL) {
1654                                 PRINT_ERROR("can not make name for"
1655                                         "session, cmd[0x%p]",
1656                                         cmd);
1657                                 res = -ESRCH;
1658                                 goto out_free_sess;
1659                         }
1660
1661                         sess->scst_sess = scst_register_session(
1662                                 tgt->scst_tgt, SCST_ATOMIC, name, sess,
1663                                 mvst_alloc_session_done);
1664                         kfree(name);
1665                 }
1666
1667                 if (sess->scst_sess == NULL) {
1668                         PRINT_ERROR("mvst tgt(%ld): scst_register_session()"
1669                                 "failed for host %ld(%p)",
1670                                 mvi->instance,
1671                                 mvi->host_no, mvi);
1672                         res = -EFAULT;
1673                         goto out_free_sess;
1674                 }
1675                 scst_sess_set_tgt_priv(sess->scst_sess, sess);
1676
1677                 /* add session data to host data structure */
1678                 list_add(&sess->sess_entry, &tgt->sess_list);
1679                 tgt->sess_count++;
1680         }
1681 #endif
1682         cmd->sess = sess;
1683         res = mvst_do_send_cmd_to_scst(mvi, cmd);
1684         if (res != 0)
1685                 goto out_free_cmd;
1686
1687 out:
1688         TRACE_EXIT_RES(res);
1689         return res;
1690
1691 out_free_sess:
1692         kfree(sess);
1693         tgt->sess_count--;
1694         if (tgt->sess_count == 0)
1695                 wake_up_all(&tgt->waitQ);
1696         /* go through */
1697
1698 out_free_cmd:
1699         mvst_free_cmd(cmd);
1700
1701         goto out;
1702 }
1703
1704 /* mvi->lock supposed to be held on entry */
1705 static int mvst_handle_task_mgmt(struct mvs_info *mvi,
1706                         struct mvs_slot_info *slot)
1707 {
1708         int res = 0, rc = -1;
1709         u64 initiator_sas_addr;
1710         u8 lun[8];
1711         u16 tag;
1712         struct mvst_mgmt_cmd *mcmd;
1713         struct mvst_tgt *tgt;
1714         struct mvst_sess *sess;
1715         struct open_address_frame *open_frame =
1716                 (struct open_address_frame *)slot->buf;
1717         struct ssp_frame_header *ssp_hdr =
1718                 (struct ssp_frame_header *)((u8 *)slot->response+8);
1719         struct ssp_task_iu *ssp_task_iu =
1720                 (struct ssp_task_iu *)((u8 *)ssp_hdr +
1721                 sizeof(struct ssp_frame_header));
1722
1723         TRACE_ENTRY();
1724
1725         tgt = mvi->tgt;
1726         memcpy(lun,  ssp_task_iu->lun, 8);
1727         tag = be16_to_cpu(ssp_task_iu->tag);
1728         initiator_sas_addr = be64_to_cpu(open_frame->src_sas_addr);
1729
1730         sess = mvst_find_sess_by_lid(tgt, initiator_sas_addr);
1731         if (sess == NULL) {
1732                 TRACE(TRACE_MGMT, "mvsttgt(%ld): task mgmt fn 0x%x for "
1733                       "non-existant session", mvi->instance,
1734                       ssp_task_iu->task_fun);
1735                 res = -EFAULT;
1736                 goto out;
1737         }
1738
1739         mcmd = kzalloc(sizeof(*mcmd), GFP_ATOMIC);
1740         if (mcmd == NULL) {
1741                 TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of mgmt cmd failed");
1742                 res = -ENOMEM;
1743                 goto out;
1744         }
1745
1746         mcmd->sess = sess;
1747         memcpy(&mcmd->task_iu, ssp_task_iu, sizeof(*ssp_task_iu));
1748
1749         switch (ssp_task_iu->task_fun) {
1750         case TMF_CLEAR_ACA:
1751                 TRACE(TRACE_MGMT, "%s", "TMF_CLEAR_ACA received");
1752                 rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_ACA,
1753                                          (uint8_t *)lun, sizeof(lun),
1754                                          SCST_ATOMIC, mcmd);
1755                 break;
1756
1757         case TMF_LU_RESET:
1758                 TRACE(TRACE_MGMT, "%s", "TMF_LU_RESET received");
1759                 rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET,
1760                                          (uint8_t *)&lun, sizeof(lun),
1761                                          SCST_ATOMIC, mcmd);
1762                 break;
1763
1764         case TMF_CLEAR_TASK_SET:
1765                 TRACE(TRACE_MGMT, "%s", "TMF_CLEAR_TASK_SET received");
1766                 rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_TASK_SET,
1767                                          (uint8_t *)&lun, sizeof(lun),
1768                                          SCST_ATOMIC, mcmd);
1769                 break;
1770
1771         case TMF_ABORT_TASK_SET:
1772                 TRACE(TRACE_MGMT, "%s", "TMF_ABORT_TASK_SET received");
1773                 rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_ABORT_TASK_SET,
1774                                          (uint8_t *)&lun, sizeof(lun),
1775                                          SCST_ATOMIC, mcmd);
1776                 break;
1777
1778         case TMF_ABORT_TASK:
1779                 TRACE(TRACE_MGMT, "%s", "TMF_ABORT_TASK received");
1780                 rc = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, tag,
1781                         SCST_ATOMIC, mcmd);
1782                 break;
1783
1784         default:
1785                 PRINT_ERROR("mvsttgt(%ld): Unknown task mgmt fn 0x%x",
1786                             mvi->instance, ssp_task_iu->task_fun);
1787                 break;
1788         }
1789
1790         if (rc != 0) {
1791                 PRINT_ERROR("mvst tgt(%ld): scst_rx_mgmt_fn_lun() failed: %d",
1792                             mvi->instance, rc);
1793                 res = -EFAULT;
1794                 goto out_free;
1795         }
1796
1797 out:
1798         TRACE_EXIT_RES(res);
1799         return res;
1800
1801 out_free:
1802         kfree(mcmd);
1803         goto out;
1804 }
1805
1806 static int mvst_notify_attach_chg(struct mvs_info *mvi)
1807 {
1808         u8 i, j;
1809         int res = SCST_AEN_RES_SUCCESS;
1810
1811         TRACE_ENTRY();
1812         if (!mvi)
1813                 return SCST_AEN_RES_FAILED;
1814
1815 #if     0
1816         for (i = 0; i < mvi->chip->n_phy; i++) {
1817                 struct mvs_phy *phy = &mvi->phy[i];
1818                 struct asd_sas_phy *sas_phy = &phy->sas_phy;
1819                 if (mvi->tgt_port[i].port_attr & MVST_TGT_PORT)
1820                         sas_phy->tproto = SAS_PROTOCOL_SSP;
1821
1822                 if (mvi->tgt_port[i].port_attached) {
1823                         for (j = 0; j < mvi->chip->n_phy; j++) {
1824                                 if (mvi->tgt_port[i].wide_port_phymap & (1<<j))
1825                                         MVS_CHIP_DISP->phy_disable(mvi, j);
1826                         }
1827                         msleep(500);
1828                         for (j = 0; j < mvi->chip->n_phy; j++) {
1829                                 if (mvi->tgt_port[i].wide_port_phymap &
1830                                         (1<<j)) {
1831                                         MVS_CHIP_DISP->phy_enable(mvi, j);
1832                                 }
1833                         }
1834                 }
1835         }
1836 #endif
1837         for (i = 0; i < mvi->chip->n_host; i++) {
1838                 mvi = ((struct mvs_info **)tgt_mvi)[i];
1839                 if (!mvi || !(mvi->flags & MVF_TARGET_MODE_ENABLE))
1840                         continue;
1841                 for (j = 0; j < mvi->chip->n_phy; j++) {
1842                         if (mvi->phy[j].phy_mode)
1843                                 MVS_CHIP_DISP->phy_disable(mvi, j);
1844                 }
1845                 msleep(500);
1846                 for (j = 0; j < mvi->chip->n_phy; j++) {
1847                         if (mvi->phy[j].phy_mode) {
1848                                 /* enable phy */
1849                                 mv_printk("Reset phy[%d] to notify iniator\n",
1850                                 j+mvi->chip->n_phy*i);
1851                                 MVS_CHIP_DISP->phy_enable(mvi, j);
1852                         }
1853                 }
1854         }
1855
1856         TRACE_EXIT_RES(res);
1857         return res;
1858 }
1859
1860 static int mvst_notify_unit_attention(struct scst_aen *aen)
1861 {
1862         int res = SCST_AEN_RES_SUCCESS, key, asc, ascq;
1863         struct mvs_info *mvi = ((struct mvs_info **)tgt_mvi)[0];
1864
1865         TRACE_ENTRY();
1866
1867         if (aen->aen_sense[0] == 0x72) {
1868                 key = aen->aen_sense[1];        /* Sense Key    */
1869                 asc = aen->aen_sense[2]; /* ASC         */
1870                 ascq = aen->aen_sense[3]; /* ASCQ */
1871         } else if (aen->aen_sense[0] == 0x70) {
1872                 key = aen->aen_sense[2];        /* Sense Key    */
1873                 asc = aen->aen_sense[12]; /* ASC                */
1874                 ascq = aen->aen_sense[13]; /* ASCQ */
1875         } else
1876                 return res;
1877         switch (key) {
1878         case UNIT_ATTENTION:
1879                 if (asc == 0x3F && ascq == 0xE)
1880                         mvst_notify_attach_chg(mvi);
1881                 break;
1882                 /*
1883                 .to support more
1884                 .
1885                 */
1886         default:
1887                 res = SCST_AEN_RES_NOT_SUPPORTED;
1888                 break;
1889         }
1890
1891         TRACE_EXIT_RES(res);
1892         return res;
1893 }
1894
1895 static int mvst_report_event(struct scst_aen *aen)
1896 {
1897         int res = 0;
1898         int event_fn = scst_aen_get_event_fn(aen);
1899
1900         TRACE_ENTRY();
1901         switch (event_fn) {
1902         case SCST_AEN_SCSI:
1903                 res = mvst_notify_unit_attention(aen);
1904                 break;
1905         default:
1906                 TRACE_MGMT_DBG("Unsupported AEN %d", event_fn);
1907                 res = SCST_AEN_RES_NOT_SUPPORTED;
1908                 break;
1909         }
1910         TRACE_EXIT_RES(res);
1911         return res;
1912 }
1913
1914 /* SCST Callback */
1915 static void mvst_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd)
1916 {
1917         struct mvst_mgmt_cmd *mcmd;
1918         unsigned long flags;
1919         int     status;
1920         TRACE_ENTRY();
1921         status = scst_mgmt_cmd_get_status(scst_mcmd);
1922         TRACE_MGMT_DBG("scst_mcmd (%p) status %#x state %#x", scst_mcmd,
1923                 status, scst_mcmd->state);
1924
1925         mcmd = scst_mgmt_cmd_get_tgt_priv(scst_mcmd);
1926         if (unlikely(mcmd == NULL)) {
1927                 PRINT_ERROR("scst_mcmd %p tgt_spec is NULL", mcmd);
1928                 goto out;
1929         }
1930
1931         spin_lock_irqsave(&mcmd->sess->tgt->mvi->lock, flags);
1932         mvst_send_notify_ack(mcmd->sess->tgt->mvi, mcmd, status);
1933         spin_unlock_irqrestore(&mcmd->sess->tgt->mvi->lock, flags);
1934
1935         scst_mgmt_cmd_set_tgt_priv(scst_mcmd, NULL);
1936         kfree(mcmd);
1937
1938 out:
1939         TRACE_EXIT();
1940         return;
1941 }
1942
1943
1944 static void mvst_send_busy(struct mvs_info *mvi, struct mvs_slot_info *slot)
1945 {
1946
1947 }
1948
1949 /* mvi->lock supposed to be held on entry */
1950 /* called via callback from mvst */
1951 /* DO NOT call mvst_put_slot in the function, the running slots
1952     are used to receive initiator command */
1953 static u8 mvst_response_ssp_command(struct mvs_info *mvi, uint32_t rx_desc)
1954 {
1955         int rc = 0;
1956         u32 slot_idx = rx_desc & RXQ_SLOT_MASK;
1957         struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
1958         struct ssp_frame_header *ssp_hdr =
1959                 (struct ssp_frame_header *)((u8 *)slot->response+8);
1960
1961         TRACE_ENTRY();
1962
1963         if (unlikely((mvi->tgt == NULL) || !MVST_IN_TARGET_MODE(mvi))) {
1964                 TRACE_DBG("receive command, but no tgt. mvi %p tgt_flag %ld",
1965                         mvi, MVST_IN_TARGET_MODE(mvi));
1966                 rc = -1;
1967                 goto out;
1968         }
1969
1970         if (!slot->open_frame) {
1971                 TRACE_DBG("Found recevied command[%p] but no open frame.",
1972                         slot->slot_scst_cmd);
1973                 rc = -1;
1974                 goto out;
1975         }
1976
1977         if (!slot->slot_tgt_port) {
1978                 mv_printk("Found recevied command[%p]"
1979                         "but no related tgt port.\n",
1980                         slot->slot_scst_cmd);
1981                 rc = -1;
1982                 goto out;
1983
1984         }
1985         /*
1986          else if(slot->slot_tgt_port->port_attr == MVST_INIT_PORT){
1987                 mv_dprintk("Found recevied command[%p] but not set
1988                 as tgt port[0x%x].\n", slot->slot_scst_cmd,
1989                 slot->slot_tgt_port->port_attr);
1990                 rc = -1;
1991                 goto out;
1992         }
1993         */
1994
1995         if ((ssp_hdr->frame_type != SSP_COMMAND) &&
1996                 (ssp_hdr->frame_type != SSP_TASK) &&
1997                 (ssp_hdr->frame_type != SSP_DATA) /* do we need ? */) {
1998                 PRINT_ERROR("mvst tgt(%ld): Received command 0x%x "
1999                      "is not intiator command",  mvi->instance,
2000                      ssp_hdr->frame_type);
2001                 rc = -1;
2002                 goto out;
2003         }
2004
2005         switch (ssp_hdr->frame_type) {
2006         case SSP_COMMAND:
2007                 {
2008                 struct ssp_command_iu *ssp_cmd_iu = NULL;
2009                 ssp_cmd_iu =    (struct ssp_command_iu *)((u8 *)ssp_hdr
2010                         + sizeof(struct ssp_frame_header));
2011
2012                 TRACE_DBG("COMMAND FRAME:lun[0-7]=%016llx.\n",
2013                         (u64)(*(u64 *)&ssp_cmd_iu->lun[0]));
2014                 TRACE_DBG("COMMAND FRAME:cdb[0-7]=%016llx,cdb[8-15]=%016llx.\n",
2015                         (u64)(*(u64 *)&ssp_cmd_iu->cdb[0]),
2016                         (u64)(*(u64 *)&ssp_cmd_iu->cdb[8]));
2017                 }
2018
2019                 rc = mvst_send_cmd_to_scst(mvi, slot);
2020                 if (unlikely(rc != 0)) {
2021                         if (rc == -ESRCH)
2022                                 mvst_send_busy(mvi, slot);
2023                         else {
2024                                 if (!mvi->tgt->tgt_shutdown) {
2025                                         mv_dprintk("mvst tgt(%ld): Unable to "
2026                                             "send the command to SCSI target "
2027                                             "mid-level, sending BUSY status.\n",
2028                                             mvi->instance);
2029                                 }
2030                                 mvst_send_busy(mvi, slot);
2031                         }
2032                 }
2033                 break;
2034
2035         case SSP_TASK:
2036                 rc = mvst_handle_task_mgmt(mvi, slot);
2037                 if (unlikely(rc != 0)) {
2038                         if (rc == -ESRCH)
2039                                 mvst_send_busy(mvi, slot);
2040                         else {
2041                                 if (!mvi->tgt->tgt_shutdown) {
2042                                         mv_dprintk("mvsttgt(%ld): Unable to "
2043                                         "send the task manage to SCSI"
2044                                         "target " "mid-level, sending BUSY"
2045                                         "status.\n", mvi->instance);
2046                                 }
2047                                 mvst_send_busy(mvi, slot);
2048                         }
2049                 }
2050                 break;
2051
2052         default:
2053                 mv_printk("mvst tgt(%ld): Received unknown frame "
2054                      "type %x.\n", mvi->instance, ssp_hdr->frame_type);
2055                 break;
2056
2057         }
2058
2059         mvst_restart_free_list(mvi, slot_idx);
2060
2061 out:
2062         TRACE_EXIT();
2063         return rc;
2064 }
2065
2066 /* mvi->lock supposed to be held on entry */
2067 /* called via callback from mvst */
2068 static void mvst_async_event(uint16_t code,
2069                         struct mvs_info *mvi, uint16_t *mailbox)
2070 {
2071         TRACE_ENTRY();
2072
2073         sBUG_ON(mvi == NULL);
2074
2075         if (unlikely(mvi->tgt == NULL)) {
2076                 TRACE(TRACE_DEBUG|TRACE_MGMT,
2077                       "ASYNC EVENT %#x, but no tgt. mvi %p tgt_flag %ld",
2078                       code, mvi, MVST_IN_TARGET_MODE(mvi));
2079                 goto out;
2080         }
2081
2082 out:
2083         TRACE_EXIT();
2084         return;
2085 }
2086
2087 void mvs_enable_taget_xmt(struct mvs_info *mvi, int PhyId)
2088 {
2089         void __iomem *regs = mvi->regs;
2090         u32 tmp;
2091
2092         tmp = mr32(MVS_PCS);
2093 #ifdef SUPPORT_TARGET
2094         tmp |= PCS_RSP_RX_EN;
2095 #endif
2096         mw32(MVS_PCS, tmp);
2097 }
2098
2099 static void mvst_register_tgt_handler(struct mvs_info *mvi)
2100 {
2101         struct mvst_tgt *tgt = NULL;
2102         int sg_tablesize;
2103         unsigned long flags = 0;
2104         struct mvst_sess *sess = NULL;
2105
2106         tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
2107         if (tgt == NULL)
2108                 return;
2109
2110         tgt->mvi = mvi;
2111         INIT_LIST_HEAD(&tgt->sess_list);
2112         init_waitqueue_head(&tgt->waitQ);
2113
2114         /* set max sg counts */
2115         sg_tablesize = SG_ALL;
2116
2117         tgt->scst_tgt = scst_register(&tgt_template, MVST_NAME);
2118         if (!tgt->scst_tgt) {
2119                 PRINT_ERROR("mvst tgt(%ld): scst_register() "
2120                             "failed for host %ld(%p)", mvi->instance,
2121                             mvi->host_no, mvi);
2122                 kfree(tgt);
2123                 return;
2124         }
2125         scst_tgt_set_sg_tablesize(tgt->scst_tgt, sg_tablesize);
2126         scst_tgt_set_tgt_priv(tgt->scst_tgt, tgt);
2127
2128         spin_lock_irqsave(&mvi->lock, flags);
2129         mvi->tgt = tgt;
2130         spin_unlock_irqrestore(&mvi->lock, flags);
2131
2132         TRACE_DBG("Enable lun for host %ld(%ld,%p)",
2133                   mvi->host_no, mvi->instance, mvi);
2134         mvi->flags |= MVF_TARGET_MODE_ENABLE;
2135 }
2136
2137 static void mvst_unregister_tgt_handler(struct mvs_info *mvi)
2138 {
2139         struct mvst_tgt *tgt = NULL;
2140         tgt = mvi->tgt;
2141         mvi->tgt = NULL; /* ensure no one gets in behind us */
2142
2143         TRACE_DBG("Shutting down host %ld(%ld,%p)",
2144                   mvi->host_no, mvi->instance, mvi);
2145         scst_unregister(tgt->scst_tgt);
2146         mvi->flags &= ~MVF_TARGET_MODE_ENABLE;
2147         /*
2148          * Free of tgt happens via callback mvst_target_release
2149          * called from scst_unregister, so we shouldn't touch it again
2150          */
2151         tgt = NULL;
2152 }
2153
2154 static void mvst_enable_tgt_port(struct mvs_info *mvi, u8 phyid)
2155 {
2156         struct mvs_phy *phy;
2157         struct asd_sas_phy *sas_phy;
2158         u8 id = 0;
2159
2160 #if 0
2161         u8 j = 0, i = 0
2162         /*enable all the phy within the same port*/
2163         for (id = 0, j = 0; id < mvi->chip->n_phy; id++) {
2164                 if (mvi->tgt_port[id].wide_port_phymap & (1<<phyid)) {
2165                         mv_printk("port %x phymap %x\n",
2166                                 id, mvi->tgt_port[id].wide_port_phymap);
2167                         break;
2168                 }
2169         }
2170
2171         if (id == mvi->chip->n_phy) {
2172                 mvst_start_sas_target(mvi, phyid);
2173                 msleep(100);
2174                 MVS_CHIP_DISP->enable_target_mode(mvi, phyid);
2175                 phy = &mvi->phy[phyid];
2176                 phy->phy_mode = 1;
2177                 sas_phy = &phy->sas_phy;
2178                 sas_phy->tproto = SAS_PROTOCOL_SSP;
2179         } else {
2180                 for_each_phy(mvi->tgt_port[id].wide_port_phymap, j, i) {
2181                         if (j & 1) {
2182                                 mvst_start_sas_target(mvi, i);
2183                                 msleep(100);
2184                                 mv_printk("set phy %x to target mode\n", i);
2185                                 MVS_CHIP_DISP->enable_target_mode(mvi, i);
2186                                 phy = &mvi->phy[i];
2187                                 phy->phy_mode = 1;
2188                                 sas_phy = &phy->sas_phy;
2189                                 sas_phy->tproto = SAS_PROTOCOL_SSP;
2190                         }
2191                 }
2192         }
2193 #else
2194         phy = &mvi->phy[phyid];
2195         for (id = 0; id < mvi->chip->n_phy; id++) {
2196                 if (mvi->phy[id].dev_sas_addr == phy->dev_sas_addr) {
2197                         mvst_start_sas_target(mvi, id);
2198                         msleep(100);
2199                         mv_printk("set phy %x to target mode\n", id);
2200                         MVS_CHIP_DISP->enable_target_mode(mvi, id);
2201                         mvi->phy[id].phy_mode = 1;
2202                         sas_phy = &phy->sas_phy;
2203                         sas_phy->tproto = SAS_PROTOCOL_SSP;
2204                 }
2205         }
2206 #endif
2207 }
2208
2209 static void mvst_disable_tgt_port(struct mvs_info *mvi, u8 phyid)
2210 {
2211         struct mvs_phy *phy;
2212         struct asd_sas_phy *sas_phy;
2213         u8 id = 0;
2214 #if     0
2215         u8 j = 0, i = 0
2216         for (id = 0, j = 0; id < mvi->chip->n_phy; id++) {
2217                 if (mvi->tgt_port[id].wide_port_phymap & (1<<phyid)) {
2218                         mv_printk("port %x phymap %x\n", phyid,
2219                                 mvi->tgt_port[id].wide_port_phymap);
2220                         break;
2221                 }
2222         }
2223         if (id == mvi->chip->n_phy) {
2224                 MVS_CHIP_DISP->disable_target_mode(mvi, phyid);
2225                 msleep(100);
2226                 mv_printk("reset PHY[%d] to notify iniator\n", phyid);
2227                 MVS_CHIP_DISP->phy_reset(mvi, phyid, 0);
2228                 phy = &mvi->phy[phyid];
2229                 phy->phy_mode = 0;
2230                 sas_phy = &phy->sas_phy;
2231                 sas_phy->tproto = 0;
2232         } else {
2233                 mv_printk("get port %x\n", id);
2234                 for_each_phy(mvi->tgt_port[id].wide_port_phymap, j, i) {
2235                         mv_printk("phy map %x get phy %x\n",
2236                                 mvi->tgt_port[id].wide_port_phymap, i);
2237                         if (j & 1) {
2238                                 MVS_CHIP_DISP->disable_target_mode(mvi, i);
2239                                 msleep(100);
2240                                 MVS_CHIP_DISP->phy_reset(mvi, i, 0);
2241                                 phy = &mvi->phy[i];
2242                                 phy->phy_mode = 0;
2243                                 sas_phy = &phy->sas_phy;
2244                                 sas_phy->tproto = 0;
2245                         }
2246                 }
2247         }
2248 #else
2249         phy = &mvi->phy[phyid];
2250         for (id = 0; id < mvi->chip->n_phy; id++) {
2251                 if (mvi->phy[id].dev_sas_addr == phy->dev_sas_addr) {
2252                         MVS_CHIP_DISP->disable_target_mode(mvi, id);
2253                         msleep(100);
2254                         mv_printk("reset PHY[%d] to notify iniator\n", id);
2255                         MVS_CHIP_DISP->phy_reset(mvi, id, 0);
2256                         phy = &mvi->phy[id];
2257                         phy->phy_mode = 0;
2258                         sas_phy = &phy->sas_phy;
2259                         sas_phy->tproto = 0;
2260                 }
2261         }
2262 #endif
2263 }
2264
2265 /* no lock held on entry */
2266 /* called via callback from mvst */
2267 static void mvst_host_action(struct mvs_info *mvi,
2268                             enum mvst_tgt_host_action_t action, u8 phyid)
2269 {
2270         struct mvs_phy *phy;
2271         struct asd_sas_phy *sas_phy;
2272         struct mvst_tgt *tgt = NULL;
2273         int phy_id = 0, target_port = 0;
2274
2275         TRACE_ENTRY();
2276
2277         sBUG_ON(mvi == NULL);
2278
2279         switch (action) {
2280         case ENABLE_TARGET_MODE:
2281                 if (mvi->phy[phyid].phy_mode == 1)
2282                         break;
2283                 if (!MVST_IN_TARGET_MODE(mvi))
2284                         mvst_register_tgt_handler(mvi);
2285
2286                 target_port++;
2287                 mv_dprintk("initiator attaching %016llx,map %x on port[%d]\n",
2288                         (mvi->tgt_port[target_port].sas_addr),
2289                         mvi->tgt_port[target_port].wide_port_phymap,
2290                         target_port);
2291                 if (target_port * MVS_TARGET_QUEUE > MVS_CAN_QUEUE) {
2292                         mv_dprintk("Warning: No sufficient slots"
2293                                 "for target port[%d].\n", target_port);
2294                         break;
2295                 }
2296
2297                 mvst_enable_tgt_port(mvi, phyid);
2298                 mvst_notify_attach_chg(mvi);
2299
2300                 mv_dprintk("Enable target mode......\n");
2301                 break;
2302
2303         case DISABLE_TARGET_MODE:
2304                 if (mvi->phy[phyid].phy_mode == 0)
2305                         break;
2306                 if (mvi->flags & MVF_TARGET_MODE_ENABLE) {
2307                         mvst_disable_tgt_port(mvi, phyid);
2308                         for (phy_id = 0; phy_id < mvi->chip->n_phy; phy_id++) {
2309                                 if (mvi->phy[phy_id].dev_info
2310                                         & PORT_DEV_SSP_TRGT)
2311                                         break;
2312                         }
2313                         if (phy_id == mvi->chip->n_phy) {
2314                                 if (mvi->tgt == NULL)
2315                                         goto out;
2316                                 mvst_unregister_tgt_handler(mvi);
2317                         }
2318                 }
2319                 mv_dprintk("Disable target mode.....\n");
2320                 break;
2321
2322         case EXIT_TARGET_MODE:
2323                 for (phy_id = 0; phy_id < mvi->chip->n_phy; phy_id++) {
2324                         if (mvi->phy[phy_id].dev_info & PORT_DEV_SSP_TRGT) {
2325                                 MVS_CHIP_DISP->disable_target_mode(mvi, phy_id);
2326                                 msleep(100);
2327                                 mv_dprintk("reset phy%d to notify init\n",
2328                                         phy_id);
2329                                 MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0);
2330                                 phy = &mvi->phy[phy_id];
2331                                 phy->phy_mode = 0;
2332                                 sas_phy = &phy->sas_phy;
2333                                 sas_phy->tproto = 0;
2334                         }
2335                 }
2336                 if (mvi->tgt == NULL)
2337                         goto out;
2338
2339                 tgt = mvi->tgt;
2340                 mvi->tgt = NULL; /* ensure no one gets in behind us */
2341
2342                 TRACE_DBG("Shutting down host %ld(%ld,%p)",
2343                           mvi->host_no, mvi->instance, mvi);
2344                 scst_unregister(tgt->scst_tgt);
2345                 mvi->flags &= ~MVF_TARGET_MODE_ENABLE;
2346                 /*
2347                  * Free of tgt happens via callback mvst_target_release
2348                  * called from scst_unregister, so we shouldn't touch it again
2349                  */
2350                 tgt = NULL;
2351                 break;
2352         default:
2353                 PRINT_ERROR("Unknown action %d", action);
2354                 break;
2355         }
2356
2357 out:
2358         TRACE_EXIT();
2359         return;
2360 }
2361
2362 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
2363
2364 #define MVST_PROC_LOG_ENTRY_NAME     "trace_level"
2365
2366 #include <linux/proc_fs.h>
2367
2368 static int mvst_log_info_show(struct seq_file *seq, void *v)
2369 {
2370         int res = 0;
2371
2372         TRACE_ENTRY();
2373
2374         res = scst_proc_log_entry_read(seq, trace_flag, NULL);
2375
2376         TRACE_EXIT_RES(res);
2377         return res;
2378 }
2379
2380 static ssize_t mvst_proc_log_entry_write(struct file *file,
2381         const char __user *buf, size_t length, loff_t *off)
2382 {
2383         int res = 0;
2384
2385         TRACE_ENTRY();
2386
2387         res = scst_proc_log_entry_write(file, buf, length, &trace_flag,
2388                 MVST_DEFAULT_LOG_FLAGS, NULL);
2389
2390         TRACE_EXIT_RES(res);
2391         return res;
2392 }
2393
2394 static struct scst_proc_data mvst_log_proc_data = {
2395         SCST_DEF_RW_SEQ_OP(mvst_proc_log_entry_write)
2396         .show = mvst_log_info_show,
2397 };
2398 #endif
2399
2400 static int mvs_prep_sspt_frame(struct mvs_info *mvi,
2401                                 struct mvs_slot_info *slot)
2402 {
2403         struct mvs_cmd_header *cmd_hdr;
2404         struct mvst_port *port = slot->slot_tgt_port;
2405         void *buf_tmp;
2406         dma_addr_t buf_tmp_dma;
2407         u32  tag = slot->target_cmd_tag;
2408         struct mvs_delivery_queue *delivery_q;
2409
2410         /* get free command header */
2411         cmd_hdr = (struct mvs_cmd_header *)&mvi->slot[tag];
2412         /* get free delivery queue */
2413         delivery_q = (struct mvs_delivery_queue *)&mvi->tx[mvi->tx_prod];
2414
2415         /* target mode, SSP target free list */
2416         delivery_q->cmd = TXQ_CMD_SSP_FREE_LIST;
2417         delivery_q->mode = TXQ_MODE_TARGET;
2418         delivery_q->priority = TXQ_PRI_NORMAL;
2419         delivery_q->sata_reg_set = 0;
2420         delivery_q->phy = port->wide_port_phymap;
2421         delivery_q->slot_nm = tag;
2422
2423         /* command header dword 2 */
2424         /* copy the tag from received command frame */
2425         cmd_hdr->target_tag = tag;
2426         cmd_hdr->tag =  0;
2427
2428         /* command header dword 3 */
2429         cmd_hdr->data_len = 0;
2430
2431         /* region 1: open address frame area (MVS_OAF_SZ bytes)  */
2432         buf_tmp  = slot->open_frame = slot->buf;
2433         buf_tmp_dma = slot->buf_dma;
2434         cmd_hdr->open_frame = cpu_to_le64(buf_tmp_dma);
2435
2436         buf_tmp += MVS_OAF_SZ;
2437         buf_tmp_dma += MVS_OAF_SZ;
2438
2439         /* region 2: status buffer (lMVS_SLOT_BUF_SZ -  MVS_OAF_SZ) */
2440         slot->response = buf_tmp;
2441         cmd_hdr->status_buf = cpu_to_le64(buf_tmp_dma);
2442
2443         /* command header dword 1 */
2444         cmd_hdr->max_rsp_frame_len =
2445                 (min(SB_RFB_MAX, MVS_SLOT_BUF_SZ - MVS_OAF_SZ)) >> 2;
2446         cmd_hdr->frame_len =  0;
2447         return 0;
2448 }
2449
2450
2451 static int
2452 mvst_restart_free_list(struct mvs_info *mvi, u8 slot_id)
2453 {
2454         struct mvs_slot_info *slot;
2455         u32 rc = 0, tag = 0;
2456         u32 pass = 0;
2457
2458         tag = slot_id;
2459         mvs_tag_set(mvi, tag);
2460         slot = &mvi->slot_info[tag];
2461         memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
2462         /* save free tag */
2463         slot->slot_scst_cmd = NULL;
2464         slot->open_frame = NULL;
2465         slot->tx = mvi->tx_prod;
2466         rc = mvs_prep_sspt_frame(mvi, slot);
2467         if (rc)
2468                 goto err_out_tag;
2469
2470         ++pass;
2471         mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
2472         goto out_done;
2473
2474 err_out_tag:
2475         PRINT_ERROR("prepare SSPT[%d] failed.", slot_id);
2476         mvst_put_slot(mvi, slot);
2477
2478 out_done:
2479         if (pass)
2480                 MVS_CHIP_DISP->start_delivery(mvi,
2481                                 (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
2482         return rc;
2483 }
2484
2485 static int
2486 mvst_start_sas_target(struct mvs_info *mvi, u8 id)
2487 {
2488         struct mvs_slot_info *slot;
2489         struct mvst_port *tgt_port = &mvi->tgt_port[id];
2490         u32 rc = 0;
2491         unsigned long flags;
2492         u32 pass = 0;
2493         u32 slot_id = 0;
2494
2495         spin_lock_irqsave(&mvi->lock, flags);
2496         do {
2497                 slot = mvst_get_slot(mvi, tgt_port);
2498                 if (!slot)
2499                         goto err_out;
2500                 slot->slot_scst_cmd = NULL;
2501                 rc = mvs_prep_sspt_frame(mvi, slot);
2502                 if (rc)
2503                         goto err_out_tag;
2504                 ++pass;
2505                 mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
2506         } while (++slot_id < MVS_TARGET_QUEUE);
2507
2508         rc = 0;
2509         goto out_done;
2510
2511 err_out_tag:
2512         PRINT_ERROR("prepare SSPT[%d] failed.", slot_id);
2513         mvst_put_slot(mvi, slot);
2514 err_out:
2515         PRINT_ERROR("No sufficient tag for SSPT, current slot=%d", slot_id);
2516
2517 out_done:
2518         if (pass)
2519                 MVS_CHIP_DISP->start_delivery(mvi,
2520                         (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
2521
2522         spin_unlock_irqrestore(&mvi->lock, flags);
2523         return rc;
2524 }
2525
2526 void mvst_init_port(struct mvs_info *mvi)
2527 {
2528         int i;
2529         for (i = 0; i < mvi->chip->n_phy; i++) {
2530                 mvi->tgt_port[i].port_id = i;
2531                 mvi->tgt_port[i].wide_port_phymap = 1<<i;
2532                 mvi->tgt_port[i].port_attached = 0;
2533                 mvi->tgt_port[i].mvi = mvi;
2534                 mvi->tgt_port[i].phy = &mvi->phy[i];
2535                 INIT_LIST_HEAD(&mvi->tgt_port[i].slot_list);
2536         }
2537 }
2538
2539 void mvst_update_wideport(struct mvs_info *mvi, int phy_no)
2540 {
2541         u8 i, j, member = 0;
2542         u32 wide_port;
2543
2544         for (i = 0; i < mvi->chip->n_phy; i++) {
2545                 if (phy_no == i)
2546                         continue;
2547
2548                 if ((mvi->phy[phy_no].att_dev_sas_addr ==
2549                         mvi->tgt_port[i].att_sas_addr) &&
2550                         (mvi->phy[phy_no].dev_sas_addr ==
2551                         mvi->tgt_port[i].sas_addr)) {
2552                         mvi->tgt_port[i].wide_port_phymap |= (1U << phy_no);
2553                         mvi->tgt_port[phy_no].wide_port_phymap = 0;
2554                         mvi->tgt_port[phy_no].port_attached = 0;
2555                         mvi->tgt_port[phy_no].sas_addr = 0;
2556                         member = 1;
2557                 }
2558         }
2559         if (!member) {
2560                 mvi->tgt_port[phy_no].wide_port_phymap |= (1U << phy_no);
2561                 mvi->tgt_port[phy_no].port_attached = 1;
2562                 mvi->tgt_port[phy_no].sas_addr = mvi->phy[phy_no].dev_sas_addr;
2563                 mvi->tgt_port[phy_no].att_sas_addr =
2564                         mvi->phy[phy_no].att_dev_sas_addr;
2565         }
2566
2567         /* config wideport */
2568         for (i = 0; i < mvi->chip->n_phy; i++) {
2569                 wide_port = mvi->tgt_port[i].wide_port_phymap;
2570                 if (wide_port == 0)
2571                         continue;
2572                 for (j = i+1; j < mvi->chip->n_phy; j++) {
2573                         wide_port = wide_port >> j;
2574                         if (wide_port & 1) {
2575                                 MVS_CHIP_DISP->write_port_cfg_addr(mvi, j,
2576                                         PHYR_WIDE_PORT);
2577                                 MVS_CHIP_DISP->write_port_cfg_data(mvi, j,
2578                                         mvi->tgt_port[i].wide_port_phymap);
2579                         } else {
2580                                 MVS_CHIP_DISP->write_port_cfg_addr(mvi, j,
2581                                         PHYR_WIDE_PORT);
2582                                 MVS_CHIP_DISP->write_port_cfg_data(mvi, j,
2583                                         0);
2584                         }
2585                 }
2586         }
2587
2588 }
2589
2590
2591 void mvst_int_port(struct mvs_info *mvi, u32 id)
2592 {
2593         struct mvst_port *tgt_port = &mvi->tgt_port[id];
2594         struct mvs_phy *phy = &mvi->phy[id];
2595
2596         phy->irq_status = mvs_read_port_irq_stat(mvi, id);
2597         /* clean status */
2598         mvs_write_port_irq_stat(mvi, id, phy->irq_status);
2599
2600         /* TBD */
2601         /*
2602         * events is port event now ,
2603         * we need check the interrupt status which belongs to per port.
2604         */
2605         if (phy->irq_status & PHYEV_RDY_CH) {
2606                 u32 tmp;
2607                 mv_dprintk("Port %d phy change!!\n", id);
2608                 tmp = mvs_read_phy_ctl(mvi, id);
2609                 if (tmp & PHY_READY_MASK) {
2610                         PRINT_INFO("Find port %d phy ready.\n", id);
2611                         tgt_port->port_attached = 1;
2612                         mvs_update_phyinfo(mvi, id, 0);
2613                 } else
2614                         PRINT_INFO("Port %d Unplug Notice!!\n", id);
2615         }
2616
2617         if (phy->irq_status &  PHYEV_DEC_ERR)
2618                 mv_dprintk("Port %d phy decoding error!!\n", id);
2619         else if (phy->irq_status & PHYEV_COMWAKE)
2620                 mv_dprintk("Port %d COMWAKE received.\n", id);
2621         else if (phy->irq_status & PHYEV_SIG_FIS)
2622                 mv_dprintk("Port %d Signature FIS received.\n", id);
2623         else
2624                 mv_dprintk("Port %d unknown error[0x%x]"
2625                 "received.\n", id, phy->irq_status);
2626 }
2627
2628 u32 mvst_check_port(struct mvs_info *mvi, u8 phy_id)
2629 {
2630         u32 att_dev_info;
2631         u32 port_attr;
2632         att_dev_info = mvi->phy[phy_id].att_dev_info;
2633
2634         if ((att_dev_info & PORT_SSP_INIT_MASK ||
2635                 att_dev_info & PORT_DEV_SMP_TRGT ||
2636                 att_dev_info & PORT_DEV_SMP_INIT) &&
2637                 !(att_dev_info & PORT_SSP_TRGT_MASK))
2638                 port_attr = MVST_TGT_PORT;
2639         else if ((att_dev_info & PORT_SSP_INIT_MASK ||
2640                  att_dev_info & PORT_DEV_SMP_TRGT ||
2641                  att_dev_info & PORT_DEV_SMP_INIT) &&
2642                  (att_dev_info & PORT_SSP_TRGT_MASK))
2643                 port_attr =  MVST_INIT_TGT_PORT;
2644         else
2645                 port_attr =  MVST_INIT_PORT;
2646
2647         return  port_attr;
2648 }
2649
2650 static int mvst_proc_log_entry_build(struct scst_tgt_template *templ)
2651 {
2652         int res = 0;
2653 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
2654         struct proc_dir_entry *p, *root;
2655
2656         TRACE_ENTRY();
2657
2658         root = scst_proc_get_tgt_root(templ);
2659         if (root) {
2660                 /* create the proc file entry for the device */
2661                 mvst_log_proc_data.data = (void *)templ->name;
2662                 p = scst_create_proc_entry(root, MVST_PROC_LOG_ENTRY_NAME,
2663                                         &mvst_log_proc_data);
2664                 if (p == NULL) {
2665                         PRINT_ERROR("Not enough memory to register "
2666                              "target driver %s entry %s in /proc",
2667                               templ->name, MVST_PROC_LOG_ENTRY_NAME);
2668                         res = -ENOMEM;
2669                         goto out;
2670                 }
2671         }
2672
2673 out:
2674
2675         TRACE_EXIT_RES(res);
2676 #endif
2677         return res;
2678 }
2679
2680 static void mvst_proc_log_entry_clean(struct scst_tgt_template *templ)
2681 {
2682 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
2683         struct proc_dir_entry *root;
2684
2685         TRACE_ENTRY();
2686
2687         root = scst_proc_get_tgt_root(templ);
2688         if (root)
2689                 remove_proc_entry(MVST_PROC_LOG_ENTRY_NAME, root);
2690
2691         TRACE_EXIT();
2692 #endif
2693         return;
2694 }
2695
2696 int mvs_tgt_register_driver(struct mvs_tgt_initiator *tgt_data)
2697 {
2698         int res = 0;
2699
2700         ENTER(__func__);
2701
2702         if ((tgt_data == NULL) || (tgt_data->magic != MVST_TARGET_MAGIC)) {
2703                 mv_dprintk("***ERROR*** Wrong version of"
2704                         "the target driver: %d\n", tgt_data->magic);
2705                 res = -EINVAL;
2706                 goto out;
2707         }
2708         memcpy(&mvs_tgt, tgt_data, sizeof(mvs_tgt));
2709 out:
2710         LEAVE(__func__);
2711         return res;
2712 }
2713
2714 void mvs_tgt_unregister_driver(void)
2715 {
2716         ENTER(__func__);
2717         memset(&mvs_tgt, 0, sizeof(mvs_tgt));
2718         LEAVE(__func__);
2719         return;
2720 }
2721
2722 void mvst_msg_insert(struct mvst_msg_queue *msg_queue,
2723         void *data, unsigned int event, u64 param)
2724 {
2725         struct mvst_msg *msg;
2726         unsigned long flags;
2727
2728         mv_dprintk("msg insert %d.\n", event);
2729
2730         spin_lock_irqsave(&msg_queue->msg_lock, flags);
2731         if (list_empty(&msg_queue->free)) {
2732                 /* should wreck some havoc ...*/
2733                 PRINT_ERROR("%s :Message queue is full.", __func__);
2734                 spin_unlock_irqrestore(&msg_queue->msg_lock, flags);
2735                 return;
2736         }
2737
2738         msg = list_entry(msg_queue->free.next, struct mvst_msg, msg_entry);
2739         msg->data = data;
2740         msg->msg  = event;
2741
2742         switch (event) {
2743         case EVENT_DEVICE_REMOVAL:
2744         case EVENT_DEVICE_ARRIVAL:
2745                 msg->param = param;
2746                 break;
2747         default:
2748                 msg->param = param;
2749                 break;
2750         }
2751
2752         list_move_tail(&msg->msg_entry, &msg_queue->tasks);
2753         spin_unlock_irqrestore(&msg_queue->msg_lock, flags);
2754
2755         if (msg_queue->msg_task)
2756                 wake_up_process(msg_queue->msg_task);
2757 }
2758
2759
2760 void mvst_init_tgt_port(struct mvs_info *mvi)
2761 {
2762         INIT_LIST_HEAD(&mvi->data_cmd_list);
2763         mvst_init_port(mvi);
2764 }
2765
2766 int  mvst_init(void)
2767 {
2768         int res = 0;
2769         TRACE_ENTRY();
2770         mvst_cmd_cachep = KMEM_CACHE(mvst_cmd, SCST_SLAB_FLAGS);
2771         if (mvst_cmd_cachep == NULL) {
2772                 res = -ENOMEM;
2773                 goto out;
2774         }
2775
2776         res = scst_register_target_template(&tgt_template);
2777         if (res < 0)
2778                 goto out_free_kmem;
2779
2780         /*
2781          * mvst_tgt_register_driver() happens in mv_target_detect
2782          * called via scst_register_target_template()
2783          */
2784
2785         res = mvst_proc_log_entry_build(&tgt_template);
2786         if (res < 0)
2787                 goto out_unreg_target;
2788
2789 out:
2790         TRACE_EXIT();
2791         return res;
2792
2793 out_unreg_target:
2794         scst_unregister_target_template(&tgt_template);
2795
2796 out_free_kmem:
2797         kmem_cache_destroy(mvst_cmd_cachep);
2798
2799         mvs_tgt_unregister_driver();
2800         goto out;
2801 }
2802
2803 void  mvst_exit(void)
2804 {
2805         TRACE_ENTRY();
2806
2807         /*mvst_shutdown_queue(&tgt_msg_queue);*/
2808         mvst_proc_log_entry_clean(&tgt_template);
2809         scst_unregister_target_template(&tgt_template);
2810         mvs_tgt_unregister_driver();
2811         kmem_cache_destroy(mvst_cmd_cachep);
2812
2813         TRACE_EXIT();
2814         return;
2815 }
2816
2817 #endif