xref: /dragonfly/sys/dev/raid/mfi/mfi_tbolt.c (revision 43926ee41b2289a99019b4b856fb85d4c0b6b91f)
1 /*-
2  * Redistribution and use in source and binary forms, with or without
3  * modification, are permitted provided that the following conditions
4  * are met:
5  *
6  *            Copyright 1994-2009 The FreeBSD Project.
7  *            All rights reserved.
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FREEBSD PROJECT OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * The views and conclusions contained in the software and documentation
28  * are those of the authors and should not be interpreted as representing
29  * official policies,either expressed or implied, of the FreeBSD Project.
30  *
31  * $FreeBSD: src/sys/dev/mfi/mfi_tbolt.c,v 1.00 2010/06/30 16:00:00 Bharat Gusain Exp $
32  * FreeBSD projects/head_mfi/ r232949
33  */
34 
35 #include "opt_mfi.h"
36 
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <sys/kernel.h>
40 #include <sys/bus.h>
41 #include <sys/conf.h>
42 #include <sys/bio.h>
43 #include <sys/buf2.h>
44 #include <sys/eventhandler.h>
45 #include <sys/callout.h>
46 #include <sys/uio.h>
47 #include <sys/sysctl.h>
48 #include <sys/systm.h>
49 #include <sys/malloc.h>
50 
51 #include <dev/raid/mfi/mfireg.h>
52 #include <dev/raid/mfi/mfi_ioctl.h>
53 #include <dev/raid/mfi/mfivar.h>
54 
55 struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc *sc);
56 union mfi_mpi2_request_descriptor *
57 mfi_tbolt_get_request_descriptor(struct mfi_softc *sc, uint16_t index);
58 void mfi_tbolt_complete_cmd(struct mfi_softc *sc);
59 int mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
60     struct mfi_cmd_tbolt *cmd);
61 static inline void mfi_tbolt_return_cmd(struct mfi_softc *sc,
62     struct mfi_cmd_tbolt *cmd);
63 union mfi_mpi2_request_descriptor *mfi_tbolt_build_mpt_cmd(struct mfi_softc
64     *sc, struct mfi_command *cmd);
65 uint8_t
66 mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd);
67 union mfi_mpi2_request_descriptor *mfi_build_and_issue_cmd(struct mfi_softc
68     *sc, struct mfi_command *mfi_cmd);
69 int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd);
70 void mfi_tbolt_build_ldio(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
71     struct mfi_cmd_tbolt *cmd);
72 static int mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command
73     *mfi_cmd, pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd);
74 static int mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command
75     *mfi_cmd, uint8_t *cdb);
76 void
77 map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status,
78      uint8_t ext_status);
79 static void mfi_issue_pending_cmds_again (struct mfi_softc *sc);
80 static void mfi_kill_hba (struct mfi_softc *sc);
81 static void mfi_process_fw_state_chg_isr(void *arg);
82 uint8_t mfi_tbolt_get_map_info(struct mfi_softc *sc);
83 
84 #define MFI_FUSION_ENABLE_INTERRUPT_MASK          (0x00000008)
85 
86 void
mfi_tbolt_enable_intr_ppc(struct mfi_softc * sc)87 mfi_tbolt_enable_intr_ppc(struct mfi_softc *sc)
88 {
89           MFI_WRITE4(sc, MFI_OMSK, ~MFI_FUSION_ENABLE_INTERRUPT_MASK);
90           MFI_READ4(sc, MFI_OMSK);
91 }
92 
93 void
mfi_tbolt_disable_intr_ppc(struct mfi_softc * sc)94 mfi_tbolt_disable_intr_ppc(struct mfi_softc *sc)
95 {
96           MFI_WRITE4(sc, MFI_OMSK, 0xFFFFFFFF);
97           MFI_READ4(sc, MFI_OMSK);
98 }
99 
100 int32_t
mfi_tbolt_read_fw_status_ppc(struct mfi_softc * sc)101 mfi_tbolt_read_fw_status_ppc(struct mfi_softc *sc)
102 {
103           return MFI_READ4(sc, MFI_OSP0);
104 }
105 
106 int32_t
mfi_tbolt_check_clear_intr_ppc(struct mfi_softc * sc)107 mfi_tbolt_check_clear_intr_ppc(struct mfi_softc *sc)
108 {
109           int32_t status, mfi_status = 0;
110 
111           status = MFI_READ4(sc, MFI_OSTS);
112 
113           if (status & 1) {
114                     MFI_WRITE4(sc, MFI_OSTS, status);
115                     MFI_READ4(sc, MFI_OSTS);
116                     if (status & MFI_STATE_CHANGE_INTERRUPT) {
117                               mfi_status |= MFI_FIRMWARE_STATE_CHANGE;
118                     }
119 
120                     return mfi_status;
121           }
122           if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
123                     return 1;
124 
125           MFI_READ4(sc, MFI_OSTS);
126           return 0;
127 }
128 
129 
130 void
mfi_tbolt_issue_cmd_ppc(struct mfi_softc * sc,bus_addr_t bus_add,uint32_t frame_cnt)131 mfi_tbolt_issue_cmd_ppc(struct mfi_softc *sc, bus_addr_t bus_add,
132    uint32_t frame_cnt)
133 {
134           bus_add |= (MFI_REQ_DESCRIPT_FLAGS_MFA
135               << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
136           MFI_WRITE4(sc, MFI_IQPL, (uint32_t)bus_add);
137           MFI_WRITE4(sc, MFI_IQPH, (uint32_t)((uint64_t)bus_add >> 32));
138 }
139 
140 /**
141  * mfi_tbolt_adp_reset - For controller reset
142  * @regs: MFI register set
143  */
mfi_tbolt_adp_reset(struct mfi_softc * sc)144 int mfi_tbolt_adp_reset(struct mfi_softc *sc)
145 {
146           int retry = 0, i = 0;
147           int HostDiag;
148 
149           MFI_WRITE4(sc, MFI_WSR, 0xF);
150           MFI_WRITE4(sc, MFI_WSR, 4);
151           MFI_WRITE4(sc, MFI_WSR, 0xB);
152           MFI_WRITE4(sc, MFI_WSR, 2);
153           MFI_WRITE4(sc, MFI_WSR, 7);
154           MFI_WRITE4(sc, MFI_WSR, 0xD);
155 
156           for (i = 0; i < 10000; i++) ;
157 
158           HostDiag = (uint32_t)MFI_READ4(sc, MFI_HDR);
159 
160           while (!( HostDiag & DIAG_WRITE_ENABLE)) {
161                     for (i = 0; i < 1000; i++);
162                     HostDiag = (uint32_t)MFI_READ4(sc, MFI_HDR);
163                     device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: retry time=%x, "
164                         "hostdiag=%x\n", retry, HostDiag);
165 
166                     if (retry++ >= 100)
167                               return 1;
168           }
169 
170           device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: HostDiag=%x\n", HostDiag);
171 
172           MFI_WRITE4(sc, MFI_HDR, (HostDiag | DIAG_RESET_ADAPTER));
173 
174           for (i=0; i < 10; i++) {
175                     for (i = 0; i < 10000; i++);
176           }
177 
178           HostDiag = (uint32_t)MFI_READ4(sc, MFI_RSR);
179           while (HostDiag & DIAG_RESET_ADAPTER) {
180                     for (i = 0; i < 1000; i++) ;
181                     HostDiag = (uint32_t)MFI_READ4(sc, MFI_RSR);
182                     device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: retry time=%x, "
183                         "hostdiag=%x\n", retry, HostDiag);
184 
185                     if (retry++ >= 1000)
186                               return 1;
187           }
188           return 0;
189 }
190 
191 /*
192  *******************************************************************************************
193  * Description:
194  *      This routine initialize Thunderbolt specific device information
195  *******************************************************************************************
196  */
mfi_tbolt_init_globals(struct mfi_softc * sc)197 void mfi_tbolt_init_globals(struct mfi_softc *sc)
198 {
199           /* Initialize single reply size and Message size */
200           sc->reply_size = MEGASAS_THUNDERBOLT_REPLY_SIZE;
201           sc->raid_io_msg_size = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
202 
203           /*
204            * Calculating how many SGEs allowed in a allocated main message
205            * (size of the Message - Raid SCSI IO message size(except SGE))
206            * / size of SGE
207            * (0x100 - (0x90 - 0x10)) / 0x10 = 8
208            */
209           sc->max_SGEs_in_main_message =
210               (uint8_t)((sc->raid_io_msg_size
211               - (sizeof(struct mfi_mpi2_request_raid_scsi_io)
212               - sizeof(MPI2_SGE_IO_UNION))) / sizeof(MPI2_SGE_IO_UNION));
213           /*
214            * (Command frame size allocaed in SRB ext - Raid SCSI IO message size)
215            * / size of SGL ;
216            * (1280 - 256) / 16 = 64
217            */
218           sc->max_SGEs_in_chain_message = (MR_COMMAND_SIZE
219               - sc->raid_io_msg_size) / sizeof(MPI2_SGE_IO_UNION);
220           /*
221            * (0x08-1) + 0x40 = 0x47 - 0x01 = 0x46  one is left for command
222            * colscing
223           */
224           sc->mfi_max_sge = (sc->max_SGEs_in_main_message - 1)
225               + sc->max_SGEs_in_chain_message - 1;
226           /*
227           * This is the offset in number of 4 * 32bit words to the next chain
228           * (0x100 - 0x10)/0x10 = 0xF(15)
229           */
230           sc->chain_offset_value_for_main_message = (sc->raid_io_msg_size
231               - sizeof(MPI2_SGE_IO_UNION))/16;
232           sc->chain_offset_value_for_mpt_ptmsg
233               = offsetof(struct mfi_mpi2_request_raid_scsi_io, SGL)/16;
234           sc->mfi_cmd_pool_tbolt = NULL;
235           sc->request_desc_pool = NULL;
236 }
237 
238 /*
239  ****************************************************************************
240  * Description:
241  *      This function calculates the memory requirement for Thunderbolt
242  *      controller
243  * Return Value:
244  *      Total required memory in bytes
245  ****************************************************************************
246  */
247 
mfi_tbolt_get_memory_requirement(struct mfi_softc * sc)248 uint32_t mfi_tbolt_get_memory_requirement(struct mfi_softc *sc)
249 {
250           uint32_t size;
251 
252           size = MEGASAS_THUNDERBOLT_MSG_ALLIGNMENT;        /* for Alignment */
253           size += sc->raid_io_msg_size * (sc->mfi_max_fw_cmds + 1);
254           size += sc->reply_size * sc->mfi_max_fw_cmds;
255           /* this is for SGL's */
256           size += MEGASAS_MAX_SZ_CHAIN_FRAME * sc->mfi_max_fw_cmds;
257           return size;
258 }
259 
260 /*
261  ****************************************************************************
262  * Description:
263  *      This function will prepare message pools for the Thunderbolt controller
264  * Arguments:
265  *      DevExt - HBA miniport driver's adapter data storage structure
266  *      pMemLocation - start of the memory allocated for Thunderbolt.
267  * Return Value:
268  *      TRUE if successful
269  *      FALSE if failed
270  ****************************************************************************
271  */
mfi_tbolt_init_desc_pool(struct mfi_softc * sc,uint8_t * mem_location,uint32_t tbolt_contg_length)272 int mfi_tbolt_init_desc_pool(struct mfi_softc *sc, uint8_t* mem_location,
273     uint32_t tbolt_contg_length)
274 {
275           uint32_t     offset = 0;
276           uint8_t      *addr = mem_location;
277 
278           /* Request Descriptor Base physical Address */
279 
280           /* For Request Decriptors Virtual Memory */
281           /* Initialise the aligned IO Frames Virtual Memory Pointer */
282           if (((uintptr_t)addr) & (0xFF)) {
283                     addr = &addr[sc->raid_io_msg_size];
284                     addr = (uint8_t *)((uintptr_t)addr & (~0xFF));
285                     sc->request_message_pool_align = addr;
286           } else
287                     sc->request_message_pool_align = addr;
288 
289           offset = sc->request_message_pool_align - sc->request_message_pool;
290           sc->request_msg_busaddr = sc->mfi_tb_busaddr + offset;
291 
292           /* DJA XXX should this be bus dma ??? */
293           /* Skip request message pool */
294           addr = &addr[sc->raid_io_msg_size * (sc->mfi_max_fw_cmds + 1)];
295           /* Reply Frame Pool is initialized */
296           sc->reply_frame_pool = (struct mfi_mpi2_reply_header *) addr;
297           if (((uintptr_t)addr) & (0xFF)) {
298                     addr = &addr[sc->reply_size];
299                     addr = (uint8_t *)((uintptr_t)addr & (~0xFF));
300           }
301           sc->reply_frame_pool_align
302                         = (struct mfi_mpi2_reply_header *)addr;
303 
304           offset = (uintptr_t)sc->reply_frame_pool_align
305               - (uintptr_t)sc->request_message_pool;
306           sc->reply_frame_busaddr = sc->mfi_tb_busaddr + offset;
307 
308           /* Skip Reply Frame Pool */
309           addr += sc->reply_size * sc->mfi_max_fw_cmds;
310           sc->reply_pool_limit = addr;
311 
312           /* initializing reply address to 0xFFFFFFFF */
313           memset((uint8_t *)sc->reply_frame_pool, 0xFF,
314                  (sc->reply_size * sc->mfi_max_fw_cmds));
315 
316           offset = sc->reply_size * sc->mfi_max_fw_cmds;
317           sc->sg_frame_busaddr = sc->reply_frame_busaddr + offset;
318           /* initialize the last_reply_idx to 0 */
319           sc->last_reply_idx = 0;
320           offset = (sc->sg_frame_busaddr + (MEGASAS_MAX_SZ_CHAIN_FRAME *
321               sc->mfi_max_fw_cmds)) - sc->mfi_tb_busaddr;
322           if (offset > tbolt_contg_length)
323                     device_printf(sc->mfi_dev, "Error:Initialized more than "
324                         "allocated\n");
325           return 0;
326 }
327 
328 /*
329  ****************************************************************************
330  * Description:
331  *   This routine prepare and issue INIT2 frame to the Firmware
332  ****************************************************************************
333  */
334 
335 int
mfi_tbolt_init_MFI_queue(struct mfi_softc * sc)336 mfi_tbolt_init_MFI_queue(struct mfi_softc *sc)
337 {
338           struct MPI2_IOC_INIT_REQUEST   *mpi2IocInit;
339           struct mfi_init_frame         *mfi_init;
340           uintptr_t                     offset = 0;
341           bus_addr_t                              phyAddress;
342           MFI_ADDRESS                             *mfiAddressTemp;
343           struct mfi_command *cm;
344           int error;
345 
346           mpi2IocInit = (struct MPI2_IOC_INIT_REQUEST *)sc->mfi_tb_ioc_init_desc;
347           /* Check if initialization is already completed */
348           if (sc->MFA_enabled) {
349                     return 1;
350           }
351 
352           lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
353           if ((cm = mfi_dequeue_free(sc)) == NULL) {
354                     lockmgr(&sc->mfi_io_lock, LK_RELEASE);
355                     return (EBUSY);
356           }
357           cm->cm_frame = (union mfi_frame *)((uintptr_t)sc->mfi_tb_init);
358           cm->cm_frame_busaddr = sc->mfi_tb_init_busaddr;
359           cm->cm_dmamap = sc->mfi_tb_init_dmamap;
360           cm->cm_frame->header.context = 0;
361           cm->cm_sc = sc;
362           cm->cm_index = 0;
363 
364           /*
365            * Abuse the SG list area of the frame to hold the init_qinfo
366            * object;
367            */
368           mfi_init = &cm->cm_frame->init;
369 
370           bzero(mpi2IocInit, sizeof(struct MPI2_IOC_INIT_REQUEST));
371           mpi2IocInit->Function  = MPI2_FUNCTION_IOC_INIT;
372           mpi2IocInit->WhoInit   = MPI2_WHOINIT_HOST_DRIVER;
373 
374           /* set MsgVersion and HeaderVersion host driver was built with */
375           mpi2IocInit->MsgVersion = MPI2_VERSION;
376           mpi2IocInit->HeaderVersion = MPI2_HEADER_VERSION;
377           mpi2IocInit->SystemRequestFrameSize = sc->raid_io_msg_size/4;
378           mpi2IocInit->ReplyDescriptorPostQueueDepth
379               = (uint16_t)sc->mfi_max_fw_cmds;
380           mpi2IocInit->ReplyFreeQueueDepth = 0; /* Not supported by MR. */
381 
382           /* Get physical address of reply frame pool */
383           offset = (uintptr_t) sc->reply_frame_pool_align
384               - (uintptr_t)sc->request_message_pool;
385           phyAddress = sc->mfi_tb_busaddr + offset;
386           mfiAddressTemp =
387               (MFI_ADDRESS *)&mpi2IocInit->ReplyDescriptorPostQueueAddress;
388           mfiAddressTemp->u.addressLow = (uint32_t)phyAddress;
389           mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32);
390 
391           /* Get physical address of request message pool */
392           offset = sc->request_message_pool_align - sc->request_message_pool;
393           phyAddress =  sc->mfi_tb_busaddr + offset;
394           mfiAddressTemp = (MFI_ADDRESS *)&mpi2IocInit->SystemRequestFrameBaseAddress;
395           mfiAddressTemp->u.addressLow = (uint32_t)phyAddress;
396           mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32);
397           mpi2IocInit->ReplyFreeQueueAddress =  0; /* Not supported by MR. */
398           mpi2IocInit->TimeStamp = time_uptime;
399 
400           if (sc->verbuf) {
401                     ksnprintf((char *)sc->verbuf, strlen(MEGASAS_VERSION) + 2, "%s\n",
402                 MEGASAS_VERSION);
403                     mfi_init->driver_ver_lo = (uint32_t)sc->verbuf_h_busaddr;
404                     mfi_init->driver_ver_hi =
405                         (uint32_t)((uint64_t)sc->verbuf_h_busaddr >> 32);
406           }
407           /* Get the physical address of the mpi2 ioc init command */
408           phyAddress =  sc->mfi_tb_ioc_init_busaddr;
409           mfi_init->qinfo_new_addr_lo = (uint32_t)phyAddress;
410           mfi_init->qinfo_new_addr_hi = (uint32_t)((uint64_t)phyAddress >> 32);
411           mfi_init->header.flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
412 
413           mfi_init->header.cmd = MFI_CMD_INIT;
414           mfi_init->header.data_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
415           mfi_init->header.cmd_status = MFI_STAT_INVALID_STATUS;
416 
417           cm->cm_data = NULL;
418           cm->cm_flags |= MFI_CMD_POLLED;
419           cm->cm_timestamp = time_uptime;
420           if ((error = mfi_mapcmd(sc, cm)) != 0) {
421                     device_printf(sc->mfi_dev, "failed to send IOC init2 "
422                         "command %d at %lx\n", error, (long)cm->cm_frame_busaddr);
423                     mfi_release_command(cm);
424                     lockmgr(&sc->mfi_io_lock, LK_RELEASE);
425                     return (error);
426           }
427           mfi_release_command(cm);
428           lockmgr(&sc->mfi_io_lock, LK_RELEASE);
429 
430           if (mfi_init->header.cmd_status == 0) {
431                     sc->MFA_enabled = 1;
432           }
433           else {
434                     device_printf(sc->mfi_dev, "Init command Failed %x\n",
435                         mfi_init->header.cmd_status);
436                     return 1;
437           }
438 
439           return 0;
440 
441 }
442 
mfi_tbolt_alloc_cmd(struct mfi_softc * sc)443 int mfi_tbolt_alloc_cmd(struct mfi_softc *sc)
444 {
445           struct mfi_cmd_tbolt *cmd;
446           bus_addr_t io_req_base_phys;
447           uint8_t *io_req_base;
448           int i = 0, j = 0, offset = 0;
449 
450           /*
451            * sc->mfi_cmd_pool_tbolt is an array of struct mfi_cmd_tbolt pointers.
452            * Allocate the dynamic array first and then allocate individual
453            * commands.
454            */
455           sc->request_desc_pool = kmalloc(sizeof(
456               union mfi_mpi2_request_descriptor) * sc->mfi_max_fw_cmds,
457               M_MFIBUF, M_NOWAIT|M_ZERO);
458           sc->mfi_cmd_pool_tbolt = kmalloc(sizeof(struct mfi_cmd_tbolt*)
459               * sc->mfi_max_fw_cmds, M_MFIBUF, M_NOWAIT|M_ZERO);
460 
461           if (!sc->mfi_cmd_pool_tbolt) {
462                     device_printf(sc->mfi_dev, "out of memory. Could not alloc "
463                         "memory for cmd_list_fusion\n");
464                     return 1;
465           }
466 
467           for (i = 0; i < sc->mfi_max_fw_cmds; i++) {
468                     sc->mfi_cmd_pool_tbolt[i] = kmalloc(sizeof(
469                         struct mfi_cmd_tbolt),M_MFIBUF, M_NOWAIT|M_ZERO);
470 
471                     if (!sc->mfi_cmd_pool_tbolt[i]) {
472                               device_printf(sc->mfi_dev, "Could not alloc cmd list "
473                                   "fusion\n");
474 
475                               for (j = 0; j < i; j++)
476                                         kfree(sc->mfi_cmd_pool_tbolt[j], M_MFIBUF);
477 
478                               kfree(sc->mfi_cmd_pool_tbolt, M_MFIBUF);
479                               sc->mfi_cmd_pool_tbolt = NULL;
480                     }
481           }
482 
483           /*
484            * The first 256 bytes (SMID 0) is not used. Don't add to the cmd
485            *list
486            */
487           io_req_base = sc->request_message_pool_align
488                     + MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
489           io_req_base_phys = sc->request_msg_busaddr
490                     + MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
491 
492           /*
493            * Add all the commands to command pool (instance->cmd_pool)
494            */
495           /* SMID 0 is reserved. Set SMID/index from 1 */
496 
497           for (i = 0; i < sc->mfi_max_fw_cmds; i++) {
498                     cmd = sc->mfi_cmd_pool_tbolt[i];
499                     offset = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * i;
500                     cmd->index = i + 1;
501                     cmd->request_desc = (union mfi_mpi2_request_descriptor *)
502                         (sc->request_desc_pool + i);
503                     cmd->io_request = (struct mfi_mpi2_request_raid_scsi_io *)
504                         (io_req_base + offset);
505                     cmd->io_request_phys_addr = io_req_base_phys + offset;
506                     cmd->sg_frame = (MPI2_SGE_IO_UNION *)(sc->reply_pool_limit
507                         + i * MEGASAS_MAX_SZ_CHAIN_FRAME);
508                     cmd->sg_frame_phys_addr = sc->sg_frame_busaddr + i
509                         * MEGASAS_MAX_SZ_CHAIN_FRAME;
510 
511                     TAILQ_INSERT_TAIL(&(sc->mfi_cmd_tbolt_tqh), cmd, next);
512           }
513           return 0;
514 }
515 
mfi_tbolt_reset(struct mfi_softc * sc)516 int mfi_tbolt_reset(struct mfi_softc *sc)
517 {
518           uint32_t fw_state;
519 
520           lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
521           if (atomic_read(&sc->fw_reset_no_pci_access)) {
522                     device_printf(sc->mfi_dev, "NO PCI ACCESS\n");
523                     lockmgr(&sc->mfi_io_lock, LK_RELEASE);
524                     return 1;
525           }
526 
527           if (sc->hw_crit_error) {
528                     device_printf(sc->mfi_dev, "HW CRITICAL ERROR\n");
529                     lockmgr(&sc->mfi_io_lock, LK_RELEASE);
530                     return 1;
531           }
532 
533           if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
534                     fw_state = sc->mfi_read_fw_status(sc);
535                     if ((fw_state & MFI_FWSTATE_FAULT) == MFI_FWSTATE_FAULT) {
536                               if ((sc->disableOnlineCtrlReset == 0)
537                                   && (sc->adpreset == 0)) {
538                                         device_printf(sc->mfi_dev, "Adapter RESET "
539                                             "condition is detected\n");
540                                         sc->adpreset = 1;
541                                         sc->issuepend_done = 0;
542                                         sc->MFA_enabled = 0;
543                                         sc->last_reply_idx = 0;
544                                         mfi_process_fw_state_chg_isr(sc);
545                               }
546                               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
547                               return 0;
548                     }
549           }
550           lockmgr(&sc->mfi_io_lock, LK_RELEASE);
551           return 1;
552 }
553 
554 /*
555  * mfi_intr_tbolt - isr entry point
556  */
mfi_intr_tbolt(void * arg)557 void mfi_intr_tbolt(void *arg)
558 {
559           struct mfi_softc *sc = (struct mfi_softc *)arg;
560 
561           if (sc->mfi_check_clear_intr(sc) == 1) {
562                     return;
563           }
564           if (sc->mfi_detaching)
565                     return;
566           lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
567           mfi_tbolt_complete_cmd(sc);
568           if (sc->mfi_flags & MFI_FLAGS_QFRZN)
569                     sc->mfi_flags &= ~MFI_FLAGS_QFRZN;
570           mfi_startio(sc);
571           lockmgr(&sc->mfi_io_lock, LK_RELEASE);
572           return;
573 }
574 
575 /**
576  * map_cmd_status - Maps FW cmd status to OS cmd status
577  * @cmd :           Pointer to cmd
578  * @status :                  status of cmd returned by FW
579  * @ext_status :    ext status of cmd returned by FW
580  */
581 
582 void
map_tbolt_cmd_status(struct mfi_command * mfi_cmd,uint8_t status,uint8_t ext_status)583 map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status,
584     uint8_t ext_status)
585 {
586 
587           switch (status) {
588 
589                     case MFI_STAT_OK:
590                               mfi_cmd->cm_frame->header.cmd_status = 0;
591                               mfi_cmd->cm_frame->dcmd.header.cmd_status = 0;
592                               break;
593 
594                     case MFI_STAT_SCSI_IO_FAILED:
595                     case MFI_STAT_LD_INIT_IN_PROGRESS:
596                               mfi_cmd->cm_frame->header.cmd_status = status;
597                               mfi_cmd->cm_frame->header.scsi_status = ext_status;
598                               mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
599                               mfi_cmd->cm_frame->dcmd.header.scsi_status
600                                   = ext_status;
601                               break;
602 
603                     case MFI_STAT_SCSI_DONE_WITH_ERROR:
604                               mfi_cmd->cm_frame->header.cmd_status = ext_status;
605                               mfi_cmd->cm_frame->dcmd.header.cmd_status = ext_status;
606                               break;
607 
608                     case MFI_STAT_LD_OFFLINE:
609                     case MFI_STAT_DEVICE_NOT_FOUND:
610                               mfi_cmd->cm_frame->header.cmd_status = status;
611                               mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
612                               break;
613 
614                     default:
615                               mfi_cmd->cm_frame->header.cmd_status = status;
616                               mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
617                               break;
618                     }
619 }
620 
621 /**
622  * mfi_tbolt_return_cmd -     Return a cmd to free command pool
623  * @instance:                 Adapter soft state
624  * @cmd:            Command packet to be returned to free command pool
625  */
626 static inline void
mfi_tbolt_return_cmd(struct mfi_softc * sc,struct mfi_cmd_tbolt * cmd)627 mfi_tbolt_return_cmd(struct mfi_softc *sc, struct mfi_cmd_tbolt *cmd)
628 {
629           mfi_lockassert(&sc->mfi_io_lock);
630 
631           TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, cmd, next);
632 }
633 
mfi_tbolt_complete_cmd(struct mfi_softc * sc)634 void mfi_tbolt_complete_cmd(struct mfi_softc *sc)
635 {
636           struct mfi_mpi2_reply_header *desc, *reply_desc;
637           struct mfi_command *cmd_mfi;  /* For MFA Cmds */
638           struct mfi_cmd_tbolt *cmd_tbolt;
639           uint16_t smid;
640           uint8_t reply_descript_type;
641           struct mfi_mpi2_request_raid_scsi_io  *scsi_io_req;
642           uint32_t status, extStatus;
643           uint16_t num_completed;
644           union desc_value val;
645 
646           desc = (struct mfi_mpi2_reply_header *)
647                     ((uintptr_t)sc->reply_frame_pool_align
648                     + sc->last_reply_idx * sc->reply_size);
649           reply_desc = desc;
650 
651           if (!reply_desc)
652                     device_printf(sc->mfi_dev, "reply desc is NULL!!\n");
653 
654           reply_descript_type = reply_desc->ReplyFlags
655                & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
656           if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
657                     return;
658 
659           num_completed = 0;
660           val.word = ((union mfi_mpi2_reply_descriptor *)desc)->words;
661 
662           /* Read Reply descriptor */
663           while ((val.u.low != 0xFFFFFFFF) && (val.u.high != 0xFFFFFFFF)) {
664 
665                     smid = reply_desc->SMID;
666                     if (!smid || smid > sc->mfi_max_fw_cmds + 1) {
667                               device_printf(sc->mfi_dev, "smid is %x. Cannot "
668                                   "proceed. Returning \n", smid);
669                               return;
670                     }
671 
672                     cmd_tbolt = sc->mfi_cmd_pool_tbolt[smid - 1];
673                     cmd_mfi = &sc->mfi_commands[cmd_tbolt->sync_cmd_idx];
674                     scsi_io_req = cmd_tbolt->io_request;
675 
676                     /* Check if internal commands */
677                     status = cmd_mfi->cm_frame->dcmd.header.cmd_status;
678                     extStatus = cmd_mfi->cm_frame->dcmd.header.scsi_status;
679 
680                     switch (scsi_io_req->Function) {
681                     case MPI2_FUNCTION_LD_IO_REQUEST:
682                               /* Regular Path IO. */
683                               /* Map the Fw Error Status. */
684                               map_tbolt_cmd_status(cmd_mfi, status,
685                                   extStatus);
686                               if ((cmd_mfi->cm_frame->dcmd.opcode
687                                   == MFI_DCMD_LD_MAP_GET_INFO)
688                                   && (cmd_mfi->cm_frame->dcmd.mbox[1] == 1)) {
689                                                   if (cmd_mfi->cm_frame->header.cmd_status
690                                                       != 0)
691                                                             device_printf(sc->mfi_dev,
692                                                                 "map sync failed\n");
693                                                   else {
694                                                             sc->map_id++;
695                                                             device_printf(sc->mfi_dev,
696                                                                 "map sync completed\n");
697                                                             mfi_release_command(cmd_mfi);
698                                                   }
699                                         }
700                               if ((cmd_mfi->cm_flags & MFI_ON_MFIQ_BUSY)
701                                   == MFI_ON_MFIQ_BUSY
702                                   && (cmd_mfi->cm_flags & MFI_CMD_POLLED) == 0) {
703                                         /* BHARAT poll workaround */
704                                         mfi_remove_busy(cmd_mfi);
705                                         cmd_mfi->cm_error = 0;
706                                         mfi_complete(sc, cmd_mfi);
707                               }
708                               mfi_tbolt_return_cmd(sc, cmd_tbolt);
709                               break;
710                     case MPI2_FUNCTION_PASSTHRU_IO_REQUEST:
711                               map_tbolt_cmd_status(cmd_mfi, status, extStatus);
712                               if ((cmd_mfi->cm_frame->dcmd.opcode
713                                   == MFI_DCMD_LD_MAP_GET_INFO)
714                                   && (cmd_mfi->cm_frame->dcmd.mbox[1] == 1)) {
715                                         if (cmd_mfi->cm_frame->header.cmd_status != 0)
716                                                   device_printf(sc->mfi_dev,
717                                                       "map sync failed\n");
718                                         else {
719                                                   sc->map_id++;
720                                                   device_printf(sc->mfi_dev,
721                                                       "map sync completed\n");
722                                                   mfi_release_command(cmd_mfi);
723                                         }
724                               }
725                               if ((cmd_mfi->cm_flags & MFI_ON_MFIQ_BUSY)
726                                   == MFI_ON_MFIQ_BUSY
727                                   && (cmd_mfi->cm_flags & MFI_CMD_POLLED) == 0) {
728                                         /* BHARAT poll workaround */
729                                         mfi_remove_busy(cmd_mfi);
730                                         cmd_mfi->cm_error = 0;
731                                         mfi_complete(sc, cmd_mfi);
732                               }
733                               mfi_tbolt_return_cmd(sc, cmd_tbolt);
734                               break;
735                     }
736 
737                     sc->last_reply_idx++;
738                     if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) {
739                               MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx);
740                               sc->last_reply_idx = 0;
741                     }
742                     /*set it back to all 0xfff.*/
743                     ((union mfi_mpi2_reply_descriptor*)desc)->words =
744                               ~((uint64_t)0x00);
745 
746                     num_completed++;
747 
748                     /* Get the next reply descriptor */
749                     desc = (struct mfi_mpi2_reply_header *)
750                         ((uintptr_t)sc->reply_frame_pool_align
751                         + sc->last_reply_idx * sc->reply_size);
752                     reply_desc = desc;
753                     val.word = ((union mfi_mpi2_reply_descriptor*)desc)->words;
754                     reply_descript_type = reply_desc->ReplyFlags
755                         & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
756                     if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
757                               break;
758           }
759 
760           if (!num_completed)
761                     return;
762 
763           /* update replyIndex to FW */
764           if (sc->last_reply_idx)
765                     MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx);
766 
767           return;
768 }
769 
770 /**
771  * mfi_get_cmd -    Get a command from the free pool
772  * @instance:                 Adapter soft state
773  *
774  * Returns a free command from the pool
775  */
776 
mfi_tbolt_get_cmd(struct mfi_softc * sc)777 struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc
778                                                               *sc)
779 {
780           struct mfi_cmd_tbolt *cmd = NULL;
781 
782           mfi_lockassert(&sc->mfi_io_lock);
783 
784           cmd = TAILQ_FIRST(&sc->mfi_cmd_tbolt_tqh);
785           TAILQ_REMOVE(&sc->mfi_cmd_tbolt_tqh, cmd, next);
786           memset((uint8_t *)cmd->sg_frame, 0, MEGASAS_MAX_SZ_CHAIN_FRAME);
787           memset((uint8_t *)cmd->io_request, 0,
788               MEGASAS_THUNDERBOLT_NEW_MSG_SIZE);
789           return cmd;
790 }
791 
792 union mfi_mpi2_request_descriptor *
mfi_tbolt_get_request_descriptor(struct mfi_softc * sc,uint16_t index)793 mfi_tbolt_get_request_descriptor(struct mfi_softc *sc, uint16_t index)
794 {
795           uint8_t *p;
796 
797           if (index >= sc->mfi_max_fw_cmds) {
798                     device_printf(sc->mfi_dev, "Invalid SMID (0x%x)request "
799                         "for descriptor\n", index);
800                     return NULL;
801           }
802           p = sc->request_desc_pool + sizeof(union mfi_mpi2_request_descriptor)
803               * index;
804           memset(p, 0, sizeof(union mfi_mpi2_request_descriptor));
805           return (union mfi_mpi2_request_descriptor *)p;
806 }
807 
808 
809 /* Used to build IOCTL cmd */
810 uint8_t
mfi_build_mpt_pass_thru(struct mfi_softc * sc,struct mfi_command * mfi_cmd)811 mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd)
812 {
813           MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
814           struct mfi_mpi2_request_raid_scsi_io *io_req;
815           struct mfi_cmd_tbolt *cmd;
816 
817           cmd = mfi_tbolt_get_cmd(sc);
818           if (!cmd)
819                     return EBUSY;
820           mfi_cmd->cm_extra_frames = cmd->index; /* Frame count used as SMID */
821           cmd->sync_cmd_idx = mfi_cmd->cm_index;
822           io_req = cmd->io_request;
823           mpi25_ieee_chain = (MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
824 
825           io_req->Function = MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
826           io_req->SGLOffset0 = offsetof(struct mfi_mpi2_request_raid_scsi_io,
827               SGL) / 4;
828           io_req->ChainOffset = sc->chain_offset_value_for_mpt_ptmsg;
829 
830           mpi25_ieee_chain->Address = mfi_cmd->cm_frame_busaddr;
831 
832           /*
833             In MFI pass thru, nextChainOffset will always be zero to
834             indicate the end of the chain.
835           */
836           mpi25_ieee_chain->Flags= MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT
837                     | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
838 
839           /* setting the length to the maximum length */
840           mpi25_ieee_chain->Length = 1024;
841 
842           return 0;
843 }
844 
845 void
mfi_tbolt_build_ldio(struct mfi_softc * sc,struct mfi_command * mfi_cmd,struct mfi_cmd_tbolt * cmd)846 mfi_tbolt_build_ldio(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
847     struct mfi_cmd_tbolt *cmd)
848 {
849           uint32_t start_lba_lo = 0, start_lba_hi = 0, device_id;
850           struct mfi_mpi2_request_raid_scsi_io    *io_request;
851           struct IO_REQUEST_INFO io_info;
852 
853           device_id = mfi_cmd->cm_frame->io.header.target_id;
854           io_request = cmd->io_request;
855           io_request->RaidContext.TargetID = device_id;
856           io_request->RaidContext.Status = 0;
857           io_request->RaidContext.exStatus =0;
858 
859           start_lba_lo = mfi_cmd->cm_frame->io.lba_lo;
860           start_lba_hi = mfi_cmd->cm_frame->io.lba_hi;
861 
862           memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
863           io_info.ldStartBlock = ((uint64_t)start_lba_hi << 32) | start_lba_lo;
864           io_info.numBlocks = mfi_cmd->cm_frame->io.header.data_len;
865           io_info.ldTgtId = device_id;
866           if ((mfi_cmd->cm_frame->header.flags & MFI_FRAME_DIR_READ) ==
867               MFI_FRAME_DIR_READ)
868                     io_info.isRead = 1;
869 
870           io_request->RaidContext.timeoutValue = MFI_FUSION_FP_DEFAULT_TIMEOUT;
871           io_request->Function = MPI2_FUNCTION_LD_IO_REQUEST;
872           io_request->DevHandle = device_id;
873           cmd->request_desc->header.RequestFlags =
874               (MFI_REQ_DESCRIPT_FLAGS_LD_IO << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
875           if ((io_request->IoFlags == 6) && (io_info.numBlocks == 0))
876                     io_request->RaidContext.RegLockLength = 0x100;
877           io_request->DataLength = mfi_cmd->cm_frame->io.header.data_len
878               * MFI_SECTOR_LEN;
879 }
880 
mfi_tbolt_is_ldio(struct mfi_command * mfi_cmd)881 int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd)
882 {
883           if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ
884               || mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
885                     return 1;
886           else
887                     return 0;
888 }
889 
890 int
mfi_tbolt_build_io(struct mfi_softc * sc,struct mfi_command * mfi_cmd,struct mfi_cmd_tbolt * cmd)891 mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd, struct mfi_cmd_tbolt *cmd)
892 {
893           uint32_t sge_count;
894           uint8_t cdb[32], cdb_len;
895 
896           memset(cdb, 0, 32);
897           struct mfi_mpi2_request_raid_scsi_io *io_request = cmd->io_request;
898 
899           /* Have to build CDB here for TB as BSD don't have a scsi layer */
900           if ((cdb_len = mfi_tbolt_build_cdb(sc, mfi_cmd, cdb)) == 1)
901                     return 1;
902 
903           /* Just the CDB length,rest of the Flags are zero */
904           io_request->IoFlags = cdb_len;
905           memcpy(io_request->CDB.CDB32, cdb, 32);
906 
907           if (mfi_tbolt_is_ldio(mfi_cmd))
908                     mfi_tbolt_build_ldio(sc, mfi_cmd , cmd);
909           else
910                     return 1;
911 
912           /*
913            * Construct SGL
914            */
915           sge_count = mfi_tbolt_make_sgl(sc, mfi_cmd,
916               (pMpi25IeeeSgeChain64_t) &io_request->SGL, cmd);
917           if (sge_count > sc->mfi_max_sge) {
918                     device_printf(sc->mfi_dev, "Error. sge_count (0x%x) exceeds "
919                         "max (0x%x) allowed\n", sge_count, sc->mfi_max_sge);
920                     return 1;
921           }
922           io_request->RaidContext.numSGE = sge_count;
923           io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
924 
925           if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
926                     io_request->Control = MPI2_SCSIIO_CONTROL_WRITE;
927           else
928                     io_request->Control = MPI2_SCSIIO_CONTROL_READ;
929 
930           io_request->SGLOffset0 = offsetof(
931               struct mfi_mpi2_request_raid_scsi_io, SGL)/4;
932 
933           io_request->SenseBufferLowAddress = mfi_cmd->cm_sense_busaddr;
934           io_request->SenseBufferLength = MFI_SENSE_LEN;
935           return 0;
936 }
937 
938 static int
mfi_tbolt_build_cdb(struct mfi_softc * sc,struct mfi_command * mfi_cmd,uint8_t * cdb)939 mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
940     uint8_t *cdb)
941 {
942           uint32_t lba_lo, lba_hi, num_lba;
943           uint8_t cdb_len;
944 
945           if (mfi_cmd == NULL || cdb == NULL)
946                     return 1;
947           num_lba = mfi_cmd->cm_frame->io.header.data_len;
948           lba_lo = mfi_cmd->cm_frame->io.lba_lo;
949           lba_hi = mfi_cmd->cm_frame->io.lba_hi;
950 
951           if ((num_lba <= 0xFF) && (lba_lo <= 0x1FFFFF)) {
952                     if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
953                               /* Read 6 or Write 6 */
954                               cdb[0] = (uint8_t) (0x0A);
955                     else
956                               cdb[0] = (uint8_t) (0x08);
957 
958                     cdb[4] = (uint8_t) num_lba;
959                     cdb[3] = (uint8_t) (lba_lo & 0xFF);
960                     cdb[2] = (uint8_t) (lba_lo >> 8);
961                     cdb[1] = (uint8_t) ((lba_lo >> 16) & 0x1F);
962                     cdb_len = 6;
963           } else if ((num_lba <= 0xFFFF) && (lba_lo <= 0xFFFFFFFF)) {
964                     if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
965                               /* Read 10 or Write 10 */
966                               cdb[0] = (uint8_t) (0x2A);
967                     else
968                               cdb[0] = (uint8_t) (0x28);
969                     cdb[8] = (uint8_t) (num_lba & 0xFF);
970                     cdb[7] = (uint8_t) (num_lba >> 8);
971                     cdb[5] = (uint8_t) (lba_lo & 0xFF);
972                     cdb[4] = (uint8_t) (lba_lo >> 8);
973                     cdb[3] = (uint8_t) (lba_lo >> 16);
974                     cdb[2] = (uint8_t) (lba_lo >> 24);
975                     cdb_len = 10;
976           } else if ((num_lba > 0xFFFF) && (lba_hi == 0)) {
977                     if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
978                               /* Read 12 or Write 12 */
979                               cdb[0] = (uint8_t) (0xAA);
980                     else
981                               cdb[0] = (uint8_t) (0xA8);
982                     cdb[9] = (uint8_t) (num_lba & 0xFF);
983                     cdb[8] = (uint8_t) (num_lba >> 8);
984                     cdb[7] = (uint8_t) (num_lba >> 16);
985                     cdb[6] = (uint8_t) (num_lba >> 24);
986                     cdb[5] = (uint8_t) (lba_lo & 0xFF);
987                     cdb[4] = (uint8_t) (lba_lo >> 8);
988                     cdb[3] = (uint8_t) (lba_lo >> 16);
989                     cdb[2] = (uint8_t) (lba_lo >> 24);
990                     cdb_len = 12;
991           } else {
992                     if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
993                               cdb[0] = (uint8_t) (0x8A);
994                     else
995                               cdb[0] = (uint8_t) (0x88);
996                     cdb[13] = (uint8_t) (num_lba & 0xFF);
997                     cdb[12] = (uint8_t) (num_lba >> 8);
998                     cdb[11] = (uint8_t) (num_lba >> 16);
999                     cdb[10] = (uint8_t) (num_lba >> 24);
1000                     cdb[9] = (uint8_t) (lba_lo & 0xFF);
1001                     cdb[8] = (uint8_t) (lba_lo >> 8);
1002                     cdb[7] = (uint8_t) (lba_lo >> 16);
1003                     cdb[6] = (uint8_t) (lba_lo >> 24);
1004                     cdb[5] = (uint8_t) (lba_hi & 0xFF);
1005                     cdb[4] = (uint8_t) (lba_hi >> 8);
1006                     cdb[3] = (uint8_t) (lba_hi >> 16);
1007                     cdb[2] = (uint8_t) (lba_hi >> 24);
1008                     cdb_len = 16;
1009           }
1010           return cdb_len;
1011 }
1012 
1013 static int
mfi_tbolt_make_sgl(struct mfi_softc * sc,struct mfi_command * mfi_cmd,pMpi25IeeeSgeChain64_t sgl_ptr,struct mfi_cmd_tbolt * cmd)1014 mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
1015                        pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd)
1016 {
1017           uint8_t i, sg_processed;
1018           uint8_t sge_count, sge_idx;
1019           union mfi_sgl *os_sgl;
1020 
1021           /*
1022            * Return 0 if there is no data transfer
1023            */
1024           if (!mfi_cmd->cm_sg || !mfi_cmd->cm_len) {
1025                     device_printf(sc->mfi_dev, "Buffer empty \n");
1026                     return 0;
1027           }
1028           os_sgl = mfi_cmd->cm_sg;
1029           sge_count = mfi_cmd->cm_frame->header.sg_count;
1030 
1031           if (sge_count > sc->mfi_max_sge) {
1032                     device_printf(sc->mfi_dev, "sgl ptr %p sg_cnt %d \n",
1033                         os_sgl, sge_count);
1034                     return sge_count;
1035           }
1036 
1037           if (sge_count > sc->max_SGEs_in_main_message)
1038                     /* One element to store the chain info */
1039                     sge_idx = sc->max_SGEs_in_main_message - 1;
1040           else
1041                     sge_idx = sge_count;
1042 
1043           for (i = 0; i < sge_idx; i++) {
1044                     /*
1045                      * For 32bit BSD we are getting 32 bit SGL's from OS
1046                      * but FW only take 64 bit SGL's so copying from 32 bit
1047                      * SGL's to 64.
1048                      */
1049                     if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
1050                               sgl_ptr->Length = os_sgl->sg_skinny[i].len;
1051                               sgl_ptr->Address = os_sgl->sg_skinny[i].addr;
1052                     } else {
1053                               sgl_ptr->Length = os_sgl->sg32[i].len;
1054                               sgl_ptr->Address = os_sgl->sg32[i].addr;
1055                     }
1056                     sgl_ptr->Flags = 0;
1057                     sgl_ptr++;
1058                     cmd->io_request->ChainOffset = 0;
1059           }
1060 
1061           sg_processed = i;
1062 
1063           if (sg_processed < sge_count) {
1064                     pMpi25IeeeSgeChain64_t sg_chain;
1065                     cmd->io_request->ChainOffset =
1066                         sc->chain_offset_value_for_main_message;
1067                     sg_chain = sgl_ptr;
1068                     /* Prepare chain element */
1069                     sg_chain->NextChainOffset = 0;
1070                     sg_chain->Flags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
1071                         MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
1072                     sg_chain->Length =  (sizeof(MPI2_SGE_IO_UNION) *
1073                         (sge_count - sg_processed));
1074                     sg_chain->Address = cmd->sg_frame_phys_addr;
1075                     sgl_ptr = (pMpi25IeeeSgeChain64_t)cmd->sg_frame;
1076                     for (; i < sge_count; i++) {
1077                               if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
1078                                         sgl_ptr->Length = os_sgl->sg_skinny[i].len;
1079                                         sgl_ptr->Address = os_sgl->sg_skinny[i].addr;
1080                               } else {
1081                                         sgl_ptr->Length = os_sgl->sg32[i].len;
1082                                         sgl_ptr->Address = os_sgl->sg32[i].addr;
1083                               }
1084                               sgl_ptr->Flags = 0;
1085                               sgl_ptr++;
1086                     }
1087           }
1088           return sge_count;
1089 }
1090 
1091 union mfi_mpi2_request_descriptor *
mfi_build_and_issue_cmd(struct mfi_softc * sc,struct mfi_command * mfi_cmd)1092 mfi_build_and_issue_cmd(struct mfi_softc *sc, struct mfi_command *mfi_cmd)
1093 {
1094           struct mfi_cmd_tbolt *cmd;
1095           union mfi_mpi2_request_descriptor *req_desc = NULL;
1096           uint16_t index;
1097           cmd = mfi_tbolt_get_cmd(sc);
1098           if (!cmd)
1099                     return NULL;
1100           mfi_cmd->cm_extra_frames = cmd->index;
1101           cmd->sync_cmd_idx = mfi_cmd->cm_index;
1102 
1103           index = cmd->index;
1104           req_desc = mfi_tbolt_get_request_descriptor(sc, index-1);
1105           if (mfi_tbolt_build_io(sc, mfi_cmd, cmd))
1106                     return NULL;
1107           req_desc->header.SMID = index;
1108           return req_desc;
1109 }
1110 
1111 union mfi_mpi2_request_descriptor *
mfi_tbolt_build_mpt_cmd(struct mfi_softc * sc,struct mfi_command * cmd)1112 mfi_tbolt_build_mpt_cmd(struct mfi_softc *sc, struct mfi_command *cmd)
1113 {
1114           union mfi_mpi2_request_descriptor *req_desc = NULL;
1115           uint16_t index;
1116           if (mfi_build_mpt_pass_thru(sc, cmd)) {
1117                     device_printf(sc->mfi_dev, "Couldn't build MFI pass thru "
1118                         "cmd\n");
1119                     return NULL;
1120           }
1121           /* For fusion the frame_count variable is used for SMID */
1122           index = cmd->cm_extra_frames;
1123 
1124           req_desc = mfi_tbolt_get_request_descriptor(sc, index - 1);
1125           if (!req_desc)
1126                     return NULL;
1127 
1128           bzero(req_desc, sizeof(*req_desc));
1129           req_desc->header.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
1130               MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1131           req_desc->header.SMID = index;
1132           return req_desc;
1133 }
1134 
1135 int
mfi_tbolt_send_frame(struct mfi_softc * sc,struct mfi_command * cm)1136 mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
1137 {
1138           struct mfi_frame_header *hdr;
1139           uint8_t *cdb;
1140           union mfi_mpi2_request_descriptor *req_desc = NULL;
1141           int tm = MFI_POLL_TIMEOUT_SECS * 1000;
1142 
1143           hdr = &cm->cm_frame->header;
1144           cdb = cm->cm_frame->pass.cdb;
1145           if (sc->adpreset)
1146                     return 1;
1147           if ((cm->cm_flags & MFI_CMD_POLLED) == 0) {
1148                     cm->cm_timestamp = time_uptime;
1149                     mfi_enqueue_busy(cm);
1150           }
1151           else {
1152                     hdr->cmd_status = 0xff;
1153                     hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
1154           }
1155 
1156           if (hdr->cmd == MFI_CMD_PD_SCSI_IO) {
1157                     /* check for inquiry commands coming from CLI */
1158                     if (cdb[0] != 0x28 && cdb[0] != 0x2A) {
1159                               if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) ==
1160                                   NULL) {
1161                                         device_printf(sc->mfi_dev, "Mapping from MFI "
1162                                             "to MPT Failed \n");
1163                                         return 1;
1164                               }
1165                     }
1166                     else
1167                               device_printf(sc->mfi_dev, "DJA NA XXX SYSPDIO\n");
1168           }
1169           else if (hdr->cmd == MFI_CMD_LD_SCSI_IO ||
1170               hdr->cmd == MFI_CMD_LD_READ || hdr->cmd == MFI_CMD_LD_WRITE) {
1171                     if ((req_desc = mfi_build_and_issue_cmd(sc, cm)) == NULL) {
1172                               device_printf(sc->mfi_dev, "LDIO Failed \n");
1173                               return 1;
1174                     }
1175           } else
1176                     if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) {
1177                               device_printf(sc->mfi_dev, "Mapping from MFI to MPT "
1178                                   "Failed\n");
1179                               return 1;
1180                     }
1181           MFI_WRITE4(sc, MFI_ILQP, (req_desc->words & 0xFFFFFFFF));
1182           MFI_WRITE4(sc, MFI_IHQP, (req_desc->words >>0x20));
1183 
1184           if ((cm->cm_flags & MFI_CMD_POLLED) == 0)
1185                     return 0;
1186 
1187           /* This is a polled command, so busy-wait for it to complete. */
1188           while (hdr->cmd_status == 0xff) {
1189                     DELAY(1000);
1190                     tm -= 1;
1191                     if (tm <= 0)
1192                               break;
1193           }
1194 
1195           if (hdr->cmd_status == 0xff) {
1196                     device_printf(sc->mfi_dev, "Frame %p timed out "
1197                           "command 0x%X\n", hdr, cm->cm_frame->dcmd.opcode);
1198                     return (ETIMEDOUT);
1199           }
1200           return 0;
1201 }
1202 
mfi_issue_pending_cmds_again(struct mfi_softc * sc)1203 static void mfi_issue_pending_cmds_again (struct mfi_softc *sc)
1204 {
1205           struct mfi_command *cm, *tmp;
1206 
1207           mfi_lockassert(&sc->mfi_io_lock);
1208           TAILQ_FOREACH_REVERSE_MUTABLE(cm, &sc->mfi_busy, BUSYQ, cm_link, tmp) {
1209 
1210                     cm->retry_for_fw_reset++;
1211 
1212                     /*
1213                      * If a command has continuously been tried multiple times
1214                      * and causing a FW reset condition, no further recoveries
1215                      * should be performed on the controller
1216                      */
1217                     if (cm->retry_for_fw_reset == 3) {
1218                               device_printf(sc->mfi_dev, "megaraid_sas: command %d "
1219                                   "was tried multiple times during adapter reset"
1220                                   "Shutting down the HBA\n", cm->cm_index);
1221                               mfi_kill_hba(sc);
1222                               sc->hw_crit_error = 1;
1223                               return;
1224                     }
1225 
1226                     if ((cm->cm_flags & MFI_ON_MFIQ_BUSY) != 0) {
1227                               struct mfi_cmd_tbolt *cmd;
1228                               mfi_remove_busy(cm);
1229                               cmd = sc->mfi_cmd_pool_tbolt[cm->cm_extra_frames -
1230                                   1 ];
1231                               mfi_tbolt_return_cmd(sc, cmd);
1232                               if ((cm->cm_flags & MFI_ON_MFIQ_MASK) == 0) {
1233                                         if (cm->cm_frame->dcmd.opcode !=
1234                                             MFI_DCMD_CTRL_EVENT_WAIT) {
1235                                                   device_printf(sc->mfi_dev,
1236                                                       "APJ ****requeue command %d \n",
1237                                                       cm->cm_index);
1238                                                   mfi_requeue_ready(cm);
1239                                         }
1240                               }
1241                               else
1242                                         mfi_release_command(cm);
1243                     }
1244           }
1245           mfi_startio(sc);
1246 }
1247 
mfi_kill_hba(struct mfi_softc * sc)1248 static void mfi_kill_hba (struct mfi_softc *sc)
1249 {
1250           if (sc->mfi_flags & MFI_FLAGS_TBOLT)
1251                     MFI_WRITE4 (sc, 0x00,MFI_STOP_ADP);
1252           else
1253                     MFI_WRITE4 (sc, MFI_IDB,MFI_STOP_ADP);
1254 }
1255 
mfi_process_fw_state_chg_isr(void * arg)1256 static void mfi_process_fw_state_chg_isr(void *arg)
1257 {
1258           struct mfi_softc *sc= (struct mfi_softc *)arg;
1259           struct mfi_cmd_tbolt *cmd;
1260           int error, status;
1261 
1262           if (sc->adpreset == 1) {
1263                     device_printf(sc->mfi_dev, "First stage of FW reset "
1264                          "initiated...\n");
1265 
1266                     sc->mfi_adp_reset(sc);
1267                     sc->mfi_enable_intr(sc);
1268 
1269                     device_printf(sc->mfi_dev, "First stage of reset complete, "
1270                         "second stage initiated...\n");
1271 
1272                     sc->adpreset = 2;
1273 
1274                     /* waiting for about 20 second before start the second init */
1275                     for (int wait = 0; wait < 20000; wait++)
1276                               DELAY(1000);
1277                     device_printf(sc->mfi_dev, "Second stage of FW reset "
1278                          "initiated...\n");
1279                     while ((status = MFI_READ4(sc, MFI_RSR)) & 0x04);
1280 
1281                     sc->mfi_disable_intr(sc);
1282 
1283                     /* We expect the FW state to be READY */
1284                     if (mfi_transition_firmware(sc)) {
1285                               device_printf(sc->mfi_dev, "controller is not in "
1286                                   "ready state\n");
1287                               mfi_kill_hba(sc);
1288                               sc->hw_crit_error= 1;
1289                               return ;
1290                     }
1291                     if ((error = mfi_tbolt_init_MFI_queue(sc)) != 0)
1292                                         return;
1293 
1294                     lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
1295 
1296                     sc->mfi_enable_intr(sc);
1297                     sc->adpreset = 0;
1298                     kfree(sc->mfi_aen_cm->cm_data, M_MFIBUF);
1299                     mfi_remove_busy(sc->mfi_aen_cm);
1300                     cmd = sc->mfi_cmd_pool_tbolt[sc->mfi_aen_cm->cm_extra_frames
1301                         - 1];
1302                     mfi_tbolt_return_cmd(sc, cmd);
1303                     if (sc->mfi_aen_cm) {
1304                               mfi_release_command(sc->mfi_aen_cm);
1305                               sc->mfi_aen_cm = NULL;
1306                     }
1307                     if (sc->map_update_cmd) {
1308                               mfi_release_command(sc->map_update_cmd);
1309                               sc->map_update_cmd = NULL;
1310                     }
1311                     mfi_issue_pending_cmds_again(sc);
1312 
1313                     /*
1314                      * Issue pending command can result in adapter being marked
1315                      * dead because of too many re-tries. Check for that
1316                      * condition before clearing the reset condition on the FW
1317                      */
1318                     if (!sc->hw_crit_error) {
1319                               /*
1320                                * Initiate AEN (Asynchronous Event Notification)
1321                                */
1322                               mfi_aen_setup(sc, sc->last_seq_num);
1323                               sc->issuepend_done = 1;
1324                               device_printf(sc->mfi_dev, "second stage of reset "
1325                                   "complete, FW is ready now.\n");
1326                     } else {
1327                               device_printf(sc->mfi_dev, "second stage of reset "
1328                                    "never completed, hba was marked offline.\n");
1329                     }
1330           } else {
1331                     device_printf(sc->mfi_dev, "mfi_process_fw_state_chg_isr "
1332                         "called with unhandled value:%d\n", sc->adpreset);
1333           }
1334           lockmgr(&sc->mfi_io_lock, LK_RELEASE);
1335 }
1336