Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/mr_sas/mr_sas.c
+++ new/usr/src/uts/common/io/mr_sas/mr_sas.c
1 1 /*
2 2 * mr_sas.c: source for mr_sas driver
3 3 *
4 4 * Solaris MegaRAID device driver for SAS2.0 controllers
5 5 * Copyright (c) 2008-2012, LSI Logic Corporation.
6 6 * All rights reserved.
7 7 *
8 8 * Version:
9 9 * Author:
10 10 * Swaminathan K S
11 11 * Arun Chandrashekhar
12 12 * Manju R
13 13 * Rasheed
14 14 * Shakeel Bukhari
15 15 *
16 16 * Redistribution and use in source and binary forms, with or without
17 17 * modification, are permitted provided that the following conditions are met:
18 18 *
19 19 * 1. Redistributions of source code must retain the above copyright notice,
20 20 * this list of conditions and the following disclaimer.
21 21 *
22 22 * 2. Redistributions in binary form must reproduce the above copyright notice,
23 23 * this list of conditions and the following disclaimer in the documentation
24 24 * and/or other materials provided with the distribution.
25 25 *
26 26 * 3. Neither the name of the author nor the names of its contributors may be
27 27 * used to endorse or promote products derived from this software without
28 28 * specific prior written permission.
29 29 *
30 30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 34 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 36 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
37 37 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
38 38 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
39 39 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
40 40 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
41 41 * DAMAGE.
42 42 */
43 43
44 44 /*
45 45 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
46 46 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
47 47 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
48 48 */
49 49
50 50 #include <sys/types.h>
51 51 #include <sys/param.h>
52 52 #include <sys/file.h>
53 53 #include <sys/errno.h>
54 54 #include <sys/open.h>
55 55 #include <sys/cred.h>
56 56 #include <sys/modctl.h>
57 57 #include <sys/conf.h>
58 58 #include <sys/devops.h>
59 59 #include <sys/cmn_err.h>
60 60 #include <sys/kmem.h>
61 61 #include <sys/stat.h>
62 62 #include <sys/mkdev.h>
63 63 #include <sys/pci.h>
64 64 #include <sys/scsi/scsi.h>
65 65 #include <sys/ddi.h>
66 66 #include <sys/sunddi.h>
67 67 #include <sys/atomic.h>
68 68 #include <sys/signal.h>
69 69 #include <sys/byteorder.h>
70 70 #include <sys/sdt.h>
71 71 #include <sys/fs/dv_node.h> /* devfs_clean */
72 72
73 73 #include "mr_sas.h"
74 74
75 75 /*
76 76 * FMA header files
77 77 */
78 78 #include <sys/ddifm.h>
79 79 #include <sys/fm/protocol.h>
80 80 #include <sys/fm/util.h>
81 81 #include <sys/fm/io/ddi.h>
82 82
83 83 /* Macros to help Skinny and stock 2108/MFI live together. */
84 84 #define WR_IB_PICK_QPORT(addr, instance) \
85 85 if ((instance)->skinny) { \
86 86 WR_IB_LOW_QPORT((addr), (instance)); \
87 87 WR_IB_HIGH_QPORT(0, (instance)); \
88 88 } else { \
89 89 WR_IB_QPORT((addr), (instance)); \
90 90 }
91 91
92 92 /*
93 93 * Local static data
94 94 */
95 95 static void *mrsas_state = NULL;
96 96 static volatile boolean_t mrsas_relaxed_ordering = B_TRUE;
97 97 volatile int debug_level_g = CL_NONE;
98 98 static volatile int msi_enable = 1;
99 99 static volatile int ctio_enable = 1;
100 100
101 101 /* Default Timeout value to issue online controller reset */
102 102 volatile int debug_timeout_g = 0xF0; /* 0xB4; */
103 103 /* Simulate consecutive firmware fault */
104 104 static volatile int debug_fw_faults_after_ocr_g = 0;
105 105 #ifdef OCRDEBUG
106 106 /* Simulate three consecutive timeout for an IO */
107 107 static volatile int debug_consecutive_timeout_after_ocr_g = 0;
108 108 #endif
109 109
110 110 #pragma weak scsi_hba_open
111 111 #pragma weak scsi_hba_close
112 112 #pragma weak scsi_hba_ioctl
113 113
114 114 /* Local static prototypes. */
115 115 static int mrsas_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
116 116 static int mrsas_attach(dev_info_t *, ddi_attach_cmd_t);
117 117 #ifdef __sparc
118 118 static int mrsas_reset(dev_info_t *, ddi_reset_cmd_t);
119 119 #else
120 120 static int mrsas_quiesce(dev_info_t *);
121 121 #endif
122 122 static int mrsas_detach(dev_info_t *, ddi_detach_cmd_t);
123 123 static int mrsas_open(dev_t *, int, int, cred_t *);
124 124 static int mrsas_close(dev_t, int, int, cred_t *);
125 125 static int mrsas_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
126 126
127 127 static int mrsas_tran_tgt_init(dev_info_t *, dev_info_t *,
128 128 scsi_hba_tran_t *, struct scsi_device *);
129 129 static struct scsi_pkt *mrsas_tran_init_pkt(struct scsi_address *, register
130 130 struct scsi_pkt *, struct buf *, int, int, int, int,
131 131 int (*)(), caddr_t);
132 132 static int mrsas_tran_start(struct scsi_address *,
133 133 register struct scsi_pkt *);
134 134 static int mrsas_tran_abort(struct scsi_address *, struct scsi_pkt *);
135 135 static int mrsas_tran_reset(struct scsi_address *, int);
136 136 static int mrsas_tran_getcap(struct scsi_address *, char *, int);
137 137 static int mrsas_tran_setcap(struct scsi_address *, char *, int, int);
138 138 static void mrsas_tran_destroy_pkt(struct scsi_address *,
139 139 struct scsi_pkt *);
140 140 static void mrsas_tran_dmafree(struct scsi_address *, struct scsi_pkt *);
141 141 static void mrsas_tran_sync_pkt(struct scsi_address *, struct scsi_pkt *);
142 142 static int mrsas_tran_quiesce(dev_info_t *dip);
143 143 static int mrsas_tran_unquiesce(dev_info_t *dip);
144 144 static uint_t mrsas_isr();
145 145 static uint_t mrsas_softintr();
146 146 static void mrsas_undo_resources(dev_info_t *, struct mrsas_instance *);
147 147
148 148 static void free_space_for_mfi(struct mrsas_instance *);
149 149 static uint32_t read_fw_status_reg_ppc(struct mrsas_instance *);
150 150 static void issue_cmd_ppc(struct mrsas_cmd *, struct mrsas_instance *);
151 151 static int issue_cmd_in_poll_mode_ppc(struct mrsas_instance *,
152 152 struct mrsas_cmd *);
153 153 static int issue_cmd_in_sync_mode_ppc(struct mrsas_instance *,
154 154 struct mrsas_cmd *);
155 155 static void enable_intr_ppc(struct mrsas_instance *);
156 156 static void disable_intr_ppc(struct mrsas_instance *);
157 157 static int intr_ack_ppc(struct mrsas_instance *);
158 158 static void flush_cache(struct mrsas_instance *instance);
159 159 void display_scsi_inquiry(caddr_t);
160 160 static int start_mfi_aen(struct mrsas_instance *instance);
161 161 static int handle_drv_ioctl(struct mrsas_instance *instance,
162 162 struct mrsas_ioctl *ioctl, int mode);
163 163 static int handle_mfi_ioctl(struct mrsas_instance *instance,
164 164 struct mrsas_ioctl *ioctl, int mode);
165 165 static int handle_mfi_aen(struct mrsas_instance *instance,
166 166 struct mrsas_aen *aen);
167 167 static struct mrsas_cmd *build_cmd(struct mrsas_instance *,
168 168 struct scsi_address *, struct scsi_pkt *, uchar_t *);
169 169 static int alloc_additional_dma_buffer(struct mrsas_instance *);
170 170 static void complete_cmd_in_sync_mode(struct mrsas_instance *,
171 171 struct mrsas_cmd *);
172 172 static int mrsas_kill_adapter(struct mrsas_instance *);
173 173 static int mrsas_issue_init_mfi(struct mrsas_instance *);
174 174 static int mrsas_reset_ppc(struct mrsas_instance *);
175 175 static uint32_t mrsas_initiate_ocr_if_fw_is_faulty(struct mrsas_instance *);
176 176 static int wait_for_outstanding(struct mrsas_instance *instance);
177 177 static int register_mfi_aen(struct mrsas_instance *instance,
178 178 uint32_t seq_num, uint32_t class_locale_word);
179 179 static int issue_mfi_pthru(struct mrsas_instance *instance, struct
180 180 mrsas_ioctl *ioctl, struct mrsas_cmd *cmd, int mode);
181 181 static int issue_mfi_dcmd(struct mrsas_instance *instance, struct
182 182 mrsas_ioctl *ioctl, struct mrsas_cmd *cmd, int mode);
183 183 static int issue_mfi_smp(struct mrsas_instance *instance, struct
184 184 mrsas_ioctl *ioctl, struct mrsas_cmd *cmd, int mode);
185 185 static int issue_mfi_stp(struct mrsas_instance *instance, struct
186 186 mrsas_ioctl *ioctl, struct mrsas_cmd *cmd, int mode);
187 187 static int abort_aen_cmd(struct mrsas_instance *instance,
188 188 struct mrsas_cmd *cmd_to_abort);
189 189
190 190 static void mrsas_rem_intrs(struct mrsas_instance *instance);
191 191 static int mrsas_add_intrs(struct mrsas_instance *instance, int intr_type);
192 192
193 193 static void mrsas_tran_tgt_free(dev_info_t *, dev_info_t *,
194 194 scsi_hba_tran_t *, struct scsi_device *);
195 195 static int mrsas_tran_bus_config(dev_info_t *, uint_t,
196 196 ddi_bus_config_op_t, void *, dev_info_t **);
197 197 static int mrsas_parse_devname(char *, int *, int *);
198 198 static int mrsas_config_all_devices(struct mrsas_instance *);
199 199 static int mrsas_config_ld(struct mrsas_instance *, uint16_t,
200 200 uint8_t, dev_info_t **);
201 201 static int mrsas_name_node(dev_info_t *, char *, int);
202 202 static void mrsas_issue_evt_taskq(struct mrsas_eventinfo *);
203 203 static void free_additional_dma_buffer(struct mrsas_instance *);
204 204 static void io_timeout_checker(void *);
205 205 static void mrsas_fm_init(struct mrsas_instance *);
206 206 static void mrsas_fm_fini(struct mrsas_instance *);
207 207
208 208 static struct mrsas_function_template mrsas_function_template_ppc = {
209 209 .read_fw_status_reg = read_fw_status_reg_ppc,
210 210 .issue_cmd = issue_cmd_ppc,
211 211 .issue_cmd_in_sync_mode = issue_cmd_in_sync_mode_ppc,
212 212 .issue_cmd_in_poll_mode = issue_cmd_in_poll_mode_ppc,
213 213 .enable_intr = enable_intr_ppc,
214 214 .disable_intr = disable_intr_ppc,
215 215 .intr_ack = intr_ack_ppc,
216 216 .init_adapter = mrsas_init_adapter_ppc
217 217 };
218 218
219 219
220 220 static struct mrsas_function_template mrsas_function_template_fusion = {
221 221 .read_fw_status_reg = tbolt_read_fw_status_reg,
222 222 .issue_cmd = tbolt_issue_cmd,
223 223 .issue_cmd_in_sync_mode = tbolt_issue_cmd_in_sync_mode,
224 224 .issue_cmd_in_poll_mode = tbolt_issue_cmd_in_poll_mode,
225 225 .enable_intr = tbolt_enable_intr,
226 226 .disable_intr = tbolt_disable_intr,
227 227 .intr_ack = tbolt_intr_ack,
228 228 .init_adapter = mrsas_init_adapter_tbolt
229 229 };
230 230
231 231
232 232 ddi_dma_attr_t mrsas_generic_dma_attr = {
233 233 DMA_ATTR_V0, /* dma_attr_version */
234 234 0, /* low DMA address range */
235 235 0xFFFFFFFFU, /* high DMA address range */
236 236 0xFFFFFFFFU, /* DMA counter register */
237 237 8, /* DMA address alignment */
238 238 0x07, /* DMA burstsizes */
239 239 1, /* min DMA size */
240 240 0xFFFFFFFFU, /* max DMA size */
241 241 0xFFFFFFFFU, /* segment boundary */
242 242 MRSAS_MAX_SGE_CNT, /* dma_attr_sglen */
243 243 512, /* granularity of device */
244 244 0 /* bus specific DMA flags */
245 245 };
246 246
247 247 int32_t mrsas_max_cap_maxxfer = 0x1000000;
248 248
249 249 /*
250 250 * Fix for: Thunderbolt controller IO timeout when IO write size is 1MEG,
251 251 * Limit size to 256K
252 252 */
253 253 uint32_t mrsas_tbolt_max_cap_maxxfer = (512 * 512);
254 254
255 255 /*
256 256 * cb_ops contains base level routines
257 257 */
258 258 static struct cb_ops mrsas_cb_ops = {
259 259 mrsas_open, /* open */
260 260 mrsas_close, /* close */
261 261 nodev, /* strategy */
262 262 nodev, /* print */
263 263 nodev, /* dump */
264 264 nodev, /* read */
265 265 nodev, /* write */
266 266 mrsas_ioctl, /* ioctl */
267 267 nodev, /* devmap */
268 268 nodev, /* mmap */
269 269 nodev, /* segmap */
270 270 nochpoll, /* poll */
271 271 nodev, /* cb_prop_op */
272 272 0, /* streamtab */
273 273 D_NEW | D_HOTPLUG, /* cb_flag */
274 274 CB_REV, /* cb_rev */
275 275 nodev, /* cb_aread */
276 276 nodev /* cb_awrite */
277 277 };
278 278
279 279 /*
280 280 * dev_ops contains configuration routines
281 281 */
282 282 static struct dev_ops mrsas_ops = {
283 283 DEVO_REV, /* rev, */
284 284 0, /* refcnt */
285 285 mrsas_getinfo, /* getinfo */
286 286 nulldev, /* identify */
287 287 nulldev, /* probe */
288 288 mrsas_attach, /* attach */
289 289 mrsas_detach, /* detach */
290 290 #ifdef __sparc
291 291 mrsas_reset, /* reset */
292 292 #else /* __sparc */
293 293 nodev,
294 294 #endif /* __sparc */
295 295 &mrsas_cb_ops, /* char/block ops */
296 296 NULL, /* bus ops */
297 297 NULL, /* power */
298 298 #ifdef __sparc
299 299 ddi_quiesce_not_needed
300 300 #else /* __sparc */
301 301 mrsas_quiesce /* quiesce */
302 302 #endif /* __sparc */
303 303 };
304 304
305 305 static struct modldrv modldrv = {
306 306 &mod_driverops, /* module type - driver */
307 307 MRSAS_VERSION,
308 308 &mrsas_ops, /* driver ops */
309 309 };
310 310
311 311 static struct modlinkage modlinkage = {
312 312 MODREV_1, /* ml_rev - must be MODREV_1 */
313 313 &modldrv, /* ml_linkage */
314 314 NULL /* end of driver linkage */
315 315 };
316 316
317 317 static struct ddi_device_acc_attr endian_attr = {
318 318 DDI_DEVICE_ATTR_V1,
319 319 DDI_STRUCTURE_LE_ACC,
320 320 DDI_STRICTORDER_ACC,
321 321 DDI_DEFAULT_ACC
322 322 };
323 323
324 324 /* Use the LSI Fast Path for the 2208 (tbolt) commands. */
325 325 unsigned int enable_fp = 1;
326 326
327 327
328 328 /*
329 329 * ************************************************************************** *
330 330 * *
331 331 * common entry points - for loadable kernel modules *
332 332 * *
333 333 * ************************************************************************** *
334 334 */
335 335
336 336 /*
337 337 * _init - initialize a loadable module
338 338 * @void
339 339 *
340 340 * The driver should perform any one-time resource allocation or data
341 341 * initialization during driver loading in _init(). For example, the driver
342 342 * should initialize any mutexes global to the driver in this routine.
343 343 * The driver should not, however, use _init() to allocate or initialize
344 344 * anything that has to do with a particular instance of the device.
345 345 * Per-instance initialization must be done in attach().
346 346 */
347 347 int
348 348 _init(void)
349 349 {
350 350 int ret;
351 351
352 352 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
353 353
354 354 ret = ddi_soft_state_init(&mrsas_state,
355 355 sizeof (struct mrsas_instance), 0);
356 356
357 357 if (ret != DDI_SUCCESS) {
358 358 cmn_err(CE_WARN, "mr_sas: could not init state");
359 359 return (ret);
360 360 }
361 361
362 362 if ((ret = scsi_hba_init(&modlinkage)) != DDI_SUCCESS) {
363 363 cmn_err(CE_WARN, "mr_sas: could not init scsi hba");
364 364 ddi_soft_state_fini(&mrsas_state);
365 365 return (ret);
366 366 }
367 367
368 368 ret = mod_install(&modlinkage);
369 369
370 370 if (ret != DDI_SUCCESS) {
371 371 cmn_err(CE_WARN, "mr_sas: mod_install failed");
372 372 scsi_hba_fini(&modlinkage);
373 373 ddi_soft_state_fini(&mrsas_state);
374 374 }
375 375
376 376 return (ret);
377 377 }
378 378
379 379 /*
380 380 * _info - returns information about a loadable module.
381 381 * @void
382 382 *
383 383 * _info() is called to return module information. This is a typical entry
384 384 * point that does predefined role. It simply calls mod_info().
385 385 */
386 386 int
387 387 _info(struct modinfo *modinfop)
388 388 {
389 389 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
390 390
391 391 return (mod_info(&modlinkage, modinfop));
392 392 }
393 393
394 394 /*
395 395 * _fini - prepare a loadable module for unloading
396 396 * @void
397 397 *
398 398 * In _fini(), the driver should release any resources that were allocated in
399 399 * _init(). The driver must remove itself from the system module list.
400 400 */
401 401 int
402 402 _fini(void)
403 403 {
404 404 int ret;
405 405
406 406 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
407 407
408 408 if ((ret = mod_remove(&modlinkage)) != DDI_SUCCESS) {
409 409 con_log(CL_ANN1,
410 410 (CE_WARN, "_fini: mod_remove() failed, error 0x%X", ret));
411 411 return (ret);
412 412 }
413 413
414 414 scsi_hba_fini(&modlinkage);
415 415 con_log(CL_DLEVEL1, (CE_NOTE, "_fini: scsi_hba_fini() done."));
416 416
417 417 ddi_soft_state_fini(&mrsas_state);
418 418 con_log(CL_DLEVEL1, (CE_NOTE, "_fini: ddi_soft_state_fini() done."));
419 419
420 420 return (ret);
421 421 }
422 422
423 423
424 424 /*
425 425 * ************************************************************************** *
426 426 * *
427 427 * common entry points - for autoconfiguration *
428 428 * *
429 429 * ************************************************************************** *
430 430 */
431 431 /*
432 432 * attach - adds a device to the system as part of initialization
433 433 * @dip:
434 434 * @cmd:
435 435 *
436 436 * The kernel calls a driver's attach() entry point to attach an instance of
437 437 * a device (for MegaRAID, it is instance of a controller) or to resume
438 438 * operation for an instance of a device that has been suspended or has been
439 439 * shut down by the power management framework
440 440 * The attach() entry point typically includes the following types of
441 441 * processing:
442 442 * - allocate a soft-state structure for the device instance (for MegaRAID,
443 443 * controller instance)
444 444 * - initialize per-instance mutexes
445 445 * - initialize condition variables
446 446 * - register the device's interrupts (for MegaRAID, controller's interrupts)
447 447 * - map the registers and memory of the device instance (for MegaRAID,
448 448 * controller instance)
449 449 * - create minor device nodes for the device instance (for MegaRAID,
450 450 * controller instance)
451 451 * - report that the device instance (for MegaRAID, controller instance) has
452 452 * attached
453 453 */
454 454 static int
455 455 mrsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
456 456 {
457 457 int instance_no;
458 458 int nregs;
459 459 int i = 0;
460 460 uint8_t irq;
461 461 uint16_t vendor_id;
462 462 uint16_t device_id;
463 463 uint16_t subsysvid;
464 464 uint16_t subsysid;
465 465 uint16_t command;
466 466 off_t reglength = 0;
467 467 int intr_types = 0;
468 468 char *data;
469 469
470 470 scsi_hba_tran_t *tran;
471 471 ddi_dma_attr_t tran_dma_attr;
472 472 struct mrsas_instance *instance;
473 473
474 474 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
475 475
476 476 /* CONSTCOND */
477 477 ASSERT(NO_COMPETING_THREADS);
478 478
479 479 instance_no = ddi_get_instance(dip);
480 480
481 481 /*
482 482 * check to see whether this device is in a DMA-capable slot.
483 483 */
484 484 if (ddi_slaveonly(dip) == DDI_SUCCESS) {
485 485 cmn_err(CE_WARN,
486 486 "mr_sas%d: Device in slave-only slot, unused",
487 487 instance_no);
488 488 return (DDI_FAILURE);
489 489 }
490 490
491 491 switch (cmd) {
492 492 case DDI_ATTACH:
493 493 /* allocate the soft state for the instance */
494 494 if (ddi_soft_state_zalloc(mrsas_state, instance_no)
495 495 != DDI_SUCCESS) {
496 496 cmn_err(CE_WARN,
497 497 "mr_sas%d: Failed to allocate soft state",
498 498 instance_no);
499 499 return (DDI_FAILURE);
500 500 }
501 501
502 502 instance = (struct mrsas_instance *)ddi_get_soft_state
503 503 (mrsas_state, instance_no);
504 504
505 505 if (instance == NULL) {
506 506 cmn_err(CE_WARN,
507 507 "mr_sas%d: Bad soft state", instance_no);
508 508 ddi_soft_state_free(mrsas_state, instance_no);
509 509 return (DDI_FAILURE);
510 510 }
511 511
512 512 instance->unroll.softs = 1;
513 513
514 514 /* Setup the PCI configuration space handles */
515 515 if (pci_config_setup(dip, &instance->pci_handle) !=
516 516 DDI_SUCCESS) {
517 517 cmn_err(CE_WARN,
518 518 "mr_sas%d: pci config setup failed ",
519 519 instance_no);
520 520
521 521 ddi_soft_state_free(mrsas_state, instance_no);
522 522 return (DDI_FAILURE);
523 523 }
524 524
525 525 if (ddi_dev_nregs(dip, &nregs) != DDI_SUCCESS) {
526 526 cmn_err(CE_WARN,
527 527 "mr_sas: failed to get registers.");
528 528
529 529 pci_config_teardown(&instance->pci_handle);
530 530 ddi_soft_state_free(mrsas_state, instance_no);
531 531 return (DDI_FAILURE);
532 532 }
533 533
534 534 vendor_id = pci_config_get16(instance->pci_handle,
535 535 PCI_CONF_VENID);
536 536 device_id = pci_config_get16(instance->pci_handle,
537 537 PCI_CONF_DEVID);
538 538
539 539 subsysvid = pci_config_get16(instance->pci_handle,
540 540 PCI_CONF_SUBVENID);
541 541 subsysid = pci_config_get16(instance->pci_handle,
542 542 PCI_CONF_SUBSYSID);
543 543
544 544 pci_config_put16(instance->pci_handle, PCI_CONF_COMM,
545 545 (pci_config_get16(instance->pci_handle,
546 546 PCI_CONF_COMM) | PCI_COMM_ME));
547 547 irq = pci_config_get8(instance->pci_handle,
548 548 PCI_CONF_ILINE);
549 549
550 550 con_log(CL_DLEVEL1, (CE_CONT, "mr_sas%d: "
551 551 "0x%x:0x%x 0x%x:0x%x, irq:%d drv-ver:%s",
552 552 instance_no, vendor_id, device_id, subsysvid,
553 553 subsysid, irq, MRSAS_VERSION));
554 554
555 555 /* enable bus-mastering */
556 556 command = pci_config_get16(instance->pci_handle,
557 557 PCI_CONF_COMM);
558 558
559 559 if (!(command & PCI_COMM_ME)) {
560 560 command |= PCI_COMM_ME;
561 561
562 562 pci_config_put16(instance->pci_handle,
563 563 PCI_CONF_COMM, command);
564 564
565 565 con_log(CL_ANN, (CE_CONT, "mr_sas%d: "
566 566 "enable bus-mastering", instance_no));
567 567 } else {
568 568 con_log(CL_DLEVEL1, (CE_CONT, "mr_sas%d: "
569 569 "bus-mastering already set", instance_no));
570 570 }
571 571
572 572 /* initialize function pointers */
573 573 switch (device_id) {
574 574 case PCI_DEVICE_ID_LSI_TBOLT:
575 575 case PCI_DEVICE_ID_LSI_INVADER:
576 576 con_log(CL_ANN, (CE_NOTE,
577 577 "mr_sas: 2208 T.B. device detected"));
578 578
579 579 instance->func_ptr =
580 580 &mrsas_function_template_fusion;
581 581 instance->tbolt = 1;
582 582 break;
583 583
584 584 case PCI_DEVICE_ID_LSI_SKINNY:
585 585 case PCI_DEVICE_ID_LSI_SKINNY_NEW:
586 586 /*
587 587 * FALLTHRU to PPC-style functions, but mark this
588 588 * instance as Skinny, because the register set is
589 589 * slightly different (See WR_IB_PICK_QPORT), and
590 590 * certain other features are available to a Skinny
591 591 * HBA.
592 592 */
593 593 instance->skinny = 1;
594 594 /* FALLTHRU */
595 595
596 596 case PCI_DEVICE_ID_LSI_2108VDE:
597 597 case PCI_DEVICE_ID_LSI_2108V:
598 598 con_log(CL_ANN, (CE_NOTE,
599 599 "mr_sas: 2108 Liberator device detected"));
600 600
601 601 instance->func_ptr =
602 602 &mrsas_function_template_ppc;
603 603 break;
604 604
605 605 default:
606 606 cmn_err(CE_WARN,
607 607 "mr_sas: Invalid device detected");
608 608
609 609 pci_config_teardown(&instance->pci_handle);
610 610 ddi_soft_state_free(mrsas_state, instance_no);
611 611 return (DDI_FAILURE);
612 612 }
613 613
614 614 instance->baseaddress = pci_config_get32(
615 615 instance->pci_handle, PCI_CONF_BASE0);
616 616 instance->baseaddress &= 0x0fffc;
617 617
618 618 instance->dip = dip;
619 619 instance->vendor_id = vendor_id;
620 620 instance->device_id = device_id;
621 621 instance->subsysvid = subsysvid;
622 622 instance->subsysid = subsysid;
623 623 instance->instance = instance_no;
624 624
625 625 /* Initialize FMA */
626 626 instance->fm_capabilities = ddi_prop_get_int(
627 627 DDI_DEV_T_ANY, instance->dip, DDI_PROP_DONTPASS,
628 628 "fm-capable", DDI_FM_EREPORT_CAPABLE |
629 629 DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE
630 630 | DDI_FM_ERRCB_CAPABLE);
631 631
632 632 mrsas_fm_init(instance);
633 633
634 634 /* Setup register map */
635 635 if ((ddi_dev_regsize(instance->dip,
636 636 REGISTER_SET_IO_2108, ®length) != DDI_SUCCESS) ||
637 637 reglength < MINIMUM_MFI_MEM_SZ) {
638 638 goto fail_attach;
639 639 }
640 640 if (reglength > DEFAULT_MFI_MEM_SZ) {
641 641 reglength = DEFAULT_MFI_MEM_SZ;
642 642 con_log(CL_DLEVEL1, (CE_NOTE,
643 643 "mr_sas: register length to map is 0x%lx bytes",
644 644 reglength));
645 645 }
646 646 if (ddi_regs_map_setup(instance->dip,
647 647 REGISTER_SET_IO_2108, &instance->regmap, 0,
648 648 reglength, &endian_attr, &instance->regmap_handle)
649 649 != DDI_SUCCESS) {
650 650 cmn_err(CE_WARN,
651 651 "mr_sas: couldn't map control registers");
652 652 goto fail_attach;
653 653 }
654 654
655 655 instance->unroll.regs = 1;
656 656
657 657 /*
658 658 * Disable Interrupt Now.
659 659 * Setup Software interrupt
660 660 */
661 661 instance->func_ptr->disable_intr(instance);
662 662
663 663 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
664 664 "mrsas-enable-msi", &data) == DDI_SUCCESS) {
665 665 if (strncmp(data, "no", 3) == 0) {
666 666 msi_enable = 0;
667 667 con_log(CL_ANN1, (CE_WARN,
668 668 "msi_enable = %d disabled", msi_enable));
669 669 }
670 670 ddi_prop_free(data);
671 671 }
672 672
673 673 con_log(CL_DLEVEL1, (CE_NOTE, "msi_enable = %d", msi_enable));
674 674
675 675 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
676 676 "mrsas-enable-fp", &data) == DDI_SUCCESS) {
677 677 if (strncmp(data, "no", 3) == 0) {
678 678 enable_fp = 0;
679 679 cmn_err(CE_NOTE,
680 680 "enable_fp = %d, Fast-Path disabled.\n",
681 681 enable_fp);
682 682 }
683 683
684 684 ddi_prop_free(data);
685 685 }
686 686
687 687 con_log(CL_DLEVEL1, (CE_NOTE, "enable_fp = %d\n", enable_fp));
688 688
689 689 /* Check for all supported interrupt types */
690 690 if (ddi_intr_get_supported_types(
691 691 dip, &intr_types) != DDI_SUCCESS) {
692 692 cmn_err(CE_WARN,
693 693 "ddi_intr_get_supported_types() failed");
694 694 goto fail_attach;
695 695 }
696 696
697 697 con_log(CL_DLEVEL1, (CE_NOTE,
698 698 "ddi_intr_get_supported_types() ret: 0x%x", intr_types));
699 699
700 700 /* Initialize and Setup Interrupt handler */
701 701 if (msi_enable && (intr_types & DDI_INTR_TYPE_MSIX)) {
702 702 if (mrsas_add_intrs(instance, DDI_INTR_TYPE_MSIX) !=
703 703 DDI_SUCCESS) {
704 704 cmn_err(CE_WARN,
705 705 "MSIX interrupt query failed");
706 706 goto fail_attach;
707 707 }
708 708 instance->intr_type = DDI_INTR_TYPE_MSIX;
709 709 } else if (msi_enable && (intr_types & DDI_INTR_TYPE_MSI)) {
710 710 if (mrsas_add_intrs(instance, DDI_INTR_TYPE_MSI) !=
711 711 DDI_SUCCESS) {
712 712 cmn_err(CE_WARN,
713 713 "MSI interrupt query failed");
714 714 goto fail_attach;
715 715 }
716 716 instance->intr_type = DDI_INTR_TYPE_MSI;
717 717 } else if (intr_types & DDI_INTR_TYPE_FIXED) {
718 718 msi_enable = 0;
719 719 if (mrsas_add_intrs(instance, DDI_INTR_TYPE_FIXED) !=
720 720 DDI_SUCCESS) {
721 721 cmn_err(CE_WARN,
722 722 "FIXED interrupt query failed");
723 723 goto fail_attach;
724 724 }
725 725 instance->intr_type = DDI_INTR_TYPE_FIXED;
726 726 } else {
727 727 cmn_err(CE_WARN, "Device cannot "
728 728 "suppport either FIXED or MSI/X "
729 729 "interrupts");
730 730 goto fail_attach;
731 731 }
732 732
733 733 instance->unroll.intr = 1;
734 734
735 735 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
736 736 "mrsas-enable-ctio", &data) == DDI_SUCCESS) {
737 737 if (strncmp(data, "no", 3) == 0) {
738 738 ctio_enable = 0;
739 739 con_log(CL_ANN1, (CE_WARN,
740 740 "ctio_enable = %d disabled", ctio_enable));
741 741 }
742 742 ddi_prop_free(data);
743 743 }
744 744
745 745 con_log(CL_DLEVEL1, (CE_WARN, "ctio_enable = %d", ctio_enable));
746 746
747 747 /* setup the mfi based low level driver */
748 748 if (mrsas_init_adapter(instance) != DDI_SUCCESS) {
749 749 cmn_err(CE_WARN, "mr_sas: "
750 750 "could not initialize the low level driver");
751 751
752 752 goto fail_attach;
753 753 }
754 754
755 755 /* Initialize all Mutex */
756 756 INIT_LIST_HEAD(&instance->completed_pool_list);
757 757 mutex_init(&instance->completed_pool_mtx, NULL,
758 758 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
759 759
760 760 mutex_init(&instance->sync_map_mtx, NULL,
761 761 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
762 762
763 763 mutex_init(&instance->app_cmd_pool_mtx, NULL,
764 764 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
765 765
766 766 mutex_init(&instance->config_dev_mtx, NULL,
767 767 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
768 768
769 769 mutex_init(&instance->cmd_pend_mtx, NULL,
770 770 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
771 771
772 772 mutex_init(&instance->ocr_flags_mtx, NULL,
773 773 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
774 774
775 775 mutex_init(&instance->int_cmd_mtx, NULL,
776 776 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
777 777 cv_init(&instance->int_cmd_cv, NULL, CV_DRIVER, NULL);
778 778
779 779 mutex_init(&instance->cmd_pool_mtx, NULL,
780 780 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
781 781
782 782 mutex_init(&instance->reg_write_mtx, NULL,
783 783 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
784 784
785 785 if (instance->tbolt) {
786 786 mutex_init(&instance->cmd_app_pool_mtx, NULL,
787 787 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
788 788
789 789 mutex_init(&instance->chip_mtx, NULL,
790 790 MUTEX_DRIVER, DDI_INTR_PRI(instance->intr_pri));
791 791
792 792 }
793 793
794 794 instance->unroll.mutexs = 1;
795 795
796 796 instance->timeout_id = (timeout_id_t)-1;
797 797
798 798 /* Register our soft-isr for highlevel interrupts. */
799 799 instance->isr_level = instance->intr_pri;
800 800 if (!(instance->tbolt)) {
801 801 if (instance->isr_level == HIGH_LEVEL_INTR) {
802 802 if (ddi_add_softintr(dip,
803 803 DDI_SOFTINT_HIGH,
804 804 &instance->soft_intr_id, NULL, NULL,
805 805 mrsas_softintr, (caddr_t)instance) !=
806 806 DDI_SUCCESS) {
807 807 cmn_err(CE_WARN,
808 808 "Software ISR did not register");
809 809
810 810 goto fail_attach;
811 811 }
812 812
813 813 instance->unroll.soft_isr = 1;
814 814
815 815 }
816 816 }
817 817
818 818 instance->softint_running = 0;
819 819
820 820 /* Allocate a transport structure */
821 821 tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
822 822
823 823 if (tran == NULL) {
824 824 cmn_err(CE_WARN,
825 825 "scsi_hba_tran_alloc failed");
826 826 goto fail_attach;
827 827 }
828 828
829 829 instance->tran = tran;
830 830 instance->unroll.tran = 1;
831 831
832 832 tran->tran_hba_private = instance;
833 833 tran->tran_tgt_init = mrsas_tran_tgt_init;
834 834 tran->tran_tgt_probe = scsi_hba_probe;
835 835 tran->tran_tgt_free = mrsas_tran_tgt_free;
836 836 tran->tran_init_pkt = mrsas_tran_init_pkt;
837 837 if (instance->tbolt)
838 838 tran->tran_start = mrsas_tbolt_tran_start;
839 839 else
840 840 tran->tran_start = mrsas_tran_start;
841 841 tran->tran_abort = mrsas_tran_abort;
842 842 tran->tran_reset = mrsas_tran_reset;
843 843 tran->tran_getcap = mrsas_tran_getcap;
844 844 tran->tran_setcap = mrsas_tran_setcap;
845 845 tran->tran_destroy_pkt = mrsas_tran_destroy_pkt;
846 846 tran->tran_dmafree = mrsas_tran_dmafree;
847 847 tran->tran_sync_pkt = mrsas_tran_sync_pkt;
848 848 tran->tran_quiesce = mrsas_tran_quiesce;
849 849 tran->tran_unquiesce = mrsas_tran_unquiesce;
850 850 tran->tran_bus_config = mrsas_tran_bus_config;
851 851
852 852 if (mrsas_relaxed_ordering)
853 853 mrsas_generic_dma_attr.dma_attr_flags |=
854 854 DDI_DMA_RELAXED_ORDERING;
855 855
856 856
857 857 tran_dma_attr = mrsas_generic_dma_attr;
858 858 tran_dma_attr.dma_attr_sgllen = instance->max_num_sge;
859 859
860 860 /* Attach this instance of the hba */
861 861 if (scsi_hba_attach_setup(dip, &tran_dma_attr, tran, 0)
862 862 != DDI_SUCCESS) {
863 863 cmn_err(CE_WARN,
864 864 "scsi_hba_attach failed");
865 865
866 866 goto fail_attach;
867 867 }
868 868 instance->unroll.tranSetup = 1;
869 869 con_log(CL_ANN1,
870 870 (CE_CONT, "scsi_hba_attach_setup() done."));
871 871
872 872 /* create devctl node for cfgadm command */
873 873 if (ddi_create_minor_node(dip, "devctl",
874 874 S_IFCHR, INST2DEVCTL(instance_no),
875 875 DDI_NT_SCSI_NEXUS, 0) == DDI_FAILURE) {
876 876 cmn_err(CE_WARN,
877 877 "mr_sas: failed to create devctl node.");
878 878
879 879 goto fail_attach;
880 880 }
881 881
882 882 instance->unroll.devctl = 1;
883 883
884 884 /* create scsi node for cfgadm command */
885 885 if (ddi_create_minor_node(dip, "scsi", S_IFCHR,
886 886 INST2SCSI(instance_no), DDI_NT_SCSI_ATTACHMENT_POINT, 0) ==
887 887 DDI_FAILURE) {
888 888 cmn_err(CE_WARN,
889 889 "mr_sas: failed to create scsi node.");
890 890
891 891 goto fail_attach;
892 892 }
893 893
894 894 instance->unroll.scsictl = 1;
895 895
896 896 (void) sprintf(instance->iocnode, "%d:lsirdctl",
897 897 instance_no);
898 898
899 899 /*
900 900 * Create a node for applications
901 901 * for issuing ioctl to the driver.
902 902 */
903 903 if (ddi_create_minor_node(dip, instance->iocnode,
904 904 S_IFCHR, INST2LSIRDCTL(instance_no), DDI_PSEUDO, 0) ==
905 905 DDI_FAILURE) {
906 906 cmn_err(CE_WARN,
907 907 "mr_sas: failed to create ioctl node.");
908 908
909 909 goto fail_attach;
910 910 }
911 911
912 912 instance->unroll.ioctl = 1;
913 913
914 914 /* Create a taskq to handle dr events */
915 915 if ((instance->taskq = ddi_taskq_create(dip,
916 916 "mrsas_dr_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL) {
917 917 cmn_err(CE_WARN,
918 918 "mr_sas: failed to create taskq ");
919 919 instance->taskq = NULL;
920 920 goto fail_attach;
921 921 }
922 922 instance->unroll.taskq = 1;
923 923 con_log(CL_ANN1, (CE_CONT, "ddi_taskq_create() done."));
924 924
925 925 /* enable interrupt */
926 926 instance->func_ptr->enable_intr(instance);
927 927
928 928 /* initiate AEN */
929 929 if (start_mfi_aen(instance)) {
930 930 cmn_err(CE_WARN,
931 931 "mr_sas: failed to initiate AEN.");
932 932 goto fail_attach;
933 933 }
934 934 instance->unroll.aenPend = 1;
935 935 con_log(CL_ANN1,
936 936 (CE_CONT, "AEN started for instance %d.", instance_no));
937 937
938 938 /* Finally! We are on the air. */
939 939 ddi_report_dev(dip);
940 940
941 941 /* FMA handle checking. */
942 942 if (mrsas_check_acc_handle(instance->regmap_handle) !=
943 943 DDI_SUCCESS) {
944 944 goto fail_attach;
945 945 }
946 946 if (mrsas_check_acc_handle(instance->pci_handle) !=
947 947 DDI_SUCCESS) {
948 948 goto fail_attach;
949 949 }
950 950
951 951 instance->mr_ld_list =
952 952 kmem_zalloc(MRDRV_MAX_LD * sizeof (struct mrsas_ld),
953 953 KM_SLEEP);
954 954 instance->unroll.ldlist_buff = 1;
955 955
956 956 #ifdef PDSUPPORT
957 957 if (instance->tbolt || instance->skinny) {
958 958 instance->mr_tbolt_pd_max = MRSAS_TBOLT_PD_TGT_MAX;
959 959 instance->mr_tbolt_pd_list =
960 960 kmem_zalloc(MRSAS_TBOLT_GET_PD_MAX(instance) *
961 961 sizeof (struct mrsas_tbolt_pd), KM_SLEEP);
962 962 ASSERT(instance->mr_tbolt_pd_list);
963 963 for (i = 0; i < instance->mr_tbolt_pd_max; i++) {
964 964 instance->mr_tbolt_pd_list[i].lun_type =
965 965 MRSAS_TBOLT_PD_LUN;
966 966 instance->mr_tbolt_pd_list[i].dev_id =
967 967 (uint8_t)i;
968 968 }
969 969
970 970 instance->unroll.pdlist_buff = 1;
971 971 }
972 972 #endif
973 973 break;
974 974 case DDI_PM_RESUME:
975 975 con_log(CL_ANN, (CE_NOTE, "mr_sas: DDI_PM_RESUME"));
976 976 break;
977 977 case DDI_RESUME:
978 978 con_log(CL_ANN, (CE_NOTE, "mr_sas: DDI_RESUME"));
979 979 break;
980 980 default:
981 981 con_log(CL_ANN,
982 982 (CE_WARN, "mr_sas: invalid attach cmd=%x", cmd));
983 983 return (DDI_FAILURE);
984 984 }
985 985
986 986
987 987 con_log(CL_DLEVEL1,
988 988 (CE_NOTE, "mrsas_attach() return SUCCESS instance_num %d",
989 989 instance_no));
990 990 return (DDI_SUCCESS);
991 991
992 992 fail_attach:
993 993
994 994 mrsas_undo_resources(dip, instance);
995 995
996 996 mrsas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
997 997 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
998 998
999 999 mrsas_fm_fini(instance);
1000 1000
1001 1001 pci_config_teardown(&instance->pci_handle);
1002 1002 ddi_soft_state_free(mrsas_state, instance_no);
1003 1003
1004 1004 con_log(CL_ANN, (CE_WARN, "mr_sas: return failure from mrsas_attach"));
1005 1005
1006 1006 cmn_err(CE_WARN, "mrsas_attach() return FAILURE instance_num %d",
1007 1007 instance_no);
1008 1008
1009 1009 return (DDI_FAILURE);
1010 1010 }
1011 1011
1012 1012 /*
1013 1013 * getinfo - gets device information
1014 1014 * @dip:
1015 1015 * @cmd:
1016 1016 * @arg:
1017 1017 * @resultp:
1018 1018 *
1019 1019 * The system calls getinfo() to obtain configuration information that only
1020 1020 * the driver knows. The mapping of minor numbers to device instance is
1021 1021 * entirely under the control of the driver. The system sometimes needs to ask
1022 1022 * the driver which device a particular dev_t represents.
1023 1023 * Given the device number return the devinfo pointer from the scsi_device
1024 1024 * structure.
1025 1025 */
1026 1026 /*ARGSUSED*/
1027 1027 static int
1028 1028 mrsas_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
1029 1029 {
1030 1030 int rval;
1031 1031 int mrsas_minor = getminor((dev_t)arg);
1032 1032
1033 1033 struct mrsas_instance *instance;
1034 1034
1035 1035 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1036 1036
1037 1037 switch (cmd) {
1038 1038 case DDI_INFO_DEVT2DEVINFO:
1039 1039 instance = (struct mrsas_instance *)
1040 1040 ddi_get_soft_state(mrsas_state,
1041 1041 MINOR2INST(mrsas_minor));
1042 1042
1043 1043 if (instance == NULL) {
1044 1044 *resultp = NULL;
1045 1045 rval = DDI_FAILURE;
1046 1046 } else {
1047 1047 *resultp = instance->dip;
1048 1048 rval = DDI_SUCCESS;
1049 1049 }
1050 1050 break;
1051 1051 case DDI_INFO_DEVT2INSTANCE:
1052 1052 *resultp = (void *)(intptr_t)
1053 1053 (MINOR2INST(getminor((dev_t)arg)));
1054 1054 rval = DDI_SUCCESS;
1055 1055 break;
1056 1056 default:
1057 1057 *resultp = NULL;
1058 1058 rval = DDI_FAILURE;
1059 1059 }
1060 1060
1061 1061 return (rval);
1062 1062 }
1063 1063
1064 1064 /*
1065 1065 * detach - detaches a device from the system
1066 1066 * @dip: pointer to the device's dev_info structure
1067 1067 * @cmd: type of detach
1068 1068 *
1069 1069 * A driver's detach() entry point is called to detach an instance of a device
1070 1070 * that is bound to the driver. The entry point is called with the instance of
1071 1071 * the device node to be detached and with DDI_DETACH, which is specified as
1072 1072 * the cmd argument to the entry point.
1073 1073 * This routine is called during driver unload. We free all the allocated
1074 1074 * resources and call the corresponding LLD so that it can also release all
1075 1075 * its resources.
1076 1076 */
1077 1077 static int
1078 1078 mrsas_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1079 1079 {
1080 1080 int instance_no;
1081 1081
1082 1082 struct mrsas_instance *instance;
1083 1083
1084 1084 con_log(CL_ANN, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1085 1085
1086 1086
1087 1087 /* CONSTCOND */
1088 1088 ASSERT(NO_COMPETING_THREADS);
1089 1089
1090 1090 instance_no = ddi_get_instance(dip);
1091 1091
1092 1092 instance = (struct mrsas_instance *)ddi_get_soft_state(mrsas_state,
1093 1093 instance_no);
1094 1094
1095 1095 if (!instance) {
1096 1096 cmn_err(CE_WARN,
1097 1097 "mr_sas:%d could not get instance in detach",
1098 1098 instance_no);
1099 1099
1100 1100 return (DDI_FAILURE);
1101 1101 }
1102 1102
1103 1103 con_log(CL_ANN, (CE_NOTE,
1104 1104 "mr_sas%d: detaching device 0x%4x:0x%4x:0x%4x:0x%4x",
1105 1105 instance_no, instance->vendor_id, instance->device_id,
1106 1106 instance->subsysvid, instance->subsysid));
1107 1107
1108 1108 switch (cmd) {
1109 1109 case DDI_DETACH:
1110 1110 con_log(CL_ANN, (CE_NOTE,
1111 1111 "mrsas_detach: DDI_DETACH"));
1112 1112
1113 1113 mutex_enter(&instance->config_dev_mtx);
1114 1114 if (instance->timeout_id != (timeout_id_t)-1) {
1115 1115 mutex_exit(&instance->config_dev_mtx);
1116 1116 (void) untimeout(instance->timeout_id);
1117 1117 instance->timeout_id = (timeout_id_t)-1;
1118 1118 mutex_enter(&instance->config_dev_mtx);
1119 1119 instance->unroll.timer = 0;
1120 1120 }
1121 1121 mutex_exit(&instance->config_dev_mtx);
1122 1122
1123 1123 if (instance->unroll.tranSetup == 1) {
1124 1124 if (scsi_hba_detach(dip) != DDI_SUCCESS) {
1125 1125 cmn_err(CE_WARN,
1126 1126 "mr_sas2%d: failed to detach",
1127 1127 instance_no);
1128 1128 return (DDI_FAILURE);
1129 1129 }
1130 1130 instance->unroll.tranSetup = 0;
1131 1131 con_log(CL_ANN1,
1132 1132 (CE_CONT, "scsi_hba_dettach() done."));
1133 1133 }
1134 1134
1135 1135 flush_cache(instance);
1136 1136
1137 1137 mrsas_undo_resources(dip, instance);
1138 1138
1139 1139 mrsas_fm_fini(instance);
1140 1140
1141 1141 pci_config_teardown(&instance->pci_handle);
1142 1142 ddi_soft_state_free(mrsas_state, instance_no);
1143 1143 break;
1144 1144
1145 1145 case DDI_PM_SUSPEND:
1146 1146 con_log(CL_ANN, (CE_NOTE,
1147 1147 "mrsas_detach: DDI_PM_SUSPEND"));
1148 1148
1149 1149 break;
1150 1150 case DDI_SUSPEND:
1151 1151 con_log(CL_ANN, (CE_NOTE,
1152 1152 "mrsas_detach: DDI_SUSPEND"));
1153 1153
1154 1154 break;
1155 1155 default:
1156 1156 con_log(CL_ANN, (CE_WARN,
1157 1157 "invalid detach command:0x%x", cmd));
1158 1158 return (DDI_FAILURE);
1159 1159 }
1160 1160
1161 1161 return (DDI_SUCCESS);
1162 1162 }
1163 1163
1164 1164
1165 1165 static void
1166 1166 mrsas_undo_resources(dev_info_t *dip, struct mrsas_instance *instance)
1167 1167 {
1168 1168 int instance_no;
1169 1169
1170 1170 con_log(CL_ANN, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1171 1171
1172 1172
1173 1173 instance_no = ddi_get_instance(dip);
1174 1174
1175 1175
1176 1176 if (instance->unroll.ioctl == 1) {
1177 1177 ddi_remove_minor_node(dip, instance->iocnode);
1178 1178 instance->unroll.ioctl = 0;
1179 1179 }
1180 1180
1181 1181 if (instance->unroll.scsictl == 1) {
1182 1182 ddi_remove_minor_node(dip, "scsi");
1183 1183 instance->unroll.scsictl = 0;
1184 1184 }
1185 1185
1186 1186 if (instance->unroll.devctl == 1) {
1187 1187 ddi_remove_minor_node(dip, "devctl");
1188 1188 instance->unroll.devctl = 0;
1189 1189 }
1190 1190
1191 1191 if (instance->unroll.tranSetup == 1) {
1192 1192 if (scsi_hba_detach(dip) != DDI_SUCCESS) {
1193 1193 cmn_err(CE_WARN,
1194 1194 "mr_sas2%d: failed to detach", instance_no);
1195 1195 return; /* DDI_FAILURE */
1196 1196 }
1197 1197 instance->unroll.tranSetup = 0;
1198 1198 con_log(CL_ANN1, (CE_CONT, "scsi_hba_dettach() done."));
1199 1199 }
1200 1200
1201 1201 if (instance->unroll.tran == 1) {
1202 1202 scsi_hba_tran_free(instance->tran);
1203 1203 instance->unroll.tran = 0;
1204 1204 con_log(CL_ANN1, (CE_CONT, "scsi_hba_tran_free() done."));
1205 1205 }
1206 1206
1207 1207 if (instance->unroll.syncCmd == 1) {
1208 1208 if (instance->tbolt) {
1209 1209 if (abort_syncmap_cmd(instance,
1210 1210 instance->map_update_cmd)) {
1211 1211 cmn_err(CE_WARN, "mrsas_detach: "
1212 1212 "failed to abort previous syncmap command");
1213 1213 }
1214 1214
1215 1215 instance->unroll.syncCmd = 0;
1216 1216 con_log(CL_ANN1, (CE_CONT, "sync cmd aborted, done."));
1217 1217 }
1218 1218 }
1219 1219
1220 1220 if (instance->unroll.aenPend == 1) {
1221 1221 if (abort_aen_cmd(instance, instance->aen_cmd))
1222 1222 cmn_err(CE_WARN, "mrsas_detach: "
1223 1223 "failed to abort prevous AEN command");
1224 1224
1225 1225 instance->unroll.aenPend = 0;
1226 1226 con_log(CL_ANN1, (CE_CONT, "aen cmd aborted, done."));
1227 1227 /* This means the controller is fully initialized and running */
1228 1228 /* Shutdown should be a last command to controller. */
1229 1229 /* shutdown_controller(); */
1230 1230 }
1231 1231
1232 1232
1233 1233 if (instance->unroll.timer == 1) {
1234 1234 if (instance->timeout_id != (timeout_id_t)-1) {
1235 1235 (void) untimeout(instance->timeout_id);
1236 1236 instance->timeout_id = (timeout_id_t)-1;
1237 1237
1238 1238 instance->unroll.timer = 0;
1239 1239 }
1240 1240 }
1241 1241
1242 1242 instance->func_ptr->disable_intr(instance);
1243 1243
1244 1244
1245 1245 if (instance->unroll.mutexs == 1) {
1246 1246 mutex_destroy(&instance->cmd_pool_mtx);
1247 1247 mutex_destroy(&instance->app_cmd_pool_mtx);
1248 1248 mutex_destroy(&instance->cmd_pend_mtx);
1249 1249 mutex_destroy(&instance->completed_pool_mtx);
1250 1250 mutex_destroy(&instance->sync_map_mtx);
1251 1251 mutex_destroy(&instance->int_cmd_mtx);
1252 1252 cv_destroy(&instance->int_cmd_cv);
1253 1253 mutex_destroy(&instance->config_dev_mtx);
1254 1254 mutex_destroy(&instance->ocr_flags_mtx);
1255 1255 mutex_destroy(&instance->reg_write_mtx);
1256 1256
1257 1257 if (instance->tbolt) {
1258 1258 mutex_destroy(&instance->cmd_app_pool_mtx);
1259 1259 mutex_destroy(&instance->chip_mtx);
1260 1260 }
1261 1261
1262 1262 instance->unroll.mutexs = 0;
1263 1263 con_log(CL_ANN1, (CE_CONT, "Destroy mutex & cv, done."));
1264 1264 }
1265 1265
1266 1266
1267 1267 if (instance->unroll.soft_isr == 1) {
1268 1268 ddi_remove_softintr(instance->soft_intr_id);
1269 1269 instance->unroll.soft_isr = 0;
1270 1270 }
1271 1271
1272 1272 if (instance->unroll.intr == 1) {
1273 1273 mrsas_rem_intrs(instance);
1274 1274 instance->unroll.intr = 0;
1275 1275 }
1276 1276
1277 1277
1278 1278 if (instance->unroll.taskq == 1) {
1279 1279 if (instance->taskq) {
1280 1280 ddi_taskq_destroy(instance->taskq);
1281 1281 instance->unroll.taskq = 0;
1282 1282 }
1283 1283
1284 1284 }
1285 1285
1286 1286 /*
1287 1287 * free dma memory allocated for
1288 1288 * cmds/frames/queues/driver version etc
1289 1289 */
1290 1290 if (instance->unroll.verBuff == 1) {
1291 1291 (void) mrsas_free_dma_obj(instance, instance->drv_ver_dma_obj);
1292 1292 instance->unroll.verBuff = 0;
1293 1293 }
1294 1294
1295 1295 if (instance->unroll.pdlist_buff == 1) {
1296 1296 if (instance->mr_tbolt_pd_list != NULL) {
1297 1297 kmem_free(instance->mr_tbolt_pd_list,
1298 1298 MRSAS_TBOLT_GET_PD_MAX(instance) *
1299 1299 sizeof (struct mrsas_tbolt_pd));
1300 1300 }
1301 1301
1302 1302 instance->mr_tbolt_pd_list = NULL;
1303 1303 instance->unroll.pdlist_buff = 0;
1304 1304 }
1305 1305
1306 1306 if (instance->unroll.ldlist_buff == 1) {
1307 1307 if (instance->mr_ld_list != NULL) {
1308 1308 kmem_free(instance->mr_ld_list, MRDRV_MAX_LD
1309 1309 * sizeof (struct mrsas_ld));
1310 1310 }
1311 1311
1312 1312 instance->mr_ld_list = NULL;
1313 1313 instance->unroll.ldlist_buff = 0;
1314 1314 }
1315 1315
1316 1316 if (instance->tbolt) {
1317 1317 if (instance->unroll.alloc_space_mpi2 == 1) {
1318 1318 free_space_for_mpi2(instance);
1319 1319 instance->unroll.alloc_space_mpi2 = 0;
1320 1320 }
1321 1321 } else {
1322 1322 if (instance->unroll.alloc_space_mfi == 1) {
1323 1323 free_space_for_mfi(instance);
1324 1324 instance->unroll.alloc_space_mfi = 0;
1325 1325 }
1326 1326 }
1327 1327
1328 1328 if (instance->unroll.regs == 1) {
1329 1329 ddi_regs_map_free(&instance->regmap_handle);
1330 1330 instance->unroll.regs = 0;
1331 1331 con_log(CL_ANN1, (CE_CONT, "ddi_regs_map_free() done."));
1332 1332 }
1333 1333 }
1334 1334
1335 1335
1336 1336
1337 1337 /*
1338 1338 * ************************************************************************** *
1339 1339 * *
1340 1340 * common entry points - for character driver types *
1341 1341 * *
1342 1342 * ************************************************************************** *
1343 1343 */
1344 1344 /*
1345 1345 * open - gets access to a device
1346 1346 * @dev:
1347 1347 * @openflags:
1348 1348 * @otyp:
1349 1349 * @credp:
1350 1350 *
1351 1351 * Access to a device by one or more application programs is controlled
1352 1352 * through the open() and close() entry points. The primary function of
1353 1353 * open() is to verify that the open request is allowed.
1354 1354 */
1355 1355 static int
1356 1356 mrsas_open(dev_t *dev, int openflags, int otyp, cred_t *credp)
1357 1357 {
1358 1358 int rval = 0;
1359 1359
1360 1360 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1361 1361
1362 1362 /* Check root permissions */
1363 1363 if (drv_priv(credp) != 0) {
1364 1364 con_log(CL_ANN, (CE_WARN,
1365 1365 "mr_sas: Non-root ioctl access denied!"));
1366 1366 return (EPERM);
1367 1367 }
1368 1368
1369 1369 /* Verify we are being opened as a character device */
1370 1370 if (otyp != OTYP_CHR) {
1371 1371 con_log(CL_ANN, (CE_WARN,
1372 1372 "mr_sas: ioctl node must be a char node"));
1373 1373 return (EINVAL);
1374 1374 }
1375 1375
1376 1376 if (ddi_get_soft_state(mrsas_state, MINOR2INST(getminor(*dev)))
1377 1377 == NULL) {
1378 1378 return (ENXIO);
1379 1379 }
1380 1380
1381 1381 if (scsi_hba_open) {
1382 1382 rval = scsi_hba_open(dev, openflags, otyp, credp);
1383 1383 }
1384 1384
1385 1385 return (rval);
1386 1386 }
1387 1387
1388 1388 /*
1389 1389 * close - gives up access to a device
1390 1390 * @dev:
1391 1391 * @openflags:
1392 1392 * @otyp:
1393 1393 * @credp:
1394 1394 *
1395 1395 * close() should perform any cleanup necessary to finish using the minor
1396 1396 * device, and prepare the device (and driver) to be opened again.
1397 1397 */
1398 1398 static int
1399 1399 mrsas_close(dev_t dev, int openflags, int otyp, cred_t *credp)
1400 1400 {
1401 1401 int rval = 0;
1402 1402
1403 1403 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1404 1404
1405 1405 /* no need for locks! */
1406 1406
1407 1407 if (scsi_hba_close) {
1408 1408 rval = scsi_hba_close(dev, openflags, otyp, credp);
1409 1409 }
1410 1410
1411 1411 return (rval);
1412 1412 }
1413 1413
1414 1414 /*
1415 1415 * ioctl - performs a range of I/O commands for character drivers
1416 1416 * @dev:
1417 1417 * @cmd:
1418 1418 * @arg:
1419 1419 * @mode:
1420 1420 * @credp:
1421 1421 * @rvalp:
1422 1422 *
1423 1423 * ioctl() routine must make sure that user data is copied into or out of the
1424 1424 * kernel address space explicitly using copyin(), copyout(), ddi_copyin(),
1425 1425 * and ddi_copyout(), as appropriate.
1426 1426 * This is a wrapper routine to serialize access to the actual ioctl routine.
1427 1427 * ioctl() should return 0 on success, or the appropriate error number. The
1428 1428 * driver may also set the value returned to the calling process through rvalp.
1429 1429 */
1430 1430
1431 1431 static int
1432 1432 mrsas_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1433 1433 int *rvalp)
1434 1434 {
1435 1435 int rval = 0;
1436 1436
1437 1437 struct mrsas_instance *instance;
1438 1438 struct mrsas_ioctl *ioctl;
1439 1439 struct mrsas_aen aen;
1440 1440 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1441 1441
1442 1442 instance = ddi_get_soft_state(mrsas_state, MINOR2INST(getminor(dev)));
1443 1443
1444 1444 if (instance == NULL) {
1445 1445 /* invalid minor number */
1446 1446 con_log(CL_ANN, (CE_WARN, "mr_sas: adapter not found."));
1447 1447 return (ENXIO);
1448 1448 }
1449 1449
1450 1450 ioctl = (struct mrsas_ioctl *)kmem_zalloc(sizeof (struct mrsas_ioctl),
1451 1451 KM_SLEEP);
1452 1452 ASSERT(ioctl);
1453 1453
1454 1454 switch ((uint_t)cmd) {
1455 1455 case MRSAS_IOCTL_FIRMWARE:
1456 1456 if (ddi_copyin((void *)arg, ioctl,
1457 1457 sizeof (struct mrsas_ioctl), mode)) {
1458 1458 con_log(CL_ANN, (CE_WARN, "mrsas_ioctl: "
1459 1459 "ERROR IOCTL copyin"));
1460 1460 kmem_free(ioctl, sizeof (struct mrsas_ioctl));
1461 1461 return (EFAULT);
1462 1462 }
1463 1463
1464 1464 if (ioctl->control_code == MRSAS_DRIVER_IOCTL_COMMON) {
1465 1465 rval = handle_drv_ioctl(instance, ioctl, mode);
1466 1466 } else {
1467 1467 rval = handle_mfi_ioctl(instance, ioctl, mode);
1468 1468 }
1469 1469
1470 1470 if (ddi_copyout((void *)ioctl, (void *)arg,
1471 1471 (sizeof (struct mrsas_ioctl) - 1), mode)) {
1472 1472 con_log(CL_ANN, (CE_WARN,
1473 1473 "mrsas_ioctl: copy_to_user failed"));
1474 1474 rval = 1;
1475 1475 }
1476 1476
1477 1477 break;
1478 1478 case MRSAS_IOCTL_AEN:
1479 1479 if (ddi_copyin((void *) arg, &aen,
1480 1480 sizeof (struct mrsas_aen), mode)) {
1481 1481 con_log(CL_ANN, (CE_WARN,
1482 1482 "mrsas_ioctl: ERROR AEN copyin"));
1483 1483 kmem_free(ioctl, sizeof (struct mrsas_ioctl));
1484 1484 return (EFAULT);
1485 1485 }
1486 1486
1487 1487 rval = handle_mfi_aen(instance, &aen);
1488 1488
1489 1489 if (ddi_copyout((void *) &aen, (void *)arg,
1490 1490 sizeof (struct mrsas_aen), mode)) {
1491 1491 con_log(CL_ANN, (CE_WARN,
1492 1492 "mrsas_ioctl: copy_to_user failed"));
1493 1493 rval = 1;
1494 1494 }
1495 1495
1496 1496 break;
1497 1497 default:
1498 1498 rval = scsi_hba_ioctl(dev, cmd, arg,
1499 1499 mode, credp, rvalp);
1500 1500
1501 1501 con_log(CL_DLEVEL1, (CE_NOTE, "mrsas_ioctl: "
1502 1502 "scsi_hba_ioctl called, ret = %x.", rval));
1503 1503 }
1504 1504
1505 1505 kmem_free(ioctl, sizeof (struct mrsas_ioctl));
1506 1506 return (rval);
1507 1507 }
1508 1508
1509 1509 /*
1510 1510 * ************************************************************************** *
1511 1511 * *
1512 1512 * common entry points - for block driver types *
1513 1513 * *
1514 1514 * ************************************************************************** *
1515 1515 */
1516 1516 #ifdef __sparc
1517 1517 /*
1518 1518 * reset - TBD
1519 1519 * @dip:
1520 1520 * @cmd:
1521 1521 *
1522 1522 * TBD
1523 1523 */
1524 1524 /*ARGSUSED*/
1525 1525 static int
1526 1526 mrsas_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
1527 1527 {
1528 1528 int instance_no;
1529 1529
1530 1530 struct mrsas_instance *instance;
1531 1531
1532 1532 instance_no = ddi_get_instance(dip);
1533 1533 instance = (struct mrsas_instance *)ddi_get_soft_state
1534 1534 (mrsas_state, instance_no);
1535 1535
1536 1536 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1537 1537
1538 1538 if (!instance) {
1539 1539 con_log(CL_ANN, (CE_WARN, "mr_sas:%d could not get adapter "
1540 1540 "in reset", instance_no));
1541 1541 return (DDI_FAILURE);
1542 1542 }
1543 1543
1544 1544 instance->func_ptr->disable_intr(instance);
1545 1545
1546 1546 con_log(CL_ANN1, (CE_CONT, "flushing cache for instance %d",
1547 1547 instance_no));
1548 1548
1549 1549 flush_cache(instance);
1550 1550
1551 1551 return (DDI_SUCCESS);
1552 1552 }
1553 1553 #else /* __sparc */
1554 1554 /*ARGSUSED*/
1555 1555 static int
1556 1556 mrsas_quiesce(dev_info_t *dip)
1557 1557 {
1558 1558 int instance_no;
1559 1559
1560 1560 struct mrsas_instance *instance;
1561 1561
1562 1562 instance_no = ddi_get_instance(dip);
1563 1563 instance = (struct mrsas_instance *)ddi_get_soft_state
1564 1564 (mrsas_state, instance_no);
1565 1565
1566 1566 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1567 1567
1568 1568 if (!instance) {
1569 1569 con_log(CL_ANN1, (CE_WARN, "mr_sas:%d could not get adapter "
1570 1570 "in quiesce", instance_no));
1571 1571 return (DDI_FAILURE);
1572 1572 }
1573 1573 if (instance->deadadapter || instance->adapterresetinprogress) {
1574 1574 con_log(CL_ANN1, (CE_WARN, "mr_sas:%d adapter is not in "
1575 1575 "healthy state", instance_no));
1576 1576 return (DDI_FAILURE);
1577 1577 }
1578 1578
1579 1579 if (abort_aen_cmd(instance, instance->aen_cmd)) {
1580 1580 con_log(CL_ANN1, (CE_WARN, "mrsas_quiesce: "
1581 1581 "failed to abort prevous AEN command QUIESCE"));
1582 1582 }
1583 1583
1584 1584 if (instance->tbolt) {
1585 1585 if (abort_syncmap_cmd(instance,
1586 1586 instance->map_update_cmd)) {
1587 1587 cmn_err(CE_WARN,
1588 1588 "mrsas_detach: failed to abort "
1589 1589 "previous syncmap command");
1590 1590 return (DDI_FAILURE);
1591 1591 }
1592 1592 }
1593 1593
1594 1594 instance->func_ptr->disable_intr(instance);
1595 1595
1596 1596 con_log(CL_ANN1, (CE_CONT, "flushing cache for instance %d",
1597 1597 instance_no));
1598 1598
1599 1599 flush_cache(instance);
1600 1600
1601 1601 if (wait_for_outstanding(instance)) {
1602 1602 con_log(CL_ANN1,
1603 1603 (CE_CONT, "wait_for_outstanding: return FAIL.\n"));
1604 1604 return (DDI_FAILURE);
1605 1605 }
1606 1606 return (DDI_SUCCESS);
1607 1607 }
1608 1608 #endif /* __sparc */
1609 1609
1610 1610 /*
1611 1611 * ************************************************************************** *
1612 1612 * *
1613 1613 * entry points (SCSI HBA) *
1614 1614 * *
1615 1615 * ************************************************************************** *
1616 1616 */
1617 1617 /*
1618 1618 * tran_tgt_init - initialize a target device instance
1619 1619 * @hba_dip:
1620 1620 * @tgt_dip:
1621 1621 * @tran:
1622 1622 * @sd:
1623 1623 *
1624 1624 * The tran_tgt_init() entry point enables the HBA to allocate and initialize
1625 1625 * any per-target resources. tran_tgt_init() also enables the HBA to qualify
1626 1626 * the device's address as valid and supportable for that particular HBA.
1627 1627 * By returning DDI_FAILURE, the instance of the target driver for that device
1628 1628 * is not probed or attached.
1629 1629 */
1630 1630 /*ARGSUSED*/
1631 1631 static int
1632 1632 mrsas_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
1633 1633 scsi_hba_tran_t *tran, struct scsi_device *sd)
1634 1634 {
1635 1635 struct mrsas_instance *instance;
1636 1636 uint16_t tgt = sd->sd_address.a_target;
1637 1637 uint8_t lun = sd->sd_address.a_lun;
1638 1638 dev_info_t *child = NULL;
1639 1639
1640 1640 con_log(CL_DLEVEL2, (CE_NOTE, "mrsas_tgt_init target %d lun %d",
1641 1641 tgt, lun));
1642 1642
1643 1643 instance = ADDR2MR(&sd->sd_address);
1644 1644
1645 1645 if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
1646 1646 /*
1647 1647 * If no persistent node exists, we don't allow .conf node
1648 1648 * to be created.
1649 1649 */
1650 1650 if ((child = mrsas_find_child(instance, tgt, lun)) != NULL) {
1651 1651 con_log(CL_DLEVEL2,
1652 1652 (CE_NOTE, "mrsas_tgt_init find child ="
1653 1653 " %p t = %d l = %d", (void *)child, tgt, lun));
1654 1654 if (ndi_merge_node(tgt_dip, mrsas_name_node) !=
1655 1655 DDI_SUCCESS)
1656 1656 /* Create this .conf node */
1657 1657 return (DDI_SUCCESS);
1658 1658 }
1659 1659 con_log(CL_DLEVEL2, (CE_NOTE, "mrsas_tgt_init in ndi_per "
1660 1660 "DDI_FAILURE t = %d l = %d", tgt, lun));
1661 1661 return (DDI_FAILURE);
1662 1662
1663 1663 }
1664 1664
1665 1665 con_log(CL_DLEVEL2, (CE_NOTE, "mrsas_tgt_init dev_dip %p tgt_dip %p",
1666 1666 (void *)instance->mr_ld_list[tgt].dip, (void *)tgt_dip));
1667 1667
1668 1668 if (tgt < MRDRV_MAX_LD && lun == 0) {
1669 1669 if (instance->mr_ld_list[tgt].dip == NULL &&
1670 1670 strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0) {
1671 1671 mutex_enter(&instance->config_dev_mtx);
1672 1672 instance->mr_ld_list[tgt].dip = tgt_dip;
1673 1673 instance->mr_ld_list[tgt].lun_type = MRSAS_LD_LUN;
1674 1674 instance->mr_ld_list[tgt].flag = MRDRV_TGT_VALID;
1675 1675 mutex_exit(&instance->config_dev_mtx);
1676 1676 }
1677 1677 }
1678 1678
1679 1679 #ifdef PDSUPPORT
1680 1680 else if (instance->tbolt || instance->skinny) {
1681 1681 if (instance->mr_tbolt_pd_list[tgt].dip == NULL) {
1682 1682 mutex_enter(&instance->config_dev_mtx);
1683 1683 instance->mr_tbolt_pd_list[tgt].dip = tgt_dip;
1684 1684 instance->mr_tbolt_pd_list[tgt].flag =
1685 1685 MRDRV_TGT_VALID;
1686 1686 mutex_exit(&instance->config_dev_mtx);
1687 1687 con_log(CL_ANN1, (CE_NOTE, "mrsas_tran_tgt_init:"
1688 1688 "t%xl%x", tgt, lun));
1689 1689 }
1690 1690 }
1691 1691 #endif
1692 1692
1693 1693 return (DDI_SUCCESS);
1694 1694 }
1695 1695
1696 1696 /*ARGSUSED*/
1697 1697 static void
1698 1698 mrsas_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
1699 1699 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
1700 1700 {
1701 1701 struct mrsas_instance *instance;
1702 1702 int tgt = sd->sd_address.a_target;
1703 1703 int lun = sd->sd_address.a_lun;
1704 1704
1705 1705 instance = ADDR2MR(&sd->sd_address);
1706 1706
1707 1707 con_log(CL_DLEVEL2, (CE_NOTE, "tgt_free t = %d l = %d", tgt, lun));
1708 1708
1709 1709 if (tgt < MRDRV_MAX_LD && lun == 0) {
1710 1710 if (instance->mr_ld_list[tgt].dip == tgt_dip) {
1711 1711 mutex_enter(&instance->config_dev_mtx);
1712 1712 instance->mr_ld_list[tgt].dip = NULL;
1713 1713 mutex_exit(&instance->config_dev_mtx);
1714 1714 }
1715 1715 }
1716 1716
1717 1717 #ifdef PDSUPPORT
1718 1718 else if (instance->tbolt || instance->skinny) {
1719 1719 mutex_enter(&instance->config_dev_mtx);
1720 1720 instance->mr_tbolt_pd_list[tgt].dip = NULL;
1721 1721 mutex_exit(&instance->config_dev_mtx);
1722 1722 con_log(CL_ANN1, (CE_NOTE, "tgt_free: Setting dip = NULL"
1723 1723 "for tgt:%x", tgt));
1724 1724 }
1725 1725 #endif
1726 1726
1727 1727 }
1728 1728
1729 1729 dev_info_t *
1730 1730 mrsas_find_child(struct mrsas_instance *instance, uint16_t tgt, uint8_t lun)
1731 1731 {
1732 1732 dev_info_t *child = NULL;
1733 1733 char addr[SCSI_MAXNAMELEN];
1734 1734 char tmp[MAXNAMELEN];
1735 1735
1736 1736 (void) sprintf(addr, "%x,%x", tgt, lun);
1737 1737 for (child = ddi_get_child(instance->dip); child;
1738 1738 child = ddi_get_next_sibling(child)) {
1739 1739
1740 1740 if (ndi_dev_is_persistent_node(child) == 0) {
1741 1741 continue;
1742 1742 }
1743 1743
1744 1744 if (mrsas_name_node(child, tmp, MAXNAMELEN) !=
1745 1745 DDI_SUCCESS) {
1746 1746 continue;
1747 1747 }
1748 1748
1749 1749 if (strcmp(addr, tmp) == 0) {
1750 1750 break;
1751 1751 }
1752 1752 }
1753 1753 con_log(CL_DLEVEL2, (CE_NOTE, "mrsas_find_child: return child = %p",
1754 1754 (void *)child));
1755 1755 return (child);
1756 1756 }
1757 1757
1758 1758 /*
1759 1759 * mrsas_name_node -
1760 1760 * @dip:
1761 1761 * @name:
1762 1762 * @len:
1763 1763 */
1764 1764 static int
1765 1765 mrsas_name_node(dev_info_t *dip, char *name, int len)
1766 1766 {
1767 1767 int tgt, lun;
1768 1768
1769 1769 tgt = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1770 1770 DDI_PROP_DONTPASS, "target", -1);
1771 1771 con_log(CL_DLEVEL2, (CE_NOTE,
1772 1772 "mrsas_name_node: dip %p tgt %d", (void *)dip, tgt));
1773 1773 if (tgt == -1) {
1774 1774 return (DDI_FAILURE);
1775 1775 }
1776 1776 lun = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1777 1777 "lun", -1);
1778 1778 con_log(CL_DLEVEL2,
1779 1779 (CE_NOTE, "mrsas_name_node: tgt %d lun %d", tgt, lun));
1780 1780 if (lun == -1) {
1781 1781 return (DDI_FAILURE);
1782 1782 }
1783 1783 (void) snprintf(name, len, "%x,%x", tgt, lun);
1784 1784 return (DDI_SUCCESS);
1785 1785 }
1786 1786
1787 1787 /*
1788 1788 * tran_init_pkt - allocate & initialize a scsi_pkt structure
1789 1789 * @ap:
1790 1790 * @pkt:
1791 1791 * @bp:
1792 1792 * @cmdlen:
1793 1793 * @statuslen:
1794 1794 * @tgtlen:
1795 1795 * @flags:
1796 1796 * @callback:
1797 1797 *
1798 1798 * The tran_init_pkt() entry point allocates and initializes a scsi_pkt
1799 1799 * structure and DMA resources for a target driver request. The
1800 1800 * tran_init_pkt() entry point is called when the target driver calls the
1801 1801 * SCSA function scsi_init_pkt(). Each call of the tran_init_pkt() entry point
1802 1802 * is a request to perform one or more of three possible services:
1803 1803 * - allocation and initialization of a scsi_pkt structure
1804 1804 * - allocation of DMA resources for data transfer
1805 1805 * - reallocation of DMA resources for the next portion of the data transfer
1806 1806 */
1807 1807 static struct scsi_pkt *
1808 1808 mrsas_tran_init_pkt(struct scsi_address *ap, register struct scsi_pkt *pkt,
1809 1809 struct buf *bp, int cmdlen, int statuslen, int tgtlen,
1810 1810 int flags, int (*callback)(), caddr_t arg)
1811 1811 {
1812 1812 struct scsa_cmd *acmd;
1813 1813 struct mrsas_instance *instance;
1814 1814 struct scsi_pkt *new_pkt;
1815 1815
1816 1816 con_log(CL_DLEVEL1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1817 1817
1818 1818 instance = ADDR2MR(ap);
1819 1819
1820 1820 /* step #1 : pkt allocation */
1821 1821 if (pkt == NULL) {
1822 1822 pkt = scsi_hba_pkt_alloc(instance->dip, ap, cmdlen, statuslen,
1823 1823 tgtlen, sizeof (struct scsa_cmd), callback, arg);
1824 1824 if (pkt == NULL) {
1825 1825 return (NULL);
1826 1826 }
1827 1827
1828 1828 acmd = PKT2CMD(pkt);
1829 1829
1830 1830 /*
1831 1831 * Initialize the new pkt - we redundantly initialize
1832 1832 * all the fields for illustrative purposes.
1833 1833 */
1834 1834 acmd->cmd_pkt = pkt;
1835 1835 acmd->cmd_flags = 0;
1836 1836 acmd->cmd_scblen = statuslen;
1837 1837 acmd->cmd_cdblen = cmdlen;
1838 1838 acmd->cmd_dmahandle = NULL;
1839 1839 acmd->cmd_ncookies = 0;
1840 1840 acmd->cmd_cookie = 0;
1841 1841 acmd->cmd_cookiecnt = 0;
1842 1842 acmd->cmd_nwin = 0;
1843 1843
1844 1844 pkt->pkt_address = *ap;
1845 1845 pkt->pkt_comp = (void (*)())NULL;
1846 1846 pkt->pkt_flags = 0;
1847 1847 pkt->pkt_time = 0;
1848 1848 pkt->pkt_resid = 0;
1849 1849 pkt->pkt_state = 0;
1850 1850 pkt->pkt_statistics = 0;
1851 1851 pkt->pkt_reason = 0;
1852 1852 new_pkt = pkt;
1853 1853 } else {
1854 1854 acmd = PKT2CMD(pkt);
1855 1855 new_pkt = NULL;
1856 1856 }
1857 1857
1858 1858 /* step #2 : dma allocation/move */
1859 1859 if (bp && bp->b_bcount != 0) {
1860 1860 if (acmd->cmd_dmahandle == NULL) {
1861 1861 if (mrsas_dma_alloc(instance, pkt, bp, flags,
1862 1862 callback) == DDI_FAILURE) {
1863 1863 if (new_pkt) {
1864 1864 scsi_hba_pkt_free(ap, new_pkt);
1865 1865 }
1866 1866 return ((struct scsi_pkt *)NULL);
1867 1867 }
1868 1868 } else {
1869 1869 if (mrsas_dma_move(instance, pkt, bp) == DDI_FAILURE) {
1870 1870 return ((struct scsi_pkt *)NULL);
1871 1871 }
1872 1872 }
1873 1873 }
1874 1874
1875 1875 return (pkt);
1876 1876 }
1877 1877
1878 1878 /*
1879 1879 * tran_start - transport a SCSI command to the addressed target
1880 1880 * @ap:
1881 1881 * @pkt:
1882 1882 *
1883 1883 * The tran_start() entry point for a SCSI HBA driver is called to transport a
1884 1884 * SCSI command to the addressed target. The SCSI command is described
1885 1885 * entirely within the scsi_pkt structure, which the target driver allocated
1886 1886 * through the HBA driver's tran_init_pkt() entry point. If the command
1887 1887 * involves a data transfer, DMA resources must also have been allocated for
1888 1888 * the scsi_pkt structure.
1889 1889 *
1890 1890 * Return Values :
1891 1891 * TRAN_BUSY - request queue is full, no more free scbs
1892 1892 * TRAN_ACCEPT - pkt has been submitted to the instance
1893 1893 */
1894 1894 static int
1895 1895 mrsas_tran_start(struct scsi_address *ap, register struct scsi_pkt *pkt)
1896 1896 {
1897 1897 uchar_t cmd_done = 0;
1898 1898
1899 1899 struct mrsas_instance *instance = ADDR2MR(ap);
1900 1900 struct mrsas_cmd *cmd;
1901 1901
1902 1902 con_log(CL_DLEVEL1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
1903 1903 if (instance->deadadapter == 1) {
1904 1904 con_log(CL_ANN1, (CE_WARN,
1905 1905 "mrsas_tran_start: return TRAN_FATAL_ERROR "
1906 1906 "for IO, as the HBA doesnt take any more IOs"));
1907 1907 if (pkt) {
1908 1908 pkt->pkt_reason = CMD_DEV_GONE;
1909 1909 pkt->pkt_statistics = STAT_DISCON;
1910 1910 }
1911 1911 return (TRAN_FATAL_ERROR);
1912 1912 }
1913 1913
1914 1914 if (instance->adapterresetinprogress) {
1915 1915 con_log(CL_ANN1, (CE_NOTE, "mrsas_tran_start: Reset flag set, "
1916 1916 "returning mfi_pkt and setting TRAN_BUSY\n"));
1917 1917 return (TRAN_BUSY);
1918 1918 }
1919 1919
1920 1920 con_log(CL_ANN1, (CE_CONT, "chkpnt:%s:%d:SCSI CDB[0]=0x%x time:%x",
1921 1921 __func__, __LINE__, pkt->pkt_cdbp[0], pkt->pkt_time));
1922 1922
1923 1923 pkt->pkt_reason = CMD_CMPLT;
1924 1924 *pkt->pkt_scbp = STATUS_GOOD; /* clear arq scsi_status */
1925 1925
1926 1926 cmd = build_cmd(instance, ap, pkt, &cmd_done);
1927 1927
1928 1928 /*
1929 1929 * Check if the command is already completed by the mrsas_build_cmd()
1930 1930 * routine. In which case the busy_flag would be clear and scb will be
1931 1931 * NULL and appropriate reason provided in pkt_reason field
1932 1932 */
1933 1933 if (cmd_done) {
1934 1934 pkt->pkt_reason = CMD_CMPLT;
1935 1935 pkt->pkt_scbp[0] = STATUS_GOOD;
1936 1936 pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET
1937 1937 | STATE_SENT_CMD;
1938 1938 if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && pkt->pkt_comp) {
1939 1939 (*pkt->pkt_comp)(pkt);
1940 1940 }
1941 1941
1942 1942 return (TRAN_ACCEPT);
1943 1943 }
1944 1944
1945 1945 if (cmd == NULL) {
1946 1946 return (TRAN_BUSY);
1947 1947 }
1948 1948
1949 1949 if ((pkt->pkt_flags & FLAG_NOINTR) == 0) {
1950 1950 if (instance->fw_outstanding > instance->max_fw_cmds) {
1951 1951 con_log(CL_ANN, (CE_CONT, "mr_sas:Firmware busy"));
1952 1952 DTRACE_PROBE2(start_tran_err,
1953 1953 uint16_t, instance->fw_outstanding,
1954 1954 uint16_t, instance->max_fw_cmds);
1955 1955 mrsas_return_mfi_pkt(instance, cmd);
1956 1956 return (TRAN_BUSY);
1957 1957 }
1958 1958
1959 1959 /* Synchronize the Cmd frame for the controller */
1960 1960 (void) ddi_dma_sync(cmd->frame_dma_obj.dma_handle, 0, 0,
1961 1961 DDI_DMA_SYNC_FORDEV);
1962 1962 con_log(CL_ANN, (CE_CONT, "issue_cmd_ppc: SCSI CDB[0]=0x%x"
1963 1963 "cmd->index:%x\n", pkt->pkt_cdbp[0], cmd->index));
1964 1964 instance->func_ptr->issue_cmd(cmd, instance);
1965 1965
1966 1966 } else {
1967 1967 struct mrsas_header *hdr = &cmd->frame->hdr;
1968 1968
1969 1969 instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd);
1970 1970
1971 1971 pkt->pkt_reason = CMD_CMPLT;
1972 1972 pkt->pkt_statistics = 0;
1973 1973 pkt->pkt_state |= STATE_XFERRED_DATA | STATE_GOT_STATUS;
1974 1974
1975 1975 switch (ddi_get8(cmd->frame_dma_obj.acc_handle,
1976 1976 &hdr->cmd_status)) {
1977 1977 case MFI_STAT_OK:
1978 1978 pkt->pkt_scbp[0] = STATUS_GOOD;
1979 1979 break;
1980 1980
1981 1981 case MFI_STAT_SCSI_DONE_WITH_ERROR:
1982 1982 con_log(CL_ANN, (CE_CONT,
1983 1983 "mrsas_tran_start: scsi done with error"));
1984 1984 pkt->pkt_reason = CMD_CMPLT;
1985 1985 pkt->pkt_statistics = 0;
1986 1986
1987 1987 ((struct scsi_status *)pkt->pkt_scbp)->sts_chk = 1;
1988 1988 break;
1989 1989
1990 1990 case MFI_STAT_DEVICE_NOT_FOUND:
1991 1991 con_log(CL_ANN, (CE_CONT,
1992 1992 "mrsas_tran_start: device not found error"));
1993 1993 pkt->pkt_reason = CMD_DEV_GONE;
1994 1994 pkt->pkt_statistics = STAT_DISCON;
1995 1995 break;
1996 1996
1997 1997 default:
1998 1998 ((struct scsi_status *)pkt->pkt_scbp)->sts_busy = 1;
1999 1999 }
2000 2000
2001 2001 (void) mrsas_common_check(instance, cmd);
2002 2002 DTRACE_PROBE2(start_nointr_done, uint8_t, hdr->cmd,
2003 2003 uint8_t, hdr->cmd_status);
2004 2004 mrsas_return_mfi_pkt(instance, cmd);
2005 2005
2006 2006 if (pkt->pkt_comp) {
2007 2007 (*pkt->pkt_comp)(pkt);
2008 2008 }
2009 2009
2010 2010 }
2011 2011
2012 2012 return (TRAN_ACCEPT);
2013 2013 }
2014 2014
2015 2015 /*
2016 2016 * tran_abort - Abort any commands that are currently in transport
2017 2017 * @ap:
2018 2018 * @pkt:
2019 2019 *
2020 2020 * The tran_abort() entry point for a SCSI HBA driver is called to abort any
2021 2021 * commands that are currently in transport for a particular target. This entry
2022 2022 * point is called when a target driver calls scsi_abort(). The tran_abort()
2023 2023 * entry point should attempt to abort the command denoted by the pkt
2024 2024 * parameter. If the pkt parameter is NULL, tran_abort() should attempt to
2025 2025 * abort all outstanding commands in the transport layer for the particular
2026 2026 * target or logical unit.
2027 2027 */
2028 2028 /*ARGSUSED*/
2029 2029 static int
2030 2030 mrsas_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
2031 2031 {
2032 2032 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2033 2033
2034 2034 /* abort command not supported by H/W */
2035 2035
2036 2036 return (DDI_FAILURE);
2037 2037 }
2038 2038
2039 2039 /*
2040 2040 * tran_reset - reset either the SCSI bus or target
2041 2041 * @ap:
2042 2042 * @level:
2043 2043 *
2044 2044 * The tran_reset() entry point for a SCSI HBA driver is called to reset either
2045 2045 * the SCSI bus or a particular SCSI target device. This entry point is called
2046 2046 * when a target driver calls scsi_reset(). The tran_reset() entry point must
2047 2047 * reset the SCSI bus if level is RESET_ALL. If level is RESET_TARGET, just the
2048 2048 * particular target or logical unit must be reset.
2049 2049 */
2050 2050 /*ARGSUSED*/
2051 2051 static int
2052 2052 mrsas_tran_reset(struct scsi_address *ap, int level)
2053 2053 {
2054 2054 struct mrsas_instance *instance = ADDR2MR(ap);
2055 2055
2056 2056 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2057 2057
2058 2058 if (wait_for_outstanding(instance)) {
2059 2059 con_log(CL_ANN1,
2060 2060 (CE_CONT, "wait_for_outstanding: return FAIL.\n"));
2061 2061 return (DDI_FAILURE);
2062 2062 } else {
2063 2063 return (DDI_SUCCESS);
2064 2064 }
2065 2065 }
2066 2066
2067 2067 /*
2068 2068 * tran_getcap - get one of a set of SCSA-defined capabilities
2069 2069 * @ap:
2070 2070 * @cap:
2071 2071 * @whom:
2072 2072 *
2073 2073 * The target driver can request the current setting of the capability for a
2074 2074 * particular target by setting the whom parameter to nonzero. A whom value of
2075 2075 * zero indicates a request for the current setting of the general capability
2076 2076 * for the SCSI bus or for adapter hardware. The tran_getcap() should return -1
2077 2077 * for undefined capabilities or the current value of the requested capability.
2078 2078 */
2079 2079 /*ARGSUSED*/
2080 2080 static int
2081 2081 mrsas_tran_getcap(struct scsi_address *ap, char *cap, int whom)
2082 2082 {
2083 2083 int rval = 0;
2084 2084
2085 2085 struct mrsas_instance *instance = ADDR2MR(ap);
2086 2086
2087 2087 con_log(CL_DLEVEL2, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2088 2088
2089 2089 /* we do allow inquiring about capabilities for other targets */
2090 2090 if (cap == NULL) {
2091 2091 return (-1);
2092 2092 }
2093 2093
2094 2094 switch (scsi_hba_lookup_capstr(cap)) {
2095 2095 case SCSI_CAP_DMA_MAX:
2096 2096 if (instance->tbolt) {
2097 2097 /* Limit to 256k max transfer */
2098 2098 rval = mrsas_tbolt_max_cap_maxxfer;
2099 2099 } else {
2100 2100 /* Limit to 16MB max transfer */
2101 2101 rval = mrsas_max_cap_maxxfer;
2102 2102 }
2103 2103 break;
2104 2104 case SCSI_CAP_MSG_OUT:
2105 2105 rval = 1;
2106 2106 break;
2107 2107 case SCSI_CAP_DISCONNECT:
2108 2108 rval = 0;
2109 2109 break;
2110 2110 case SCSI_CAP_SYNCHRONOUS:
2111 2111 rval = 0;
2112 2112 break;
2113 2113 case SCSI_CAP_WIDE_XFER:
2114 2114 rval = 1;
2115 2115 break;
2116 2116 case SCSI_CAP_TAGGED_QING:
2117 2117 rval = 1;
2118 2118 break;
2119 2119 case SCSI_CAP_UNTAGGED_QING:
2120 2120 rval = 1;
2121 2121 break;
2122 2122 case SCSI_CAP_PARITY:
2123 2123 rval = 1;
2124 2124 break;
2125 2125 case SCSI_CAP_INITIATOR_ID:
2126 2126 rval = instance->init_id;
2127 2127 break;
2128 2128 case SCSI_CAP_ARQ:
2129 2129 rval = 1;
2130 2130 break;
2131 2131 case SCSI_CAP_LINKED_CMDS:
2132 2132 rval = 0;
2133 2133 break;
2134 2134 case SCSI_CAP_RESET_NOTIFICATION:
2135 2135 rval = 1;
2136 2136 break;
2137 2137 case SCSI_CAP_GEOMETRY:
2138 2138 rval = -1;
2139 2139
2140 2140 break;
2141 2141 default:
2142 2142 con_log(CL_DLEVEL2, (CE_NOTE, "Default cap coming 0x%x",
2143 2143 scsi_hba_lookup_capstr(cap)));
2144 2144 rval = -1;
2145 2145 break;
2146 2146 }
2147 2147
2148 2148 return (rval);
2149 2149 }
2150 2150
2151 2151 /*
2152 2152 * tran_setcap - set one of a set of SCSA-defined capabilities
2153 2153 * @ap:
2154 2154 * @cap:
2155 2155 * @value:
2156 2156 * @whom:
2157 2157 *
2158 2158 * The target driver might request that the new value be set for a particular
2159 2159 * target by setting the whom parameter to nonzero. A whom value of zero
2160 2160 * means that request is to set the new value for the SCSI bus or for adapter
2161 2161 * hardware in general.
2162 2162 * The tran_setcap() should return the following values as appropriate:
2163 2163 * - -1 for undefined capabilities
2164 2164 * - 0 if the HBA driver cannot set the capability to the requested value
2165 2165 * - 1 if the HBA driver is able to set the capability to the requested value
2166 2166 */
2167 2167 /*ARGSUSED*/
2168 2168 static int
2169 2169 mrsas_tran_setcap(struct scsi_address *ap, char *cap, int value, int whom)
2170 2170 {
2171 2171 int rval = 1;
2172 2172
2173 2173 con_log(CL_DLEVEL2, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2174 2174
2175 2175 /* We don't allow setting capabilities for other targets */
2176 2176 if (cap == NULL || whom == 0) {
2177 2177 return (-1);
2178 2178 }
2179 2179
2180 2180 switch (scsi_hba_lookup_capstr(cap)) {
2181 2181 case SCSI_CAP_DMA_MAX:
2182 2182 case SCSI_CAP_MSG_OUT:
2183 2183 case SCSI_CAP_PARITY:
2184 2184 case SCSI_CAP_LINKED_CMDS:
2185 2185 case SCSI_CAP_RESET_NOTIFICATION:
2186 2186 case SCSI_CAP_DISCONNECT:
2187 2187 case SCSI_CAP_SYNCHRONOUS:
2188 2188 case SCSI_CAP_UNTAGGED_QING:
2189 2189 case SCSI_CAP_WIDE_XFER:
2190 2190 case SCSI_CAP_INITIATOR_ID:
2191 2191 case SCSI_CAP_ARQ:
2192 2192 /*
2193 2193 * None of these are settable via
2194 2194 * the capability interface.
2195 2195 */
2196 2196 break;
2197 2197 case SCSI_CAP_TAGGED_QING:
2198 2198 rval = 1;
2199 2199 break;
2200 2200 case SCSI_CAP_SECTOR_SIZE:
2201 2201 rval = 1;
2202 2202 break;
2203 2203
2204 2204 case SCSI_CAP_TOTAL_SECTORS:
2205 2205 rval = 1;
2206 2206 break;
2207 2207 default:
2208 2208 rval = -1;
2209 2209 break;
2210 2210 }
2211 2211
2212 2212 return (rval);
2213 2213 }
2214 2214
2215 2215 /*
2216 2216 * tran_destroy_pkt - deallocate scsi_pkt structure
2217 2217 * @ap:
2218 2218 * @pkt:
2219 2219 *
2220 2220 * The tran_destroy_pkt() entry point is the HBA driver function that
2221 2221 * deallocates scsi_pkt structures. The tran_destroy_pkt() entry point is
2222 2222 * called when the target driver calls scsi_destroy_pkt(). The
2223 2223 * tran_destroy_pkt() entry point must free any DMA resources that have been
2224 2224 * allocated for the packet. An implicit DMA synchronization occurs if the
2225 2225 * DMA resources are freed and any cached data remains after the completion
2226 2226 * of the transfer.
2227 2227 */
2228 2228 static void
2229 2229 mrsas_tran_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
2230 2230 {
2231 2231 struct scsa_cmd *acmd = PKT2CMD(pkt);
2232 2232
2233 2233 con_log(CL_DLEVEL2, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2234 2234
2235 2235 if (acmd->cmd_flags & CFLAG_DMAVALID) {
2236 2236 acmd->cmd_flags &= ~CFLAG_DMAVALID;
2237 2237
2238 2238 (void) ddi_dma_unbind_handle(acmd->cmd_dmahandle);
2239 2239
2240 2240 ddi_dma_free_handle(&acmd->cmd_dmahandle);
2241 2241
2242 2242 acmd->cmd_dmahandle = NULL;
2243 2243 }
2244 2244
2245 2245 /* free the pkt */
2246 2246 scsi_hba_pkt_free(ap, pkt);
2247 2247 }
2248 2248
2249 2249 /*
2250 2250 * tran_dmafree - deallocates DMA resources
2251 2251 * @ap:
2252 2252 * @pkt:
2253 2253 *
2254 2254 * The tran_dmafree() entry point deallocates DMAQ resources that have been
2255 2255 * allocated for a scsi_pkt structure. The tran_dmafree() entry point is
2256 2256 * called when the target driver calls scsi_dmafree(). The tran_dmafree() must
2257 2257 * free only DMA resources allocated for a scsi_pkt structure, not the
2258 2258 * scsi_pkt itself. When DMA resources are freed, a DMA synchronization is
2259 2259 * implicitly performed.
2260 2260 */
2261 2261 /*ARGSUSED*/
2262 2262 static void
2263 2263 mrsas_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
2264 2264 {
2265 2265 register struct scsa_cmd *acmd = PKT2CMD(pkt);
2266 2266
2267 2267 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2268 2268
2269 2269 if (acmd->cmd_flags & CFLAG_DMAVALID) {
2270 2270 acmd->cmd_flags &= ~CFLAG_DMAVALID;
2271 2271
2272 2272 (void) ddi_dma_unbind_handle(acmd->cmd_dmahandle);
2273 2273
2274 2274 ddi_dma_free_handle(&acmd->cmd_dmahandle);
2275 2275
2276 2276 acmd->cmd_dmahandle = NULL;
2277 2277 }
2278 2278 }
2279 2279
2280 2280 /*
2281 2281 * tran_sync_pkt - synchronize the DMA object allocated
2282 2282 * @ap:
2283 2283 * @pkt:
2284 2284 *
2285 2285 * The tran_sync_pkt() entry point synchronizes the DMA object allocated for
2286 2286 * the scsi_pkt structure before or after a DMA transfer. The tran_sync_pkt()
2287 2287 * entry point is called when the target driver calls scsi_sync_pkt(). If the
2288 2288 * data transfer direction is a DMA read from device to memory, tran_sync_pkt()
2289 2289 * must synchronize the CPU's view of the data. If the data transfer direction
2290 2290 * is a DMA write from memory to device, tran_sync_pkt() must synchronize the
2291 2291 * device's view of the data.
2292 2292 */
2293 2293 /*ARGSUSED*/
2294 2294 static void
2295 2295 mrsas_tran_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
2296 2296 {
2297 2297 register struct scsa_cmd *acmd = PKT2CMD(pkt);
2298 2298
2299 2299 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2300 2300
2301 2301 if (acmd->cmd_flags & CFLAG_DMAVALID) {
2302 2302 (void) ddi_dma_sync(acmd->cmd_dmahandle, acmd->cmd_dma_offset,
2303 2303 acmd->cmd_dma_len, (acmd->cmd_flags & CFLAG_DMASEND) ?
2304 2304 DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
2305 2305 }
2306 2306 }
2307 2307
2308 2308 /*ARGSUSED*/
2309 2309 static int
2310 2310 mrsas_tran_quiesce(dev_info_t *dip)
2311 2311 {
2312 2312 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2313 2313
2314 2314 return (1);
2315 2315 }
2316 2316
2317 2317 /*ARGSUSED*/
2318 2318 static int
2319 2319 mrsas_tran_unquiesce(dev_info_t *dip)
2320 2320 {
2321 2321 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2322 2322
2323 2323 return (1);
2324 2324 }
2325 2325
2326 2326
2327 2327 /*
2328 2328 * mrsas_isr(caddr_t)
2329 2329 *
2330 2330 * The Interrupt Service Routine
2331 2331 *
2332 2332 * Collect status for all completed commands and do callback
2333 2333 *
2334 2334 */
2335 2335 static uint_t
2336 2336 mrsas_isr(struct mrsas_instance *instance)
2337 2337 {
2338 2338 int need_softintr;
2339 2339 uint32_t producer;
2340 2340 uint32_t consumer;
2341 2341 uint32_t context;
2342 2342 int retval;
2343 2343
2344 2344 struct mrsas_cmd *cmd;
2345 2345 struct mrsas_header *hdr;
2346 2346 struct scsi_pkt *pkt;
2347 2347
2348 2348 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2349 2349 ASSERT(instance);
2350 2350 if (instance->tbolt) {
2351 2351 mutex_enter(&instance->chip_mtx);
2352 2352 if ((instance->intr_type == DDI_INTR_TYPE_FIXED) &&
2353 2353 !(instance->func_ptr->intr_ack(instance))) {
2354 2354 mutex_exit(&instance->chip_mtx);
2355 2355 return (DDI_INTR_UNCLAIMED);
2356 2356 }
2357 2357 retval = mr_sas_tbolt_process_outstanding_cmd(instance);
2358 2358 mutex_exit(&instance->chip_mtx);
2359 2359 return (retval);
2360 2360 } else {
2361 2361 if ((instance->intr_type == DDI_INTR_TYPE_FIXED) &&
2362 2362 !instance->func_ptr->intr_ack(instance)) {
2363 2363 return (DDI_INTR_UNCLAIMED);
2364 2364 }
2365 2365 }
2366 2366
2367 2367 (void) ddi_dma_sync(instance->mfi_internal_dma_obj.dma_handle,
2368 2368 0, 0, DDI_DMA_SYNC_FORCPU);
2369 2369
2370 2370 if (mrsas_check_dma_handle(instance->mfi_internal_dma_obj.dma_handle)
2371 2371 != DDI_SUCCESS) {
2372 2372 mrsas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
2373 2373 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
2374 2374 con_log(CL_ANN1, (CE_WARN,
2375 2375 "mr_sas_isr(): FMA check, returning DDI_INTR_UNCLAIMED"));
2376 2376 return (DDI_INTR_CLAIMED);
2377 2377 }
2378 2378 con_log(CL_ANN1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
2379 2379
2380 2380 #ifdef OCRDEBUG
2381 2381 if (debug_consecutive_timeout_after_ocr_g == 1) {
2382 2382 con_log(CL_ANN1, (CE_NOTE,
2383 2383 "simulating consecutive timeout after ocr"));
2384 2384 return (DDI_INTR_CLAIMED);
2385 2385 }
2386 2386 #endif
2387 2387
2388 2388 mutex_enter(&instance->completed_pool_mtx);
2389 2389 mutex_enter(&instance->cmd_pend_mtx);
2390 2390
2391 2391 producer = ddi_get32(instance->mfi_internal_dma_obj.acc_handle,
2392 2392 instance->producer);
2393 2393 consumer = ddi_get32(instance->mfi_internal_dma_obj.acc_handle,
2394 2394 instance->consumer);
2395 2395
2396 2396 con_log(CL_ANN, (CE_CONT, " producer %x consumer %x ",
2397 2397 producer, consumer));
2398 2398 if (producer == consumer) {
2399 2399 con_log(CL_ANN, (CE_WARN, "producer == consumer case"));
2400 2400 DTRACE_PROBE2(isr_pc_err, uint32_t, producer,
2401 2401 uint32_t, consumer);
2402 2402 mutex_exit(&instance->cmd_pend_mtx);
2403 2403 mutex_exit(&instance->completed_pool_mtx);
2404 2404 return (DDI_INTR_CLAIMED);
2405 2405 }
2406 2406
2407 2407 while (consumer != producer) {
2408 2408 context = ddi_get32(instance->mfi_internal_dma_obj.acc_handle,
2409 2409 &instance->reply_queue[consumer]);
2410 2410 cmd = instance->cmd_list[context];
2411 2411
2412 2412 if (cmd->sync_cmd == MRSAS_TRUE) {
2413 2413 hdr = (struct mrsas_header *)&cmd->frame->hdr;
2414 2414 if (hdr) {
2415 2415 mlist_del_init(&cmd->list);
2416 2416 }
2417 2417 } else {
2418 2418 pkt = cmd->pkt;
2419 2419 if (pkt) {
2420 2420 mlist_del_init(&cmd->list);
2421 2421 }
2422 2422 }
2423 2423
2424 2424 mlist_add_tail(&cmd->list, &instance->completed_pool_list);
2425 2425
2426 2426 consumer++;
2427 2427 if (consumer == (instance->max_fw_cmds + 1)) {
2428 2428 consumer = 0;
2429 2429 }
2430 2430 }
2431 2431 ddi_put32(instance->mfi_internal_dma_obj.acc_handle,
2432 2432 instance->consumer, consumer);
2433 2433 mutex_exit(&instance->cmd_pend_mtx);
2434 2434 mutex_exit(&instance->completed_pool_mtx);
2435 2435
2436 2436 (void) ddi_dma_sync(instance->mfi_internal_dma_obj.dma_handle,
2437 2437 0, 0, DDI_DMA_SYNC_FORDEV);
2438 2438
2439 2439 if (instance->softint_running) {
2440 2440 need_softintr = 0;
2441 2441 } else {
2442 2442 need_softintr = 1;
2443 2443 }
2444 2444
2445 2445 if (instance->isr_level == HIGH_LEVEL_INTR) {
2446 2446 if (need_softintr) {
2447 2447 ddi_trigger_softintr(instance->soft_intr_id);
2448 2448 }
2449 2449 } else {
2450 2450 /*
2451 2451 * Not a high-level interrupt, therefore call the soft level
2452 2452 * interrupt explicitly
2453 2453 */
2454 2454 (void) mrsas_softintr(instance);
2455 2455 }
2456 2456
2457 2457 return (DDI_INTR_CLAIMED);
2458 2458 }
2459 2459
2460 2460
2461 2461 /*
2462 2462 * ************************************************************************** *
2463 2463 * *
2464 2464 * libraries *
2465 2465 * *
2466 2466 * ************************************************************************** *
2467 2467 */
2468 2468 /*
2469 2469 * get_mfi_pkt : Get a command from the free pool
2470 2470 * After successful allocation, the caller of this routine
2471 2471 * must clear the frame buffer (memset to zero) before
2472 2472 * using the packet further.
2473 2473 *
2474 2474 * ***** Note *****
2475 2475 * After clearing the frame buffer the context id of the
2476 2476 * frame buffer SHOULD be restored back.
2477 2477 */
2478 2478 struct mrsas_cmd *
2479 2479 mrsas_get_mfi_pkt(struct mrsas_instance *instance)
2480 2480 {
2481 2481 mlist_t *head = &instance->cmd_pool_list;
2482 2482 struct mrsas_cmd *cmd = NULL;
2483 2483
2484 2484 mutex_enter(&instance->cmd_pool_mtx);
2485 2485
2486 2486 if (!mlist_empty(head)) {
2487 2487 cmd = mlist_entry(head->next, struct mrsas_cmd, list);
2488 2488 mlist_del_init(head->next);
2489 2489 }
2490 2490 if (cmd != NULL) {
2491 2491 cmd->pkt = NULL;
2492 2492 cmd->retry_count_for_ocr = 0;
2493 2493 cmd->drv_pkt_time = 0;
2494 2494
2495 2495 }
2496 2496 mutex_exit(&instance->cmd_pool_mtx);
2497 2497
2498 2498 return (cmd);
2499 2499 }
2500 2500
2501 2501 static struct mrsas_cmd *
2502 2502 get_mfi_app_pkt(struct mrsas_instance *instance)
2503 2503 {
2504 2504 mlist_t *head = &instance->app_cmd_pool_list;
2505 2505 struct mrsas_cmd *cmd = NULL;
2506 2506
2507 2507 mutex_enter(&instance->app_cmd_pool_mtx);
2508 2508
2509 2509 if (!mlist_empty(head)) {
2510 2510 cmd = mlist_entry(head->next, struct mrsas_cmd, list);
2511 2511 mlist_del_init(head->next);
2512 2512 }
2513 2513 if (cmd != NULL) {
2514 2514 cmd->pkt = NULL;
2515 2515 cmd->retry_count_for_ocr = 0;
2516 2516 cmd->drv_pkt_time = 0;
2517 2517 }
2518 2518
2519 2519 mutex_exit(&instance->app_cmd_pool_mtx);
2520 2520
2521 2521 return (cmd);
2522 2522 }
2523 2523 /*
2524 2524 * return_mfi_pkt : Return a cmd to free command pool
2525 2525 */
2526 2526 void
2527 2527 mrsas_return_mfi_pkt(struct mrsas_instance *instance, struct mrsas_cmd *cmd)
2528 2528 {
2529 2529 mutex_enter(&instance->cmd_pool_mtx);
2530 2530 /* use mlist_add_tail for debug assistance */
2531 2531 mlist_add_tail(&cmd->list, &instance->cmd_pool_list);
2532 2532
2533 2533 mutex_exit(&instance->cmd_pool_mtx);
2534 2534 }
2535 2535
2536 2536 static void
2537 2537 return_mfi_app_pkt(struct mrsas_instance *instance, struct mrsas_cmd *cmd)
2538 2538 {
2539 2539 mutex_enter(&instance->app_cmd_pool_mtx);
2540 2540
2541 2541 mlist_add(&cmd->list, &instance->app_cmd_pool_list);
2542 2542
2543 2543 mutex_exit(&instance->app_cmd_pool_mtx);
2544 2544 }
2545 2545 void
2546 2546 push_pending_mfi_pkt(struct mrsas_instance *instance, struct mrsas_cmd *cmd)
2547 2547 {
2548 2548 struct scsi_pkt *pkt;
2549 2549 struct mrsas_header *hdr;
2550 2550 con_log(CL_DLEVEL2, (CE_NOTE, "push_pending_pkt(): Called\n"));
2551 2551 mutex_enter(&instance->cmd_pend_mtx);
2552 2552 mlist_del_init(&cmd->list);
2553 2553 mlist_add_tail(&cmd->list, &instance->cmd_pend_list);
2554 2554 if (cmd->sync_cmd == MRSAS_TRUE) {
2555 2555 hdr = (struct mrsas_header *)&cmd->frame->hdr;
2556 2556 if (hdr) {
2557 2557 con_log(CL_ANN1, (CE_CONT,
2558 2558 "push_pending_mfi_pkt: "
2559 2559 "cmd %p index %x "
2560 2560 "time %llx",
2561 2561 (void *)cmd, cmd->index,
2562 2562 gethrtime()));
2563 2563 /* Wait for specified interval */
2564 2564 cmd->drv_pkt_time = ddi_get16(
2565 2565 cmd->frame_dma_obj.acc_handle, &hdr->timeout);
2566 2566 if (cmd->drv_pkt_time < debug_timeout_g)
2567 2567 cmd->drv_pkt_time = (uint16_t)debug_timeout_g;
2568 2568 con_log(CL_ANN1, (CE_CONT,
2569 2569 "push_pending_pkt(): "
2570 2570 "Called IO Timeout Value %x\n",
2571 2571 cmd->drv_pkt_time));
2572 2572 }
2573 2573 if (hdr && instance->timeout_id == (timeout_id_t)-1) {
2574 2574 instance->timeout_id = timeout(io_timeout_checker,
2575 2575 (void *) instance, drv_usectohz(MRSAS_1_SECOND));
2576 2576 }
2577 2577 } else {
2578 2578 pkt = cmd->pkt;
2579 2579 if (pkt) {
2580 2580 con_log(CL_ANN1, (CE_CONT,
2581 2581 "push_pending_mfi_pkt: "
2582 2582 "cmd %p index %x pkt %p, "
2583 2583 "time %llx",
2584 2584 (void *)cmd, cmd->index, (void *)pkt,
2585 2585 gethrtime()));
2586 2586 cmd->drv_pkt_time = (uint16_t)debug_timeout_g;
2587 2587 }
2588 2588 if (pkt && instance->timeout_id == (timeout_id_t)-1) {
2589 2589 instance->timeout_id = timeout(io_timeout_checker,
2590 2590 (void *) instance, drv_usectohz(MRSAS_1_SECOND));
2591 2591 }
2592 2592 }
2593 2593
2594 2594 mutex_exit(&instance->cmd_pend_mtx);
2595 2595
2596 2596 }
2597 2597
2598 2598 int
2599 2599 mrsas_print_pending_cmds(struct mrsas_instance *instance)
2600 2600 {
2601 2601 mlist_t *head = &instance->cmd_pend_list;
2602 2602 mlist_t *tmp = head;
2603 2603 struct mrsas_cmd *cmd = NULL;
2604 2604 struct mrsas_header *hdr;
2605 2605 unsigned int flag = 1;
2606 2606 struct scsi_pkt *pkt;
2607 2607 int saved_level;
2608 2608 int cmd_count = 0;
2609 2609
2610 2610 saved_level = debug_level_g;
2611 2611 debug_level_g = CL_ANN1;
2612 2612
2613 2613 cmn_err(CE_NOTE, "mrsas_print_pending_cmds(): Called\n");
2614 2614
2615 2615 while (flag) {
2616 2616 mutex_enter(&instance->cmd_pend_mtx);
2617 2617 tmp = tmp->next;
2618 2618 if (tmp == head) {
2619 2619 mutex_exit(&instance->cmd_pend_mtx);
2620 2620 flag = 0;
2621 2621 con_log(CL_ANN1, (CE_CONT, "mrsas_print_pending_cmds():"
2622 2622 " NO MORE CMDS PENDING....\n"));
2623 2623 break;
2624 2624 } else {
2625 2625 cmd = mlist_entry(tmp, struct mrsas_cmd, list);
2626 2626 mutex_exit(&instance->cmd_pend_mtx);
2627 2627 if (cmd) {
2628 2628 if (cmd->sync_cmd == MRSAS_TRUE) {
2629 2629 hdr = (struct mrsas_header *)
2630 2630 &cmd->frame->hdr;
2631 2631 if (hdr) {
2632 2632 con_log(CL_ANN1, (CE_CONT,
2633 2633 "print: cmd %p index 0x%x "
2634 2634 "drv_pkt_time 0x%x (NO-PKT)"
2635 2635 " hdr %p\n", (void *)cmd,
2636 2636 cmd->index,
2637 2637 cmd->drv_pkt_time,
2638 2638 (void *)hdr));
2639 2639 }
2640 2640 } else {
2641 2641 pkt = cmd->pkt;
2642 2642 if (pkt) {
2643 2643 con_log(CL_ANN1, (CE_CONT,
2644 2644 "print: cmd %p index 0x%x "
2645 2645 "drv_pkt_time 0x%x pkt %p \n",
2646 2646 (void *)cmd, cmd->index,
2647 2647 cmd->drv_pkt_time, (void *)pkt));
2648 2648 }
2649 2649 }
2650 2650
2651 2651 if (++cmd_count == 1) {
2652 2652 mrsas_print_cmd_details(instance, cmd,
2653 2653 0xDD);
2654 2654 } else {
2655 2655 mrsas_print_cmd_details(instance, cmd,
2656 2656 1);
2657 2657 }
2658 2658
2659 2659 }
2660 2660 }
2661 2661 }
2662 2662 con_log(CL_ANN1, (CE_CONT, "mrsas_print_pending_cmds(): Done\n"));
2663 2663
2664 2664
2665 2665 debug_level_g = saved_level;
2666 2666
2667 2667 return (DDI_SUCCESS);
2668 2668 }
2669 2669
2670 2670
2671 2671 int
2672 2672 mrsas_complete_pending_cmds(struct mrsas_instance *instance)
2673 2673 {
2674 2674
2675 2675 struct mrsas_cmd *cmd = NULL;
2676 2676 struct scsi_pkt *pkt;
2677 2677 struct mrsas_header *hdr;
2678 2678
2679 2679 struct mlist_head *pos, *next;
2680 2680
2681 2681 con_log(CL_ANN1, (CE_NOTE,
2682 2682 "mrsas_complete_pending_cmds(): Called"));
2683 2683
2684 2684 mutex_enter(&instance->cmd_pend_mtx);
2685 2685 mlist_for_each_safe(pos, next, &instance->cmd_pend_list) {
2686 2686 cmd = mlist_entry(pos, struct mrsas_cmd, list);
2687 2687 if (cmd) {
2688 2688 pkt = cmd->pkt;
2689 2689 if (pkt) { /* for IO */
2690 2690 if (((pkt->pkt_flags & FLAG_NOINTR)
2691 2691 == 0) && pkt->pkt_comp) {
2692 2692 pkt->pkt_reason
2693 2693 = CMD_DEV_GONE;
2694 2694 pkt->pkt_statistics
2695 2695 = STAT_DISCON;
2696 2696 con_log(CL_ANN1, (CE_CONT,
2697 2697 "fail and posting to scsa "
2698 2698 "cmd %p index %x"
2699 2699 " pkt %p "
2700 2700 "time : %llx",
2701 2701 (void *)cmd, cmd->index,
2702 2702 (void *)pkt, gethrtime()));
2703 2703 (*pkt->pkt_comp)(pkt);
2704 2704 }
2705 2705 } else { /* for DCMDS */
2706 2706 if (cmd->sync_cmd == MRSAS_TRUE) {
2707 2707 hdr = (struct mrsas_header *)&cmd->frame->hdr;
2708 2708 con_log(CL_ANN1, (CE_CONT,
2709 2709 "posting invalid status to application "
2710 2710 "cmd %p index %x"
2711 2711 " hdr %p "
2712 2712 "time : %llx",
2713 2713 (void *)cmd, cmd->index,
2714 2714 (void *)hdr, gethrtime()));
2715 2715 hdr->cmd_status = MFI_STAT_INVALID_STATUS;
2716 2716 complete_cmd_in_sync_mode(instance, cmd);
2717 2717 }
2718 2718 }
2719 2719 mlist_del_init(&cmd->list);
2720 2720 } else {
2721 2721 con_log(CL_ANN1, (CE_CONT,
2722 2722 "mrsas_complete_pending_cmds:"
2723 2723 "NULL command\n"));
2724 2724 }
2725 2725 con_log(CL_ANN1, (CE_CONT,
2726 2726 "mrsas_complete_pending_cmds:"
2727 2727 "looping for more commands\n"));
2728 2728 }
2729 2729 mutex_exit(&instance->cmd_pend_mtx);
2730 2730
2731 2731 con_log(CL_ANN1, (CE_CONT, "mrsas_complete_pending_cmds(): DONE\n"));
2732 2732 return (DDI_SUCCESS);
2733 2733 }
2734 2734
2735 2735 void
2736 2736 mrsas_print_cmd_details(struct mrsas_instance *instance, struct mrsas_cmd *cmd,
2737 2737 int detail)
2738 2738 {
2739 2739 struct scsi_pkt *pkt = cmd->pkt;
2740 2740 Mpi2RaidSCSIIORequest_t *scsi_io = cmd->scsi_io_request;
2741 2741 int i;
2742 2742 int saved_level;
2743 2743 ddi_acc_handle_t acc_handle =
2744 2744 instance->mpi2_frame_pool_dma_obj.acc_handle;
2745 2745
2746 2746 if (detail == 0xDD) {
2747 2747 saved_level = debug_level_g;
2748 2748 debug_level_g = CL_ANN1;
2749 2749 }
2750 2750
2751 2751
2752 2752 if (instance->tbolt) {
2753 2753 con_log(CL_ANN1, (CE_CONT, "print_cmd_details: cmd %p "
2754 2754 "cmd->index 0x%x SMID 0x%x timer 0x%x sec\n",
2755 2755 (void *)cmd, cmd->index, cmd->SMID, cmd->drv_pkt_time));
2756 2756 } else {
2757 2757 con_log(CL_ANN1, (CE_CONT, "print_cmd_details: cmd %p "
2758 2758 "cmd->index 0x%x timer 0x%x sec\n",
2759 2759 (void *)cmd, cmd->index, cmd->drv_pkt_time));
2760 2760 }
2761 2761
2762 2762 if (pkt) {
2763 2763 con_log(CL_ANN1, (CE_CONT, "scsi_pkt CDB[0]=0x%x",
2764 2764 pkt->pkt_cdbp[0]));
2765 2765 } else {
2766 2766 con_log(CL_ANN1, (CE_CONT, "NO-PKT"));
2767 2767 }
2768 2768
2769 2769 if ((detail == 0xDD) && instance->tbolt) {
2770 2770 con_log(CL_ANN1, (CE_CONT, "RAID_SCSI_IO_REQUEST\n"));
2771 2771 con_log(CL_ANN1, (CE_CONT, "DevHandle=0x%X Function=0x%X "
2772 2772 "IoFlags=0x%X SGLFlags=0x%X DataLength=0x%X\n",
2773 2773 ddi_get16(acc_handle, &scsi_io->DevHandle),
2774 2774 ddi_get8(acc_handle, &scsi_io->Function),
2775 2775 ddi_get16(acc_handle, &scsi_io->IoFlags),
2776 2776 ddi_get16(acc_handle, &scsi_io->SGLFlags),
2777 2777 ddi_get32(acc_handle, &scsi_io->DataLength)));
2778 2778
2779 2779 for (i = 0; i < 32; i++) {
2780 2780 con_log(CL_ANN1, (CE_CONT, "CDB[%d]=0x%x ", i,
2781 2781 ddi_get8(acc_handle, &scsi_io->CDB.CDB32[i])));
2782 2782 }
2783 2783
2784 2784 con_log(CL_ANN1, (CE_CONT, "RAID-CONTEXT\n"));
2785 2785 con_log(CL_ANN1, (CE_CONT, "status=0x%X extStatus=0x%X "
2786 2786 "ldTargetId=0x%X timeoutValue=0x%X regLockFlags=0x%X "
2787 2787 "RAIDFlags=0x%X regLockRowLBA=0x%" PRIu64
2788 2788 " regLockLength=0x%X spanArm=0x%X\n",
2789 2789 ddi_get8(acc_handle, &scsi_io->RaidContext.status),
2790 2790 ddi_get8(acc_handle, &scsi_io->RaidContext.extStatus),
2791 2791 ddi_get16(acc_handle, &scsi_io->RaidContext.ldTargetId),
2792 2792 ddi_get16(acc_handle, &scsi_io->RaidContext.timeoutValue),
2793 2793 ddi_get8(acc_handle, &scsi_io->RaidContext.regLockFlags),
2794 2794 ddi_get8(acc_handle, &scsi_io->RaidContext.RAIDFlags),
2795 2795 ddi_get64(acc_handle, &scsi_io->RaidContext.regLockRowLBA),
2796 2796 ddi_get32(acc_handle, &scsi_io->RaidContext.regLockLength),
2797 2797 ddi_get8(acc_handle, &scsi_io->RaidContext.spanArm)));
2798 2798 }
2799 2799
2800 2800 if (detail == 0xDD) {
2801 2801 debug_level_g = saved_level;
2802 2802 }
2803 2803 }
2804 2804
2805 2805
2806 2806 int
2807 2807 mrsas_issue_pending_cmds(struct mrsas_instance *instance)
2808 2808 {
2809 2809 mlist_t *head = &instance->cmd_pend_list;
2810 2810 mlist_t *tmp = head->next;
2811 2811 struct mrsas_cmd *cmd = NULL;
2812 2812 struct scsi_pkt *pkt;
2813 2813
2814 2814 con_log(CL_ANN1, (CE_NOTE, "mrsas_issue_pending_cmds(): Called"));
2815 2815 while (tmp != head) {
2816 2816 mutex_enter(&instance->cmd_pend_mtx);
2817 2817 cmd = mlist_entry(tmp, struct mrsas_cmd, list);
2818 2818 tmp = tmp->next;
2819 2819 mutex_exit(&instance->cmd_pend_mtx);
2820 2820 if (cmd) {
2821 2821 con_log(CL_ANN1, (CE_CONT,
2822 2822 "mrsas_issue_pending_cmds(): "
2823 2823 "Got a cmd: cmd %p index 0x%x drv_pkt_time 0x%x ",
2824 2824 (void *)cmd, cmd->index, cmd->drv_pkt_time));
2825 2825
2826 2826 /* Reset command timeout value */
2827 2827 if (cmd->drv_pkt_time < debug_timeout_g)
2828 2828 cmd->drv_pkt_time = (uint16_t)debug_timeout_g;
2829 2829
2830 2830 cmd->retry_count_for_ocr++;
2831 2831
2832 2832 cmn_err(CE_CONT, "cmd retry count = %d\n",
2833 2833 cmd->retry_count_for_ocr);
2834 2834
2835 2835 if (cmd->retry_count_for_ocr > IO_RETRY_COUNT) {
2836 2836 cmn_err(CE_WARN, "mrsas_issue_pending_cmds(): "
2837 2837 "cmd->retry_count exceeded limit >%d\n",
2838 2838 IO_RETRY_COUNT);
2839 2839 mrsas_print_cmd_details(instance, cmd, 0xDD);
2840 2840
2841 2841 cmn_err(CE_WARN,
2842 2842 "mrsas_issue_pending_cmds():"
2843 2843 "Calling KILL Adapter\n");
2844 2844 if (instance->tbolt)
2845 2845 mrsas_tbolt_kill_adapter(instance);
2846 2846 else
2847 2847 (void) mrsas_kill_adapter(instance);
2848 2848 return (DDI_FAILURE);
2849 2849 }
2850 2850
2851 2851 pkt = cmd->pkt;
2852 2852 if (pkt) {
2853 2853 con_log(CL_ANN1, (CE_CONT,
2854 2854 "PENDING PKT-CMD ISSUE: cmd %p index %x "
2855 2855 "pkt %p time %llx",
2856 2856 (void *)cmd, cmd->index,
2857 2857 (void *)pkt,
2858 2858 gethrtime()));
2859 2859
2860 2860 } else {
2861 2861 cmn_err(CE_CONT,
2862 2862 "mrsas_issue_pending_cmds(): NO-PKT, "
2863 2863 "cmd %p index 0x%x drv_pkt_time 0x%x ",
2864 2864 (void *)cmd, cmd->index, cmd->drv_pkt_time);
2865 2865 }
2866 2866
2867 2867
2868 2868 if (cmd->sync_cmd == MRSAS_TRUE) {
2869 2869 cmn_err(CE_CONT, "mrsas_issue_pending_cmds(): "
2870 2870 "SYNC_CMD == TRUE \n");
2871 2871 instance->func_ptr->issue_cmd_in_sync_mode(
2872 2872 instance, cmd);
2873 2873 } else {
2874 2874 instance->func_ptr->issue_cmd(cmd, instance);
2875 2875 }
2876 2876 } else {
2877 2877 con_log(CL_ANN1, (CE_CONT,
2878 2878 "mrsas_issue_pending_cmds: NULL command\n"));
2879 2879 }
2880 2880 con_log(CL_ANN1, (CE_CONT,
2881 2881 "mrsas_issue_pending_cmds:"
2882 2882 "looping for more commands"));
2883 2883 }
2884 2884 con_log(CL_ANN1, (CE_CONT, "mrsas_issue_pending_cmds(): DONE\n"));
2885 2885 return (DDI_SUCCESS);
2886 2886 }
2887 2887
2888 2888
2889 2889
2890 2890 /*
2891 2891 * destroy_mfi_frame_pool
2892 2892 */
2893 2893 void
2894 2894 destroy_mfi_frame_pool(struct mrsas_instance *instance)
2895 2895 {
2896 2896 int i;
2897 2897 uint32_t max_cmd = instance->max_fw_cmds;
2898 2898
2899 2899 struct mrsas_cmd *cmd;
2900 2900
2901 2901 /* return all frames to pool */
2902 2902
2903 2903 for (i = 0; i < max_cmd; i++) {
2904 2904
2905 2905 cmd = instance->cmd_list[i];
2906 2906
2907 2907 if (cmd->frame_dma_obj_status == DMA_OBJ_ALLOCATED)
2908 2908 (void) mrsas_free_dma_obj(instance, cmd->frame_dma_obj);
2909 2909
2910 2910 cmd->frame_dma_obj_status = DMA_OBJ_FREED;
2911 2911 }
2912 2912
2913 2913 }
2914 2914
2915 2915 /*
2916 2916 * create_mfi_frame_pool
2917 2917 */
2918 2918 int
2919 2919 create_mfi_frame_pool(struct mrsas_instance *instance)
2920 2920 {
2921 2921 int i = 0;
2922 2922 int cookie_cnt;
2923 2923 uint16_t max_cmd;
2924 2924 uint16_t sge_sz;
2925 2925 uint32_t sgl_sz;
2926 2926 uint32_t tot_frame_size;
2927 2927 struct mrsas_cmd *cmd;
2928 2928 int retval = DDI_SUCCESS;
2929 2929
2930 2930 max_cmd = instance->max_fw_cmds;
2931 2931 sge_sz = sizeof (struct mrsas_sge_ieee);
2932 2932 /* calculated the number of 64byte frames required for SGL */
2933 2933 sgl_sz = sge_sz * instance->max_num_sge;
2934 2934 tot_frame_size = sgl_sz + MRMFI_FRAME_SIZE + SENSE_LENGTH;
2935 2935
2936 2936 con_log(CL_DLEVEL3, (CE_NOTE, "create_mfi_frame_pool: "
2937 2937 "sgl_sz %x tot_frame_size %x", sgl_sz, tot_frame_size));
2938 2938
2939 2939 while (i < max_cmd) {
2940 2940 cmd = instance->cmd_list[i];
2941 2941
2942 2942 cmd->frame_dma_obj.size = tot_frame_size;
2943 2943 cmd->frame_dma_obj.dma_attr = mrsas_generic_dma_attr;
2944 2944 cmd->frame_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
2945 2945 cmd->frame_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
2946 2946 cmd->frame_dma_obj.dma_attr.dma_attr_sgllen = 1;
2947 2947 cmd->frame_dma_obj.dma_attr.dma_attr_align = 64;
2948 2948
2949 2949 cookie_cnt = mrsas_alloc_dma_obj(instance, &cmd->frame_dma_obj,
2950 2950 (uchar_t)DDI_STRUCTURE_LE_ACC);
2951 2951
2952 2952 if (cookie_cnt == -1 || cookie_cnt > 1) {
2953 2953 cmn_err(CE_WARN,
2954 2954 "create_mfi_frame_pool: could not alloc.");
2955 2955 retval = DDI_FAILURE;
2956 2956 goto mrsas_undo_frame_pool;
2957 2957 }
2958 2958
2959 2959 bzero(cmd->frame_dma_obj.buffer, tot_frame_size);
2960 2960
2961 2961 cmd->frame_dma_obj_status = DMA_OBJ_ALLOCATED;
2962 2962 cmd->frame = (union mrsas_frame *)cmd->frame_dma_obj.buffer;
2963 2963 cmd->frame_phys_addr =
2964 2964 cmd->frame_dma_obj.dma_cookie[0].dmac_address;
2965 2965
2966 2966 cmd->sense = (uint8_t *)(((unsigned long)
2967 2967 cmd->frame_dma_obj.buffer) +
2968 2968 tot_frame_size - SENSE_LENGTH);
2969 2969 cmd->sense_phys_addr =
2970 2970 cmd->frame_dma_obj.dma_cookie[0].dmac_address +
2971 2971 tot_frame_size - SENSE_LENGTH;
2972 2972
2973 2973 if (!cmd->frame || !cmd->sense) {
2974 2974 cmn_err(CE_WARN,
2975 2975 "mr_sas: pci_pool_alloc failed");
2976 2976 retval = ENOMEM;
2977 2977 goto mrsas_undo_frame_pool;
2978 2978 }
2979 2979
2980 2980 ddi_put32(cmd->frame_dma_obj.acc_handle,
2981 2981 &cmd->frame->io.context, cmd->index);
2982 2982 i++;
2983 2983
2984 2984 con_log(CL_DLEVEL3, (CE_NOTE, "[%x]-%x",
2985 2985 cmd->index, cmd->frame_phys_addr));
2986 2986 }
2987 2987
2988 2988 return (DDI_SUCCESS);
2989 2989
2990 2990 mrsas_undo_frame_pool:
2991 2991 if (i > 0)
2992 2992 destroy_mfi_frame_pool(instance);
2993 2993
2994 2994 return (retval);
2995 2995 }
2996 2996
2997 2997 /*
2998 2998 * free_additional_dma_buffer
2999 2999 */
3000 3000 static void
3001 3001 free_additional_dma_buffer(struct mrsas_instance *instance)
3002 3002 {
3003 3003 if (instance->mfi_internal_dma_obj.status == DMA_OBJ_ALLOCATED) {
3004 3004 (void) mrsas_free_dma_obj(instance,
3005 3005 instance->mfi_internal_dma_obj);
3006 3006 instance->mfi_internal_dma_obj.status = DMA_OBJ_FREED;
3007 3007 }
3008 3008
3009 3009 if (instance->mfi_evt_detail_obj.status == DMA_OBJ_ALLOCATED) {
3010 3010 (void) mrsas_free_dma_obj(instance,
3011 3011 instance->mfi_evt_detail_obj);
3012 3012 instance->mfi_evt_detail_obj.status = DMA_OBJ_FREED;
3013 3013 }
3014 3014 }
3015 3015
3016 3016 /*
3017 3017 * alloc_additional_dma_buffer
3018 3018 */
3019 3019 static int
3020 3020 alloc_additional_dma_buffer(struct mrsas_instance *instance)
3021 3021 {
3022 3022 uint32_t reply_q_sz;
3023 3023 uint32_t internal_buf_size = PAGESIZE*2;
3024 3024
3025 3025 /* max cmds plus 1 + producer & consumer */
3026 3026 reply_q_sz = sizeof (uint32_t) * (instance->max_fw_cmds + 1 + 2);
3027 3027
3028 3028 instance->mfi_internal_dma_obj.size = internal_buf_size;
3029 3029 instance->mfi_internal_dma_obj.dma_attr = mrsas_generic_dma_attr;
3030 3030 instance->mfi_internal_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3031 3031 instance->mfi_internal_dma_obj.dma_attr.dma_attr_count_max =
3032 3032 0xFFFFFFFFU;
3033 3033 instance->mfi_internal_dma_obj.dma_attr.dma_attr_sgllen = 1;
3034 3034
3035 3035 if (mrsas_alloc_dma_obj(instance, &instance->mfi_internal_dma_obj,
3036 3036 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
3037 3037 cmn_err(CE_WARN,
3038 3038 "mr_sas: could not alloc reply queue");
3039 3039 return (DDI_FAILURE);
3040 3040 }
3041 3041
3042 3042 bzero(instance->mfi_internal_dma_obj.buffer, internal_buf_size);
3043 3043
3044 3044 instance->mfi_internal_dma_obj.status |= DMA_OBJ_ALLOCATED;
3045 3045
3046 3046 instance->producer = (uint32_t *)((unsigned long)
3047 3047 instance->mfi_internal_dma_obj.buffer);
3048 3048 instance->consumer = (uint32_t *)((unsigned long)
3049 3049 instance->mfi_internal_dma_obj.buffer + 4);
3050 3050 instance->reply_queue = (uint32_t *)((unsigned long)
3051 3051 instance->mfi_internal_dma_obj.buffer + 8);
3052 3052 instance->internal_buf = (caddr_t)(((unsigned long)
3053 3053 instance->mfi_internal_dma_obj.buffer) + reply_q_sz + 8);
3054 3054 instance->internal_buf_dmac_add =
3055 3055 instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address +
3056 3056 (reply_q_sz + 8);
3057 3057 instance->internal_buf_size = internal_buf_size -
3058 3058 (reply_q_sz + 8);
3059 3059
3060 3060 /* allocate evt_detail */
3061 3061 instance->mfi_evt_detail_obj.size = sizeof (struct mrsas_evt_detail);
3062 3062 instance->mfi_evt_detail_obj.dma_attr = mrsas_generic_dma_attr;
3063 3063 instance->mfi_evt_detail_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3064 3064 instance->mfi_evt_detail_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
3065 3065 instance->mfi_evt_detail_obj.dma_attr.dma_attr_sgllen = 1;
3066 3066 instance->mfi_evt_detail_obj.dma_attr.dma_attr_align = 1;
3067 3067
3068 3068 if (mrsas_alloc_dma_obj(instance, &instance->mfi_evt_detail_obj,
3069 3069 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
3070 3070 cmn_err(CE_WARN, "alloc_additional_dma_buffer: "
3071 3071 "could not allocate data transfer buffer.");
3072 3072 goto mrsas_undo_internal_buff;
3073 3073 }
3074 3074
3075 3075 bzero(instance->mfi_evt_detail_obj.buffer,
3076 3076 sizeof (struct mrsas_evt_detail));
3077 3077
3078 3078 instance->mfi_evt_detail_obj.status |= DMA_OBJ_ALLOCATED;
3079 3079
3080 3080 return (DDI_SUCCESS);
3081 3081
3082 3082 mrsas_undo_internal_buff:
3083 3083 if (instance->mfi_internal_dma_obj.status == DMA_OBJ_ALLOCATED) {
3084 3084 (void) mrsas_free_dma_obj(instance,
3085 3085 instance->mfi_internal_dma_obj);
3086 3086 instance->mfi_internal_dma_obj.status = DMA_OBJ_FREED;
3087 3087 }
3088 3088
3089 3089 return (DDI_FAILURE);
3090 3090 }
3091 3091
3092 3092
3093 3093 void
3094 3094 mrsas_free_cmd_pool(struct mrsas_instance *instance)
3095 3095 {
3096 3096 int i;
3097 3097 uint32_t max_cmd;
3098 3098 size_t sz;
3099 3099
3100 3100 /* already freed */
3101 3101 if (instance->cmd_list == NULL) {
3102 3102 return;
3103 3103 }
3104 3104
3105 3105 max_cmd = instance->max_fw_cmds;
3106 3106
3107 3107 /* size of cmd_list array */
3108 3108 sz = sizeof (struct mrsas_cmd *) * max_cmd;
3109 3109
3110 3110 /* First free each cmd */
3111 3111 for (i = 0; i < max_cmd; i++) {
3112 3112 if (instance->cmd_list[i] != NULL) {
3113 3113 kmem_free(instance->cmd_list[i],
3114 3114 sizeof (struct mrsas_cmd));
3115 3115 }
3116 3116
3117 3117 instance->cmd_list[i] = NULL;
3118 3118 }
3119 3119
3120 3120 /* Now, free cmd_list array */
3121 3121 if (instance->cmd_list != NULL)
3122 3122 kmem_free(instance->cmd_list, sz);
3123 3123
3124 3124 instance->cmd_list = NULL;
3125 3125
3126 3126 INIT_LIST_HEAD(&instance->cmd_pool_list);
3127 3127 INIT_LIST_HEAD(&instance->cmd_pend_list);
3128 3128 if (instance->tbolt) {
3129 3129 INIT_LIST_HEAD(&instance->cmd_app_pool_list);
3130 3130 } else {
3131 3131 INIT_LIST_HEAD(&instance->app_cmd_pool_list);
3132 3132 }
3133 3133
3134 3134 }
3135 3135
3136 3136
3137 3137 /*
3138 3138 * mrsas_alloc_cmd_pool
3139 3139 */
3140 3140 int
3141 3141 mrsas_alloc_cmd_pool(struct mrsas_instance *instance)
3142 3142 {
3143 3143 int i;
3144 3144 int count;
3145 3145 uint32_t max_cmd;
3146 3146 uint32_t reserve_cmd;
3147 3147 size_t sz;
3148 3148
3149 3149 struct mrsas_cmd *cmd;
3150 3150
3151 3151 max_cmd = instance->max_fw_cmds;
3152 3152 con_log(CL_ANN1, (CE_NOTE, "mrsas_alloc_cmd_pool: "
3153 3153 "max_cmd %x", max_cmd));
3154 3154
3155 3155
3156 3156 sz = sizeof (struct mrsas_cmd *) * max_cmd;
3157 3157
3158 3158 /*
3159 3159 * instance->cmd_list is an array of struct mrsas_cmd pointers.
3160 3160 * Allocate the dynamic array first and then allocate individual
3161 3161 * commands.
3162 3162 */
3163 3163 instance->cmd_list = kmem_zalloc(sz, KM_SLEEP);
3164 3164 ASSERT(instance->cmd_list);
3165 3165
3166 3166 /* create a frame pool and assign one frame to each cmd */
3167 3167 for (count = 0; count < max_cmd; count++) {
3168 3168 instance->cmd_list[count] =
3169 3169 kmem_zalloc(sizeof (struct mrsas_cmd), KM_SLEEP);
3170 3170 ASSERT(instance->cmd_list[count]);
3171 3171 }
3172 3172
3173 3173 /* add all the commands to command pool */
3174 3174
3175 3175 INIT_LIST_HEAD(&instance->cmd_pool_list);
3176 3176 INIT_LIST_HEAD(&instance->cmd_pend_list);
3177 3177 INIT_LIST_HEAD(&instance->app_cmd_pool_list);
3178 3178
3179 3179 /*
3180 3180 * When max_cmd is lower than MRSAS_APP_RESERVED_CMDS, how do I split
3181 3181 * into app_cmd and regular cmd? For now, just take
3182 3182 * max(1/8th of max, 4);
3183 3183 */
3184 3184 reserve_cmd = min(MRSAS_APP_RESERVED_CMDS,
3185 3185 max(max_cmd >> 3, MRSAS_APP_MIN_RESERVED_CMDS));
3186 3186
3187 3187 for (i = 0; i < reserve_cmd; i++) {
3188 3188 cmd = instance->cmd_list[i];
3189 3189 cmd->index = i;
3190 3190 mlist_add_tail(&cmd->list, &instance->app_cmd_pool_list);
3191 3191 }
3192 3192
3193 3193
3194 3194 for (i = reserve_cmd; i < max_cmd; i++) {
3195 3195 cmd = instance->cmd_list[i];
3196 3196 cmd->index = i;
3197 3197 mlist_add_tail(&cmd->list, &instance->cmd_pool_list);
3198 3198 }
3199 3199
3200 3200 return (DDI_SUCCESS);
3201 3201
3202 3202 mrsas_undo_cmds:
3203 3203 if (count > 0) {
3204 3204 /* free each cmd */
3205 3205 for (i = 0; i < count; i++) {
3206 3206 if (instance->cmd_list[i] != NULL) {
3207 3207 kmem_free(instance->cmd_list[i],
3208 3208 sizeof (struct mrsas_cmd));
3209 3209 }
3210 3210 instance->cmd_list[i] = NULL;
3211 3211 }
3212 3212 }
3213 3213
3214 3214 mrsas_undo_cmd_list:
3215 3215 if (instance->cmd_list != NULL)
3216 3216 kmem_free(instance->cmd_list, sz);
3217 3217 instance->cmd_list = NULL;
3218 3218
3219 3219 return (DDI_FAILURE);
3220 3220 }
3221 3221
3222 3222
3223 3223 /*
3224 3224 * free_space_for_mfi
3225 3225 */
3226 3226 static void
3227 3227 free_space_for_mfi(struct mrsas_instance *instance)
3228 3228 {
3229 3229
3230 3230 /* already freed */
3231 3231 if (instance->cmd_list == NULL) {
3232 3232 return;
3233 3233 }
3234 3234
3235 3235 /* Free additional dma buffer */
3236 3236 free_additional_dma_buffer(instance);
3237 3237
3238 3238 /* Free the MFI frame pool */
3239 3239 destroy_mfi_frame_pool(instance);
3240 3240
3241 3241 /* Free all the commands in the cmd_list */
3242 3242 /* Free the cmd_list buffer itself */
3243 3243 mrsas_free_cmd_pool(instance);
3244 3244 }
3245 3245
3246 3246 /*
3247 3247 * alloc_space_for_mfi
3248 3248 */
3249 3249 static int
3250 3250 alloc_space_for_mfi(struct mrsas_instance *instance)
3251 3251 {
3252 3252 /* Allocate command pool (memory for cmd_list & individual commands) */
3253 3253 if (mrsas_alloc_cmd_pool(instance)) {
3254 3254 cmn_err(CE_WARN, "error creating cmd pool");
3255 3255 return (DDI_FAILURE);
3256 3256 }
3257 3257
3258 3258 /* Allocate MFI Frame pool */
3259 3259 if (create_mfi_frame_pool(instance)) {
3260 3260 cmn_err(CE_WARN, "error creating frame DMA pool");
3261 3261 goto mfi_undo_cmd_pool;
3262 3262 }
3263 3263
3264 3264 /* Allocate additional DMA buffer */
3265 3265 if (alloc_additional_dma_buffer(instance)) {
3266 3266 cmn_err(CE_WARN, "error creating frame DMA pool");
3267 3267 goto mfi_undo_frame_pool;
3268 3268 }
3269 3269
3270 3270 return (DDI_SUCCESS);
3271 3271
3272 3272 mfi_undo_frame_pool:
3273 3273 destroy_mfi_frame_pool(instance);
3274 3274
3275 3275 mfi_undo_cmd_pool:
3276 3276 mrsas_free_cmd_pool(instance);
3277 3277
3278 3278 return (DDI_FAILURE);
3279 3279 }
3280 3280
3281 3281
3282 3282
3283 3283 /*
3284 3284 * get_ctrl_info
3285 3285 */
3286 3286 static int
3287 3287 get_ctrl_info(struct mrsas_instance *instance,
3288 3288 struct mrsas_ctrl_info *ctrl_info)
3289 3289 {
3290 3290 int ret = 0;
3291 3291
3292 3292 struct mrsas_cmd *cmd;
3293 3293 struct mrsas_dcmd_frame *dcmd;
3294 3294 struct mrsas_ctrl_info *ci;
3295 3295
3296 3296 if (instance->tbolt) {
3297 3297 cmd = get_raid_msg_mfi_pkt(instance);
3298 3298 } else {
3299 3299 cmd = mrsas_get_mfi_pkt(instance);
3300 3300 }
3301 3301
3302 3302 if (!cmd) {
3303 3303 con_log(CL_ANN, (CE_WARN,
3304 3304 "Failed to get a cmd for ctrl info"));
3305 3305 DTRACE_PROBE2(info_mfi_err, uint16_t, instance->fw_outstanding,
3306 3306 uint16_t, instance->max_fw_cmds);
3307 3307 return (DDI_FAILURE);
3308 3308 }
3309 3309
3310 3310 /* Clear the frame buffer and assign back the context id */
3311 3311 (void) memset((char *)&cmd->frame[0], 0, sizeof (union mrsas_frame));
3312 3312 ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
3313 3313 cmd->index);
3314 3314
3315 3315 dcmd = &cmd->frame->dcmd;
3316 3316
3317 3317 ci = (struct mrsas_ctrl_info *)instance->internal_buf;
3318 3318
3319 3319 if (!ci) {
3320 3320 cmn_err(CE_WARN,
3321 3321 "Failed to alloc mem for ctrl info");
3322 3322 mrsas_return_mfi_pkt(instance, cmd);
3323 3323 return (DDI_FAILURE);
3324 3324 }
3325 3325
3326 3326 (void) memset(ci, 0, sizeof (struct mrsas_ctrl_info));
3327 3327
3328 3328 /* for( i = 0; i < DCMD_MBOX_SZ; i++ ) dcmd->mbox.b[i] = 0; */
3329 3329 (void) memset(dcmd->mbox.b, 0, DCMD_MBOX_SZ);
3330 3330
3331 3331 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd, MFI_CMD_OP_DCMD);
3332 3332 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd_status,
3333 3333 MFI_CMD_STATUS_POLL_MODE);
3334 3334 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->sge_count, 1);
3335 3335 ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->flags,
3336 3336 MFI_FRAME_DIR_READ);
3337 3337 ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->timeout, 0);
3338 3338 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->data_xfer_len,
3339 3339 sizeof (struct mrsas_ctrl_info));
3340 3340 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->opcode,
3341 3341 MR_DCMD_CTRL_GET_INFO);
3342 3342 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].phys_addr,
3343 3343 instance->internal_buf_dmac_add);
3344 3344 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].length,
3345 3345 sizeof (struct mrsas_ctrl_info));
3346 3346
3347 3347 cmd->frame_count = 1;
3348 3348
3349 3349 if (instance->tbolt) {
3350 3350 mr_sas_tbolt_build_mfi_cmd(instance, cmd);
3351 3351 }
3352 3352
3353 3353 if (!instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
3354 3354 ret = 0;
3355 3355
3356 3356 ctrl_info->max_request_size = ddi_get32(
3357 3357 cmd->frame_dma_obj.acc_handle, &ci->max_request_size);
3358 3358
3359 3359 ctrl_info->ld_present_count = ddi_get16(
3360 3360 cmd->frame_dma_obj.acc_handle, &ci->ld_present_count);
3361 3361
3362 3362 ctrl_info->properties.on_off_properties = ddi_get32(
3363 3363 cmd->frame_dma_obj.acc_handle,
3364 3364 &ci->properties.on_off_properties);
3365 3365 ddi_rep_get8(cmd->frame_dma_obj.acc_handle,
3366 3366 (uint8_t *)(ctrl_info->product_name),
3367 3367 (uint8_t *)(ci->product_name), 80 * sizeof (char),
3368 3368 DDI_DEV_AUTOINCR);
3369 3369 /* should get more members of ci with ddi_get when needed */
3370 3370 } else {
3371 3371 cmn_err(CE_WARN, "get_ctrl_info: Ctrl info failed");
3372 3372 ret = -1;
3373 3373 }
3374 3374
3375 3375 if (mrsas_common_check(instance, cmd) != DDI_SUCCESS) {
3376 3376 ret = -1;
3377 3377 }
3378 3378 if (instance->tbolt) {
3379 3379 return_raid_msg_mfi_pkt(instance, cmd);
3380 3380 } else {
3381 3381 mrsas_return_mfi_pkt(instance, cmd);
3382 3382 }
3383 3383
3384 3384 return (ret);
3385 3385 }
3386 3386
3387 3387 /*
3388 3388 * abort_aen_cmd
3389 3389 */
3390 3390 static int
3391 3391 abort_aen_cmd(struct mrsas_instance *instance,
3392 3392 struct mrsas_cmd *cmd_to_abort)
3393 3393 {
3394 3394 int ret = 0;
3395 3395
3396 3396 struct mrsas_cmd *cmd;
3397 3397 struct mrsas_abort_frame *abort_fr;
3398 3398
3399 3399 con_log(CL_ANN1, (CE_NOTE, "chkpnt: abort_aen:%d", __LINE__));
3400 3400
3401 3401 if (instance->tbolt) {
3402 3402 cmd = get_raid_msg_mfi_pkt(instance);
3403 3403 } else {
3404 3404 cmd = mrsas_get_mfi_pkt(instance);
3405 3405 }
3406 3406
3407 3407 if (!cmd) {
3408 3408 con_log(CL_ANN1, (CE_WARN,
3409 3409 "abort_aen_cmd():Failed to get a cmd for abort_aen_cmd"));
3410 3410 DTRACE_PROBE2(abort_mfi_err, uint16_t, instance->fw_outstanding,
3411 3411 uint16_t, instance->max_fw_cmds);
3412 3412 return (DDI_FAILURE);
3413 3413 }
3414 3414
3415 3415 /* Clear the frame buffer and assign back the context id */
3416 3416 (void) memset((char *)&cmd->frame[0], 0, sizeof (union mrsas_frame));
3417 3417 ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
3418 3418 cmd->index);
3419 3419
3420 3420 abort_fr = &cmd->frame->abort;
3421 3421
3422 3422 /* prepare and issue the abort frame */
3423 3423 ddi_put8(cmd->frame_dma_obj.acc_handle,
3424 3424 &abort_fr->cmd, MFI_CMD_OP_ABORT);
3425 3425 ddi_put8(cmd->frame_dma_obj.acc_handle, &abort_fr->cmd_status,
3426 3426 MFI_CMD_STATUS_SYNC_MODE);
3427 3427 ddi_put16(cmd->frame_dma_obj.acc_handle, &abort_fr->flags, 0);
3428 3428 ddi_put32(cmd->frame_dma_obj.acc_handle, &abort_fr->abort_context,
3429 3429 cmd_to_abort->index);
3430 3430 ddi_put32(cmd->frame_dma_obj.acc_handle,
3431 3431 &abort_fr->abort_mfi_phys_addr_lo, cmd_to_abort->frame_phys_addr);
3432 3432 ddi_put32(cmd->frame_dma_obj.acc_handle,
3433 3433 &abort_fr->abort_mfi_phys_addr_hi, 0);
3434 3434
3435 3435 instance->aen_cmd->abort_aen = 1;
3436 3436
3437 3437 cmd->frame_count = 1;
3438 3438
3439 3439 if (instance->tbolt) {
3440 3440 mr_sas_tbolt_build_mfi_cmd(instance, cmd);
3441 3441 }
3442 3442
3443 3443 if (instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
3444 3444 con_log(CL_ANN1, (CE_WARN,
3445 3445 "abort_aen_cmd: issue_cmd_in_poll_mode failed"));
3446 3446 ret = -1;
3447 3447 } else {
3448 3448 ret = 0;
3449 3449 }
3450 3450
3451 3451 instance->aen_cmd->abort_aen = 1;
3452 3452 instance->aen_cmd = 0;
3453 3453
3454 3454 if (instance->tbolt) {
3455 3455 return_raid_msg_mfi_pkt(instance, cmd);
3456 3456 } else {
3457 3457 mrsas_return_mfi_pkt(instance, cmd);
3458 3458 }
3459 3459
3460 3460 atomic_add_16(&instance->fw_outstanding, (-1));
3461 3461
3462 3462 return (ret);
3463 3463 }
3464 3464
3465 3465
3466 3466 static int
3467 3467 mrsas_build_init_cmd(struct mrsas_instance *instance,
3468 3468 struct mrsas_cmd **cmd_ptr)
3469 3469 {
3470 3470 struct mrsas_cmd *cmd;
3471 3471 struct mrsas_init_frame *init_frame;
3472 3472 struct mrsas_init_queue_info *initq_info;
3473 3473 struct mrsas_drv_ver drv_ver_info;
3474 3474
3475 3475
3476 3476 /*
3477 3477 * Prepare a init frame. Note the init frame points to queue info
3478 3478 * structure. Each frame has SGL allocated after first 64 bytes. For
3479 3479 * this frame - since we don't need any SGL - we use SGL's space as
3480 3480 * queue info structure
3481 3481 */
3482 3482 cmd = *cmd_ptr;
3483 3483
3484 3484
3485 3485 /* Clear the frame buffer and assign back the context id */
3486 3486 (void) memset((char *)&cmd->frame[0], 0, sizeof (union mrsas_frame));
3487 3487 ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
3488 3488 cmd->index);
3489 3489
3490 3490 init_frame = (struct mrsas_init_frame *)cmd->frame;
3491 3491 initq_info = (struct mrsas_init_queue_info *)
3492 3492 ((unsigned long)init_frame + 64);
3493 3493
3494 3494 (void) memset(init_frame, 0, MRMFI_FRAME_SIZE);
3495 3495 (void) memset(initq_info, 0, sizeof (struct mrsas_init_queue_info));
3496 3496
3497 3497 ddi_put32(cmd->frame_dma_obj.acc_handle, &initq_info->init_flags, 0);
3498 3498
3499 3499 ddi_put32(cmd->frame_dma_obj.acc_handle,
3500 3500 &initq_info->reply_queue_entries, instance->max_fw_cmds + 1);
3501 3501
3502 3502 ddi_put32(cmd->frame_dma_obj.acc_handle,
3503 3503 &initq_info->producer_index_phys_addr_hi, 0);
3504 3504 ddi_put32(cmd->frame_dma_obj.acc_handle,
3505 3505 &initq_info->producer_index_phys_addr_lo,
3506 3506 instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address);
3507 3507
3508 3508 ddi_put32(cmd->frame_dma_obj.acc_handle,
3509 3509 &initq_info->consumer_index_phys_addr_hi, 0);
3510 3510 ddi_put32(cmd->frame_dma_obj.acc_handle,
3511 3511 &initq_info->consumer_index_phys_addr_lo,
3512 3512 instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address + 4);
3513 3513
3514 3514 ddi_put32(cmd->frame_dma_obj.acc_handle,
3515 3515 &initq_info->reply_queue_start_phys_addr_hi, 0);
3516 3516 ddi_put32(cmd->frame_dma_obj.acc_handle,
3517 3517 &initq_info->reply_queue_start_phys_addr_lo,
3518 3518 instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address + 8);
3519 3519
3520 3520 ddi_put8(cmd->frame_dma_obj.acc_handle,
3521 3521 &init_frame->cmd, MFI_CMD_OP_INIT);
3522 3522 ddi_put8(cmd->frame_dma_obj.acc_handle, &init_frame->cmd_status,
3523 3523 MFI_CMD_STATUS_POLL_MODE);
3524 3524 ddi_put16(cmd->frame_dma_obj.acc_handle, &init_frame->flags, 0);
3525 3525 ddi_put32(cmd->frame_dma_obj.acc_handle,
3526 3526 &init_frame->queue_info_new_phys_addr_lo,
3527 3527 cmd->frame_phys_addr + 64);
3528 3528 ddi_put32(cmd->frame_dma_obj.acc_handle,
3529 3529 &init_frame->queue_info_new_phys_addr_hi, 0);
3530 3530
3531 3531
3532 3532 /* fill driver version information */
3533 3533 fill_up_drv_ver(&drv_ver_info);
3534 3534
3535 3535 /* allocate the driver version data transfer buffer */
3536 3536 instance->drv_ver_dma_obj.size = sizeof (drv_ver_info.drv_ver);
3537 3537 instance->drv_ver_dma_obj.dma_attr = mrsas_generic_dma_attr;
3538 3538 instance->drv_ver_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3539 3539 instance->drv_ver_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
3540 3540 instance->drv_ver_dma_obj.dma_attr.dma_attr_sgllen = 1;
3541 3541 instance->drv_ver_dma_obj.dma_attr.dma_attr_align = 1;
3542 3542
3543 3543 if (mrsas_alloc_dma_obj(instance, &instance->drv_ver_dma_obj,
3544 3544 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
3545 3545 con_log(CL_ANN, (CE_WARN,
3546 3546 "init_mfi : Could not allocate driver version buffer."));
3547 3547 return (DDI_FAILURE);
3548 3548 }
3549 3549 /* copy driver version to dma buffer */
3550 3550 (void) memset(instance->drv_ver_dma_obj.buffer, 0,
3551 3551 sizeof (drv_ver_info.drv_ver));
3552 3552 ddi_rep_put8(cmd->frame_dma_obj.acc_handle,
3553 3553 (uint8_t *)drv_ver_info.drv_ver,
3554 3554 (uint8_t *)instance->drv_ver_dma_obj.buffer,
3555 3555 sizeof (drv_ver_info.drv_ver), DDI_DEV_AUTOINCR);
3556 3556
3557 3557
3558 3558 /* copy driver version physical address to init frame */
3559 3559 ddi_put64(cmd->frame_dma_obj.acc_handle, &init_frame->driverversion,
3560 3560 instance->drv_ver_dma_obj.dma_cookie[0].dmac_address);
3561 3561
3562 3562 ddi_put32(cmd->frame_dma_obj.acc_handle, &init_frame->data_xfer_len,
3563 3563 sizeof (struct mrsas_init_queue_info));
3564 3564
3565 3565 cmd->frame_count = 1;
3566 3566
3567 3567 *cmd_ptr = cmd;
3568 3568
3569 3569 return (DDI_SUCCESS);
3570 3570 }
3571 3571
3572 3572
3573 3573 /*
3574 3574 * mrsas_init_adapter_ppc - Initialize MFI interface adapter.
3575 3575 */
3576 3576 int
3577 3577 mrsas_init_adapter_ppc(struct mrsas_instance *instance)
3578 3578 {
3579 3579 struct mrsas_cmd *cmd;
3580 3580
3581 3581 /*
3582 3582 * allocate memory for mfi adapter(cmd pool, individual commands, mfi
3583 3583 * frames etc
3584 3584 */
3585 3585 if (alloc_space_for_mfi(instance) != DDI_SUCCESS) {
3586 3586 con_log(CL_ANN, (CE_NOTE,
3587 3587 "Error, failed to allocate memory for MFI adapter"));
3588 3588 return (DDI_FAILURE);
3589 3589 }
3590 3590
3591 3591 /* Build INIT command */
3592 3592 cmd = mrsas_get_mfi_pkt(instance);
3593 3593 if (cmd == NULL) {
3594 3594 DTRACE_PROBE2(init_adapter_mfi_err, uint16_t,
3595 3595 instance->fw_outstanding, uint16_t, instance->max_fw_cmds);
3596 3596 return (DDI_FAILURE);
3597 3597 }
3598 3598
3599 3599 if (mrsas_build_init_cmd(instance, &cmd) != DDI_SUCCESS) {
3600 3600 con_log(CL_ANN,
3601 3601 (CE_NOTE, "Error, failed to build INIT command"));
3602 3602
3603 3603 goto fail_undo_alloc_mfi_space;
3604 3604 }
3605 3605
3606 3606 /*
3607 3607 * Disable interrupt before sending init frame ( see linux driver code)
3608 3608 * send INIT MFI frame in polled mode
3609 3609 */
3610 3610 if (instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
3611 3611 con_log(CL_ANN, (CE_WARN, "failed to init firmware"));
3612 3612 goto fail_fw_init;
3613 3613 }
3614 3614
3615 3615 if (mrsas_common_check(instance, cmd) != DDI_SUCCESS)
3616 3616 goto fail_fw_init;
3617 3617 mrsas_return_mfi_pkt(instance, cmd);
3618 3618
3619 3619 if (ctio_enable &&
3620 3620 (instance->func_ptr->read_fw_status_reg(instance) & 0x04000000)) {
3621 3621 con_log(CL_ANN, (CE_NOTE, "mr_sas: IEEE SGL's supported"));
3622 3622 instance->flag_ieee = 1;
3623 3623 } else {
3624 3624 instance->flag_ieee = 0;
3625 3625 }
3626 3626
3627 3627 ASSERT(!instance->skinny || instance->flag_ieee);
3628 3628
3629 3629 instance->unroll.alloc_space_mfi = 1;
3630 3630 instance->unroll.verBuff = 1;
3631 3631
3632 3632 return (DDI_SUCCESS);
3633 3633
3634 3634
3635 3635 fail_fw_init:
3636 3636 (void) mrsas_free_dma_obj(instance, instance->drv_ver_dma_obj);
3637 3637
3638 3638 fail_undo_alloc_mfi_space:
3639 3639 mrsas_return_mfi_pkt(instance, cmd);
3640 3640 free_space_for_mfi(instance);
3641 3641
3642 3642 return (DDI_FAILURE);
3643 3643
3644 3644 }
3645 3645
3646 3646 /*
3647 3647 * mrsas_init_adapter - Initialize adapter.
3648 3648 */
3649 3649 int
3650 3650 mrsas_init_adapter(struct mrsas_instance *instance)
3651 3651 {
3652 3652 struct mrsas_ctrl_info ctrl_info;
3653 3653
3654 3654
3655 3655 /* we expect the FW state to be READY */
3656 3656 if (mfi_state_transition_to_ready(instance)) {
3657 3657 con_log(CL_ANN, (CE_WARN, "mr_sas: F/W is not ready"));
3658 3658 return (DDI_FAILURE);
3659 3659 }
3660 3660
3661 3661 /* get various operational parameters from status register */
3662 3662 instance->max_num_sge =
3663 3663 (instance->func_ptr->read_fw_status_reg(instance) &
3664 3664 0xFF0000) >> 0x10;
3665 3665 instance->max_num_sge =
3666 3666 (instance->max_num_sge > MRSAS_MAX_SGE_CNT) ?
3667 3667 MRSAS_MAX_SGE_CNT : instance->max_num_sge;
3668 3668
3669 3669 /*
3670 3670 * Reduce the max supported cmds by 1. This is to ensure that the
3671 3671 * reply_q_sz (1 more than the max cmd that driver may send)
3672 3672 * does not exceed max cmds that the FW can support
3673 3673 */
3674 3674 instance->max_fw_cmds =
3675 3675 instance->func_ptr->read_fw_status_reg(instance) & 0xFFFF;
3676 3676 instance->max_fw_cmds = instance->max_fw_cmds - 1;
3677 3677
3678 3678
3679 3679
3680 3680 /* Initialize adapter */
3681 3681 if (instance->func_ptr->init_adapter(instance) != DDI_SUCCESS) {
3682 3682 con_log(CL_ANN,
3683 3683 (CE_WARN, "mr_sas: could not initialize adapter"));
3684 3684 return (DDI_FAILURE);
3685 3685 }
3686 3686
3687 3687 /* gather misc FW related information */
3688 3688 instance->disable_online_ctrl_reset = 0;
3689 3689
3690 3690 if (!get_ctrl_info(instance, &ctrl_info)) {
3691 3691 instance->max_sectors_per_req = ctrl_info.max_request_size;
3692 3692 con_log(CL_ANN1, (CE_NOTE,
3693 3693 "product name %s ld present %d",
3694 3694 ctrl_info.product_name, ctrl_info.ld_present_count));
3695 3695 } else {
3696 3696 instance->max_sectors_per_req = instance->max_num_sge *
3697 3697 PAGESIZE / 512;
3698 3698 }
3699 3699
3700 3700 if (ctrl_info.properties.on_off_properties & DISABLE_OCR_PROP_FLAG)
3701 3701 instance->disable_online_ctrl_reset = 1;
3702 3702
3703 3703 return (DDI_SUCCESS);
3704 3704
3705 3705 }
3706 3706
3707 3707
3708 3708
3709 3709 static int
3710 3710 mrsas_issue_init_mfi(struct mrsas_instance *instance)
3711 3711 {
3712 3712 struct mrsas_cmd *cmd;
3713 3713 struct mrsas_init_frame *init_frame;
3714 3714 struct mrsas_init_queue_info *initq_info;
3715 3715
3716 3716 /*
3717 3717 * Prepare a init frame. Note the init frame points to queue info
3718 3718 * structure. Each frame has SGL allocated after first 64 bytes. For
3719 3719 * this frame - since we don't need any SGL - we use SGL's space as
3720 3720 * queue info structure
3721 3721 */
3722 3722 con_log(CL_ANN1, (CE_NOTE,
3723 3723 "mrsas_issue_init_mfi: entry\n"));
3724 3724 cmd = get_mfi_app_pkt(instance);
3725 3725
3726 3726 if (!cmd) {
3727 3727 con_log(CL_ANN1, (CE_WARN,
3728 3728 "mrsas_issue_init_mfi: get_pkt failed\n"));
3729 3729 return (DDI_FAILURE);
3730 3730 }
3731 3731
3732 3732 /* Clear the frame buffer and assign back the context id */
3733 3733 (void) memset((char *)&cmd->frame[0], 0, sizeof (union mrsas_frame));
3734 3734 ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
3735 3735 cmd->index);
3736 3736
3737 3737 init_frame = (struct mrsas_init_frame *)cmd->frame;
3738 3738 initq_info = (struct mrsas_init_queue_info *)
3739 3739 ((unsigned long)init_frame + 64);
3740 3740
3741 3741 (void) memset(init_frame, 0, MRMFI_FRAME_SIZE);
3742 3742 (void) memset(initq_info, 0, sizeof (struct mrsas_init_queue_info));
3743 3743
3744 3744 ddi_put32(cmd->frame_dma_obj.acc_handle, &initq_info->init_flags, 0);
3745 3745
3746 3746 ddi_put32(cmd->frame_dma_obj.acc_handle,
3747 3747 &initq_info->reply_queue_entries, instance->max_fw_cmds + 1);
3748 3748 ddi_put32(cmd->frame_dma_obj.acc_handle,
3749 3749 &initq_info->producer_index_phys_addr_hi, 0);
3750 3750 ddi_put32(cmd->frame_dma_obj.acc_handle,
3751 3751 &initq_info->producer_index_phys_addr_lo,
3752 3752 instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address);
3753 3753 ddi_put32(cmd->frame_dma_obj.acc_handle,
3754 3754 &initq_info->consumer_index_phys_addr_hi, 0);
3755 3755 ddi_put32(cmd->frame_dma_obj.acc_handle,
3756 3756 &initq_info->consumer_index_phys_addr_lo,
3757 3757 instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address + 4);
3758 3758
3759 3759 ddi_put32(cmd->frame_dma_obj.acc_handle,
3760 3760 &initq_info->reply_queue_start_phys_addr_hi, 0);
3761 3761 ddi_put32(cmd->frame_dma_obj.acc_handle,
3762 3762 &initq_info->reply_queue_start_phys_addr_lo,
3763 3763 instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address + 8);
3764 3764
3765 3765 ddi_put8(cmd->frame_dma_obj.acc_handle,
3766 3766 &init_frame->cmd, MFI_CMD_OP_INIT);
3767 3767 ddi_put8(cmd->frame_dma_obj.acc_handle, &init_frame->cmd_status,
3768 3768 MFI_CMD_STATUS_POLL_MODE);
3769 3769 ddi_put16(cmd->frame_dma_obj.acc_handle, &init_frame->flags, 0);
3770 3770 ddi_put32(cmd->frame_dma_obj.acc_handle,
3771 3771 &init_frame->queue_info_new_phys_addr_lo,
3772 3772 cmd->frame_phys_addr + 64);
3773 3773 ddi_put32(cmd->frame_dma_obj.acc_handle,
3774 3774 &init_frame->queue_info_new_phys_addr_hi, 0);
3775 3775
3776 3776 ddi_put32(cmd->frame_dma_obj.acc_handle, &init_frame->data_xfer_len,
3777 3777 sizeof (struct mrsas_init_queue_info));
3778 3778
3779 3779 cmd->frame_count = 1;
3780 3780
3781 3781 /* issue the init frame in polled mode */
3782 3782 if (instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
3783 3783 con_log(CL_ANN1, (CE_WARN,
3784 3784 "mrsas_issue_init_mfi():failed to "
3785 3785 "init firmware"));
3786 3786 return_mfi_app_pkt(instance, cmd);
3787 3787 return (DDI_FAILURE);
3788 3788 }
3789 3789
3790 3790 if (mrsas_common_check(instance, cmd) != DDI_SUCCESS) {
3791 3791 return_mfi_app_pkt(instance, cmd);
3792 3792 return (DDI_FAILURE);
3793 3793 }
3794 3794
3795 3795 return_mfi_app_pkt(instance, cmd);
3796 3796 con_log(CL_ANN1, (CE_CONT, "mrsas_issue_init_mfi: Done"));
3797 3797
3798 3798 return (DDI_SUCCESS);
3799 3799 }
3800 3800 /*
3801 3801 * mfi_state_transition_to_ready : Move the FW to READY state
3802 3802 *
3803 3803 * @reg_set : MFI register set
3804 3804 */
3805 3805 int
3806 3806 mfi_state_transition_to_ready(struct mrsas_instance *instance)
3807 3807 {
3808 3808 int i;
3809 3809 uint8_t max_wait;
3810 3810 uint32_t fw_ctrl = 0;
3811 3811 uint32_t fw_state;
3812 3812 uint32_t cur_state;
3813 3813 uint32_t cur_abs_reg_val;
3814 3814 uint32_t prev_abs_reg_val;
3815 3815 uint32_t status;
3816 3816
3817 3817 cur_abs_reg_val =
3818 3818 instance->func_ptr->read_fw_status_reg(instance);
3819 3819 fw_state =
3820 3820 cur_abs_reg_val & MFI_STATE_MASK;
3821 3821 con_log(CL_ANN1, (CE_CONT,
3822 3822 "mfi_state_transition_to_ready:FW state = 0x%x", fw_state));
3823 3823
3824 3824 while (fw_state != MFI_STATE_READY) {
3825 3825 con_log(CL_ANN, (CE_CONT,
3826 3826 "mfi_state_transition_to_ready:FW state%x", fw_state));
3827 3827
3828 3828 switch (fw_state) {
3829 3829 case MFI_STATE_FAULT:
3830 3830 con_log(CL_ANN, (CE_NOTE,
3831 3831 "mr_sas: FW in FAULT state!!"));
3832 3832
3833 3833 return (ENODEV);
3834 3834 case MFI_STATE_WAIT_HANDSHAKE:
3835 3835 /* set the CLR bit in IMR0 */
3836 3836 con_log(CL_ANN1, (CE_NOTE,
3837 3837 "mr_sas: FW waiting for HANDSHAKE"));
3838 3838 /*
3839 3839 * PCI_Hot Plug: MFI F/W requires
3840 3840 * (MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG)
3841 3841 * to be set
3842 3842 */
3843 3843 /* WR_IB_MSG_0(MFI_INIT_CLEAR_HANDSHAKE, instance); */
3844 3844 if (!instance->tbolt && !instance->skinny) {
3845 3845 WR_IB_DOORBELL(MFI_INIT_CLEAR_HANDSHAKE |
3846 3846 MFI_INIT_HOTPLUG, instance);
3847 3847 } else {
3848 3848 WR_RESERVED0_REGISTER(MFI_INIT_CLEAR_HANDSHAKE |
3849 3849 MFI_INIT_HOTPLUG, instance);
3850 3850 }
3851 3851 max_wait = (instance->tbolt == 1) ? 180 : 2;
3852 3852 cur_state = MFI_STATE_WAIT_HANDSHAKE;
3853 3853 break;
3854 3854 case MFI_STATE_BOOT_MESSAGE_PENDING:
3855 3855 /* set the CLR bit in IMR0 */
3856 3856 con_log(CL_ANN1, (CE_NOTE,
3857 3857 "mr_sas: FW state boot message pending"));
3858 3858 /*
3859 3859 * PCI_Hot Plug: MFI F/W requires
3860 3860 * (MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG)
3861 3861 * to be set
3862 3862 */
3863 3863 if (!instance->tbolt && !instance->skinny) {
3864 3864 WR_IB_DOORBELL(MFI_INIT_HOTPLUG, instance);
3865 3865 } else {
3866 3866 WR_RESERVED0_REGISTER(MFI_INIT_HOTPLUG,
3867 3867 instance);
3868 3868 }
3869 3869 max_wait = (instance->tbolt == 1) ? 180 : 10;
3870 3870 cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
3871 3871 break;
3872 3872 case MFI_STATE_OPERATIONAL:
3873 3873 /* bring it to READY state; assuming max wait 2 secs */
3874 3874 instance->func_ptr->disable_intr(instance);
3875 3875 con_log(CL_ANN1, (CE_NOTE,
3876 3876 "mr_sas: FW in OPERATIONAL state"));
3877 3877 /*
3878 3878 * PCI_Hot Plug: MFI F/W requires
3879 3879 * (MFI_INIT_READY | MFI_INIT_MFIMODE | MFI_INIT_ABORT)
3880 3880 * to be set
3881 3881 */
3882 3882 /* WR_IB_DOORBELL(MFI_INIT_READY, instance); */
3883 3883 if (!instance->tbolt && !instance->skinny) {
3884 3884 WR_IB_DOORBELL(MFI_RESET_FLAGS, instance);
3885 3885 } else {
3886 3886 WR_RESERVED0_REGISTER(MFI_RESET_FLAGS,
3887 3887 instance);
3888 3888
3889 3889 for (i = 0; i < (10 * 1000); i++) {
3890 3890 status =
3891 3891 RD_RESERVED0_REGISTER(instance);
3892 3892 if (status & 1) {
3893 3893 delay(1 *
3894 3894 drv_usectohz(MILLISEC));
3895 3895 } else {
3896 3896 break;
3897 3897 }
3898 3898 }
3899 3899
3900 3900 }
3901 3901 max_wait = (instance->tbolt == 1) ? 180 : 10;
3902 3902 cur_state = MFI_STATE_OPERATIONAL;
3903 3903 break;
3904 3904 case MFI_STATE_UNDEFINED:
3905 3905 /* this state should not last for more than 2 seconds */
3906 3906 con_log(CL_ANN1, (CE_NOTE, "FW state undefined"));
3907 3907
3908 3908 max_wait = (instance->tbolt == 1) ? 180 : 2;
3909 3909 cur_state = MFI_STATE_UNDEFINED;
3910 3910 break;
3911 3911 case MFI_STATE_BB_INIT:
3912 3912 max_wait = (instance->tbolt == 1) ? 180 : 2;
3913 3913 cur_state = MFI_STATE_BB_INIT;
3914 3914 break;
3915 3915 case MFI_STATE_FW_INIT:
3916 3916 max_wait = (instance->tbolt == 1) ? 180 : 2;
3917 3917 cur_state = MFI_STATE_FW_INIT;
3918 3918 break;
3919 3919 case MFI_STATE_FW_INIT_2:
3920 3920 max_wait = 180;
3921 3921 cur_state = MFI_STATE_FW_INIT_2;
3922 3922 break;
3923 3923 case MFI_STATE_DEVICE_SCAN:
3924 3924 max_wait = 180;
3925 3925 cur_state = MFI_STATE_DEVICE_SCAN;
3926 3926 prev_abs_reg_val = cur_abs_reg_val;
3927 3927 con_log(CL_NONE, (CE_NOTE,
3928 3928 "Device scan in progress ...\n"));
3929 3929 break;
3930 3930 case MFI_STATE_FLUSH_CACHE:
3931 3931 max_wait = 180;
3932 3932 cur_state = MFI_STATE_FLUSH_CACHE;
3933 3933 break;
3934 3934 default:
3935 3935 con_log(CL_ANN1, (CE_NOTE,
3936 3936 "mr_sas: Unknown state 0x%x", fw_state));
3937 3937 return (ENODEV);
3938 3938 }
3939 3939
3940 3940 /* the cur_state should not last for more than max_wait secs */
3941 3941 for (i = 0; i < (max_wait * MILLISEC); i++) {
3942 3942 /* fw_state = RD_OB_MSG_0(instance) & MFI_STATE_MASK; */
3943 3943 cur_abs_reg_val =
3944 3944 instance->func_ptr->read_fw_status_reg(instance);
3945 3945 fw_state = cur_abs_reg_val & MFI_STATE_MASK;
3946 3946
3947 3947 if (fw_state == cur_state) {
3948 3948 delay(1 * drv_usectohz(MILLISEC));
3949 3949 } else {
3950 3950 break;
3951 3951 }
3952 3952 }
3953 3953 if (fw_state == MFI_STATE_DEVICE_SCAN) {
3954 3954 if (prev_abs_reg_val != cur_abs_reg_val) {
3955 3955 continue;
3956 3956 }
3957 3957 }
3958 3958
3959 3959 /* return error if fw_state hasn't changed after max_wait */
3960 3960 if (fw_state == cur_state) {
3961 3961 con_log(CL_ANN1, (CE_WARN,
3962 3962 "FW state hasn't changed in %d secs", max_wait));
3963 3963 return (ENODEV);
3964 3964 }
3965 3965 };
3966 3966
3967 3967 /* This may also need to apply to Skinny, but for now, don't worry. */
3968 3968 if (!instance->tbolt && !instance->skinny) {
3969 3969 fw_ctrl = RD_IB_DOORBELL(instance);
3970 3970 con_log(CL_ANN1, (CE_CONT,
3971 3971 "mfi_state_transition_to_ready:FW ctrl = 0x%x", fw_ctrl));
3972 3972
3973 3973 /*
3974 3974 * Write 0xF to the doorbell register to do the following.
3975 3975 * - Abort all outstanding commands (bit 0).
3976 3976 * - Transition from OPERATIONAL to READY state (bit 1).
3977 3977 * - Discard (possible) low MFA posted in 64-bit mode (bit-2).
3978 3978 * - Set to release FW to continue running (i.e. BIOS handshake
3979 3979 * (bit 3).
3980 3980 */
3981 3981 WR_IB_DOORBELL(0xF, instance);
3982 3982 }
3983 3983
3984 3984 if (mrsas_check_acc_handle(instance->regmap_handle) != DDI_SUCCESS) {
3985 3985 return (EIO);
3986 3986 }
3987 3987
3988 3988 return (DDI_SUCCESS);
3989 3989 }
3990 3990
3991 3991 /*
3992 3992 * get_seq_num
3993 3993 */
3994 3994 static int
3995 3995 get_seq_num(struct mrsas_instance *instance,
3996 3996 struct mrsas_evt_log_info *eli)
3997 3997 {
3998 3998 int ret = DDI_SUCCESS;
3999 3999
4000 4000 dma_obj_t dcmd_dma_obj;
4001 4001 struct mrsas_cmd *cmd;
4002 4002 struct mrsas_dcmd_frame *dcmd;
4003 4003 struct mrsas_evt_log_info *eli_tmp;
4004 4004 if (instance->tbolt) {
4005 4005 cmd = get_raid_msg_mfi_pkt(instance);
4006 4006 } else {
4007 4007 cmd = mrsas_get_mfi_pkt(instance);
4008 4008 }
4009 4009
4010 4010 if (!cmd) {
4011 4011 cmn_err(CE_WARN, "mr_sas: failed to get a cmd");
4012 4012 DTRACE_PROBE2(seq_num_mfi_err, uint16_t,
4013 4013 instance->fw_outstanding, uint16_t, instance->max_fw_cmds);
4014 4014 return (ENOMEM);
4015 4015 }
4016 4016
4017 4017 /* Clear the frame buffer and assign back the context id */
4018 4018 (void) memset((char *)&cmd->frame[0], 0, sizeof (union mrsas_frame));
4019 4019 ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
4020 4020 cmd->index);
4021 4021
4022 4022 dcmd = &cmd->frame->dcmd;
4023 4023
4024 4024 /* allocate the data transfer buffer */
4025 4025 dcmd_dma_obj.size = sizeof (struct mrsas_evt_log_info);
4026 4026 dcmd_dma_obj.dma_attr = mrsas_generic_dma_attr;
4027 4027 dcmd_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
4028 4028 dcmd_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
4029 4029 dcmd_dma_obj.dma_attr.dma_attr_sgllen = 1;
4030 4030 dcmd_dma_obj.dma_attr.dma_attr_align = 1;
4031 4031
4032 4032 if (mrsas_alloc_dma_obj(instance, &dcmd_dma_obj,
4033 4033 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
4034 4034 cmn_err(CE_WARN,
4035 4035 "get_seq_num: could not allocate data transfer buffer.");
4036 4036 return (DDI_FAILURE);
4037 4037 }
4038 4038
4039 4039 (void) memset(dcmd_dma_obj.buffer, 0,
4040 4040 sizeof (struct mrsas_evt_log_info));
4041 4041
4042 4042 (void) memset(dcmd->mbox.b, 0, DCMD_MBOX_SZ);
4043 4043
4044 4044 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd, MFI_CMD_OP_DCMD);
4045 4045 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd_status, 0);
4046 4046 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->sge_count, 1);
4047 4047 ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->flags,
4048 4048 MFI_FRAME_DIR_READ);
4049 4049 ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->timeout, 0);
4050 4050 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->data_xfer_len,
4051 4051 sizeof (struct mrsas_evt_log_info));
4052 4052 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->opcode,
4053 4053 MR_DCMD_CTRL_EVENT_GET_INFO);
4054 4054 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].length,
4055 4055 sizeof (struct mrsas_evt_log_info));
4056 4056 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].phys_addr,
4057 4057 dcmd_dma_obj.dma_cookie[0].dmac_address);
4058 4058
4059 4059 cmd->sync_cmd = MRSAS_TRUE;
4060 4060 cmd->frame_count = 1;
4061 4061
4062 4062 if (instance->tbolt) {
4063 4063 mr_sas_tbolt_build_mfi_cmd(instance, cmd);
4064 4064 }
4065 4065
4066 4066 if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
4067 4067 cmn_err(CE_WARN, "get_seq_num: "
4068 4068 "failed to issue MRSAS_DCMD_CTRL_EVENT_GET_INFO");
4069 4069 ret = DDI_FAILURE;
4070 4070 } else {
4071 4071 eli_tmp = (struct mrsas_evt_log_info *)dcmd_dma_obj.buffer;
4072 4072 eli->newest_seq_num = ddi_get32(cmd->frame_dma_obj.acc_handle,
4073 4073 &eli_tmp->newest_seq_num);
4074 4074 ret = DDI_SUCCESS;
4075 4075 }
4076 4076
4077 4077 if (mrsas_free_dma_obj(instance, dcmd_dma_obj) != DDI_SUCCESS)
4078 4078 ret = DDI_FAILURE;
4079 4079
4080 4080 if (instance->tbolt) {
4081 4081 return_raid_msg_mfi_pkt(instance, cmd);
4082 4082 } else {
4083 4083 mrsas_return_mfi_pkt(instance, cmd);
4084 4084 }
4085 4085
4086 4086 return (ret);
4087 4087 }
4088 4088
4089 4089 /*
4090 4090 * start_mfi_aen
4091 4091 */
4092 4092 static int
4093 4093 start_mfi_aen(struct mrsas_instance *instance)
4094 4094 {
4095 4095 int ret = 0;
4096 4096
4097 4097 struct mrsas_evt_log_info eli;
4098 4098 union mrsas_evt_class_locale class_locale;
4099 4099
4100 4100 /* get the latest sequence number from FW */
4101 4101 (void) memset(&eli, 0, sizeof (struct mrsas_evt_log_info));
4102 4102
4103 4103 if (get_seq_num(instance, &eli)) {
4104 4104 cmn_err(CE_WARN, "start_mfi_aen: failed to get seq num");
4105 4105 return (-1);
4106 4106 }
4107 4107
4108 4108 /* register AEN with FW for latest sequence number plus 1 */
4109 4109 class_locale.members.reserved = 0;
4110 4110 class_locale.members.locale = LE_16(MR_EVT_LOCALE_ALL);
4111 4111 class_locale.members.class = MR_EVT_CLASS_INFO;
4112 4112 class_locale.word = LE_32(class_locale.word);
4113 4113 ret = register_mfi_aen(instance, eli.newest_seq_num + 1,
4114 4114 class_locale.word);
4115 4115
4116 4116 if (ret) {
4117 4117 cmn_err(CE_WARN, "start_mfi_aen: aen registration failed");
4118 4118 return (-1);
4119 4119 }
4120 4120
4121 4121
4122 4122 return (ret);
4123 4123 }
4124 4124
4125 4125 /*
4126 4126 * flush_cache
4127 4127 */
4128 4128 static void
4129 4129 flush_cache(struct mrsas_instance *instance)
4130 4130 {
4131 4131 struct mrsas_cmd *cmd = NULL;
4132 4132 struct mrsas_dcmd_frame *dcmd;
4133 4133 if (instance->tbolt) {
4134 4134 cmd = get_raid_msg_mfi_pkt(instance);
4135 4135 } else {
4136 4136 cmd = mrsas_get_mfi_pkt(instance);
4137 4137 }
4138 4138
4139 4139 if (!cmd) {
4140 4140 con_log(CL_ANN1, (CE_WARN,
4141 4141 "flush_cache():Failed to get a cmd for flush_cache"));
4142 4142 DTRACE_PROBE2(flush_cache_err, uint16_t,
4143 4143 instance->fw_outstanding, uint16_t, instance->max_fw_cmds);
4144 4144 return;
4145 4145 }
4146 4146
4147 4147 /* Clear the frame buffer and assign back the context id */
4148 4148 (void) memset((char *)&cmd->frame[0], 0, sizeof (union mrsas_frame));
4149 4149 ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
4150 4150 cmd->index);
4151 4151
4152 4152 dcmd = &cmd->frame->dcmd;
4153 4153
4154 4154 (void) memset(dcmd->mbox.b, 0, DCMD_MBOX_SZ);
4155 4155
4156 4156 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd, MFI_CMD_OP_DCMD);
4157 4157 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd_status, 0x0);
4158 4158 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->sge_count, 0);
4159 4159 ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->flags,
4160 4160 MFI_FRAME_DIR_NONE);
4161 4161 ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->timeout, 0);
4162 4162 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->data_xfer_len, 0);
4163 4163 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->opcode,
4164 4164 MR_DCMD_CTRL_CACHE_FLUSH);
4165 4165 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->mbox.b[0],
4166 4166 MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE);
4167 4167
4168 4168 cmd->frame_count = 1;
4169 4169
4170 4170 if (instance->tbolt) {
4171 4171 mr_sas_tbolt_build_mfi_cmd(instance, cmd);
4172 4172 }
4173 4173
4174 4174 if (instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
4175 4175 con_log(CL_ANN1, (CE_WARN,
4176 4176 "flush_cache: failed to issue MFI_DCMD_CTRL_CACHE_FLUSH"));
4177 4177 }
4178 4178 con_log(CL_ANN1, (CE_CONT, "flush_cache done"));
4179 4179 if (instance->tbolt) {
4180 4180 return_raid_msg_mfi_pkt(instance, cmd);
4181 4181 } else {
4182 4182 mrsas_return_mfi_pkt(instance, cmd);
4183 4183 }
4184 4184
4185 4185 }
4186 4186
4187 4187 /*
4188 4188 * service_mfi_aen- Completes an AEN command
4189 4189 * @instance: Adapter soft state
4190 4190 * @cmd: Command to be completed
4191 4191 *
4192 4192 */
4193 4193 void
4194 4194 service_mfi_aen(struct mrsas_instance *instance, struct mrsas_cmd *cmd)
4195 4195 {
4196 4196 uint32_t seq_num;
4197 4197 struct mrsas_evt_detail *evt_detail =
4198 4198 (struct mrsas_evt_detail *)instance->mfi_evt_detail_obj.buffer;
4199 4199 int rval = 0;
4200 4200 int tgt = 0;
4201 4201 uint8_t dtype;
4202 4202 #ifdef PDSUPPORT
4203 4203 mrsas_pd_address_t *pd_addr;
4204 4204 #endif
4205 4205 ddi_acc_handle_t acc_handle;
4206 4206
4207 4207 con_log(CL_ANN, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
4208 4208
4209 4209 acc_handle = cmd->frame_dma_obj.acc_handle;
4210 4210 cmd->cmd_status = ddi_get8(acc_handle, &cmd->frame->io.cmd_status);
4211 4211 if (cmd->cmd_status == ENODATA) {
4212 4212 cmd->cmd_status = 0;
4213 4213 }
4214 4214
4215 4215 /*
4216 4216 * log the MFI AEN event to the sysevent queue so that
4217 4217 * application will get noticed
4218 4218 */
4219 4219 if (ddi_log_sysevent(instance->dip, DDI_VENDOR_LSI, "LSIMEGA", "SAS",
4220 4220 NULL, NULL, DDI_NOSLEEP) != DDI_SUCCESS) {
4221 4221 int instance_no = ddi_get_instance(instance->dip);
4222 4222 con_log(CL_ANN, (CE_WARN,
4223 4223 "mr_sas%d: Failed to log AEN event", instance_no));
4224 4224 }
4225 4225 /*
4226 4226 * Check for any ld devices that has changed state. i.e. online
4227 4227 * or offline.
4228 4228 */
4229 4229 con_log(CL_ANN1, (CE_CONT,
4230 4230 "AEN: code = %x class = %x locale = %x args = %x",
4231 4231 ddi_get32(acc_handle, &evt_detail->code),
4232 4232 evt_detail->cl.members.class,
4233 4233 ddi_get16(acc_handle, &evt_detail->cl.members.locale),
4234 4234 ddi_get8(acc_handle, &evt_detail->arg_type)));
4235 4235
4236 4236 switch (ddi_get32(acc_handle, &evt_detail->code)) {
4237 4237 case MR_EVT_CFG_CLEARED: {
4238 4238 for (tgt = 0; tgt < MRDRV_MAX_LD; tgt++) {
4239 4239 if (instance->mr_ld_list[tgt].dip != NULL) {
4240 4240 mutex_enter(&instance->config_dev_mtx);
4241 4241 instance->mr_ld_list[tgt].flag =
4242 4242 (uint8_t)~MRDRV_TGT_VALID;
4243 4243 mutex_exit(&instance->config_dev_mtx);
4244 4244 rval = mrsas_service_evt(instance, tgt, 0,
4245 4245 MRSAS_EVT_UNCONFIG_TGT, NULL);
4246 4246 con_log(CL_ANN1, (CE_WARN,
4247 4247 "mr_sas: CFG CLEARED AEN rval = %d "
4248 4248 "tgt id = %d", rval, tgt));
4249 4249 }
4250 4250 }
4251 4251 break;
4252 4252 }
4253 4253
4254 4254 case MR_EVT_LD_DELETED: {
4255 4255 tgt = ddi_get16(acc_handle, &evt_detail->args.ld.target_id);
4256 4256 mutex_enter(&instance->config_dev_mtx);
4257 4257 instance->mr_ld_list[tgt].flag = (uint8_t)~MRDRV_TGT_VALID;
4258 4258 mutex_exit(&instance->config_dev_mtx);
4259 4259 rval = mrsas_service_evt(instance,
4260 4260 ddi_get16(acc_handle, &evt_detail->args.ld.target_id), 0,
4261 4261 MRSAS_EVT_UNCONFIG_TGT, NULL);
4262 4262 con_log(CL_ANN1, (CE_WARN, "mr_sas: LD DELETED AEN rval = %d "
4263 4263 "tgt id = %d index = %d", rval,
4264 4264 ddi_get16(acc_handle, &evt_detail->args.ld.target_id),
4265 4265 ddi_get8(acc_handle, &evt_detail->args.ld.ld_index)));
4266 4266 break;
4267 4267 } /* End of MR_EVT_LD_DELETED */
4268 4268
4269 4269 case MR_EVT_LD_CREATED: {
4270 4270 rval = mrsas_service_evt(instance,
4271 4271 ddi_get16(acc_handle, &evt_detail->args.ld.target_id), 0,
4272 4272 MRSAS_EVT_CONFIG_TGT, NULL);
4273 4273 con_log(CL_ANN1, (CE_WARN, "mr_sas: LD CREATED AEN rval = %d "
4274 4274 "tgt id = %d index = %d", rval,
4275 4275 ddi_get16(acc_handle, &evt_detail->args.ld.target_id),
4276 4276 ddi_get8(acc_handle, &evt_detail->args.ld.ld_index)));
4277 4277 break;
4278 4278 } /* End of MR_EVT_LD_CREATED */
4279 4279
4280 4280 #ifdef PDSUPPORT
4281 4281 case MR_EVT_PD_REMOVED_EXT: {
4282 4282 if (instance->tbolt || instance->skinny) {
4283 4283 pd_addr = &evt_detail->args.pd_addr;
4284 4284 dtype = pd_addr->scsi_dev_type;
4285 4285 con_log(CL_DLEVEL1, (CE_NOTE,
4286 4286 " MR_EVT_PD_REMOVED_EXT: dtype = %x,"
4287 4287 " arg_type = %d ", dtype, evt_detail->arg_type));
4288 4288 tgt = ddi_get16(acc_handle,
4289 4289 &evt_detail->args.pd.device_id);
4290 4290 mutex_enter(&instance->config_dev_mtx);
4291 4291 instance->mr_tbolt_pd_list[tgt].flag =
4292 4292 (uint8_t)~MRDRV_TGT_VALID;
4293 4293 mutex_exit(&instance->config_dev_mtx);
4294 4294 rval = mrsas_service_evt(instance, ddi_get16(
4295 4295 acc_handle, &evt_detail->args.pd.device_id),
4296 4296 1, MRSAS_EVT_UNCONFIG_TGT, NULL);
4297 4297 con_log(CL_ANN1, (CE_WARN, "mr_sas: PD_REMOVED:"
4298 4298 "rval = %d tgt id = %d ", rval,
4299 4299 ddi_get16(acc_handle,
4300 4300 &evt_detail->args.pd.device_id)));
4301 4301 }
4302 4302 break;
4303 4303 } /* End of MR_EVT_PD_REMOVED_EXT */
4304 4304
4305 4305 case MR_EVT_PD_INSERTED_EXT: {
4306 4306 if (instance->tbolt || instance->skinny) {
4307 4307 rval = mrsas_service_evt(instance,
4308 4308 ddi_get16(acc_handle,
4309 4309 &evt_detail->args.pd.device_id),
4310 4310 1, MRSAS_EVT_CONFIG_TGT, NULL);
4311 4311 con_log(CL_ANN1, (CE_WARN, "mr_sas: PD_INSERTEDi_EXT:"
4312 4312 "rval = %d tgt id = %d ", rval,
4313 4313 ddi_get16(acc_handle,
4314 4314 &evt_detail->args.pd.device_id)));
4315 4315 }
4316 4316 break;
4317 4317 } /* End of MR_EVT_PD_INSERTED_EXT */
4318 4318
4319 4319 case MR_EVT_PD_STATE_CHANGE: {
4320 4320 if (instance->tbolt || instance->skinny) {
4321 4321 tgt = ddi_get16(acc_handle,
4322 4322 &evt_detail->args.pd.device_id);
4323 4323 if ((evt_detail->args.pd_state.prevState ==
4324 4324 PD_SYSTEM) &&
4325 4325 (evt_detail->args.pd_state.newState != PD_SYSTEM)) {
4326 4326 mutex_enter(&instance->config_dev_mtx);
4327 4327 instance->mr_tbolt_pd_list[tgt].flag =
4328 4328 (uint8_t)~MRDRV_TGT_VALID;
4329 4329 mutex_exit(&instance->config_dev_mtx);
4330 4330 rval = mrsas_service_evt(instance,
4331 4331 ddi_get16(acc_handle,
4332 4332 &evt_detail->args.pd.device_id),
4333 4333 1, MRSAS_EVT_UNCONFIG_TGT, NULL);
4334 4334 con_log(CL_ANN1, (CE_WARN, "mr_sas: PD_REMOVED:"
4335 4335 "rval = %d tgt id = %d ", rval,
4336 4336 ddi_get16(acc_handle,
4337 4337 &evt_detail->args.pd.device_id)));
4338 4338 break;
4339 4339 }
4340 4340 if ((evt_detail->args.pd_state.prevState
4341 4341 == UNCONFIGURED_GOOD) &&
4342 4342 (evt_detail->args.pd_state.newState == PD_SYSTEM)) {
4343 4343 rval = mrsas_service_evt(instance,
4344 4344 ddi_get16(acc_handle,
4345 4345 &evt_detail->args.pd.device_id),
4346 4346 1, MRSAS_EVT_CONFIG_TGT, NULL);
4347 4347 con_log(CL_ANN1, (CE_WARN,
4348 4348 "mr_sas: PD_INSERTED: rval = %d "
4349 4349 " tgt id = %d ", rval,
4350 4350 ddi_get16(acc_handle,
4351 4351 &evt_detail->args.pd.device_id)));
4352 4352 break;
4353 4353 }
4354 4354 }
4355 4355 break;
4356 4356 }
4357 4357 #endif
4358 4358
4359 4359 } /* End of Main Switch */
4360 4360
4361 4361 /* get copy of seq_num and class/locale for re-registration */
4362 4362 seq_num = ddi_get32(acc_handle, &evt_detail->seq_num);
4363 4363 seq_num++;
4364 4364 (void) memset(instance->mfi_evt_detail_obj.buffer, 0,
4365 4365 sizeof (struct mrsas_evt_detail));
4366 4366
4367 4367 ddi_put8(acc_handle, &cmd->frame->dcmd.cmd_status, 0x0);
4368 4368 ddi_put32(acc_handle, &cmd->frame->dcmd.mbox.w[0], seq_num);
4369 4369
4370 4370 instance->aen_seq_num = seq_num;
4371 4371
4372 4372 cmd->frame_count = 1;
4373 4373
4374 4374 cmd->retry_count_for_ocr = 0;
4375 4375 cmd->drv_pkt_time = 0;
4376 4376
4377 4377 /* Issue the aen registration frame */
4378 4378 instance->func_ptr->issue_cmd(cmd, instance);
4379 4379 }
4380 4380
4381 4381 /*
4382 4382 * complete_cmd_in_sync_mode - Completes an internal command
4383 4383 * @instance: Adapter soft state
4384 4384 * @cmd: Command to be completed
4385 4385 *
4386 4386 * The issue_cmd_in_sync_mode() function waits for a command to complete
4387 4387 * after it issues a command. This function wakes up that waiting routine by
4388 4388 * calling wake_up() on the wait queue.
4389 4389 */
4390 4390 static void
4391 4391 complete_cmd_in_sync_mode(struct mrsas_instance *instance,
4392 4392 struct mrsas_cmd *cmd)
4393 4393 {
4394 4394 cmd->cmd_status = ddi_get8(cmd->frame_dma_obj.acc_handle,
4395 4395 &cmd->frame->io.cmd_status);
4396 4396
4397 4397 cmd->sync_cmd = MRSAS_FALSE;
4398 4398
4399 4399 con_log(CL_ANN1, (CE_NOTE, "complete_cmd_in_sync_mode called %p \n",
4400 4400 (void *)cmd));
4401 4401
4402 4402 mutex_enter(&instance->int_cmd_mtx);
4403 4403 if (cmd->cmd_status == ENODATA) {
4404 4404 cmd->cmd_status = 0;
4405 4405 }
4406 4406 cv_broadcast(&instance->int_cmd_cv);
4407 4407 mutex_exit(&instance->int_cmd_mtx);
4408 4408
4409 4409 }
4410 4410
4411 4411 /*
4412 4412 * Call this function inside mrsas_softintr.
4413 4413 * mrsas_initiate_ocr_if_fw_is_faulty - Initiates OCR if FW status is faulty
4414 4414 * @instance: Adapter soft state
4415 4415 */
4416 4416
4417 4417 static uint32_t
4418 4418 mrsas_initiate_ocr_if_fw_is_faulty(struct mrsas_instance *instance)
4419 4419 {
4420 4420 uint32_t cur_abs_reg_val;
4421 4421 uint32_t fw_state;
4422 4422
4423 4423 cur_abs_reg_val = instance->func_ptr->read_fw_status_reg(instance);
4424 4424 fw_state = cur_abs_reg_val & MFI_STATE_MASK;
4425 4425 if (fw_state == MFI_STATE_FAULT) {
4426 4426 if (instance->disable_online_ctrl_reset == 1) {
4427 4427 cmn_err(CE_WARN,
4428 4428 "mrsas_initiate_ocr_if_fw_is_faulty: "
4429 4429 "FW in Fault state, detected in ISR: "
4430 4430 "FW doesn't support ocr ");
4431 4431
4432 4432 return (ADAPTER_RESET_NOT_REQUIRED);
4433 4433 } else {
4434 4434 con_log(CL_ANN, (CE_NOTE,
4435 4435 "mrsas_initiate_ocr_if_fw_is_faulty: FW in Fault "
4436 4436 "state, detected in ISR: FW supports ocr "));
4437 4437
4438 4438 return (ADAPTER_RESET_REQUIRED);
4439 4439 }
4440 4440 }
4441 4441
4442 4442 return (ADAPTER_RESET_NOT_REQUIRED);
4443 4443 }
4444 4444
4445 4445 /*
4446 4446 * mrsas_softintr - The Software ISR
4447 4447 * @param arg : HBA soft state
4448 4448 *
4449 4449 * called from high-level interrupt if hi-level interrupt are not there,
4450 4450 * otherwise triggered as a soft interrupt
4451 4451 */
4452 4452 static uint_t
4453 4453 mrsas_softintr(struct mrsas_instance *instance)
4454 4454 {
4455 4455 struct scsi_pkt *pkt;
4456 4456 struct scsa_cmd *acmd;
4457 4457 struct mrsas_cmd *cmd;
4458 4458 struct mlist_head *pos, *next;
4459 4459 mlist_t process_list;
4460 4460 struct mrsas_header *hdr;
4461 4461 struct scsi_arq_status *arqstat;
4462 4462
4463 4463 con_log(CL_ANN1, (CE_NOTE, "mrsas_softintr() called."));
4464 4464
4465 4465 ASSERT(instance);
4466 4466
4467 4467 mutex_enter(&instance->completed_pool_mtx);
4468 4468
4469 4469 if (mlist_empty(&instance->completed_pool_list)) {
4470 4470 mutex_exit(&instance->completed_pool_mtx);
4471 4471 return (DDI_INTR_CLAIMED);
4472 4472 }
4473 4473
4474 4474 instance->softint_running = 1;
4475 4475
4476 4476 INIT_LIST_HEAD(&process_list);
4477 4477 mlist_splice(&instance->completed_pool_list, &process_list);
4478 4478 INIT_LIST_HEAD(&instance->completed_pool_list);
4479 4479
4480 4480 mutex_exit(&instance->completed_pool_mtx);
4481 4481
4482 4482 /* perform all callbacks first, before releasing the SCBs */
4483 4483 mlist_for_each_safe(pos, next, &process_list) {
4484 4484 cmd = mlist_entry(pos, struct mrsas_cmd, list);
4485 4485
4486 4486 /* syncronize the Cmd frame for the controller */
4487 4487 (void) ddi_dma_sync(cmd->frame_dma_obj.dma_handle,
4488 4488 0, 0, DDI_DMA_SYNC_FORCPU);
4489 4489
4490 4490 if (mrsas_check_dma_handle(cmd->frame_dma_obj.dma_handle) !=
4491 4491 DDI_SUCCESS) {
4492 4492 mrsas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
4493 4493 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
4494 4494 con_log(CL_ANN1, (CE_WARN,
4495 4495 "mrsas_softintr: "
4496 4496 "FMA check reports DMA handle failure"));
4497 4497 return (DDI_INTR_CLAIMED);
4498 4498 }
4499 4499
4500 4500 hdr = &cmd->frame->hdr;
4501 4501
4502 4502 /* remove the internal command from the process list */
4503 4503 mlist_del_init(&cmd->list);
4504 4504
4505 4505 switch (ddi_get8(cmd->frame_dma_obj.acc_handle, &hdr->cmd)) {
4506 4506 case MFI_CMD_OP_PD_SCSI:
4507 4507 case MFI_CMD_OP_LD_SCSI:
4508 4508 case MFI_CMD_OP_LD_READ:
4509 4509 case MFI_CMD_OP_LD_WRITE:
4510 4510 /*
4511 4511 * MFI_CMD_OP_PD_SCSI and MFI_CMD_OP_LD_SCSI
4512 4512 * could have been issued either through an
4513 4513 * IO path or an IOCTL path. If it was via IOCTL,
4514 4514 * we will send it to internal completion.
4515 4515 */
4516 4516 if (cmd->sync_cmd == MRSAS_TRUE) {
4517 4517 complete_cmd_in_sync_mode(instance, cmd);
4518 4518 break;
4519 4519 }
4520 4520
4521 4521 /* regular commands */
4522 4522 acmd = cmd->cmd;
4523 4523 pkt = CMD2PKT(acmd);
4524 4524
4525 4525 if (acmd->cmd_flags & CFLAG_DMAVALID) {
4526 4526 if (acmd->cmd_flags & CFLAG_CONSISTENT) {
4527 4527 (void) ddi_dma_sync(acmd->cmd_dmahandle,
4528 4528 acmd->cmd_dma_offset,
4529 4529 acmd->cmd_dma_len,
4530 4530 DDI_DMA_SYNC_FORCPU);
4531 4531 }
4532 4532 }
4533 4533
4534 4534 pkt->pkt_reason = CMD_CMPLT;
4535 4535 pkt->pkt_statistics = 0;
4536 4536 pkt->pkt_state = STATE_GOT_BUS
4537 4537 | STATE_GOT_TARGET | STATE_SENT_CMD
4538 4538 | STATE_XFERRED_DATA | STATE_GOT_STATUS;
4539 4539
4540 4540 con_log(CL_ANN, (CE_CONT,
4541 4541 "CDB[0] = %x completed for %s: size %lx context %x",
4542 4542 pkt->pkt_cdbp[0], ((acmd->islogical) ? "LD" : "PD"),
4543 4543 acmd->cmd_dmacount, hdr->context));
4544 4544 DTRACE_PROBE3(softintr_cdb, uint8_t, pkt->pkt_cdbp[0],
4545 4545 uint_t, acmd->cmd_cdblen, ulong_t,
4546 4546 acmd->cmd_dmacount);
4547 4547
4548 4548 if (pkt->pkt_cdbp[0] == SCMD_INQUIRY) {
4549 4549 struct scsi_inquiry *inq;
4550 4550
4551 4551 if (acmd->cmd_dmacount != 0) {
4552 4552 bp_mapin(acmd->cmd_buf);
4553 4553 inq = (struct scsi_inquiry *)
4554 4554 acmd->cmd_buf->b_un.b_addr;
4555 4555
4556 4556 #ifdef PDSUPPORT
4557 4557 if (hdr->cmd_status == MFI_STAT_OK) {
4558 4558 display_scsi_inquiry(
4559 4559 (caddr_t)inq);
4560 4560 }
4561 4561 #else
4562 4562 /* don't expose physical drives to OS */
4563 4563 if (acmd->islogical &&
4564 4564 (hdr->cmd_status == MFI_STAT_OK)) {
4565 4565 display_scsi_inquiry(
4566 4566 (caddr_t)inq);
4567 4567 } else if ((hdr->cmd_status ==
4568 4568 MFI_STAT_OK) && inq->inq_dtype ==
4569 4569 DTYPE_DIRECT) {
4570 4570
4571 4571 display_scsi_inquiry(
4572 4572 (caddr_t)inq);
4573 4573
4574 4574 /* for physical disk */
4575 4575 hdr->cmd_status =
4576 4576 MFI_STAT_DEVICE_NOT_FOUND;
4577 4577 }
4578 4578 #endif /* PDSUPPORT */
4579 4579 }
4580 4580 }
4581 4581
4582 4582 DTRACE_PROBE2(softintr_done, uint8_t, hdr->cmd,
4583 4583 uint8_t, hdr->cmd_status);
4584 4584
4585 4585 switch (hdr->cmd_status) {
4586 4586 case MFI_STAT_OK:
4587 4587 pkt->pkt_scbp[0] = STATUS_GOOD;
4588 4588 break;
4589 4589 case MFI_STAT_LD_CC_IN_PROGRESS:
4590 4590 case MFI_STAT_LD_RECON_IN_PROGRESS:
4591 4591 pkt->pkt_scbp[0] = STATUS_GOOD;
4592 4592 break;
4593 4593 case MFI_STAT_LD_INIT_IN_PROGRESS:
4594 4594 con_log(CL_ANN,
4595 4595 (CE_WARN, "Initialization in Progress"));
4596 4596 pkt->pkt_reason = CMD_TRAN_ERR;
4597 4597
4598 4598 break;
4599 4599 case MFI_STAT_SCSI_DONE_WITH_ERROR:
4600 4600 con_log(CL_ANN, (CE_CONT, "scsi_done error"));
4601 4601
4602 4602 pkt->pkt_reason = CMD_CMPLT;
4603 4603 ((struct scsi_status *)
4604 4604 pkt->pkt_scbp)->sts_chk = 1;
4605 4605
4606 4606 if (pkt->pkt_cdbp[0] == SCMD_TEST_UNIT_READY) {
4607 4607 con_log(CL_ANN,
4608 4608 (CE_WARN, "TEST_UNIT_READY fail"));
4609 4609 } else {
4610 4610 pkt->pkt_state |= STATE_ARQ_DONE;
4611 4611 arqstat = (void *)(pkt->pkt_scbp);
4612 4612 arqstat->sts_rqpkt_reason = CMD_CMPLT;
4613 4613 arqstat->sts_rqpkt_resid = 0;
4614 4614 arqstat->sts_rqpkt_state |=
4615 4615 STATE_GOT_BUS | STATE_GOT_TARGET
4616 4616 | STATE_SENT_CMD
4617 4617 | STATE_XFERRED_DATA;
4618 4618 *(uint8_t *)&arqstat->sts_rqpkt_status =
4619 4619 STATUS_GOOD;
4620 4620 ddi_rep_get8(
4621 4621 cmd->frame_dma_obj.acc_handle,
4622 4622 (uint8_t *)
4623 4623 &(arqstat->sts_sensedata),
4624 4624 cmd->sense,
4625 4625 sizeof (struct scsi_extended_sense),
4626 4626 DDI_DEV_AUTOINCR);
4627 4627 }
4628 4628 break;
4629 4629 case MFI_STAT_LD_OFFLINE:
4630 4630 case MFI_STAT_DEVICE_NOT_FOUND:
4631 4631 con_log(CL_ANN, (CE_CONT,
4632 4632 "mrsas_softintr:device not found error"));
4633 4633 pkt->pkt_reason = CMD_DEV_GONE;
4634 4634 pkt->pkt_statistics = STAT_DISCON;
4635 4635 break;
4636 4636 case MFI_STAT_LD_LBA_OUT_OF_RANGE:
4637 4637 pkt->pkt_state |= STATE_ARQ_DONE;
4638 4638 pkt->pkt_reason = CMD_CMPLT;
4639 4639 ((struct scsi_status *)
4640 4640 pkt->pkt_scbp)->sts_chk = 1;
4641 4641
4642 4642 arqstat = (void *)(pkt->pkt_scbp);
4643 4643 arqstat->sts_rqpkt_reason = CMD_CMPLT;
4644 4644 arqstat->sts_rqpkt_resid = 0;
4645 4645 arqstat->sts_rqpkt_state |= STATE_GOT_BUS
4646 4646 | STATE_GOT_TARGET | STATE_SENT_CMD
4647 4647 | STATE_XFERRED_DATA;
4648 4648 *(uint8_t *)&arqstat->sts_rqpkt_status =
4649 4649 STATUS_GOOD;
4650 4650
4651 4651 arqstat->sts_sensedata.es_valid = 1;
4652 4652 arqstat->sts_sensedata.es_key =
4653 4653 KEY_ILLEGAL_REQUEST;
4654 4654 arqstat->sts_sensedata.es_class =
4655 4655 CLASS_EXTENDED_SENSE;
4656 4656
4657 4657 /*
4658 4658 * LOGICAL BLOCK ADDRESS OUT OF RANGE:
4659 4659 * ASC: 0x21h; ASCQ: 0x00h;
4660 4660 */
4661 4661 arqstat->sts_sensedata.es_add_code = 0x21;
4662 4662 arqstat->sts_sensedata.es_qual_code = 0x00;
4663 4663
4664 4664 break;
4665 4665
4666 4666 default:
4667 4667 con_log(CL_ANN, (CE_CONT, "Unknown status!"));
4668 4668 pkt->pkt_reason = CMD_TRAN_ERR;
4669 4669
4670 4670 break;
4671 4671 }
4672 4672
4673 4673 atomic_add_16(&instance->fw_outstanding, (-1));
4674 4674
4675 4675 (void) mrsas_common_check(instance, cmd);
4676 4676
4677 4677 if (acmd->cmd_dmahandle) {
4678 4678 if (mrsas_check_dma_handle(
4679 4679 acmd->cmd_dmahandle) != DDI_SUCCESS) {
4680 4680 ddi_fm_service_impact(instance->dip,
4681 4681 DDI_SERVICE_UNAFFECTED);
4682 4682 pkt->pkt_reason = CMD_TRAN_ERR;
4683 4683 pkt->pkt_statistics = 0;
4684 4684 }
4685 4685 }
4686 4686
4687 4687 mrsas_return_mfi_pkt(instance, cmd);
4688 4688
4689 4689 /* Call the callback routine */
4690 4690 if (((pkt->pkt_flags & FLAG_NOINTR) == 0) &&
4691 4691 pkt->pkt_comp) {
4692 4692 (*pkt->pkt_comp)(pkt);
4693 4693 }
4694 4694
4695 4695 break;
4696 4696
4697 4697 case MFI_CMD_OP_SMP:
4698 4698 case MFI_CMD_OP_STP:
4699 4699 complete_cmd_in_sync_mode(instance, cmd);
4700 4700 break;
4701 4701
4702 4702 case MFI_CMD_OP_DCMD:
4703 4703 /* see if got an event notification */
4704 4704 if (ddi_get32(cmd->frame_dma_obj.acc_handle,
4705 4705 &cmd->frame->dcmd.opcode) ==
4706 4706 MR_DCMD_CTRL_EVENT_WAIT) {
4707 4707 if ((instance->aen_cmd == cmd) &&
4708 4708 (instance->aen_cmd->abort_aen)) {
4709 4709 con_log(CL_ANN, (CE_WARN,
4710 4710 "mrsas_softintr: "
4711 4711 "aborted_aen returned"));
4712 4712 } else {
4713 4713 atomic_add_16(&instance->fw_outstanding,
4714 4714 (-1));
4715 4715 service_mfi_aen(instance, cmd);
4716 4716 }
4717 4717 } else {
4718 4718 complete_cmd_in_sync_mode(instance, cmd);
4719 4719 }
4720 4720
4721 4721 break;
4722 4722
4723 4723 case MFI_CMD_OP_ABORT:
4724 4724 con_log(CL_ANN, (CE_NOTE, "MFI_CMD_OP_ABORT complete"));
4725 4725 /*
4726 4726 * MFI_CMD_OP_ABORT successfully completed
4727 4727 * in the synchronous mode
4728 4728 */
4729 4729 complete_cmd_in_sync_mode(instance, cmd);
4730 4730 break;
4731 4731
4732 4732 default:
4733 4733 mrsas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
4734 4734 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
4735 4735
4736 4736 if (cmd->pkt != NULL) {
4737 4737 pkt = cmd->pkt;
4738 4738 if (((pkt->pkt_flags & FLAG_NOINTR) == 0) &&
4739 4739 pkt->pkt_comp) {
4740 4740
4741 4741 con_log(CL_ANN1, (CE_CONT, "posting to "
4742 4742 "scsa cmd %p index %x pkt %p"
4743 4743 "time %llx, default ", (void *)cmd,
4744 4744 cmd->index, (void *)pkt,
4745 4745 gethrtime()));
4746 4746
4747 4747 (*pkt->pkt_comp)(pkt);
4748 4748
4749 4749 }
4750 4750 }
4751 4751 con_log(CL_ANN, (CE_WARN, "Cmd type unknown !"));
4752 4752 break;
4753 4753 }
4754 4754 }
4755 4755
4756 4756 instance->softint_running = 0;
4757 4757
4758 4758 return (DDI_INTR_CLAIMED);
4759 4759 }
4760 4760
4761 4761 /*
4762 4762 * mrsas_alloc_dma_obj
4763 4763 *
4764 4764 * Allocate the memory and other resources for an dma object.
4765 4765 */
4766 4766 int
4767 4767 mrsas_alloc_dma_obj(struct mrsas_instance *instance, dma_obj_t *obj,
4768 4768 uchar_t endian_flags)
4769 4769 {
4770 4770 int i;
4771 4771 size_t alen = 0;
4772 4772 uint_t cookie_cnt;
4773 4773 struct ddi_device_acc_attr tmp_endian_attr;
4774 4774
4775 4775 tmp_endian_attr = endian_attr;
4776 4776 tmp_endian_attr.devacc_attr_endian_flags = endian_flags;
4777 4777 tmp_endian_attr.devacc_attr_access = DDI_DEFAULT_ACC;
4778 4778
4779 4779 i = ddi_dma_alloc_handle(instance->dip, &obj->dma_attr,
4780 4780 DDI_DMA_SLEEP, NULL, &obj->dma_handle);
4781 4781 if (i != DDI_SUCCESS) {
4782 4782
4783 4783 switch (i) {
4784 4784 case DDI_DMA_BADATTR :
4785 4785 con_log(CL_ANN, (CE_WARN,
4786 4786 "Failed ddi_dma_alloc_handle- Bad attribute"));
4787 4787 break;
4788 4788 case DDI_DMA_NORESOURCES :
4789 4789 con_log(CL_ANN, (CE_WARN,
4790 4790 "Failed ddi_dma_alloc_handle- No Resources"));
4791 4791 break;
4792 4792 default :
4793 4793 con_log(CL_ANN, (CE_WARN,
4794 4794 "Failed ddi_dma_alloc_handle: "
4795 4795 "unknown status %d", i));
4796 4796 break;
4797 4797 }
4798 4798
4799 4799 return (-1);
4800 4800 }
4801 4801
4802 4802 if ((ddi_dma_mem_alloc(obj->dma_handle, obj->size, &tmp_endian_attr,
4803 4803 DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
4804 4804 &obj->buffer, &alen, &obj->acc_handle) != DDI_SUCCESS) ||
4805 4805 alen < obj->size) {
4806 4806
4807 4807 ddi_dma_free_handle(&obj->dma_handle);
4808 4808
4809 4809 con_log(CL_ANN, (CE_WARN, "Failed : ddi_dma_mem_alloc"));
4810 4810
4811 4811 return (-1);
4812 4812 }
4813 4813
4814 4814 if (ddi_dma_addr_bind_handle(obj->dma_handle, NULL, obj->buffer,
4815 4815 obj->size, DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_SLEEP,
4816 4816 NULL, &obj->dma_cookie[0], &cookie_cnt) != DDI_SUCCESS) {
4817 4817
4818 4818 ddi_dma_mem_free(&obj->acc_handle);
4819 4819 ddi_dma_free_handle(&obj->dma_handle);
4820 4820
4821 4821 con_log(CL_ANN, (CE_WARN, "Failed : ddi_dma_addr_bind_handle"));
4822 4822
4823 4823 return (-1);
4824 4824 }
4825 4825
4826 4826 if (mrsas_check_dma_handle(obj->dma_handle) != DDI_SUCCESS) {
4827 4827 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
4828 4828 return (-1);
4829 4829 }
4830 4830
4831 4831 if (mrsas_check_acc_handle(obj->acc_handle) != DDI_SUCCESS) {
4832 4832 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
4833 4833 return (-1);
4834 4834 }
4835 4835
4836 4836 return (cookie_cnt);
4837 4837 }
4838 4838
4839 4839 /*
4840 4840 * mrsas_free_dma_obj(struct mrsas_instance *, dma_obj_t)
4841 4841 *
4842 4842 * De-allocate the memory and other resources for an dma object, which must
4843 4843 * have been alloated by a previous call to mrsas_alloc_dma_obj()
4844 4844 */
4845 4845 int
4846 4846 mrsas_free_dma_obj(struct mrsas_instance *instance, dma_obj_t obj)
4847 4847 {
4848 4848
4849 4849 if ((obj.dma_handle == NULL) || (obj.acc_handle == NULL)) {
4850 4850 return (DDI_SUCCESS);
4851 4851 }
4852 4852
4853 4853 /*
4854 4854 * NOTE: These check-handle functions fail if *_handle == NULL, but
4855 4855 * this function succeeds because of the previous check.
4856 4856 */
4857 4857 if (mrsas_check_dma_handle(obj.dma_handle) != DDI_SUCCESS) {
4858 4858 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
4859 4859 return (DDI_FAILURE);
4860 4860 }
4861 4861
4862 4862 if (mrsas_check_acc_handle(obj.acc_handle) != DDI_SUCCESS) {
4863 4863 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
4864 4864 return (DDI_FAILURE);
4865 4865 }
4866 4866
4867 4867 (void) ddi_dma_unbind_handle(obj.dma_handle);
4868 4868 ddi_dma_mem_free(&obj.acc_handle);
4869 4869 ddi_dma_free_handle(&obj.dma_handle);
4870 4870 obj.acc_handle = NULL;
4871 4871 return (DDI_SUCCESS);
4872 4872 }
4873 4873
4874 4874 /*
4875 4875 * mrsas_dma_alloc(instance_t *, struct scsi_pkt *, struct buf *,
4876 4876 * int, int (*)())
4877 4877 *
4878 4878 * Allocate dma resources for a new scsi command
4879 4879 */
4880 4880 int
4881 4881 mrsas_dma_alloc(struct mrsas_instance *instance, struct scsi_pkt *pkt,
4882 4882 struct buf *bp, int flags, int (*callback)())
4883 4883 {
4884 4884 int dma_flags;
4885 4885 int (*cb)(caddr_t);
4886 4886 int i;
4887 4887
4888 4888 ddi_dma_attr_t tmp_dma_attr = mrsas_generic_dma_attr;
4889 4889 struct scsa_cmd *acmd = PKT2CMD(pkt);
4890 4890
4891 4891 acmd->cmd_buf = bp;
4892 4892
4893 4893 if (bp->b_flags & B_READ) {
4894 4894 acmd->cmd_flags &= ~CFLAG_DMASEND;
4895 4895 dma_flags = DDI_DMA_READ;
4896 4896 } else {
4897 4897 acmd->cmd_flags |= CFLAG_DMASEND;
4898 4898 dma_flags = DDI_DMA_WRITE;
4899 4899 }
4900 4900
4901 4901 if (flags & PKT_CONSISTENT) {
4902 4902 acmd->cmd_flags |= CFLAG_CONSISTENT;
4903 4903 dma_flags |= DDI_DMA_CONSISTENT;
4904 4904 }
4905 4905
4906 4906 if (flags & PKT_DMA_PARTIAL) {
4907 4907 dma_flags |= DDI_DMA_PARTIAL;
4908 4908 }
4909 4909
4910 4910 dma_flags |= DDI_DMA_REDZONE;
4911 4911
4912 4912 cb = (callback == NULL_FUNC) ? DDI_DMA_DONTWAIT : DDI_DMA_SLEEP;
4913 4913
4914 4914 tmp_dma_attr.dma_attr_sgllen = instance->max_num_sge;
4915 4915 tmp_dma_attr.dma_attr_addr_hi = 0xffffffffffffffffull;
4916 4916 if (instance->tbolt) {
4917 4917 /* OCR-RESET FIX */
4918 4918 tmp_dma_attr.dma_attr_count_max =
4919 4919 (U64)mrsas_tbolt_max_cap_maxxfer; /* limit to 256K */
4920 4920 tmp_dma_attr.dma_attr_maxxfer =
4921 4921 (U64)mrsas_tbolt_max_cap_maxxfer; /* limit to 256K */
4922 4922 }
4923 4923
4924 4924 if ((i = ddi_dma_alloc_handle(instance->dip, &tmp_dma_attr,
4925 4925 cb, 0, &acmd->cmd_dmahandle)) != DDI_SUCCESS) {
4926 4926 switch (i) {
4927 4927 case DDI_DMA_BADATTR:
4928 4928 bioerror(bp, EFAULT);
4929 4929 return (DDI_FAILURE);
4930 4930
4931 4931 case DDI_DMA_NORESOURCES:
4932 4932 bioerror(bp, 0);
4933 4933 return (DDI_FAILURE);
4934 4934
4935 4935 default:
4936 4936 con_log(CL_ANN, (CE_PANIC, "ddi_dma_alloc_handle: "
4937 4937 "impossible result (0x%x)", i));
4938 4938 bioerror(bp, EFAULT);
4939 4939 return (DDI_FAILURE);
4940 4940 }
4941 4941 }
4942 4942
4943 4943 i = ddi_dma_buf_bind_handle(acmd->cmd_dmahandle, bp, dma_flags,
4944 4944 cb, 0, &acmd->cmd_dmacookies[0], &acmd->cmd_ncookies);
4945 4945
4946 4946 switch (i) {
4947 4947 case DDI_DMA_PARTIAL_MAP:
4948 4948 if ((dma_flags & DDI_DMA_PARTIAL) == 0) {
4949 4949 con_log(CL_ANN, (CE_PANIC, "ddi_dma_buf_bind_handle: "
4950 4950 "DDI_DMA_PARTIAL_MAP impossible"));
4951 4951 goto no_dma_cookies;
4952 4952 }
4953 4953
4954 4954 if (ddi_dma_numwin(acmd->cmd_dmahandle, &acmd->cmd_nwin) ==
4955 4955 DDI_FAILURE) {
4956 4956 con_log(CL_ANN, (CE_PANIC, "ddi_dma_numwin failed"));
4957 4957 goto no_dma_cookies;
4958 4958 }
4959 4959
4960 4960 if (ddi_dma_getwin(acmd->cmd_dmahandle, acmd->cmd_curwin,
4961 4961 &acmd->cmd_dma_offset, &acmd->cmd_dma_len,
4962 4962 &acmd->cmd_dmacookies[0], &acmd->cmd_ncookies) ==
4963 4963 DDI_FAILURE) {
4964 4964
4965 4965 con_log(CL_ANN, (CE_PANIC, "ddi_dma_getwin failed"));
4966 4966 goto no_dma_cookies;
4967 4967 }
4968 4968
4969 4969 goto get_dma_cookies;
4970 4970 case DDI_DMA_MAPPED:
4971 4971 acmd->cmd_nwin = 1;
4972 4972 acmd->cmd_dma_len = 0;
4973 4973 acmd->cmd_dma_offset = 0;
4974 4974
4975 4975 get_dma_cookies:
4976 4976 i = 0;
4977 4977 acmd->cmd_dmacount = 0;
4978 4978 for (;;) {
4979 4979 acmd->cmd_dmacount +=
4980 4980 acmd->cmd_dmacookies[i++].dmac_size;
4981 4981
4982 4982 if (i == instance->max_num_sge ||
4983 4983 i == acmd->cmd_ncookies)
4984 4984 break;
4985 4985
4986 4986 ddi_dma_nextcookie(acmd->cmd_dmahandle,
4987 4987 &acmd->cmd_dmacookies[i]);
4988 4988 }
4989 4989
4990 4990 acmd->cmd_cookie = i;
4991 4991 acmd->cmd_cookiecnt = i;
4992 4992
4993 4993 acmd->cmd_flags |= CFLAG_DMAVALID;
4994 4994
4995 4995 if (bp->b_bcount >= acmd->cmd_dmacount) {
4996 4996 pkt->pkt_resid = bp->b_bcount - acmd->cmd_dmacount;
4997 4997 } else {
4998 4998 pkt->pkt_resid = 0;
4999 4999 }
5000 5000
5001 5001 return (DDI_SUCCESS);
5002 5002 case DDI_DMA_NORESOURCES:
5003 5003 bioerror(bp, 0);
5004 5004 break;
5005 5005 case DDI_DMA_NOMAPPING:
5006 5006 bioerror(bp, EFAULT);
5007 5007 break;
5008 5008 case DDI_DMA_TOOBIG:
5009 5009 bioerror(bp, EINVAL);
5010 5010 break;
5011 5011 case DDI_DMA_INUSE:
5012 5012 con_log(CL_ANN, (CE_PANIC, "ddi_dma_buf_bind_handle:"
5013 5013 " DDI_DMA_INUSE impossible"));
5014 5014 break;
5015 5015 default:
5016 5016 con_log(CL_ANN, (CE_PANIC, "ddi_dma_buf_bind_handle: "
5017 5017 "impossible result (0x%x)", i));
5018 5018 break;
5019 5019 }
5020 5020
5021 5021 no_dma_cookies:
5022 5022 ddi_dma_free_handle(&acmd->cmd_dmahandle);
5023 5023 acmd->cmd_dmahandle = NULL;
5024 5024 acmd->cmd_flags &= ~CFLAG_DMAVALID;
5025 5025 return (DDI_FAILURE);
5026 5026 }
5027 5027
5028 5028 /*
5029 5029 * mrsas_dma_move(struct mrsas_instance *, struct scsi_pkt *, struct buf *)
5030 5030 *
5031 5031 * move dma resources to next dma window
5032 5032 *
5033 5033 */
5034 5034 int
5035 5035 mrsas_dma_move(struct mrsas_instance *instance, struct scsi_pkt *pkt,
5036 5036 struct buf *bp)
5037 5037 {
5038 5038 int i = 0;
5039 5039
5040 5040 struct scsa_cmd *acmd = PKT2CMD(pkt);
5041 5041
5042 5042 /*
5043 5043 * If there are no more cookies remaining in this window,
5044 5044 * must move to the next window first.
5045 5045 */
5046 5046 if (acmd->cmd_cookie == acmd->cmd_ncookies) {
5047 5047 if (acmd->cmd_curwin == acmd->cmd_nwin && acmd->cmd_nwin == 1) {
5048 5048 return (DDI_SUCCESS);
5049 5049 }
5050 5050
5051 5051 /* at last window, cannot move */
5052 5052 if (++acmd->cmd_curwin >= acmd->cmd_nwin) {
5053 5053 return (DDI_FAILURE);
5054 5054 }
5055 5055
5056 5056 if (ddi_dma_getwin(acmd->cmd_dmahandle, acmd->cmd_curwin,
5057 5057 &acmd->cmd_dma_offset, &acmd->cmd_dma_len,
5058 5058 &acmd->cmd_dmacookies[0], &acmd->cmd_ncookies) ==
5059 5059 DDI_FAILURE) {
5060 5060 return (DDI_FAILURE);
5061 5061 }
5062 5062
5063 5063 acmd->cmd_cookie = 0;
5064 5064 } else {
5065 5065 /* still more cookies in this window - get the next one */
5066 5066 ddi_dma_nextcookie(acmd->cmd_dmahandle,
5067 5067 &acmd->cmd_dmacookies[0]);
5068 5068 }
5069 5069
5070 5070 /* get remaining cookies in this window, up to our maximum */
5071 5071 for (;;) {
5072 5072 acmd->cmd_dmacount += acmd->cmd_dmacookies[i++].dmac_size;
5073 5073 acmd->cmd_cookie++;
5074 5074
5075 5075 if (i == instance->max_num_sge ||
5076 5076 acmd->cmd_cookie == acmd->cmd_ncookies) {
5077 5077 break;
5078 5078 }
5079 5079
5080 5080 ddi_dma_nextcookie(acmd->cmd_dmahandle,
5081 5081 &acmd->cmd_dmacookies[i]);
5082 5082 }
5083 5083
5084 5084 acmd->cmd_cookiecnt = i;
5085 5085
5086 5086 if (bp->b_bcount >= acmd->cmd_dmacount) {
5087 5087 pkt->pkt_resid = bp->b_bcount - acmd->cmd_dmacount;
5088 5088 } else {
5089 5089 pkt->pkt_resid = 0;
5090 5090 }
5091 5091
5092 5092 return (DDI_SUCCESS);
5093 5093 }
5094 5094
5095 5095 /*
5096 5096 * build_cmd
5097 5097 */
5098 5098 static struct mrsas_cmd *
5099 5099 build_cmd(struct mrsas_instance *instance, struct scsi_address *ap,
5100 5100 struct scsi_pkt *pkt, uchar_t *cmd_done)
5101 5101 {
5102 5102 uint16_t flags = 0;
5103 5103 uint32_t i;
5104 5104 uint32_t context;
5105 5105 uint32_t sge_bytes;
5106 5106 uint32_t tmp_data_xfer_len;
5107 5107 ddi_acc_handle_t acc_handle;
5108 5108 struct mrsas_cmd *cmd;
5109 5109 struct mrsas_sge64 *mfi_sgl;
5110 5110 struct mrsas_sge_ieee *mfi_sgl_ieee;
5111 5111 struct scsa_cmd *acmd = PKT2CMD(pkt);
5112 5112 struct mrsas_pthru_frame *pthru;
5113 5113 struct mrsas_io_frame *ldio;
5114 5114
5115 5115 /* find out if this is logical or physical drive command. */
5116 5116 acmd->islogical = MRDRV_IS_LOGICAL(ap);
5117 5117 acmd->device_id = MAP_DEVICE_ID(instance, ap);
5118 5118 *cmd_done = 0;
5119 5119
5120 5120 /* get the command packet */
5121 5121 if (!(cmd = mrsas_get_mfi_pkt(instance))) {
5122 5122 DTRACE_PROBE2(build_cmd_mfi_err, uint16_t,
5123 5123 instance->fw_outstanding, uint16_t, instance->max_fw_cmds);
5124 5124 return (NULL);
5125 5125 }
5126 5126
5127 5127 acc_handle = cmd->frame_dma_obj.acc_handle;
5128 5128
5129 5129 /* Clear the frame buffer and assign back the context id */
5130 5130 (void) memset((char *)&cmd->frame[0], 0, sizeof (union mrsas_frame));
5131 5131 ddi_put32(acc_handle, &cmd->frame->hdr.context, cmd->index);
5132 5132
5133 5133 cmd->pkt = pkt;
5134 5134 cmd->cmd = acmd;
5135 5135 DTRACE_PROBE3(build_cmds, uint8_t, pkt->pkt_cdbp[0],
5136 5136 ulong_t, acmd->cmd_dmacount, ulong_t, acmd->cmd_dma_len);
5137 5137
5138 5138 /* lets get the command directions */
5139 5139 if (acmd->cmd_flags & CFLAG_DMASEND) {
5140 5140 flags = MFI_FRAME_DIR_WRITE;
5141 5141
5142 5142 if (acmd->cmd_flags & CFLAG_CONSISTENT) {
5143 5143 (void) ddi_dma_sync(acmd->cmd_dmahandle,
5144 5144 acmd->cmd_dma_offset, acmd->cmd_dma_len,
5145 5145 DDI_DMA_SYNC_FORDEV);
5146 5146 }
5147 5147 } else if (acmd->cmd_flags & ~CFLAG_DMASEND) {
5148 5148 flags = MFI_FRAME_DIR_READ;
5149 5149
5150 5150 if (acmd->cmd_flags & CFLAG_CONSISTENT) {
5151 5151 (void) ddi_dma_sync(acmd->cmd_dmahandle,
5152 5152 acmd->cmd_dma_offset, acmd->cmd_dma_len,
5153 5153 DDI_DMA_SYNC_FORCPU);
5154 5154 }
5155 5155 } else {
5156 5156 flags = MFI_FRAME_DIR_NONE;
5157 5157 }
5158 5158
5159 5159 if (instance->flag_ieee) {
5160 5160 flags |= MFI_FRAME_IEEE;
5161 5161 }
5162 5162 flags |= MFI_FRAME_SGL64;
5163 5163
5164 5164 switch (pkt->pkt_cdbp[0]) {
5165 5165
5166 5166 /*
5167 5167 * case SCMD_SYNCHRONIZE_CACHE:
5168 5168 * flush_cache(instance);
5169 5169 * mrsas_return_mfi_pkt(instance, cmd);
5170 5170 * *cmd_done = 1;
5171 5171 *
5172 5172 * return (NULL);
5173 5173 */
5174 5174
5175 5175 case SCMD_READ:
5176 5176 case SCMD_WRITE:
5177 5177 case SCMD_READ_G1:
5178 5178 case SCMD_WRITE_G1:
5179 5179 case SCMD_READ_G4:
5180 5180 case SCMD_WRITE_G4:
5181 5181 case SCMD_READ_G5:
5182 5182 case SCMD_WRITE_G5:
5183 5183 if (acmd->islogical) {
5184 5184 ldio = (struct mrsas_io_frame *)cmd->frame;
5185 5185
5186 5186 /*
5187 5187 * preare the Logical IO frame:
5188 5188 * 2nd bit is zero for all read cmds
5189 5189 */
5190 5190 ddi_put8(acc_handle, &ldio->cmd,
5191 5191 (pkt->pkt_cdbp[0] & 0x02) ? MFI_CMD_OP_LD_WRITE
5192 5192 : MFI_CMD_OP_LD_READ);
5193 5193 ddi_put8(acc_handle, &ldio->cmd_status, 0x0);
5194 5194 ddi_put8(acc_handle, &ldio->scsi_status, 0x0);
5195 5195 ddi_put8(acc_handle, &ldio->target_id, acmd->device_id);
5196 5196 ddi_put16(acc_handle, &ldio->timeout, 0);
5197 5197 ddi_put8(acc_handle, &ldio->reserved_0, 0);
5198 5198 ddi_put16(acc_handle, &ldio->pad_0, 0);
5199 5199 ddi_put16(acc_handle, &ldio->flags, flags);
5200 5200
5201 5201 /* Initialize sense Information */
5202 5202 bzero(cmd->sense, SENSE_LENGTH);
5203 5203 ddi_put8(acc_handle, &ldio->sense_len, SENSE_LENGTH);
5204 5204 ddi_put32(acc_handle, &ldio->sense_buf_phys_addr_hi, 0);
5205 5205 ddi_put32(acc_handle, &ldio->sense_buf_phys_addr_lo,
5206 5206 cmd->sense_phys_addr);
5207 5207 ddi_put32(acc_handle, &ldio->start_lba_hi, 0);
5208 5208 ddi_put8(acc_handle, &ldio->access_byte,
5209 5209 (acmd->cmd_cdblen != 6) ? pkt->pkt_cdbp[1] : 0);
5210 5210 ddi_put8(acc_handle, &ldio->sge_count,
5211 5211 acmd->cmd_cookiecnt);
5212 5212 if (instance->flag_ieee) {
5213 5213 mfi_sgl_ieee =
5214 5214 (struct mrsas_sge_ieee *)&ldio->sgl;
5215 5215 } else {
5216 5216 mfi_sgl = (struct mrsas_sge64 *)&ldio->sgl;
5217 5217 }
5218 5218
5219 5219 context = ddi_get32(acc_handle, &ldio->context);
5220 5220
5221 5221 if (acmd->cmd_cdblen == CDB_GROUP0) {
5222 5222 /* 6-byte cdb */
5223 5223 ddi_put32(acc_handle, &ldio->lba_count, (
5224 5224 (uint16_t)(pkt->pkt_cdbp[4])));
5225 5225
5226 5226 ddi_put32(acc_handle, &ldio->start_lba_lo, (
5227 5227 ((uint32_t)(pkt->pkt_cdbp[3])) |
5228 5228 ((uint32_t)(pkt->pkt_cdbp[2]) << 8) |
5229 5229 ((uint32_t)((pkt->pkt_cdbp[1]) & 0x1F)
5230 5230 << 16)));
5231 5231 } else if (acmd->cmd_cdblen == CDB_GROUP1) {
5232 5232 /* 10-byte cdb */
5233 5233 ddi_put32(acc_handle, &ldio->lba_count, (
5234 5234 ((uint16_t)(pkt->pkt_cdbp[8])) |
5235 5235 ((uint16_t)(pkt->pkt_cdbp[7]) << 8)));
5236 5236
5237 5237 ddi_put32(acc_handle, &ldio->start_lba_lo, (
5238 5238 ((uint32_t)(pkt->pkt_cdbp[5])) |
5239 5239 ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
5240 5240 ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
5241 5241 ((uint32_t)(pkt->pkt_cdbp[2]) << 24)));
5242 5242 } else if (acmd->cmd_cdblen == CDB_GROUP5) {
5243 5243 /* 12-byte cdb */
5244 5244 ddi_put32(acc_handle, &ldio->lba_count, (
5245 5245 ((uint32_t)(pkt->pkt_cdbp[9])) |
5246 5246 ((uint32_t)(pkt->pkt_cdbp[8]) << 8) |
5247 5247 ((uint32_t)(pkt->pkt_cdbp[7]) << 16) |
5248 5248 ((uint32_t)(pkt->pkt_cdbp[6]) << 24)));
5249 5249
5250 5250 ddi_put32(acc_handle, &ldio->start_lba_lo, (
5251 5251 ((uint32_t)(pkt->pkt_cdbp[5])) |
5252 5252 ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
5253 5253 ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
5254 5254 ((uint32_t)(pkt->pkt_cdbp[2]) << 24)));
5255 5255 } else if (acmd->cmd_cdblen == CDB_GROUP4) {
5256 5256 /* 16-byte cdb */
5257 5257 ddi_put32(acc_handle, &ldio->lba_count, (
5258 5258 ((uint32_t)(pkt->pkt_cdbp[13])) |
5259 5259 ((uint32_t)(pkt->pkt_cdbp[12]) << 8) |
5260 5260 ((uint32_t)(pkt->pkt_cdbp[11]) << 16) |
5261 5261 ((uint32_t)(pkt->pkt_cdbp[10]) << 24)));
5262 5262
5263 5263 ddi_put32(acc_handle, &ldio->start_lba_lo, (
5264 5264 ((uint32_t)(pkt->pkt_cdbp[9])) |
5265 5265 ((uint32_t)(pkt->pkt_cdbp[8]) << 8) |
5266 5266 ((uint32_t)(pkt->pkt_cdbp[7]) << 16) |
5267 5267 ((uint32_t)(pkt->pkt_cdbp[6]) << 24)));
5268 5268
5269 5269 ddi_put32(acc_handle, &ldio->start_lba_hi, (
5270 5270 ((uint32_t)(pkt->pkt_cdbp[5])) |
5271 5271 ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
5272 5272 ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
5273 5273 ((uint32_t)(pkt->pkt_cdbp[2]) << 24)));
5274 5274 }
5275 5275
5276 5276 break;
5277 5277 }
5278 5278 /* fall through For all non-rd/wr and physical disk cmds */
5279 5279 default:
5280 5280
5281 5281 switch (pkt->pkt_cdbp[0]) {
5282 5282 case SCMD_MODE_SENSE:
5283 5283 case SCMD_MODE_SENSE_G1: {
5284 5284 union scsi_cdb *cdbp;
5285 5285 uint16_t page_code;
5286 5286
5287 5287 cdbp = (void *)pkt->pkt_cdbp;
5288 5288 page_code = (uint16_t)cdbp->cdb_un.sg.scsi[0];
5289 5289 switch (page_code) {
5290 5290 case 0x3:
5291 5291 case 0x4:
5292 5292 (void) mrsas_mode_sense_build(pkt);
5293 5293 mrsas_return_mfi_pkt(instance, cmd);
5294 5294 *cmd_done = 1;
5295 5295 return (NULL);
5296 5296 }
5297 5297 break;
5298 5298 }
5299 5299 default:
5300 5300 break;
5301 5301 }
5302 5302
5303 5303 pthru = (struct mrsas_pthru_frame *)cmd->frame;
5304 5304
5305 5305 /* prepare the DCDB frame */
5306 5306 ddi_put8(acc_handle, &pthru->cmd, (acmd->islogical) ?
5307 5307 MFI_CMD_OP_LD_SCSI : MFI_CMD_OP_PD_SCSI);
5308 5308 ddi_put8(acc_handle, &pthru->cmd_status, 0x0);
5309 5309 ddi_put8(acc_handle, &pthru->scsi_status, 0x0);
5310 5310 ddi_put8(acc_handle, &pthru->target_id, acmd->device_id);
5311 5311 ddi_put8(acc_handle, &pthru->lun, 0);
5312 5312 ddi_put8(acc_handle, &pthru->cdb_len, acmd->cmd_cdblen);
5313 5313 ddi_put16(acc_handle, &pthru->timeout, 0);
5314 5314 ddi_put16(acc_handle, &pthru->flags, flags);
5315 5315 tmp_data_xfer_len = 0;
5316 5316 for (i = 0; i < acmd->cmd_cookiecnt; i++) {
5317 5317 tmp_data_xfer_len += acmd->cmd_dmacookies[i].dmac_size;
5318 5318 }
5319 5319 ddi_put32(acc_handle, &pthru->data_xfer_len,
5320 5320 tmp_data_xfer_len);
5321 5321 ddi_put8(acc_handle, &pthru->sge_count, acmd->cmd_cookiecnt);
5322 5322 if (instance->flag_ieee) {
5323 5323 mfi_sgl_ieee = (struct mrsas_sge_ieee *)&pthru->sgl;
5324 5324 } else {
5325 5325 mfi_sgl = (struct mrsas_sge64 *)&pthru->sgl;
5326 5326 }
5327 5327
5328 5328 bzero(cmd->sense, SENSE_LENGTH);
5329 5329 ddi_put8(acc_handle, &pthru->sense_len, SENSE_LENGTH);
5330 5330 ddi_put32(acc_handle, &pthru->sense_buf_phys_addr_hi, 0);
5331 5331 ddi_put32(acc_handle, &pthru->sense_buf_phys_addr_lo,
5332 5332 cmd->sense_phys_addr);
5333 5333
5334 5334 context = ddi_get32(acc_handle, &pthru->context);
5335 5335 ddi_rep_put8(acc_handle, (uint8_t *)pkt->pkt_cdbp,
5336 5336 (uint8_t *)pthru->cdb, acmd->cmd_cdblen, DDI_DEV_AUTOINCR);
5337 5337
5338 5338 break;
5339 5339 }
5340 5340 #ifdef lint
5341 5341 context = context;
5342 5342 #endif
5343 5343 /* prepare the scatter-gather list for the firmware */
5344 5344 if (instance->flag_ieee) {
5345 5345 for (i = 0; i < acmd->cmd_cookiecnt; i++, mfi_sgl_ieee++) {
5346 5346 ddi_put64(acc_handle, &mfi_sgl_ieee->phys_addr,
5347 5347 acmd->cmd_dmacookies[i].dmac_laddress);
5348 5348 ddi_put32(acc_handle, &mfi_sgl_ieee->length,
5349 5349 acmd->cmd_dmacookies[i].dmac_size);
5350 5350 }
5351 5351 sge_bytes = sizeof (struct mrsas_sge_ieee)*acmd->cmd_cookiecnt;
5352 5352 } else {
5353 5353 for (i = 0; i < acmd->cmd_cookiecnt; i++, mfi_sgl++) {
5354 5354 ddi_put64(acc_handle, &mfi_sgl->phys_addr,
5355 5355 acmd->cmd_dmacookies[i].dmac_laddress);
5356 5356 ddi_put32(acc_handle, &mfi_sgl->length,
5357 5357 acmd->cmd_dmacookies[i].dmac_size);
5358 5358 }
5359 5359 sge_bytes = sizeof (struct mrsas_sge64)*acmd->cmd_cookiecnt;
5360 5360 }
5361 5361
5362 5362 cmd->frame_count = (sge_bytes / MRMFI_FRAME_SIZE) +
5363 5363 ((sge_bytes % MRMFI_FRAME_SIZE) ? 1 : 0) + 1;
5364 5364
5365 5365 if (cmd->frame_count >= 8) {
5366 5366 cmd->frame_count = 8;
5367 5367 }
5368 5368
5369 5369 return (cmd);
5370 5370 }
5371 5371
5372 5372 /*
5373 5373 * wait_for_outstanding - Wait for all outstanding cmds
5374 5374 * @instance: Adapter soft state
5375 5375 *
5376 5376 * This function waits for upto MRDRV_RESET_WAIT_TIME seconds for FW to
5377 5377 * complete all its outstanding commands. Returns error if one or more IOs
5378 5378 * are pending after this time period.
5379 5379 */
5380 5380 static int
5381 5381 wait_for_outstanding(struct mrsas_instance *instance)
5382 5382 {
5383 5383 int i;
5384 5384 uint32_t wait_time = 90;
5385 5385
5386 5386 for (i = 0; i < wait_time; i++) {
5387 5387 if (!instance->fw_outstanding) {
5388 5388 break;
5389 5389 }
5390 5390
5391 5391 drv_usecwait(MILLISEC); /* wait for 1000 usecs */;
5392 5392 }
5393 5393
5394 5394 if (instance->fw_outstanding) {
5395 5395 return (1);
5396 5396 }
5397 5397
5398 5398 return (0);
5399 5399 }
5400 5400
5401 5401 /*
5402 5402 * issue_mfi_pthru
5403 5403 */
5404 5404 static int
5405 5405 issue_mfi_pthru(struct mrsas_instance *instance, struct mrsas_ioctl *ioctl,
5406 5406 struct mrsas_cmd *cmd, int mode)
5407 5407 {
5408 5408 void *ubuf;
5409 5409 uint32_t kphys_addr = 0;
5410 5410 uint32_t xferlen = 0;
5411 5411 uint32_t new_xfer_length = 0;
5412 5412 uint_t model;
5413 5413 ddi_acc_handle_t acc_handle = cmd->frame_dma_obj.acc_handle;
5414 5414 dma_obj_t pthru_dma_obj;
5415 5415 struct mrsas_pthru_frame *kpthru;
5416 5416 struct mrsas_pthru_frame *pthru;
5417 5417 int i;
5418 5418 pthru = &cmd->frame->pthru;
5419 5419 kpthru = (struct mrsas_pthru_frame *)&ioctl->frame[0];
5420 5420
5421 5421 if (instance->adapterresetinprogress) {
5422 5422 con_log(CL_ANN1, (CE_WARN, "issue_mfi_pthru: Reset flag set, "
5423 5423 "returning mfi_pkt and setting TRAN_BUSY\n"));
5424 5424 return (DDI_FAILURE);
5425 5425 }
5426 5426 model = ddi_model_convert_from(mode & FMODELS);
5427 5427 if (model == DDI_MODEL_ILP32) {
5428 5428 con_log(CL_ANN1, (CE_CONT, "issue_mfi_pthru: DDI_MODEL_LP32"));
5429 5429
5430 5430 xferlen = kpthru->sgl.sge32[0].length;
5431 5431
5432 5432 ubuf = (void *)(ulong_t)kpthru->sgl.sge32[0].phys_addr;
5433 5433 } else {
5434 5434 #ifdef _ILP32
5435 5435 con_log(CL_ANN1, (CE_CONT, "issue_mfi_pthru: DDI_MODEL_LP32"));
5436 5436 xferlen = kpthru->sgl.sge32[0].length;
5437 5437 ubuf = (void *)(ulong_t)kpthru->sgl.sge32[0].phys_addr;
5438 5438 #else
5439 5439 con_log(CL_ANN1, (CE_CONT, "issue_mfi_pthru: DDI_MODEL_LP64"));
5440 5440 xferlen = kpthru->sgl.sge64[0].length;
5441 5441 ubuf = (void *)(ulong_t)kpthru->sgl.sge64[0].phys_addr;
5442 5442 #endif
5443 5443 }
5444 5444
5445 5445 if (xferlen) {
5446 5446 /* means IOCTL requires DMA */
5447 5447 /* allocate the data transfer buffer */
5448 5448 /* pthru_dma_obj.size = xferlen; */
5449 5449 MRSAS_GET_BOUNDARY_ALIGNED_LEN(xferlen, new_xfer_length,
5450 5450 PAGESIZE);
5451 5451 pthru_dma_obj.size = new_xfer_length;
5452 5452 pthru_dma_obj.dma_attr = mrsas_generic_dma_attr;
5453 5453 pthru_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
5454 5454 pthru_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
5455 5455 pthru_dma_obj.dma_attr.dma_attr_sgllen = 1;
5456 5456 pthru_dma_obj.dma_attr.dma_attr_align = 1;
5457 5457
5458 5458 /* allocate kernel buffer for DMA */
5459 5459 if (mrsas_alloc_dma_obj(instance, &pthru_dma_obj,
5460 5460 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
5461 5461 con_log(CL_ANN, (CE_WARN, "issue_mfi_pthru: "
5462 5462 "could not allocate data transfer buffer."));
5463 5463 return (DDI_FAILURE);
5464 5464 }
5465 5465 (void) memset(pthru_dma_obj.buffer, 0, xferlen);
5466 5466
5467 5467 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
5468 5468 if (kpthru->flags & MFI_FRAME_DIR_WRITE) {
5469 5469 for (i = 0; i < xferlen; i++) {
5470 5470 if (ddi_copyin((uint8_t *)ubuf+i,
5471 5471 (uint8_t *)pthru_dma_obj.buffer+i,
5472 5472 1, mode)) {
5473 5473 con_log(CL_ANN, (CE_WARN,
5474 5474 "issue_mfi_pthru : "
5475 5475 "copy from user space failed"));
5476 5476 return (DDI_FAILURE);
5477 5477 }
5478 5478 }
5479 5479 }
5480 5480
5481 5481 kphys_addr = pthru_dma_obj.dma_cookie[0].dmac_address;
5482 5482 }
5483 5483
5484 5484 ddi_put8(acc_handle, &pthru->cmd, kpthru->cmd);
5485 5485 ddi_put8(acc_handle, &pthru->sense_len, SENSE_LENGTH);
5486 5486 ddi_put8(acc_handle, &pthru->cmd_status, 0);
5487 5487 ddi_put8(acc_handle, &pthru->scsi_status, 0);
5488 5488 ddi_put8(acc_handle, &pthru->target_id, kpthru->target_id);
5489 5489 ddi_put8(acc_handle, &pthru->lun, kpthru->lun);
5490 5490 ddi_put8(acc_handle, &pthru->cdb_len, kpthru->cdb_len);
5491 5491 ddi_put8(acc_handle, &pthru->sge_count, kpthru->sge_count);
5492 5492 ddi_put16(acc_handle, &pthru->timeout, kpthru->timeout);
5493 5493 ddi_put32(acc_handle, &pthru->data_xfer_len, kpthru->data_xfer_len);
5494 5494
5495 5495 ddi_put32(acc_handle, &pthru->sense_buf_phys_addr_hi, 0);
5496 5496 pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
5497 5497 /* ddi_put32(acc_handle, &pthru->sense_buf_phys_addr_lo, 0); */
5498 5498
5499 5499 ddi_rep_put8(acc_handle, (uint8_t *)kpthru->cdb, (uint8_t *)pthru->cdb,
5500 5500 pthru->cdb_len, DDI_DEV_AUTOINCR);
5501 5501
5502 5502 ddi_put16(acc_handle, &pthru->flags, kpthru->flags & ~MFI_FRAME_SGL64);
5503 5503 ddi_put32(acc_handle, &pthru->sgl.sge32[0].length, xferlen);
5504 5504 ddi_put32(acc_handle, &pthru->sgl.sge32[0].phys_addr, kphys_addr);
5505 5505
5506 5506 cmd->sync_cmd = MRSAS_TRUE;
5507 5507 cmd->frame_count = 1;
5508 5508
5509 5509 if (instance->tbolt) {
5510 5510 mr_sas_tbolt_build_mfi_cmd(instance, cmd);
5511 5511 }
5512 5512
5513 5513 if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
5514 5514 con_log(CL_ANN, (CE_WARN,
5515 5515 "issue_mfi_pthru: fw_ioctl failed"));
5516 5516 } else {
5517 5517 if (xferlen && kpthru->flags & MFI_FRAME_DIR_READ) {
5518 5518 for (i = 0; i < xferlen; i++) {
5519 5519 if (ddi_copyout(
5520 5520 (uint8_t *)pthru_dma_obj.buffer+i,
5521 5521 (uint8_t *)ubuf+i, 1, mode)) {
5522 5522 con_log(CL_ANN, (CE_WARN,
5523 5523 "issue_mfi_pthru : "
5524 5524 "copy to user space failed"));
5525 5525 return (DDI_FAILURE);
5526 5526 }
5527 5527 }
5528 5528 }
5529 5529 }
5530 5530
5531 5531 kpthru->cmd_status = ddi_get8(acc_handle, &pthru->cmd_status);
5532 5532 kpthru->scsi_status = ddi_get8(acc_handle, &pthru->scsi_status);
5533 5533
5534 5534 con_log(CL_ANN, (CE_CONT, "issue_mfi_pthru: cmd_status %x, "
5535 5535 "scsi_status %x", kpthru->cmd_status, kpthru->scsi_status));
5536 5536 DTRACE_PROBE3(issue_pthru, uint8_t, kpthru->cmd, uint8_t,
5537 5537 kpthru->cmd_status, uint8_t, kpthru->scsi_status);
5538 5538
5539 5539 if (kpthru->sense_len) {
5540 5540 uint_t sense_len = SENSE_LENGTH;
5541 5541 void *sense_ubuf =
5542 5542 (void *)(ulong_t)kpthru->sense_buf_phys_addr_lo;
5543 5543 if (kpthru->sense_len <= SENSE_LENGTH) {
5544 5544 sense_len = kpthru->sense_len;
5545 5545 }
5546 5546
5547 5547 for (i = 0; i < sense_len; i++) {
5548 5548 if (ddi_copyout(
5549 5549 (uint8_t *)cmd->sense+i,
5550 5550 (uint8_t *)sense_ubuf+i, 1, mode)) {
5551 5551 con_log(CL_ANN, (CE_WARN,
5552 5552 "issue_mfi_pthru : "
5553 5553 "copy to user space failed"));
5554 5554 }
5555 5555 con_log(CL_DLEVEL1, (CE_WARN,
5556 5556 "Copying Sense info sense_buff[%d] = 0x%X",
5557 5557 i, *((uint8_t *)cmd->sense + i)));
5558 5558 }
5559 5559 }
5560 5560 (void) ddi_dma_sync(cmd->frame_dma_obj.dma_handle, 0, 0,
5561 5561 DDI_DMA_SYNC_FORDEV);
5562 5562
5563 5563 if (xferlen) {
5564 5564 /* free kernel buffer */
5565 5565 if (mrsas_free_dma_obj(instance, pthru_dma_obj) != DDI_SUCCESS)
5566 5566 return (DDI_FAILURE);
5567 5567 }
5568 5568
5569 5569 return (DDI_SUCCESS);
5570 5570 }
5571 5571
5572 5572 /*
5573 5573 * issue_mfi_dcmd
5574 5574 */
5575 5575 static int
5576 5576 issue_mfi_dcmd(struct mrsas_instance *instance, struct mrsas_ioctl *ioctl,
5577 5577 struct mrsas_cmd *cmd, int mode)
5578 5578 {
5579 5579 void *ubuf;
5580 5580 uint32_t kphys_addr = 0;
5581 5581 uint32_t xferlen = 0;
5582 5582 uint32_t new_xfer_length = 0;
5583 5583 uint32_t model;
5584 5584 dma_obj_t dcmd_dma_obj;
5585 5585 struct mrsas_dcmd_frame *kdcmd;
5586 5586 struct mrsas_dcmd_frame *dcmd;
5587 5587 ddi_acc_handle_t acc_handle = cmd->frame_dma_obj.acc_handle;
5588 5588 int i;
5589 5589 dcmd = &cmd->frame->dcmd;
5590 5590 kdcmd = (struct mrsas_dcmd_frame *)&ioctl->frame[0];
5591 5591
5592 5592 if (instance->adapterresetinprogress) {
5593 5593 con_log(CL_ANN1, (CE_NOTE, "Reset flag set, "
5594 5594 "returning mfi_pkt and setting TRAN_BUSY"));
5595 5595 return (DDI_FAILURE);
5596 5596 }
5597 5597 model = ddi_model_convert_from(mode & FMODELS);
5598 5598 if (model == DDI_MODEL_ILP32) {
5599 5599 con_log(CL_ANN1, (CE_CONT, "issue_mfi_dcmd: DDI_MODEL_ILP32"));
5600 5600
5601 5601 xferlen = kdcmd->sgl.sge32[0].length;
5602 5602
5603 5603 ubuf = (void *)(ulong_t)kdcmd->sgl.sge32[0].phys_addr;
5604 5604 } else {
5605 5605 #ifdef _ILP32
5606 5606 con_log(CL_ANN1, (CE_CONT, "issue_mfi_dcmd: DDI_MODEL_ILP32"));
5607 5607 xferlen = kdcmd->sgl.sge32[0].length;
5608 5608 ubuf = (void *)(ulong_t)kdcmd->sgl.sge32[0].phys_addr;
5609 5609 #else
5610 5610 con_log(CL_ANN1, (CE_CONT, "issue_mfi_dcmd: DDI_MODEL_LP64"));
5611 5611 xferlen = kdcmd->sgl.sge64[0].length;
5612 5612 ubuf = (void *)(ulong_t)kdcmd->sgl.sge64[0].phys_addr;
5613 5613 #endif
5614 5614 }
5615 5615 if (xferlen) {
5616 5616 /* means IOCTL requires DMA */
5617 5617 /* allocate the data transfer buffer */
5618 5618 /* dcmd_dma_obj.size = xferlen; */
5619 5619 MRSAS_GET_BOUNDARY_ALIGNED_LEN(xferlen, new_xfer_length,
5620 5620 PAGESIZE);
5621 5621 dcmd_dma_obj.size = new_xfer_length;
5622 5622 dcmd_dma_obj.dma_attr = mrsas_generic_dma_attr;
5623 5623 dcmd_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
5624 5624 dcmd_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
5625 5625 dcmd_dma_obj.dma_attr.dma_attr_sgllen = 1;
5626 5626 dcmd_dma_obj.dma_attr.dma_attr_align = 1;
5627 5627
5628 5628 /* allocate kernel buffer for DMA */
5629 5629 if (mrsas_alloc_dma_obj(instance, &dcmd_dma_obj,
5630 5630 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
5631 5631 con_log(CL_ANN,
5632 5632 (CE_WARN, "issue_mfi_dcmd: could not "
5633 5633 "allocate data transfer buffer."));
5634 5634 return (DDI_FAILURE);
5635 5635 }
5636 5636 (void) memset(dcmd_dma_obj.buffer, 0, xferlen);
5637 5637
5638 5638 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
5639 5639 if (kdcmd->flags & MFI_FRAME_DIR_WRITE) {
5640 5640 for (i = 0; i < xferlen; i++) {
5641 5641 if (ddi_copyin((uint8_t *)ubuf + i,
5642 5642 (uint8_t *)dcmd_dma_obj.buffer + i,
5643 5643 1, mode)) {
5644 5644 con_log(CL_ANN, (CE_WARN,
5645 5645 "issue_mfi_dcmd : "
5646 5646 "copy from user space failed"));
5647 5647 return (DDI_FAILURE);
5648 5648 }
5649 5649 }
5650 5650 }
5651 5651
5652 5652 kphys_addr = dcmd_dma_obj.dma_cookie[0].dmac_address;
5653 5653 }
5654 5654
5655 5655 ddi_put8(acc_handle, &dcmd->cmd, kdcmd->cmd);
5656 5656 ddi_put8(acc_handle, &dcmd->cmd_status, 0);
5657 5657 ddi_put8(acc_handle, &dcmd->sge_count, kdcmd->sge_count);
5658 5658 ddi_put16(acc_handle, &dcmd->timeout, kdcmd->timeout);
5659 5659 ddi_put32(acc_handle, &dcmd->data_xfer_len, kdcmd->data_xfer_len);
5660 5660 ddi_put32(acc_handle, &dcmd->opcode, kdcmd->opcode);
5661 5661
5662 5662 ddi_rep_put8(acc_handle, (uint8_t *)kdcmd->mbox.b,
5663 5663 (uint8_t *)dcmd->mbox.b, DCMD_MBOX_SZ, DDI_DEV_AUTOINCR);
5664 5664
5665 5665 ddi_put16(acc_handle, &dcmd->flags, kdcmd->flags & ~MFI_FRAME_SGL64);
5666 5666 ddi_put32(acc_handle, &dcmd->sgl.sge32[0].length, xferlen);
5667 5667 ddi_put32(acc_handle, &dcmd->sgl.sge32[0].phys_addr, kphys_addr);
5668 5668
5669 5669 cmd->sync_cmd = MRSAS_TRUE;
5670 5670 cmd->frame_count = 1;
5671 5671
5672 5672 if (instance->tbolt) {
5673 5673 mr_sas_tbolt_build_mfi_cmd(instance, cmd);
5674 5674 }
5675 5675
5676 5676 if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
5677 5677 con_log(CL_ANN, (CE_WARN, "issue_mfi_dcmd: fw_ioctl failed"));
5678 5678 } else {
5679 5679 if (xferlen && (kdcmd->flags & MFI_FRAME_DIR_READ)) {
5680 5680 for (i = 0; i < xferlen; i++) {
5681 5681 if (ddi_copyout(
5682 5682 (uint8_t *)dcmd_dma_obj.buffer + i,
5683 5683 (uint8_t *)ubuf + i,
5684 5684 1, mode)) {
5685 5685 con_log(CL_ANN, (CE_WARN,
5686 5686 "issue_mfi_dcmd : "
5687 5687 "copy to user space failed"));
5688 5688 return (DDI_FAILURE);
5689 5689 }
5690 5690 }
5691 5691 }
5692 5692 }
5693 5693
5694 5694 kdcmd->cmd_status = ddi_get8(acc_handle, &dcmd->cmd_status);
5695 5695 con_log(CL_ANN,
5696 5696 (CE_CONT, "issue_mfi_dcmd: cmd_status %x", kdcmd->cmd_status));
5697 5697 DTRACE_PROBE3(issue_dcmd, uint32_t, kdcmd->opcode, uint8_t,
5698 5698 kdcmd->cmd, uint8_t, kdcmd->cmd_status);
5699 5699
5700 5700 if (xferlen) {
5701 5701 /* free kernel buffer */
5702 5702 if (mrsas_free_dma_obj(instance, dcmd_dma_obj) != DDI_SUCCESS)
5703 5703 return (DDI_FAILURE);
5704 5704 }
5705 5705
5706 5706 return (DDI_SUCCESS);
5707 5707 }
5708 5708
5709 5709 /*
5710 5710 * issue_mfi_smp
5711 5711 */
5712 5712 static int
5713 5713 issue_mfi_smp(struct mrsas_instance *instance, struct mrsas_ioctl *ioctl,
5714 5714 struct mrsas_cmd *cmd, int mode)
5715 5715 {
5716 5716 void *request_ubuf;
5717 5717 void *response_ubuf;
5718 5718 uint32_t request_xferlen = 0;
5719 5719 uint32_t response_xferlen = 0;
5720 5720 uint32_t new_xfer_length1 = 0;
5721 5721 uint32_t new_xfer_length2 = 0;
5722 5722 uint_t model;
5723 5723 dma_obj_t request_dma_obj;
5724 5724 dma_obj_t response_dma_obj;
5725 5725 ddi_acc_handle_t acc_handle = cmd->frame_dma_obj.acc_handle;
5726 5726 struct mrsas_smp_frame *ksmp;
5727 5727 struct mrsas_smp_frame *smp;
5728 5728 struct mrsas_sge32 *sge32;
5729 5729 #ifndef _ILP32
5730 5730 struct mrsas_sge64 *sge64;
5731 5731 #endif
5732 5732 int i;
5733 5733 uint64_t tmp_sas_addr;
5734 5734
5735 5735 smp = &cmd->frame->smp;
5736 5736 ksmp = (struct mrsas_smp_frame *)&ioctl->frame[0];
5737 5737
5738 5738 if (instance->adapterresetinprogress) {
5739 5739 con_log(CL_ANN1, (CE_WARN, "Reset flag set, "
5740 5740 "returning mfi_pkt and setting TRAN_BUSY\n"));
5741 5741 return (DDI_FAILURE);
5742 5742 }
5743 5743 model = ddi_model_convert_from(mode & FMODELS);
5744 5744 if (model == DDI_MODEL_ILP32) {
5745 5745 con_log(CL_ANN1, (CE_CONT, "issue_mfi_smp: DDI_MODEL_ILP32"));
5746 5746
5747 5747 sge32 = &ksmp->sgl[0].sge32[0];
5748 5748 response_xferlen = sge32[0].length;
5749 5749 request_xferlen = sge32[1].length;
5750 5750 con_log(CL_ANN, (CE_CONT, "issue_mfi_smp: "
5751 5751 "response_xferlen = %x, request_xferlen = %x",
5752 5752 response_xferlen, request_xferlen));
5753 5753
5754 5754 response_ubuf = (void *)(ulong_t)sge32[0].phys_addr;
5755 5755 request_ubuf = (void *)(ulong_t)sge32[1].phys_addr;
5756 5756 con_log(CL_ANN1, (CE_CONT, "issue_mfi_smp: "
5757 5757 "response_ubuf = %p, request_ubuf = %p",
5758 5758 response_ubuf, request_ubuf));
5759 5759 } else {
5760 5760 #ifdef _ILP32
5761 5761 con_log(CL_ANN1, (CE_CONT, "issue_mfi_smp: DDI_MODEL_ILP32"));
5762 5762
5763 5763 sge32 = &ksmp->sgl[0].sge32[0];
5764 5764 response_xferlen = sge32[0].length;
5765 5765 request_xferlen = sge32[1].length;
5766 5766 con_log(CL_ANN, (CE_CONT, "issue_mfi_smp: "
5767 5767 "response_xferlen = %x, request_xferlen = %x",
5768 5768 response_xferlen, request_xferlen));
5769 5769
5770 5770 response_ubuf = (void *)(ulong_t)sge32[0].phys_addr;
5771 5771 request_ubuf = (void *)(ulong_t)sge32[1].phys_addr;
5772 5772 con_log(CL_ANN1, (CE_CONT, "issue_mfi_smp: "
5773 5773 "response_ubuf = %p, request_ubuf = %p",
5774 5774 response_ubuf, request_ubuf));
5775 5775 #else
5776 5776 con_log(CL_ANN1, (CE_CONT, "issue_mfi_smp: DDI_MODEL_LP64"));
5777 5777
5778 5778 sge64 = &ksmp->sgl[0].sge64[0];
5779 5779 response_xferlen = sge64[0].length;
5780 5780 request_xferlen = sge64[1].length;
5781 5781
5782 5782 response_ubuf = (void *)(ulong_t)sge64[0].phys_addr;
5783 5783 request_ubuf = (void *)(ulong_t)sge64[1].phys_addr;
5784 5784 #endif
5785 5785 }
5786 5786 if (request_xferlen) {
5787 5787 /* means IOCTL requires DMA */
5788 5788 /* allocate the data transfer buffer */
5789 5789 /* request_dma_obj.size = request_xferlen; */
5790 5790 MRSAS_GET_BOUNDARY_ALIGNED_LEN(request_xferlen,
5791 5791 new_xfer_length1, PAGESIZE);
5792 5792 request_dma_obj.size = new_xfer_length1;
5793 5793 request_dma_obj.dma_attr = mrsas_generic_dma_attr;
5794 5794 request_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
5795 5795 request_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
5796 5796 request_dma_obj.dma_attr.dma_attr_sgllen = 1;
5797 5797 request_dma_obj.dma_attr.dma_attr_align = 1;
5798 5798
5799 5799 /* allocate kernel buffer for DMA */
5800 5800 if (mrsas_alloc_dma_obj(instance, &request_dma_obj,
5801 5801 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
5802 5802 con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
5803 5803 "could not allocate data transfer buffer."));
5804 5804 return (DDI_FAILURE);
5805 5805 }
5806 5806 (void) memset(request_dma_obj.buffer, 0, request_xferlen);
5807 5807
5808 5808 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
5809 5809 for (i = 0; i < request_xferlen; i++) {
5810 5810 if (ddi_copyin((uint8_t *)request_ubuf + i,
5811 5811 (uint8_t *)request_dma_obj.buffer + i,
5812 5812 1, mode)) {
5813 5813 con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
5814 5814 "copy from user space failed"));
5815 5815 return (DDI_FAILURE);
5816 5816 }
5817 5817 }
5818 5818 }
5819 5819
5820 5820 if (response_xferlen) {
5821 5821 /* means IOCTL requires DMA */
5822 5822 /* allocate the data transfer buffer */
5823 5823 /* response_dma_obj.size = response_xferlen; */
5824 5824 MRSAS_GET_BOUNDARY_ALIGNED_LEN(response_xferlen,
5825 5825 new_xfer_length2, PAGESIZE);
5826 5826 response_dma_obj.size = new_xfer_length2;
5827 5827 response_dma_obj.dma_attr = mrsas_generic_dma_attr;
5828 5828 response_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
5829 5829 response_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
5830 5830 response_dma_obj.dma_attr.dma_attr_sgllen = 1;
5831 5831 response_dma_obj.dma_attr.dma_attr_align = 1;
5832 5832
5833 5833 /* allocate kernel buffer for DMA */
5834 5834 if (mrsas_alloc_dma_obj(instance, &response_dma_obj,
5835 5835 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
5836 5836 con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
5837 5837 "could not allocate data transfer buffer."));
5838 5838 return (DDI_FAILURE);
5839 5839 }
5840 5840 (void) memset(response_dma_obj.buffer, 0, response_xferlen);
5841 5841
5842 5842 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
5843 5843 for (i = 0; i < response_xferlen; i++) {
5844 5844 if (ddi_copyin((uint8_t *)response_ubuf + i,
5845 5845 (uint8_t *)response_dma_obj.buffer + i,
5846 5846 1, mode)) {
5847 5847 con_log(CL_ANN, (CE_WARN, "issue_mfi_smp: "
5848 5848 "copy from user space failed"));
5849 5849 return (DDI_FAILURE);
5850 5850 }
5851 5851 }
5852 5852 }
5853 5853
5854 5854 ddi_put8(acc_handle, &smp->cmd, ksmp->cmd);
5855 5855 ddi_put8(acc_handle, &smp->cmd_status, 0);
5856 5856 ddi_put8(acc_handle, &smp->connection_status, 0);
5857 5857 ddi_put8(acc_handle, &smp->sge_count, ksmp->sge_count);
5858 5858 /* smp->context = ksmp->context; */
5859 5859 ddi_put16(acc_handle, &smp->timeout, ksmp->timeout);
5860 5860 ddi_put32(acc_handle, &smp->data_xfer_len, ksmp->data_xfer_len);
5861 5861
5862 5862 bcopy((void *)&ksmp->sas_addr, (void *)&tmp_sas_addr,
5863 5863 sizeof (uint64_t));
5864 5864 ddi_put64(acc_handle, &smp->sas_addr, tmp_sas_addr);
5865 5865
5866 5866 ddi_put16(acc_handle, &smp->flags, ksmp->flags & ~MFI_FRAME_SGL64);
5867 5867
5868 5868 model = ddi_model_convert_from(mode & FMODELS);
5869 5869 if (model == DDI_MODEL_ILP32) {
5870 5870 con_log(CL_ANN1, (CE_CONT,
5871 5871 "issue_mfi_smp: DDI_MODEL_ILP32"));
5872 5872
5873 5873 sge32 = &smp->sgl[0].sge32[0];
5874 5874 ddi_put32(acc_handle, &sge32[0].length, response_xferlen);
5875 5875 ddi_put32(acc_handle, &sge32[0].phys_addr,
5876 5876 response_dma_obj.dma_cookie[0].dmac_address);
5877 5877 ddi_put32(acc_handle, &sge32[1].length, request_xferlen);
5878 5878 ddi_put32(acc_handle, &sge32[1].phys_addr,
5879 5879 request_dma_obj.dma_cookie[0].dmac_address);
5880 5880 } else {
5881 5881 #ifdef _ILP32
5882 5882 con_log(CL_ANN1, (CE_CONT,
5883 5883 "issue_mfi_smp: DDI_MODEL_ILP32"));
5884 5884 sge32 = &smp->sgl[0].sge32[0];
5885 5885 ddi_put32(acc_handle, &sge32[0].length, response_xferlen);
5886 5886 ddi_put32(acc_handle, &sge32[0].phys_addr,
5887 5887 response_dma_obj.dma_cookie[0].dmac_address);
5888 5888 ddi_put32(acc_handle, &sge32[1].length, request_xferlen);
5889 5889 ddi_put32(acc_handle, &sge32[1].phys_addr,
5890 5890 request_dma_obj.dma_cookie[0].dmac_address);
5891 5891 #else
5892 5892 con_log(CL_ANN1, (CE_CONT,
5893 5893 "issue_mfi_smp: DDI_MODEL_LP64"));
5894 5894 sge64 = &smp->sgl[0].sge64[0];
5895 5895 ddi_put32(acc_handle, &sge64[0].length, response_xferlen);
5896 5896 ddi_put64(acc_handle, &sge64[0].phys_addr,
5897 5897 response_dma_obj.dma_cookie[0].dmac_address);
5898 5898 ddi_put32(acc_handle, &sge64[1].length, request_xferlen);
5899 5899 ddi_put64(acc_handle, &sge64[1].phys_addr,
5900 5900 request_dma_obj.dma_cookie[0].dmac_address);
5901 5901 #endif
5902 5902 }
5903 5903 con_log(CL_ANN1, (CE_CONT, "issue_mfi_smp : "
5904 5904 "smp->response_xferlen = %d, smp->request_xferlen = %d "
5905 5905 "smp->data_xfer_len = %d", ddi_get32(acc_handle, &sge32[0].length),
5906 5906 ddi_get32(acc_handle, &sge32[1].length),
5907 5907 ddi_get32(acc_handle, &smp->data_xfer_len)));
5908 5908
5909 5909 cmd->sync_cmd = MRSAS_TRUE;
5910 5910 cmd->frame_count = 1;
5911 5911
5912 5912 if (instance->tbolt) {
5913 5913 mr_sas_tbolt_build_mfi_cmd(instance, cmd);
5914 5914 }
5915 5915
5916 5916 if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
5917 5917 con_log(CL_ANN, (CE_WARN,
5918 5918 "issue_mfi_smp: fw_ioctl failed"));
5919 5919 } else {
5920 5920 con_log(CL_ANN1, (CE_CONT,
5921 5921 "issue_mfi_smp: copy to user space"));
5922 5922
5923 5923 if (request_xferlen) {
5924 5924 for (i = 0; i < request_xferlen; i++) {
5925 5925 if (ddi_copyout(
5926 5926 (uint8_t *)request_dma_obj.buffer +
5927 5927 i, (uint8_t *)request_ubuf + i,
5928 5928 1, mode)) {
5929 5929 con_log(CL_ANN, (CE_WARN,
5930 5930 "issue_mfi_smp : copy to user space"
5931 5931 " failed"));
5932 5932 return (DDI_FAILURE);
5933 5933 }
5934 5934 }
5935 5935 }
5936 5936
5937 5937 if (response_xferlen) {
5938 5938 for (i = 0; i < response_xferlen; i++) {
5939 5939 if (ddi_copyout(
5940 5940 (uint8_t *)response_dma_obj.buffer
5941 5941 + i, (uint8_t *)response_ubuf
5942 5942 + i, 1, mode)) {
5943 5943 con_log(CL_ANN, (CE_WARN,
5944 5944 "issue_mfi_smp : copy to "
5945 5945 "user space failed"));
5946 5946 return (DDI_FAILURE);
5947 5947 }
5948 5948 }
5949 5949 }
5950 5950 }
5951 5951
5952 5952 ksmp->cmd_status = ddi_get8(acc_handle, &smp->cmd_status);
5953 5953 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_smp: smp->cmd_status = %d",
5954 5954 ksmp->cmd_status));
5955 5955 DTRACE_PROBE2(issue_smp, uint8_t, ksmp->cmd, uint8_t, ksmp->cmd_status);
5956 5956
5957 5957 if (request_xferlen) {
5958 5958 /* free kernel buffer */
5959 5959 if (mrsas_free_dma_obj(instance, request_dma_obj) !=
5960 5960 DDI_SUCCESS)
5961 5961 return (DDI_FAILURE);
5962 5962 }
5963 5963
5964 5964 if (response_xferlen) {
5965 5965 /* free kernel buffer */
5966 5966 if (mrsas_free_dma_obj(instance, response_dma_obj) !=
5967 5967 DDI_SUCCESS)
5968 5968 return (DDI_FAILURE);
5969 5969 }
5970 5970
5971 5971 return (DDI_SUCCESS);
5972 5972 }
5973 5973
5974 5974 /*
5975 5975 * issue_mfi_stp
5976 5976 */
5977 5977 static int
5978 5978 issue_mfi_stp(struct mrsas_instance *instance, struct mrsas_ioctl *ioctl,
5979 5979 struct mrsas_cmd *cmd, int mode)
5980 5980 {
5981 5981 void *fis_ubuf;
5982 5982 void *data_ubuf;
5983 5983 uint32_t fis_xferlen = 0;
5984 5984 uint32_t new_xfer_length1 = 0;
5985 5985 uint32_t new_xfer_length2 = 0;
5986 5986 uint32_t data_xferlen = 0;
5987 5987 uint_t model;
5988 5988 dma_obj_t fis_dma_obj;
5989 5989 dma_obj_t data_dma_obj;
5990 5990 struct mrsas_stp_frame *kstp;
5991 5991 struct mrsas_stp_frame *stp;
5992 5992 ddi_acc_handle_t acc_handle = cmd->frame_dma_obj.acc_handle;
5993 5993 int i;
5994 5994
5995 5995 stp = &cmd->frame->stp;
5996 5996 kstp = (struct mrsas_stp_frame *)&ioctl->frame[0];
5997 5997
5998 5998 if (instance->adapterresetinprogress) {
5999 5999 con_log(CL_ANN1, (CE_WARN, "Reset flag set, "
6000 6000 "returning mfi_pkt and setting TRAN_BUSY\n"));
6001 6001 return (DDI_FAILURE);
6002 6002 }
6003 6003 model = ddi_model_convert_from(mode & FMODELS);
6004 6004 if (model == DDI_MODEL_ILP32) {
6005 6005 con_log(CL_ANN1, (CE_CONT, "issue_mfi_stp: DDI_MODEL_ILP32"));
6006 6006
6007 6007 fis_xferlen = kstp->sgl.sge32[0].length;
6008 6008 data_xferlen = kstp->sgl.sge32[1].length;
6009 6009
6010 6010 fis_ubuf = (void *)(ulong_t)kstp->sgl.sge32[0].phys_addr;
6011 6011 data_ubuf = (void *)(ulong_t)kstp->sgl.sge32[1].phys_addr;
6012 6012 } else {
6013 6013 #ifdef _ILP32
6014 6014 con_log(CL_ANN1, (CE_CONT, "issue_mfi_stp: DDI_MODEL_ILP32"));
6015 6015
6016 6016 fis_xferlen = kstp->sgl.sge32[0].length;
6017 6017 data_xferlen = kstp->sgl.sge32[1].length;
6018 6018
6019 6019 fis_ubuf = (void *)(ulong_t)kstp->sgl.sge32[0].phys_addr;
6020 6020 data_ubuf = (void *)(ulong_t)kstp->sgl.sge32[1].phys_addr;
6021 6021 #else
6022 6022 con_log(CL_ANN1, (CE_CONT, "issue_mfi_stp: DDI_MODEL_LP64"));
6023 6023
6024 6024 fis_xferlen = kstp->sgl.sge64[0].length;
6025 6025 data_xferlen = kstp->sgl.sge64[1].length;
6026 6026
6027 6027 fis_ubuf = (void *)(ulong_t)kstp->sgl.sge64[0].phys_addr;
6028 6028 data_ubuf = (void *)(ulong_t)kstp->sgl.sge64[1].phys_addr;
6029 6029 #endif
6030 6030 }
6031 6031
6032 6032
6033 6033 if (fis_xferlen) {
6034 6034 con_log(CL_ANN, (CE_CONT, "issue_mfi_stp: "
6035 6035 "fis_ubuf = %p fis_xferlen = %x", fis_ubuf, fis_xferlen));
6036 6036
6037 6037 /* means IOCTL requires DMA */
6038 6038 /* allocate the data transfer buffer */
6039 6039 /* fis_dma_obj.size = fis_xferlen; */
6040 6040 MRSAS_GET_BOUNDARY_ALIGNED_LEN(fis_xferlen,
6041 6041 new_xfer_length1, PAGESIZE);
6042 6042 fis_dma_obj.size = new_xfer_length1;
6043 6043 fis_dma_obj.dma_attr = mrsas_generic_dma_attr;
6044 6044 fis_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
6045 6045 fis_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
6046 6046 fis_dma_obj.dma_attr.dma_attr_sgllen = 1;
6047 6047 fis_dma_obj.dma_attr.dma_attr_align = 1;
6048 6048
6049 6049 /* allocate kernel buffer for DMA */
6050 6050 if (mrsas_alloc_dma_obj(instance, &fis_dma_obj,
6051 6051 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
6052 6052 con_log(CL_ANN, (CE_WARN, "issue_mfi_stp : "
6053 6053 "could not allocate data transfer buffer."));
6054 6054 return (DDI_FAILURE);
6055 6055 }
6056 6056 (void) memset(fis_dma_obj.buffer, 0, fis_xferlen);
6057 6057
6058 6058 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
6059 6059 for (i = 0; i < fis_xferlen; i++) {
6060 6060 if (ddi_copyin((uint8_t *)fis_ubuf + i,
6061 6061 (uint8_t *)fis_dma_obj.buffer + i, 1, mode)) {
6062 6062 con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: "
6063 6063 "copy from user space failed"));
6064 6064 return (DDI_FAILURE);
6065 6065 }
6066 6066 }
6067 6067 }
6068 6068
6069 6069 if (data_xferlen) {
6070 6070 con_log(CL_ANN, (CE_CONT, "issue_mfi_stp: data_ubuf = %p "
6071 6071 "data_xferlen = %x", data_ubuf, data_xferlen));
6072 6072
6073 6073 /* means IOCTL requires DMA */
6074 6074 /* allocate the data transfer buffer */
6075 6075 /* data_dma_obj.size = data_xferlen; */
6076 6076 MRSAS_GET_BOUNDARY_ALIGNED_LEN(data_xferlen, new_xfer_length2,
6077 6077 PAGESIZE);
6078 6078 data_dma_obj.size = new_xfer_length2;
6079 6079 data_dma_obj.dma_attr = mrsas_generic_dma_attr;
6080 6080 data_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
6081 6081 data_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
6082 6082 data_dma_obj.dma_attr.dma_attr_sgllen = 1;
6083 6083 data_dma_obj.dma_attr.dma_attr_align = 1;
6084 6084
6085 6085 /* allocate kernel buffer for DMA */
6086 6086 if (mrsas_alloc_dma_obj(instance, &data_dma_obj,
6087 6087 (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
6088 6088 con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: "
6089 6089 "could not allocate data transfer buffer."));
6090 6090 return (DDI_FAILURE);
6091 6091 }
6092 6092 (void) memset(data_dma_obj.buffer, 0, data_xferlen);
6093 6093
6094 6094 /* If IOCTL requires DMA WRITE, do ddi_copyin IOCTL data copy */
6095 6095 for (i = 0; i < data_xferlen; i++) {
6096 6096 if (ddi_copyin((uint8_t *)data_ubuf + i,
6097 6097 (uint8_t *)data_dma_obj.buffer + i, 1, mode)) {
6098 6098 con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: "
6099 6099 "copy from user space failed"));
6100 6100 return (DDI_FAILURE);
6101 6101 }
6102 6102 }
6103 6103 }
6104 6104
6105 6105 ddi_put8(acc_handle, &stp->cmd, kstp->cmd);
6106 6106 ddi_put8(acc_handle, &stp->cmd_status, 0);
6107 6107 ddi_put8(acc_handle, &stp->connection_status, 0);
6108 6108 ddi_put8(acc_handle, &stp->target_id, kstp->target_id);
6109 6109 ddi_put8(acc_handle, &stp->sge_count, kstp->sge_count);
6110 6110
6111 6111 ddi_put16(acc_handle, &stp->timeout, kstp->timeout);
6112 6112 ddi_put32(acc_handle, &stp->data_xfer_len, kstp->data_xfer_len);
6113 6113
6114 6114 ddi_rep_put8(acc_handle, (uint8_t *)kstp->fis, (uint8_t *)stp->fis, 10,
6115 6115 DDI_DEV_AUTOINCR);
6116 6116
6117 6117 ddi_put16(acc_handle, &stp->flags, kstp->flags & ~MFI_FRAME_SGL64);
6118 6118 ddi_put32(acc_handle, &stp->stp_flags, kstp->stp_flags);
6119 6119 ddi_put32(acc_handle, &stp->sgl.sge32[0].length, fis_xferlen);
6120 6120 ddi_put32(acc_handle, &stp->sgl.sge32[0].phys_addr,
6121 6121 fis_dma_obj.dma_cookie[0].dmac_address);
6122 6122 ddi_put32(acc_handle, &stp->sgl.sge32[1].length, data_xferlen);
6123 6123 ddi_put32(acc_handle, &stp->sgl.sge32[1].phys_addr,
6124 6124 data_dma_obj.dma_cookie[0].dmac_address);
6125 6125
6126 6126 cmd->sync_cmd = MRSAS_TRUE;
6127 6127 cmd->frame_count = 1;
6128 6128
6129 6129 if (instance->tbolt) {
6130 6130 mr_sas_tbolt_build_mfi_cmd(instance, cmd);
6131 6131 }
6132 6132
6133 6133 if (instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd)) {
6134 6134 con_log(CL_ANN, (CE_WARN, "issue_mfi_stp: fw_ioctl failed"));
6135 6135 } else {
6136 6136
6137 6137 if (fis_xferlen) {
6138 6138 for (i = 0; i < fis_xferlen; i++) {
6139 6139 if (ddi_copyout(
6140 6140 (uint8_t *)fis_dma_obj.buffer + i,
6141 6141 (uint8_t *)fis_ubuf + i, 1, mode)) {
6142 6142 con_log(CL_ANN, (CE_WARN,
6143 6143 "issue_mfi_stp : copy to "
6144 6144 "user space failed"));
6145 6145 return (DDI_FAILURE);
6146 6146 }
6147 6147 }
6148 6148 }
6149 6149 }
6150 6150 if (data_xferlen) {
6151 6151 for (i = 0; i < data_xferlen; i++) {
6152 6152 if (ddi_copyout(
6153 6153 (uint8_t *)data_dma_obj.buffer + i,
6154 6154 (uint8_t *)data_ubuf + i, 1, mode)) {
6155 6155 con_log(CL_ANN, (CE_WARN,
6156 6156 "issue_mfi_stp : copy to"
6157 6157 " user space failed"));
6158 6158 return (DDI_FAILURE);
6159 6159 }
6160 6160 }
6161 6161 }
6162 6162
6163 6163 kstp->cmd_status = ddi_get8(acc_handle, &stp->cmd_status);
6164 6164 con_log(CL_ANN1, (CE_NOTE, "issue_mfi_stp: stp->cmd_status = %d",
6165 6165 kstp->cmd_status));
6166 6166 DTRACE_PROBE2(issue_stp, uint8_t, kstp->cmd, uint8_t, kstp->cmd_status);
6167 6167
6168 6168 if (fis_xferlen) {
6169 6169 /* free kernel buffer */
6170 6170 if (mrsas_free_dma_obj(instance, fis_dma_obj) != DDI_SUCCESS)
6171 6171 return (DDI_FAILURE);
6172 6172 }
6173 6173
6174 6174 if (data_xferlen) {
6175 6175 /* free kernel buffer */
6176 6176 if (mrsas_free_dma_obj(instance, data_dma_obj) != DDI_SUCCESS)
6177 6177 return (DDI_FAILURE);
6178 6178 }
6179 6179
6180 6180 return (DDI_SUCCESS);
6181 6181 }
6182 6182
6183 6183 /*
6184 6184 * fill_up_drv_ver
6185 6185 */
6186 6186 void
6187 6187 fill_up_drv_ver(struct mrsas_drv_ver *dv)
6188 6188 {
6189 6189 (void) memset(dv, 0, sizeof (struct mrsas_drv_ver));
6190 6190
6191 6191 (void) memcpy(dv->signature, "$LSI LOGIC$", strlen("$LSI LOGIC$"));
6192 6192 (void) memcpy(dv->os_name, "Solaris", strlen("Solaris"));
6193 6193 (void) memcpy(dv->drv_name, "mr_sas", strlen("mr_sas"));
6194 6194 (void) memcpy(dv->drv_ver, MRSAS_VERSION, strlen(MRSAS_VERSION));
6195 6195 (void) memcpy(dv->drv_rel_date, MRSAS_RELDATE,
6196 6196 strlen(MRSAS_RELDATE));
6197 6197
6198 6198 }
6199 6199
6200 6200 /*
6201 6201 * handle_drv_ioctl
6202 6202 */
6203 6203 static int
6204 6204 handle_drv_ioctl(struct mrsas_instance *instance, struct mrsas_ioctl *ioctl,
6205 6205 int mode)
6206 6206 {
6207 6207 int i;
6208 6208 int rval = DDI_SUCCESS;
6209 6209 int *props = NULL;
6210 6210 void *ubuf;
6211 6211
6212 6212 uint8_t *pci_conf_buf;
6213 6213 uint32_t xferlen;
6214 6214 uint32_t num_props;
6215 6215 uint_t model;
6216 6216 struct mrsas_dcmd_frame *kdcmd;
6217 6217 struct mrsas_drv_ver dv;
6218 6218 struct mrsas_pci_information pi;
6219 6219
6220 6220 kdcmd = (struct mrsas_dcmd_frame *)&ioctl->frame[0];
6221 6221
6222 6222 model = ddi_model_convert_from(mode & FMODELS);
6223 6223 if (model == DDI_MODEL_ILP32) {
6224 6224 con_log(CL_ANN1, (CE_CONT,
6225 6225 "handle_drv_ioctl: DDI_MODEL_ILP32"));
6226 6226
6227 6227 xferlen = kdcmd->sgl.sge32[0].length;
6228 6228
6229 6229 ubuf = (void *)(ulong_t)kdcmd->sgl.sge32[0].phys_addr;
6230 6230 } else {
6231 6231 #ifdef _ILP32
6232 6232 con_log(CL_ANN1, (CE_CONT,
6233 6233 "handle_drv_ioctl: DDI_MODEL_ILP32"));
6234 6234 xferlen = kdcmd->sgl.sge32[0].length;
6235 6235 ubuf = (void *)(ulong_t)kdcmd->sgl.sge32[0].phys_addr;
6236 6236 #else
6237 6237 con_log(CL_ANN1, (CE_CONT,
6238 6238 "handle_drv_ioctl: DDI_MODEL_LP64"));
6239 6239 xferlen = kdcmd->sgl.sge64[0].length;
6240 6240 ubuf = (void *)(ulong_t)kdcmd->sgl.sge64[0].phys_addr;
6241 6241 #endif
6242 6242 }
6243 6243 con_log(CL_ANN1, (CE_CONT, "handle_drv_ioctl: "
6244 6244 "dataBuf=%p size=%d bytes", ubuf, xferlen));
6245 6245
6246 6246 switch (kdcmd->opcode) {
6247 6247 case MRSAS_DRIVER_IOCTL_DRIVER_VERSION:
6248 6248 con_log(CL_ANN1, (CE_CONT, "handle_drv_ioctl: "
6249 6249 "MRSAS_DRIVER_IOCTL_DRIVER_VERSION"));
6250 6250
6251 6251 fill_up_drv_ver(&dv);
6252 6252
6253 6253 if (ddi_copyout(&dv, ubuf, xferlen, mode)) {
6254 6254 con_log(CL_ANN, (CE_WARN, "handle_drv_ioctl: "
6255 6255 "MRSAS_DRIVER_IOCTL_DRIVER_VERSION : "
6256 6256 "copy to user space failed"));
6257 6257 kdcmd->cmd_status = 1;
6258 6258 rval = 1;
6259 6259 } else {
6260 6260 kdcmd->cmd_status = 0;
6261 6261 }
6262 6262 break;
6263 6263 case MRSAS_DRIVER_IOCTL_PCI_INFORMATION:
6264 6264 con_log(CL_ANN1, (CE_NOTE, "handle_drv_ioctl: "
6265 6265 "MRSAS_DRIVER_IOCTL_PCI_INFORMAITON"));
6266 6266
6267 6267 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, instance->dip,
6268 6268 0, "reg", &props, &num_props)) {
6269 6269 con_log(CL_ANN, (CE_WARN, "handle_drv_ioctl: "
6270 6270 "MRSAS_DRIVER_IOCTL_PCI_INFORMATION : "
6271 6271 "ddi_prop_look_int_array failed"));
6272 6272 rval = DDI_FAILURE;
6273 6273 } else {
6274 6274
6275 6275 pi.busNumber = (props[0] >> 16) & 0xFF;
6276 6276 pi.deviceNumber = (props[0] >> 11) & 0x1f;
6277 6277 pi.functionNumber = (props[0] >> 8) & 0x7;
6278 6278 ddi_prop_free((void *)props);
6279 6279 }
6280 6280
6281 6281 pci_conf_buf = (uint8_t *)&pi.pciHeaderInfo;
6282 6282
6283 6283 for (i = 0; i < (sizeof (struct mrsas_pci_information) -
6284 6284 offsetof(struct mrsas_pci_information, pciHeaderInfo));
6285 6285 i++) {
6286 6286 pci_conf_buf[i] =
6287 6287 pci_config_get8(instance->pci_handle, i);
6288 6288 }
6289 6289
6290 6290 if (ddi_copyout(&pi, ubuf, xferlen, mode)) {
6291 6291 con_log(CL_ANN, (CE_WARN, "handle_drv_ioctl: "
6292 6292 "MRSAS_DRIVER_IOCTL_PCI_INFORMATION : "
6293 6293 "copy to user space failed"));
6294 6294 kdcmd->cmd_status = 1;
6295 6295 rval = 1;
6296 6296 } else {
6297 6297 kdcmd->cmd_status = 0;
6298 6298 }
6299 6299 break;
6300 6300 default:
6301 6301 con_log(CL_ANN, (CE_WARN, "handle_drv_ioctl: "
6302 6302 "invalid driver specific IOCTL opcode = 0x%x",
6303 6303 kdcmd->opcode));
6304 6304 kdcmd->cmd_status = 1;
6305 6305 rval = DDI_FAILURE;
6306 6306 break;
6307 6307 }
6308 6308
6309 6309 return (rval);
6310 6310 }
6311 6311
6312 6312 /*
6313 6313 * handle_mfi_ioctl
6314 6314 */
6315 6315 static int
6316 6316 handle_mfi_ioctl(struct mrsas_instance *instance, struct mrsas_ioctl *ioctl,
6317 6317 int mode)
6318 6318 {
6319 6319 int rval = DDI_SUCCESS;
6320 6320
6321 6321 struct mrsas_header *hdr;
6322 6322 struct mrsas_cmd *cmd;
6323 6323
6324 6324 if (instance->tbolt) {
6325 6325 cmd = get_raid_msg_mfi_pkt(instance);
6326 6326 } else {
6327 6327 cmd = mrsas_get_mfi_pkt(instance);
6328 6328 }
6329 6329 if (!cmd) {
6330 6330 con_log(CL_ANN, (CE_WARN, "mr_sas: "
6331 6331 "failed to get a cmd packet"));
6332 6332 DTRACE_PROBE2(mfi_ioctl_err, uint16_t,
6333 6333 instance->fw_outstanding, uint16_t, instance->max_fw_cmds);
6334 6334 return (DDI_FAILURE);
6335 6335 }
6336 6336
6337 6337 /* Clear the frame buffer and assign back the context id */
6338 6338 (void) memset((char *)&cmd->frame[0], 0, sizeof (union mrsas_frame));
6339 6339 ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
6340 6340 cmd->index);
6341 6341
6342 6342 hdr = (struct mrsas_header *)&ioctl->frame[0];
6343 6343
6344 6344 switch (ddi_get8(cmd->frame_dma_obj.acc_handle, &hdr->cmd)) {
6345 6345 case MFI_CMD_OP_DCMD:
6346 6346 rval = issue_mfi_dcmd(instance, ioctl, cmd, mode);
6347 6347 break;
6348 6348 case MFI_CMD_OP_SMP:
6349 6349 rval = issue_mfi_smp(instance, ioctl, cmd, mode);
6350 6350 break;
6351 6351 case MFI_CMD_OP_STP:
6352 6352 rval = issue_mfi_stp(instance, ioctl, cmd, mode);
6353 6353 break;
6354 6354 case MFI_CMD_OP_LD_SCSI:
6355 6355 case MFI_CMD_OP_PD_SCSI:
6356 6356 rval = issue_mfi_pthru(instance, ioctl, cmd, mode);
6357 6357 break;
6358 6358 default:
6359 6359 con_log(CL_ANN, (CE_WARN, "handle_mfi_ioctl: "
6360 6360 "invalid mfi ioctl hdr->cmd = %d", hdr->cmd));
6361 6361 rval = DDI_FAILURE;
6362 6362 break;
6363 6363 }
6364 6364
6365 6365 if (mrsas_common_check(instance, cmd) != DDI_SUCCESS)
6366 6366 rval = DDI_FAILURE;
6367 6367
6368 6368 if (instance->tbolt) {
6369 6369 return_raid_msg_mfi_pkt(instance, cmd);
6370 6370 } else {
6371 6371 mrsas_return_mfi_pkt(instance, cmd);
6372 6372 }
6373 6373
6374 6374 return (rval);
6375 6375 }
6376 6376
6377 6377 /*
6378 6378 * AEN
6379 6379 */
6380 6380 static int
6381 6381 handle_mfi_aen(struct mrsas_instance *instance, struct mrsas_aen *aen)
6382 6382 {
6383 6383 int rval = 0;
6384 6384
6385 6385 rval = register_mfi_aen(instance, instance->aen_seq_num,
6386 6386 aen->class_locale_word);
6387 6387
6388 6388 aen->cmd_status = (uint8_t)rval;
6389 6389
6390 6390 return (rval);
6391 6391 }
6392 6392
6393 6393 static int
6394 6394 register_mfi_aen(struct mrsas_instance *instance, uint32_t seq_num,
6395 6395 uint32_t class_locale_word)
6396 6396 {
6397 6397 int ret_val;
6398 6398
6399 6399 struct mrsas_cmd *cmd, *aen_cmd;
6400 6400 struct mrsas_dcmd_frame *dcmd;
6401 6401 union mrsas_evt_class_locale curr_aen;
6402 6402 union mrsas_evt_class_locale prev_aen;
6403 6403
6404 6404 con_log(CL_ANN, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
6405 6405 /*
6406 6406 * If there an AEN pending already (aen_cmd), check if the
6407 6407 * class_locale of that pending AEN is inclusive of the new
6408 6408 * AEN request we currently have. If it is, then we don't have
6409 6409 * to do anything. In other words, whichever events the current
6410 6410 * AEN request is subscribing to, have already been subscribed
6411 6411 * to.
6412 6412 *
6413 6413 * If the old_cmd is _not_ inclusive, then we have to abort
6414 6414 * that command, form a class_locale that is superset of both
6415 6415 * old and current and re-issue to the FW
6416 6416 */
6417 6417
6418 6418 curr_aen.word = LE_32(class_locale_word);
6419 6419 curr_aen.members.locale = LE_16(curr_aen.members.locale);
6420 6420 aen_cmd = instance->aen_cmd;
6421 6421 if (aen_cmd) {
6422 6422 prev_aen.word = ddi_get32(aen_cmd->frame_dma_obj.acc_handle,
6423 6423 &aen_cmd->frame->dcmd.mbox.w[1]);
6424 6424 prev_aen.word = LE_32(prev_aen.word);
6425 6425 prev_aen.members.locale = LE_16(prev_aen.members.locale);
6426 6426 /*
6427 6427 * A class whose enum value is smaller is inclusive of all
6428 6428 * higher values. If a PROGRESS (= -1) was previously
6429 6429 * registered, then a new registration requests for higher
6430 6430 * classes need not be sent to FW. They are automatically
6431 6431 * included.
6432 6432 *
6433 6433 * Locale numbers don't have such hierarchy. They are bitmap
6434 6434 * values
6435 6435 */
6436 6436 if ((prev_aen.members.class <= curr_aen.members.class) &&
6437 6437 !((prev_aen.members.locale & curr_aen.members.locale) ^
6438 6438 curr_aen.members.locale)) {
6439 6439 /*
6440 6440 * Previously issued event registration includes
6441 6441 * current request. Nothing to do.
6442 6442 */
6443 6443
6444 6444 return (0);
6445 6445 } else {
6446 6446 curr_aen.members.locale |= prev_aen.members.locale;
6447 6447
6448 6448 if (prev_aen.members.class < curr_aen.members.class)
6449 6449 curr_aen.members.class = prev_aen.members.class;
6450 6450
6451 6451 ret_val = abort_aen_cmd(instance, aen_cmd);
6452 6452
6453 6453 if (ret_val) {
6454 6454 con_log(CL_ANN, (CE_WARN, "register_mfi_aen: "
6455 6455 "failed to abort prevous AEN command"));
6456 6456
6457 6457 return (ret_val);
6458 6458 }
6459 6459 }
6460 6460 } else {
6461 6461 curr_aen.word = LE_32(class_locale_word);
6462 6462 curr_aen.members.locale = LE_16(curr_aen.members.locale);
6463 6463 }
6464 6464
6465 6465 if (instance->tbolt) {
6466 6466 cmd = get_raid_msg_mfi_pkt(instance);
6467 6467 } else {
6468 6468 cmd = mrsas_get_mfi_pkt(instance);
6469 6469 }
6470 6470
6471 6471 if (!cmd) {
6472 6472 DTRACE_PROBE2(mfi_aen_err, uint16_t, instance->fw_outstanding,
6473 6473 uint16_t, instance->max_fw_cmds);
6474 6474 return (ENOMEM);
6475 6475 }
6476 6476
6477 6477 /* Clear the frame buffer and assign back the context id */
6478 6478 (void) memset((char *)&cmd->frame[0], 0, sizeof (union mrsas_frame));
6479 6479 ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
6480 6480 cmd->index);
6481 6481
6482 6482 dcmd = &cmd->frame->dcmd;
6483 6483
6484 6484 /* for(i = 0; i < DCMD_MBOX_SZ; i++) dcmd->mbox.b[i] = 0; */
6485 6485 (void) memset(dcmd->mbox.b, 0, DCMD_MBOX_SZ);
6486 6486
6487 6487 (void) memset(instance->mfi_evt_detail_obj.buffer, 0,
6488 6488 sizeof (struct mrsas_evt_detail));
6489 6489
6490 6490 /* Prepare DCMD for aen registration */
6491 6491 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd, MFI_CMD_OP_DCMD);
6492 6492 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd_status, 0x0);
6493 6493 ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->sge_count, 1);
6494 6494 ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->flags,
6495 6495 MFI_FRAME_DIR_READ);
6496 6496 ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->timeout, 0);
6497 6497 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->data_xfer_len,
6498 6498 sizeof (struct mrsas_evt_detail));
6499 6499 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->opcode,
6500 6500 MR_DCMD_CTRL_EVENT_WAIT);
6501 6501 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->mbox.w[0], seq_num);
6502 6502 curr_aen.members.locale = LE_16(curr_aen.members.locale);
6503 6503 curr_aen.word = LE_32(curr_aen.word);
6504 6504 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->mbox.w[1],
6505 6505 curr_aen.word);
6506 6506 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].phys_addr,
6507 6507 instance->mfi_evt_detail_obj.dma_cookie[0].dmac_address);
6508 6508 ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].length,
6509 6509 sizeof (struct mrsas_evt_detail));
6510 6510
6511 6511 instance->aen_seq_num = seq_num;
6512 6512
6513 6513
6514 6514 /*
6515 6515 * Store reference to the cmd used to register for AEN. When an
6516 6516 * application wants us to register for AEN, we have to abort this
6517 6517 * cmd and re-register with a new EVENT LOCALE supplied by that app
6518 6518 */
6519 6519 instance->aen_cmd = cmd;
6520 6520
6521 6521 cmd->frame_count = 1;
6522 6522
6523 6523 /* Issue the aen registration frame */
6524 6524 /* atomic_add_16 (&instance->fw_outstanding, 1); */
6525 6525 if (instance->tbolt) {
6526 6526 mr_sas_tbolt_build_mfi_cmd(instance, cmd);
6527 6527 }
6528 6528 instance->func_ptr->issue_cmd(cmd, instance);
6529 6529
6530 6530 return (0);
6531 6531 }
6532 6532
6533 6533 void
6534 6534 display_scsi_inquiry(caddr_t scsi_inq)
6535 6535 {
6536 6536 #define MAX_SCSI_DEVICE_CODE 14
6537 6537 int i;
6538 6538 char inquiry_buf[256] = {0};
6539 6539 int len;
6540 6540 const char *const scsi_device_types[] = {
6541 6541 "Direct-Access ",
6542 6542 "Sequential-Access",
6543 6543 "Printer ",
6544 6544 "Processor ",
6545 6545 "WORM ",
6546 6546 "CD-ROM ",
6547 6547 "Scanner ",
6548 6548 "Optical Device ",
6549 6549 "Medium Changer ",
6550 6550 "Communications ",
6551 6551 "Unknown ",
6552 6552 "Unknown ",
6553 6553 "Unknown ",
6554 6554 "Enclosure ",
6555 6555 };
6556 6556
6557 6557 len = 0;
6558 6558
6559 6559 len += snprintf(inquiry_buf + len, 265 - len, " Vendor: ");
6560 6560 for (i = 8; i < 16; i++) {
6561 6561 len += snprintf(inquiry_buf + len, 265 - len, "%c",
6562 6562 scsi_inq[i]);
6563 6563 }
6564 6564
6565 6565 len += snprintf(inquiry_buf + len, 265 - len, " Model: ");
6566 6566
6567 6567 for (i = 16; i < 32; i++) {
6568 6568 len += snprintf(inquiry_buf + len, 265 - len, "%c",
6569 6569 scsi_inq[i]);
6570 6570 }
6571 6571
6572 6572 len += snprintf(inquiry_buf + len, 265 - len, " Rev: ");
6573 6573
6574 6574 for (i = 32; i < 36; i++) {
6575 6575 len += snprintf(inquiry_buf + len, 265 - len, "%c",
6576 6576 scsi_inq[i]);
6577 6577 }
6578 6578
6579 6579 len += snprintf(inquiry_buf + len, 265 - len, "\n");
6580 6580
6581 6581
6582 6582 i = scsi_inq[0] & 0x1f;
6583 6583
6584 6584
6585 6585 len += snprintf(inquiry_buf + len, 265 - len, " Type: %s ",
6586 6586 i < MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] :
6587 6587 "Unknown ");
6588 6588
6589 6589
6590 6590 len += snprintf(inquiry_buf + len, 265 - len,
6591 6591 " ANSI SCSI revision: %02x", scsi_inq[2] & 0x07);
6592 6592
6593 6593 if ((scsi_inq[2] & 0x07) == 1 && (scsi_inq[3] & 0x0f) == 1) {
6594 6594 len += snprintf(inquiry_buf + len, 265 - len, " CCS\n");
6595 6595 } else {
6596 6596 len += snprintf(inquiry_buf + len, 265 - len, "\n");
6597 6597 }
6598 6598
6599 6599 con_log(CL_DLEVEL2, (CE_CONT, inquiry_buf));
6600 6600 }
6601 6601
6602 6602 static void
6603 6603 io_timeout_checker(void *arg)
6604 6604 {
6605 6605 struct scsi_pkt *pkt;
6606 6606 struct mrsas_instance *instance = arg;
6607 6607 struct mrsas_cmd *cmd = NULL;
6608 6608 struct mrsas_header *hdr;
6609 6609 int time = 0;
6610 6610 int counter = 0;
6611 6611 struct mlist_head *pos, *next;
6612 6612 mlist_t process_list;
6613 6613
6614 6614 if (instance->adapterresetinprogress == 1) {
6615 6615 con_log(CL_ANN, (CE_NOTE, "io_timeout_checker:"
6616 6616 " reset in progress"));
6617 6617
6618 6618 instance->timeout_id = timeout(io_timeout_checker,
6619 6619 (void *) instance, drv_usectohz(MRSAS_1_SECOND));
6620 6620 return;
6621 6621 }
6622 6622
6623 6623 /* See if this check needs to be in the beginning or last in ISR */
6624 6624 if (mrsas_initiate_ocr_if_fw_is_faulty(instance) == 1) {
6625 6625 cmn_err(CE_WARN, "io_timeout_checker: "
6626 6626 "FW Fault, calling reset adapter");
6627 6627 cmn_err(CE_CONT, "io_timeout_checker: "
6628 6628 "fw_outstanding 0x%X max_fw_cmds 0x%X",
6629 6629 instance->fw_outstanding, instance->max_fw_cmds);
6630 6630 if (instance->adapterresetinprogress == 0) {
6631 6631 instance->adapterresetinprogress = 1;
6632 6632 if (instance->tbolt)
6633 6633 (void) mrsas_tbolt_reset_ppc(instance);
6634 6634 else
6635 6635 (void) mrsas_reset_ppc(instance);
6636 6636 instance->adapterresetinprogress = 0;
6637 6637 }
6638 6638 instance->timeout_id = timeout(io_timeout_checker,
6639 6639 (void *) instance, drv_usectohz(MRSAS_1_SECOND));
6640 6640 return;
6641 6641 }
6642 6642
6643 6643 INIT_LIST_HEAD(&process_list);
6644 6644
6645 6645 mutex_enter(&instance->cmd_pend_mtx);
6646 6646 mlist_for_each_safe(pos, next, &instance->cmd_pend_list) {
6647 6647 cmd = mlist_entry(pos, struct mrsas_cmd, list);
6648 6648
6649 6649 if (cmd == NULL) {
6650 6650 continue;
6651 6651 }
6652 6652
6653 6653 if (cmd->sync_cmd == MRSAS_TRUE) {
6654 6654 hdr = (struct mrsas_header *)&cmd->frame->hdr;
6655 6655 if (hdr == NULL) {
6656 6656 continue;
6657 6657 }
6658 6658 time = --cmd->drv_pkt_time;
6659 6659 } else {
6660 6660 pkt = cmd->pkt;
6661 6661 if (pkt == NULL) {
6662 6662 continue;
6663 6663 }
6664 6664 time = --cmd->drv_pkt_time;
6665 6665 }
6666 6666 if (time <= 0) {
6667 6667 cmn_err(CE_WARN, "%llx: "
6668 6668 "io_timeout_checker: TIMING OUT: pkt: %p, "
6669 6669 "cmd %p fw_outstanding 0x%X max_fw_cmds 0x%X\n",
6670 6670 gethrtime(), (void *)pkt, (void *)cmd,
6671 6671 instance->fw_outstanding, instance->max_fw_cmds);
6672 6672
6673 6673 counter++;
6674 6674 break;
6675 6675 }
6676 6676 }
6677 6677 mutex_exit(&instance->cmd_pend_mtx);
6678 6678
6679 6679 if (counter) {
6680 6680 if (instance->disable_online_ctrl_reset == 1) {
6681 6681 cmn_err(CE_WARN, "mr_sas %d: %s(): OCR is NOT "
6682 6682 "supported by Firmware, KILL adapter!!!",
6683 6683 instance->instance, __func__);
6684 6684
6685 6685 if (instance->tbolt)
6686 6686 mrsas_tbolt_kill_adapter(instance);
6687 6687 else
6688 6688 (void) mrsas_kill_adapter(instance);
6689 6689
6690 6690 return;
6691 6691 } else {
6692 6692 if (cmd->retry_count_for_ocr <= IO_RETRY_COUNT) {
6693 6693 if (instance->adapterresetinprogress == 0) {
6694 6694 if (instance->tbolt) {
6695 6695 (void) mrsas_tbolt_reset_ppc(
6696 6696 instance);
6697 6697 } else {
6698 6698 (void) mrsas_reset_ppc(
6699 6699 instance);
6700 6700 }
6701 6701 }
6702 6702 } else {
6703 6703 cmn_err(CE_WARN,
6704 6704 "io_timeout_checker: "
6705 6705 "cmd %p cmd->index %d "
6706 6706 "timed out even after 3 resets: "
6707 6707 "so KILL adapter", (void *)cmd, cmd->index);
6708 6708
6709 6709 mrsas_print_cmd_details(instance, cmd, 0xDD);
6710 6710
6711 6711 if (instance->tbolt)
6712 6712 mrsas_tbolt_kill_adapter(instance);
6713 6713 else
6714 6714 (void) mrsas_kill_adapter(instance);
6715 6715 return;
6716 6716 }
6717 6717 }
6718 6718 }
6719 6719 con_log(CL_ANN, (CE_NOTE, "mrsas: "
6720 6720 "schedule next timeout check: "
6721 6721 "do timeout \n"));
6722 6722 instance->timeout_id =
6723 6723 timeout(io_timeout_checker, (void *)instance,
6724 6724 drv_usectohz(MRSAS_1_SECOND));
6725 6725 }
6726 6726
↓ open down ↓ |
6726 lines elided |
↑ open up ↑ |
6727 6727 static uint32_t
6728 6728 read_fw_status_reg_ppc(struct mrsas_instance *instance)
6729 6729 {
6730 6730 return ((uint32_t)RD_OB_SCRATCH_PAD_0(instance));
6731 6731 }
6732 6732
6733 6733 static void
6734 6734 issue_cmd_ppc(struct mrsas_cmd *cmd, struct mrsas_instance *instance)
6735 6735 {
6736 6736 struct scsi_pkt *pkt;
6737 - atomic_add_16(&instance->fw_outstanding, 1);
6737 + atomic_inc_16(&instance->fw_outstanding);
6738 6738
6739 6739 pkt = cmd->pkt;
6740 6740 if (pkt) {
6741 6741 con_log(CL_DLEVEL1, (CE_NOTE, "%llx : issue_cmd_ppc:"
6742 6742 "ISSUED CMD TO FW : called : cmd:"
6743 6743 ": %p instance : %p pkt : %p pkt_time : %x\n",
6744 6744 gethrtime(), (void *)cmd, (void *)instance,
6745 6745 (void *)pkt, cmd->drv_pkt_time));
6746 6746 if (instance->adapterresetinprogress) {
6747 6747 cmd->drv_pkt_time = (uint16_t)debug_timeout_g;
6748 6748 con_log(CL_ANN1, (CE_NOTE, "Reset the scsi_pkt timer"));
6749 6749 } else {
6750 6750 push_pending_mfi_pkt(instance, cmd);
6751 6751 }
6752 6752
6753 6753 } else {
6754 6754 con_log(CL_DLEVEL1, (CE_NOTE, "%llx : issue_cmd_ppc:"
6755 6755 "ISSUED CMD TO FW : called : cmd : %p, instance: %p"
6756 6756 "(NO PKT)\n", gethrtime(), (void *)cmd, (void *)instance));
6757 6757 }
6758 6758
6759 6759 mutex_enter(&instance->reg_write_mtx);
6760 6760 /* Issue the command to the FW */
6761 6761 WR_IB_PICK_QPORT((cmd->frame_phys_addr) |
6762 6762 (((cmd->frame_count - 1) << 1) | 1), instance);
6763 6763 mutex_exit(&instance->reg_write_mtx);
6764 6764
6765 6765 }
6766 6766
6767 6767 /*
6768 6768 * issue_cmd_in_sync_mode
6769 6769 */
6770 6770 static int
6771 6771 issue_cmd_in_sync_mode_ppc(struct mrsas_instance *instance,
6772 6772 struct mrsas_cmd *cmd)
6773 6773 {
6774 6774 int i;
6775 6775 uint32_t msecs = MFI_POLL_TIMEOUT_SECS * MILLISEC;
6776 6776 struct mrsas_header *hdr = &cmd->frame->hdr;
6777 6777
6778 6778 con_log(CL_ANN1, (CE_NOTE, "issue_cmd_in_sync_mode_ppc: called"));
6779 6779
6780 6780 if (instance->adapterresetinprogress) {
6781 6781 cmd->drv_pkt_time = ddi_get16(
6782 6782 cmd->frame_dma_obj.acc_handle, &hdr->timeout);
6783 6783 if (cmd->drv_pkt_time < debug_timeout_g)
6784 6784 cmd->drv_pkt_time = (uint16_t)debug_timeout_g;
6785 6785
6786 6786 con_log(CL_ANN1, (CE_NOTE, "sync_mode_ppc: "
6787 6787 "issue and return in reset case\n"));
6788 6788 WR_IB_PICK_QPORT((cmd->frame_phys_addr) |
6789 6789 (((cmd->frame_count - 1) << 1) | 1), instance);
6790 6790
6791 6791 return (DDI_SUCCESS);
6792 6792 } else {
6793 6793 con_log(CL_ANN1, (CE_NOTE, "sync_mode_ppc: pushing the pkt\n"));
6794 6794 push_pending_mfi_pkt(instance, cmd);
6795 6795 }
6796 6796
6797 6797 cmd->cmd_status = ENODATA;
6798 6798
6799 6799 mutex_enter(&instance->reg_write_mtx);
6800 6800 /* Issue the command to the FW */
6801 6801 WR_IB_PICK_QPORT((cmd->frame_phys_addr) |
6802 6802 (((cmd->frame_count - 1) << 1) | 1), instance);
6803 6803 mutex_exit(&instance->reg_write_mtx);
6804 6804
6805 6805 mutex_enter(&instance->int_cmd_mtx);
6806 6806 for (i = 0; i < msecs && (cmd->cmd_status == ENODATA); i++) {
6807 6807 cv_wait(&instance->int_cmd_cv, &instance->int_cmd_mtx);
6808 6808 }
6809 6809 mutex_exit(&instance->int_cmd_mtx);
6810 6810
6811 6811 con_log(CL_ANN1, (CE_NOTE, "issue_cmd_in_sync_mode_ppc: done"));
6812 6812
6813 6813 if (i < (msecs -1)) {
6814 6814 return (DDI_SUCCESS);
6815 6815 } else {
6816 6816 return (DDI_FAILURE);
6817 6817 }
6818 6818 }
6819 6819
6820 6820 /*
6821 6821 * issue_cmd_in_poll_mode
6822 6822 */
6823 6823 static int
6824 6824 issue_cmd_in_poll_mode_ppc(struct mrsas_instance *instance,
6825 6825 struct mrsas_cmd *cmd)
6826 6826 {
6827 6827 int i;
6828 6828 uint16_t flags;
6829 6829 uint32_t msecs = MFI_POLL_TIMEOUT_SECS * MILLISEC;
6830 6830 struct mrsas_header *frame_hdr;
6831 6831
6832 6832 con_log(CL_ANN1, (CE_NOTE, "issue_cmd_in_poll_mode_ppc: called"));
6833 6833
6834 6834 frame_hdr = (struct mrsas_header *)cmd->frame;
6835 6835 ddi_put8(cmd->frame_dma_obj.acc_handle, &frame_hdr->cmd_status,
6836 6836 MFI_CMD_STATUS_POLL_MODE);
6837 6837 flags = ddi_get16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags);
6838 6838 flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
6839 6839
6840 6840 ddi_put16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags, flags);
6841 6841
6842 6842 /* issue the frame using inbound queue port */
6843 6843 WR_IB_PICK_QPORT((cmd->frame_phys_addr) |
6844 6844 (((cmd->frame_count - 1) << 1) | 1), instance);
6845 6845
6846 6846 /* wait for cmd_status to change from 0xFF */
6847 6847 for (i = 0; i < msecs && (
6848 6848 ddi_get8(cmd->frame_dma_obj.acc_handle, &frame_hdr->cmd_status)
6849 6849 == MFI_CMD_STATUS_POLL_MODE); i++) {
6850 6850 drv_usecwait(MILLISEC); /* wait for 1000 usecs */
6851 6851 }
6852 6852
6853 6853 if (ddi_get8(cmd->frame_dma_obj.acc_handle, &frame_hdr->cmd_status)
6854 6854 == MFI_CMD_STATUS_POLL_MODE) {
6855 6855 con_log(CL_ANN, (CE_NOTE, "issue_cmd_in_poll_mode: "
6856 6856 "cmd polling timed out"));
6857 6857 return (DDI_FAILURE);
6858 6858 }
6859 6859
6860 6860 return (DDI_SUCCESS);
6861 6861 }
6862 6862
6863 6863 static void
6864 6864 enable_intr_ppc(struct mrsas_instance *instance)
6865 6865 {
6866 6866 uint32_t mask;
6867 6867
6868 6868 con_log(CL_ANN1, (CE_NOTE, "enable_intr_ppc: called"));
6869 6869
6870 6870 if (instance->skinny) {
6871 6871 /* For SKINNY, write ~0x1, from BSD's mfi driver. */
6872 6872 WR_OB_INTR_MASK(0xfffffffe, instance);
6873 6873 } else {
6874 6874 /* WR_OB_DOORBELL_CLEAR(0xFFFFFFFF, instance); */
6875 6875 WR_OB_DOORBELL_CLEAR(OB_DOORBELL_CLEAR_MASK, instance);
6876 6876
6877 6877 /* WR_OB_INTR_MASK(~0x80000000, instance); */
6878 6878 WR_OB_INTR_MASK(~(MFI_REPLY_2108_MESSAGE_INTR_MASK), instance);
6879 6879 }
6880 6880
6881 6881 /* dummy read to force PCI flush */
6882 6882 mask = RD_OB_INTR_MASK(instance);
6883 6883
6884 6884 con_log(CL_ANN1, (CE_NOTE, "enable_intr_ppc: "
6885 6885 "outbound_intr_mask = 0x%x", mask));
6886 6886 }
6887 6887
6888 6888 static void
6889 6889 disable_intr_ppc(struct mrsas_instance *instance)
6890 6890 {
6891 6891 uint32_t mask;
6892 6892
6893 6893 con_log(CL_ANN1, (CE_NOTE, "disable_intr_ppc: called"));
6894 6894
6895 6895 con_log(CL_ANN1, (CE_NOTE, "disable_intr_ppc: before : "
6896 6896 "outbound_intr_mask = 0x%x", RD_OB_INTR_MASK(instance)));
6897 6897
6898 6898 /* For now, assume there are no extras needed for Skinny support. */
6899 6899
6900 6900 WR_OB_INTR_MASK(OB_INTR_MASK, instance);
6901 6901
6902 6902 con_log(CL_ANN1, (CE_NOTE, "disable_intr_ppc: after : "
6903 6903 "outbound_intr_mask = 0x%x", RD_OB_INTR_MASK(instance)));
6904 6904
6905 6905 /* dummy read to force PCI flush */
6906 6906 mask = RD_OB_INTR_MASK(instance);
6907 6907 #ifdef lint
6908 6908 mask = mask;
6909 6909 #endif
6910 6910 }
6911 6911
6912 6912 static int
6913 6913 intr_ack_ppc(struct mrsas_instance *instance)
6914 6914 {
6915 6915 uint32_t status;
6916 6916 int ret = DDI_INTR_CLAIMED;
6917 6917
6918 6918 con_log(CL_ANN1, (CE_NOTE, "intr_ack_ppc: called"));
6919 6919
6920 6920 /* check if it is our interrupt */
6921 6921 status = RD_OB_INTR_STATUS(instance);
6922 6922
6923 6923 con_log(CL_ANN1, (CE_NOTE, "intr_ack_ppc: status = 0x%x", status));
6924 6924
6925 6925 /*
6926 6926 * NOTE: Some drivers call out SKINNY here, but the return is the same
6927 6927 * for SKINNY and 2108.
6928 6928 */
6929 6929 if (!(status & MFI_REPLY_2108_MESSAGE_INTR)) {
6930 6930 ret = DDI_INTR_UNCLAIMED;
6931 6931 }
6932 6932
6933 6933 if (mrsas_check_acc_handle(instance->regmap_handle) != DDI_SUCCESS) {
6934 6934 ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
6935 6935 ret = DDI_INTR_UNCLAIMED;
6936 6936 }
6937 6937
6938 6938 if (ret == DDI_INTR_UNCLAIMED) {
6939 6939 return (ret);
6940 6940 }
6941 6941
6942 6942 /*
6943 6943 * Clear the interrupt by writing back the same value.
6944 6944 * Another case where SKINNY is slightly different.
6945 6945 */
6946 6946 if (instance->skinny) {
6947 6947 WR_OB_INTR_STATUS(status, instance);
6948 6948 } else {
6949 6949 WR_OB_DOORBELL_CLEAR(status, instance);
6950 6950 }
6951 6951
6952 6952 /* dummy READ */
6953 6953 status = RD_OB_INTR_STATUS(instance);
6954 6954
6955 6955 con_log(CL_ANN1, (CE_NOTE, "intr_ack_ppc: interrupt cleared"));
6956 6956
6957 6957 return (ret);
6958 6958 }
6959 6959
6960 6960 /*
6961 6961 * Marks HBA as bad. This will be called either when an
6962 6962 * IO packet times out even after 3 FW resets
6963 6963 * or FW is found to be fault even after 3 continuous resets.
6964 6964 */
6965 6965
6966 6966 static int
6967 6967 mrsas_kill_adapter(struct mrsas_instance *instance)
6968 6968 {
6969 6969 if (instance->deadadapter == 1)
6970 6970 return (DDI_FAILURE);
6971 6971
6972 6972 con_log(CL_ANN1, (CE_NOTE, "mrsas_kill_adapter: "
6973 6973 "Writing to doorbell with MFI_STOP_ADP "));
6974 6974 mutex_enter(&instance->ocr_flags_mtx);
6975 6975 instance->deadadapter = 1;
6976 6976 mutex_exit(&instance->ocr_flags_mtx);
6977 6977 instance->func_ptr->disable_intr(instance);
6978 6978 WR_IB_DOORBELL(MFI_STOP_ADP, instance);
6979 6979 (void) mrsas_complete_pending_cmds(instance);
6980 6980 return (DDI_SUCCESS);
6981 6981 }
6982 6982
6983 6983
6984 6984 static int
6985 6985 mrsas_reset_ppc(struct mrsas_instance *instance)
6986 6986 {
6987 6987 uint32_t status;
6988 6988 uint32_t retry = 0;
6989 6989 uint32_t cur_abs_reg_val;
6990 6990 uint32_t fw_state;
6991 6991
6992 6992 con_log(CL_ANN, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
6993 6993
6994 6994 if (instance->deadadapter == 1) {
6995 6995 cmn_err(CE_WARN, "mrsas_reset_ppc: "
6996 6996 "no more resets as HBA has been marked dead ");
6997 6997 return (DDI_FAILURE);
6998 6998 }
6999 6999 mutex_enter(&instance->ocr_flags_mtx);
7000 7000 instance->adapterresetinprogress = 1;
7001 7001 mutex_exit(&instance->ocr_flags_mtx);
7002 7002 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: adpterresetinprogress "
7003 7003 "flag set, time %llx", gethrtime()));
7004 7004
7005 7005 instance->func_ptr->disable_intr(instance);
7006 7006 retry_reset:
7007 7007 WR_IB_WRITE_SEQ(0, instance);
7008 7008 WR_IB_WRITE_SEQ(4, instance);
7009 7009 WR_IB_WRITE_SEQ(0xb, instance);
7010 7010 WR_IB_WRITE_SEQ(2, instance);
7011 7011 WR_IB_WRITE_SEQ(7, instance);
7012 7012 WR_IB_WRITE_SEQ(0xd, instance);
7013 7013 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: magic number written "
7014 7014 "to write sequence register\n"));
7015 7015 delay(100 * drv_usectohz(MILLISEC));
7016 7016 status = RD_OB_DRWE(instance);
7017 7017
7018 7018 while (!(status & DIAG_WRITE_ENABLE)) {
7019 7019 delay(100 * drv_usectohz(MILLISEC));
7020 7020 status = RD_OB_DRWE(instance);
7021 7021 if (retry++ == 100) {
7022 7022 cmn_err(CE_WARN, "mrsas_reset_ppc: DRWE bit "
7023 7023 "check retry count %d", retry);
7024 7024 return (DDI_FAILURE);
7025 7025 }
7026 7026 }
7027 7027 WR_IB_DRWE(status | DIAG_RESET_ADAPTER, instance);
7028 7028 delay(100 * drv_usectohz(MILLISEC));
7029 7029 status = RD_OB_DRWE(instance);
7030 7030 while (status & DIAG_RESET_ADAPTER) {
7031 7031 delay(100 * drv_usectohz(MILLISEC));
7032 7032 status = RD_OB_DRWE(instance);
7033 7033 if (retry++ == 100) {
7034 7034 cmn_err(CE_WARN, "mrsas_reset_ppc: "
7035 7035 "RESET FAILED. KILL adapter called.");
7036 7036
7037 7037 (void) mrsas_kill_adapter(instance);
7038 7038 return (DDI_FAILURE);
7039 7039 }
7040 7040 }
7041 7041 con_log(CL_ANN, (CE_NOTE, "mrsas_reset_ppc: Adapter reset complete"));
7042 7042 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7043 7043 "Calling mfi_state_transition_to_ready"));
7044 7044
7045 7045 /* Mark HBA as bad, if FW is fault after 3 continuous resets */
7046 7046 if (mfi_state_transition_to_ready(instance) ||
7047 7047 debug_fw_faults_after_ocr_g == 1) {
7048 7048 cur_abs_reg_val =
7049 7049 instance->func_ptr->read_fw_status_reg(instance);
7050 7050 fw_state = cur_abs_reg_val & MFI_STATE_MASK;
7051 7051
7052 7052 #ifdef OCRDEBUG
7053 7053 con_log(CL_ANN1, (CE_NOTE,
7054 7054 "mrsas_reset_ppc :before fake: FW is not ready "
7055 7055 "FW state = 0x%x", fw_state));
7056 7056 if (debug_fw_faults_after_ocr_g == 1)
7057 7057 fw_state = MFI_STATE_FAULT;
7058 7058 #endif
7059 7059
7060 7060 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc : FW is not ready "
7061 7061 "FW state = 0x%x", fw_state));
7062 7062
7063 7063 if (fw_state == MFI_STATE_FAULT) {
7064 7064 /* increment the count */
7065 7065 instance->fw_fault_count_after_ocr++;
7066 7066 if (instance->fw_fault_count_after_ocr
7067 7067 < MAX_FW_RESET_COUNT) {
7068 7068 cmn_err(CE_WARN, "mrsas_reset_ppc: "
7069 7069 "FW is in fault after OCR count %d "
7070 7070 "Retry Reset",
7071 7071 instance->fw_fault_count_after_ocr);
7072 7072 goto retry_reset;
7073 7073
7074 7074 } else {
7075 7075 cmn_err(CE_WARN, "mrsas_reset_ppc: "
7076 7076 "Max Reset Count exceeded >%d"
7077 7077 "Mark HBA as bad, KILL adapter",
7078 7078 MAX_FW_RESET_COUNT);
7079 7079
7080 7080 (void) mrsas_kill_adapter(instance);
7081 7081 return (DDI_FAILURE);
7082 7082 }
7083 7083 }
7084 7084 }
7085 7085 /* reset the counter as FW is up after OCR */
7086 7086 instance->fw_fault_count_after_ocr = 0;
7087 7087
7088 7088
7089 7089 ddi_put32(instance->mfi_internal_dma_obj.acc_handle,
7090 7090 instance->producer, 0);
7091 7091
7092 7092 ddi_put32(instance->mfi_internal_dma_obj.acc_handle,
7093 7093 instance->consumer, 0);
7094 7094
7095 7095 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7096 7096 " after resetting produconsumer chck indexs:"
7097 7097 "producer %x consumer %x", *instance->producer,
7098 7098 *instance->consumer));
7099 7099
7100 7100 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7101 7101 "Calling mrsas_issue_init_mfi"));
7102 7102 (void) mrsas_issue_init_mfi(instance);
7103 7103 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7104 7104 "mrsas_issue_init_mfi Done"));
7105 7105
7106 7106 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7107 7107 "Calling mrsas_print_pending_cmd\n"));
7108 7108 (void) mrsas_print_pending_cmds(instance);
7109 7109 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7110 7110 "mrsas_print_pending_cmd done\n"));
7111 7111
7112 7112 instance->func_ptr->enable_intr(instance);
7113 7113 instance->fw_outstanding = 0;
7114 7114
7115 7115 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7116 7116 "Calling mrsas_issue_pending_cmds"));
7117 7117 (void) mrsas_issue_pending_cmds(instance);
7118 7118 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7119 7119 "issue_pending_cmds done.\n"));
7120 7120
7121 7121 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7122 7122 "Calling aen registration"));
7123 7123
7124 7124
7125 7125 instance->aen_cmd->retry_count_for_ocr = 0;
7126 7126 instance->aen_cmd->drv_pkt_time = 0;
7127 7127
7128 7128 instance->func_ptr->issue_cmd(instance->aen_cmd, instance);
7129 7129 con_log(CL_ANN1, (CE_NOTE, "Unsetting adpresetinprogress flag.\n"));
7130 7130
7131 7131 mutex_enter(&instance->ocr_flags_mtx);
7132 7132 instance->adapterresetinprogress = 0;
7133 7133 mutex_exit(&instance->ocr_flags_mtx);
7134 7134 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc: "
7135 7135 "adpterresetinprogress flag unset"));
7136 7136
7137 7137 con_log(CL_ANN1, (CE_NOTE, "mrsas_reset_ppc done\n"));
7138 7138 return (DDI_SUCCESS);
7139 7139 }
7140 7140
7141 7141 /*
7142 7142 * FMA functions.
7143 7143 */
7144 7144 int
7145 7145 mrsas_common_check(struct mrsas_instance *instance, struct mrsas_cmd *cmd)
7146 7146 {
7147 7147 int ret = DDI_SUCCESS;
7148 7148
7149 7149 if (cmd != NULL &&
7150 7150 mrsas_check_dma_handle(cmd->frame_dma_obj.dma_handle) !=
7151 7151 DDI_SUCCESS) {
7152 7152 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
7153 7153 if (cmd->pkt != NULL) {
7154 7154 cmd->pkt->pkt_reason = CMD_TRAN_ERR;
7155 7155 cmd->pkt->pkt_statistics = 0;
7156 7156 }
7157 7157 ret = DDI_FAILURE;
7158 7158 }
7159 7159 if (mrsas_check_dma_handle(instance->mfi_internal_dma_obj.dma_handle)
7160 7160 != DDI_SUCCESS) {
7161 7161 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
7162 7162 if (cmd != NULL && cmd->pkt != NULL) {
7163 7163 cmd->pkt->pkt_reason = CMD_TRAN_ERR;
7164 7164 cmd->pkt->pkt_statistics = 0;
7165 7165 }
7166 7166 ret = DDI_FAILURE;
7167 7167 }
7168 7168 if (mrsas_check_dma_handle(instance->mfi_evt_detail_obj.dma_handle) !=
7169 7169 DDI_SUCCESS) {
7170 7170 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
7171 7171 if (cmd != NULL && cmd->pkt != NULL) {
7172 7172 cmd->pkt->pkt_reason = CMD_TRAN_ERR;
7173 7173 cmd->pkt->pkt_statistics = 0;
7174 7174 }
7175 7175 ret = DDI_FAILURE;
7176 7176 }
7177 7177 if (mrsas_check_acc_handle(instance->regmap_handle) != DDI_SUCCESS) {
7178 7178 ddi_fm_service_impact(instance->dip, DDI_SERVICE_UNAFFECTED);
7179 7179
7180 7180 ddi_fm_acc_err_clear(instance->regmap_handle, DDI_FME_VER0);
7181 7181
7182 7182 if (cmd != NULL && cmd->pkt != NULL) {
7183 7183 cmd->pkt->pkt_reason = CMD_TRAN_ERR;
7184 7184 cmd->pkt->pkt_statistics = 0;
7185 7185 }
7186 7186 ret = DDI_FAILURE;
7187 7187 }
7188 7188
7189 7189 return (ret);
7190 7190 }
7191 7191
7192 7192 /*ARGSUSED*/
7193 7193 static int
7194 7194 mrsas_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
7195 7195 {
7196 7196 /*
7197 7197 * as the driver can always deal with an error in any dma or
7198 7198 * access handle, we can just return the fme_status value.
7199 7199 */
7200 7200 pci_ereport_post(dip, err, NULL);
7201 7201 return (err->fme_status);
7202 7202 }
7203 7203
7204 7204 static void
7205 7205 mrsas_fm_init(struct mrsas_instance *instance)
7206 7206 {
7207 7207 /* Need to change iblock to priority for new MSI intr */
7208 7208 ddi_iblock_cookie_t fm_ibc;
7209 7209
7210 7210 /* Only register with IO Fault Services if we have some capability */
7211 7211 if (instance->fm_capabilities) {
7212 7212 /* Adjust access and dma attributes for FMA */
7213 7213 endian_attr.devacc_attr_access = DDI_FLAGERR_ACC;
7214 7214 mrsas_generic_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
7215 7215
7216 7216 /*
7217 7217 * Register capabilities with IO Fault Services.
7218 7218 * fm_capabilities will be updated to indicate
7219 7219 * capabilities actually supported (not requested.)
7220 7220 */
7221 7221
7222 7222 ddi_fm_init(instance->dip, &instance->fm_capabilities, &fm_ibc);
7223 7223
7224 7224 /*
7225 7225 * Initialize pci ereport capabilities if ereport
7226 7226 * capable (should always be.)
7227 7227 */
7228 7228
7229 7229 if (DDI_FM_EREPORT_CAP(instance->fm_capabilities) ||
7230 7230 DDI_FM_ERRCB_CAP(instance->fm_capabilities)) {
7231 7231 pci_ereport_setup(instance->dip);
7232 7232 }
7233 7233
7234 7234 /*
7235 7235 * Register error callback if error callback capable.
7236 7236 */
7237 7237 if (DDI_FM_ERRCB_CAP(instance->fm_capabilities)) {
7238 7238 ddi_fm_handler_register(instance->dip,
7239 7239 mrsas_fm_error_cb, (void*) instance);
7240 7240 }
7241 7241 } else {
7242 7242 endian_attr.devacc_attr_access = DDI_DEFAULT_ACC;
7243 7243 mrsas_generic_dma_attr.dma_attr_flags = 0;
7244 7244 }
7245 7245 }
7246 7246
7247 7247 static void
7248 7248 mrsas_fm_fini(struct mrsas_instance *instance)
7249 7249 {
7250 7250 /* Only unregister FMA capabilities if registered */
7251 7251 if (instance->fm_capabilities) {
7252 7252 /*
7253 7253 * Un-register error callback if error callback capable.
7254 7254 */
7255 7255 if (DDI_FM_ERRCB_CAP(instance->fm_capabilities)) {
7256 7256 ddi_fm_handler_unregister(instance->dip);
7257 7257 }
7258 7258
7259 7259 /*
7260 7260 * Release any resources allocated by pci_ereport_setup()
7261 7261 */
7262 7262 if (DDI_FM_EREPORT_CAP(instance->fm_capabilities) ||
7263 7263 DDI_FM_ERRCB_CAP(instance->fm_capabilities)) {
7264 7264 pci_ereport_teardown(instance->dip);
7265 7265 }
7266 7266
7267 7267 /* Unregister from IO Fault Services */
7268 7268 ddi_fm_fini(instance->dip);
7269 7269
7270 7270 /* Adjust access and dma attributes for FMA */
7271 7271 endian_attr.devacc_attr_access = DDI_DEFAULT_ACC;
7272 7272 mrsas_generic_dma_attr.dma_attr_flags = 0;
7273 7273 }
7274 7274 }
7275 7275
7276 7276 int
7277 7277 mrsas_check_acc_handle(ddi_acc_handle_t handle)
7278 7278 {
7279 7279 ddi_fm_error_t de;
7280 7280
7281 7281 if (handle == NULL) {
7282 7282 return (DDI_FAILURE);
7283 7283 }
7284 7284
7285 7285 ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
7286 7286
7287 7287 return (de.fme_status);
7288 7288 }
7289 7289
7290 7290 int
7291 7291 mrsas_check_dma_handle(ddi_dma_handle_t handle)
7292 7292 {
7293 7293 ddi_fm_error_t de;
7294 7294
7295 7295 if (handle == NULL) {
7296 7296 return (DDI_FAILURE);
7297 7297 }
7298 7298
7299 7299 ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
7300 7300
7301 7301 return (de.fme_status);
7302 7302 }
7303 7303
7304 7304 void
7305 7305 mrsas_fm_ereport(struct mrsas_instance *instance, char *detail)
7306 7306 {
7307 7307 uint64_t ena;
7308 7308 char buf[FM_MAX_CLASS];
7309 7309
7310 7310 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
7311 7311 ena = fm_ena_generate(0, FM_ENA_FMT1);
7312 7312 if (DDI_FM_EREPORT_CAP(instance->fm_capabilities)) {
7313 7313 ddi_fm_ereport_post(instance->dip, buf, ena, DDI_NOSLEEP,
7314 7314 FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERSION, NULL);
7315 7315 }
7316 7316 }
7317 7317
7318 7318 static int
7319 7319 mrsas_add_intrs(struct mrsas_instance *instance, int intr_type)
7320 7320 {
7321 7321
7322 7322 dev_info_t *dip = instance->dip;
7323 7323 int avail, actual, count;
7324 7324 int i, flag, ret;
7325 7325
7326 7326 con_log(CL_DLEVEL1, (CE_NOTE, "mrsas_add_intrs: intr_type = %x",
7327 7327 intr_type));
7328 7328
7329 7329 /* Get number of interrupts */
7330 7330 ret = ddi_intr_get_nintrs(dip, intr_type, &count);
7331 7331 if ((ret != DDI_SUCCESS) || (count == 0)) {
7332 7332 con_log(CL_ANN, (CE_WARN, "ddi_intr_get_nintrs() failed:"
7333 7333 "ret %d count %d", ret, count));
7334 7334
7335 7335 return (DDI_FAILURE);
7336 7336 }
7337 7337
7338 7338 con_log(CL_DLEVEL1, (CE_NOTE, "mrsas_add_intrs: count = %d ", count));
7339 7339
7340 7340 /* Get number of available interrupts */
7341 7341 ret = ddi_intr_get_navail(dip, intr_type, &avail);
7342 7342 if ((ret != DDI_SUCCESS) || (avail == 0)) {
7343 7343 con_log(CL_ANN, (CE_WARN, "ddi_intr_get_navail() failed:"
7344 7344 "ret %d avail %d", ret, avail));
7345 7345
7346 7346 return (DDI_FAILURE);
7347 7347 }
7348 7348 con_log(CL_DLEVEL1, (CE_NOTE, "mrsas_add_intrs: avail = %d ", avail));
7349 7349
7350 7350 /* Only one interrupt routine. So limit the count to 1 */
7351 7351 if (count > 1) {
7352 7352 count = 1;
7353 7353 }
7354 7354
7355 7355 /*
7356 7356 * Allocate an array of interrupt handlers. Currently we support
7357 7357 * only one interrupt. The framework can be extended later.
7358 7358 */
7359 7359 instance->intr_htable_size = count * sizeof (ddi_intr_handle_t);
7360 7360 instance->intr_htable = kmem_zalloc(instance->intr_htable_size,
7361 7361 KM_SLEEP);
7362 7362 ASSERT(instance->intr_htable);
7363 7363
7364 7364 flag = ((intr_type == DDI_INTR_TYPE_MSI) ||
7365 7365 (intr_type == DDI_INTR_TYPE_MSIX)) ?
7366 7366 DDI_INTR_ALLOC_STRICT : DDI_INTR_ALLOC_NORMAL;
7367 7367
7368 7368 /* Allocate interrupt */
7369 7369 ret = ddi_intr_alloc(dip, instance->intr_htable, intr_type, 0,
7370 7370 count, &actual, flag);
7371 7371
7372 7372 if ((ret != DDI_SUCCESS) || (actual == 0)) {
7373 7373 con_log(CL_ANN, (CE_WARN, "mrsas_add_intrs: "
7374 7374 "avail = %d", avail));
7375 7375 goto mrsas_free_htable;
7376 7376 }
7377 7377
7378 7378 if (actual < count) {
7379 7379 con_log(CL_ANN, (CE_WARN, "mrsas_add_intrs: "
7380 7380 "Requested = %d Received = %d", count, actual));
7381 7381 }
7382 7382 instance->intr_cnt = actual;
7383 7383
7384 7384 /*
7385 7385 * Get the priority of the interrupt allocated.
7386 7386 */
7387 7387 if ((ret = ddi_intr_get_pri(instance->intr_htable[0],
7388 7388 &instance->intr_pri)) != DDI_SUCCESS) {
7389 7389 con_log(CL_ANN, (CE_WARN, "mrsas_add_intrs: "
7390 7390 "get priority call failed"));
7391 7391 goto mrsas_free_handles;
7392 7392 }
7393 7393
7394 7394 /*
7395 7395 * Test for high level mutex. we don't support them.
7396 7396 */
7397 7397 if (instance->intr_pri >= ddi_intr_get_hilevel_pri()) {
7398 7398 con_log(CL_ANN, (CE_WARN, "mrsas_add_intrs: "
7399 7399 "High level interrupts not supported."));
7400 7400 goto mrsas_free_handles;
7401 7401 }
7402 7402
7403 7403 con_log(CL_DLEVEL1, (CE_NOTE, "mrsas_add_intrs: intr_pri = 0x%x ",
7404 7404 instance->intr_pri));
7405 7405
7406 7406 /* Call ddi_intr_add_handler() */
7407 7407 for (i = 0; i < actual; i++) {
7408 7408 ret = ddi_intr_add_handler(instance->intr_htable[i],
7409 7409 (ddi_intr_handler_t *)mrsas_isr, (caddr_t)instance,
7410 7410 (caddr_t)(uintptr_t)i);
7411 7411
7412 7412 if (ret != DDI_SUCCESS) {
7413 7413 con_log(CL_ANN, (CE_WARN, "mrsas_add_intrs:"
7414 7414 "failed %d", ret));
7415 7415 goto mrsas_free_handles;
7416 7416 }
7417 7417
7418 7418 }
7419 7419
7420 7420 con_log(CL_DLEVEL1, (CE_NOTE, " ddi_intr_add_handler done"));
7421 7421
7422 7422 if ((ret = ddi_intr_get_cap(instance->intr_htable[0],
7423 7423 &instance->intr_cap)) != DDI_SUCCESS) {
7424 7424 con_log(CL_ANN, (CE_WARN, "ddi_intr_get_cap() failed %d",
7425 7425 ret));
7426 7426 goto mrsas_free_handlers;
7427 7427 }
7428 7428
7429 7429 if (instance->intr_cap & DDI_INTR_FLAG_BLOCK) {
7430 7430 con_log(CL_ANN, (CE_WARN, "Calling ddi_intr_block _enable"));
7431 7431
7432 7432 (void) ddi_intr_block_enable(instance->intr_htable,
7433 7433 instance->intr_cnt);
7434 7434 } else {
7435 7435 con_log(CL_ANN, (CE_NOTE, " calling ddi_intr_enable"));
7436 7436
7437 7437 for (i = 0; i < instance->intr_cnt; i++) {
7438 7438 (void) ddi_intr_enable(instance->intr_htable[i]);
7439 7439 con_log(CL_ANN, (CE_NOTE, "ddi intr enable returns "
7440 7440 "%d", i));
7441 7441 }
7442 7442 }
7443 7443
7444 7444 return (DDI_SUCCESS);
7445 7445
7446 7446 mrsas_free_handlers:
7447 7447 for (i = 0; i < actual; i++)
7448 7448 (void) ddi_intr_remove_handler(instance->intr_htable[i]);
7449 7449
7450 7450 mrsas_free_handles:
7451 7451 for (i = 0; i < actual; i++)
7452 7452 (void) ddi_intr_free(instance->intr_htable[i]);
7453 7453
7454 7454 mrsas_free_htable:
7455 7455 if (instance->intr_htable != NULL)
7456 7456 kmem_free(instance->intr_htable, instance->intr_htable_size);
7457 7457
7458 7458 instance->intr_htable = NULL;
7459 7459 instance->intr_htable_size = 0;
7460 7460
7461 7461 return (DDI_FAILURE);
7462 7462
7463 7463 }
7464 7464
7465 7465
7466 7466 static void
7467 7467 mrsas_rem_intrs(struct mrsas_instance *instance)
7468 7468 {
7469 7469 int i;
7470 7470
7471 7471 con_log(CL_ANN, (CE_NOTE, "mrsas_rem_intrs called"));
7472 7472
7473 7473 /* Disable all interrupts first */
7474 7474 if (instance->intr_cap & DDI_INTR_FLAG_BLOCK) {
7475 7475 (void) ddi_intr_block_disable(instance->intr_htable,
7476 7476 instance->intr_cnt);
7477 7477 } else {
7478 7478 for (i = 0; i < instance->intr_cnt; i++) {
7479 7479 (void) ddi_intr_disable(instance->intr_htable[i]);
7480 7480 }
7481 7481 }
7482 7482
7483 7483 /* Remove all the handlers */
7484 7484
7485 7485 for (i = 0; i < instance->intr_cnt; i++) {
7486 7486 (void) ddi_intr_remove_handler(instance->intr_htable[i]);
7487 7487 (void) ddi_intr_free(instance->intr_htable[i]);
7488 7488 }
7489 7489
7490 7490 if (instance->intr_htable != NULL)
7491 7491 kmem_free(instance->intr_htable, instance->intr_htable_size);
7492 7492
7493 7493 instance->intr_htable = NULL;
7494 7494 instance->intr_htable_size = 0;
7495 7495
7496 7496 }
7497 7497
7498 7498 static int
7499 7499 mrsas_tran_bus_config(dev_info_t *parent, uint_t flags,
7500 7500 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
7501 7501 {
7502 7502 struct mrsas_instance *instance;
7503 7503 int config;
7504 7504 int rval = NDI_SUCCESS;
7505 7505
7506 7506 char *ptr = NULL;
7507 7507 int tgt, lun;
7508 7508
7509 7509 con_log(CL_ANN1, (CE_NOTE, "Bus config called for op = %x", op));
7510 7510
7511 7511 if ((instance = ddi_get_soft_state(mrsas_state,
7512 7512 ddi_get_instance(parent))) == NULL) {
7513 7513 return (NDI_FAILURE);
7514 7514 }
7515 7515
7516 7516 /* Hold nexus during bus_config */
7517 7517 ndi_devi_enter(parent, &config);
7518 7518 switch (op) {
7519 7519 case BUS_CONFIG_ONE: {
7520 7520
7521 7521 /* parse wwid/target name out of name given */
7522 7522 if ((ptr = strchr((char *)arg, '@')) == NULL) {
7523 7523 rval = NDI_FAILURE;
7524 7524 break;
7525 7525 }
7526 7526 ptr++;
7527 7527
7528 7528 if (mrsas_parse_devname(arg, &tgt, &lun) != 0) {
7529 7529 rval = NDI_FAILURE;
7530 7530 break;
7531 7531 }
7532 7532
7533 7533 if (lun == 0) {
7534 7534 rval = mrsas_config_ld(instance, tgt, lun, childp);
7535 7535 #ifdef PDSUPPORT
7536 7536 } else if ((instance->tbolt || instance->skinny) && lun != 0) {
7537 7537 rval = mrsas_tbolt_config_pd(instance,
7538 7538 tgt, lun, childp);
7539 7539 #endif
7540 7540 } else {
7541 7541 rval = NDI_FAILURE;
7542 7542 }
7543 7543
7544 7544 break;
7545 7545 }
7546 7546 case BUS_CONFIG_DRIVER:
7547 7547 case BUS_CONFIG_ALL: {
7548 7548
7549 7549 rval = mrsas_config_all_devices(instance);
7550 7550
7551 7551 rval = NDI_SUCCESS;
7552 7552 break;
7553 7553 }
7554 7554 }
7555 7555
7556 7556 if (rval == NDI_SUCCESS) {
7557 7557 rval = ndi_busop_bus_config(parent, flags, op, arg, childp, 0);
7558 7558
7559 7559 }
7560 7560 ndi_devi_exit(parent, config);
7561 7561
7562 7562 con_log(CL_ANN1, (CE_NOTE, "mrsas_tran_bus_config: rval = %x",
7563 7563 rval));
7564 7564 return (rval);
7565 7565 }
7566 7566
7567 7567 static int
7568 7568 mrsas_config_all_devices(struct mrsas_instance *instance)
7569 7569 {
7570 7570 int rval, tgt;
7571 7571
7572 7572 for (tgt = 0; tgt < MRDRV_MAX_LD; tgt++) {
7573 7573 (void) mrsas_config_ld(instance, tgt, 0, NULL);
7574 7574
7575 7575 }
7576 7576
7577 7577 #ifdef PDSUPPORT
7578 7578 /* Config PD devices connected to the card */
7579 7579 if (instance->tbolt || instance->skinny) {
7580 7580 for (tgt = 0; tgt < instance->mr_tbolt_pd_max; tgt++) {
7581 7581 (void) mrsas_tbolt_config_pd(instance, tgt, 1, NULL);
7582 7582 }
7583 7583 }
7584 7584 #endif
7585 7585
7586 7586 rval = NDI_SUCCESS;
7587 7587 return (rval);
7588 7588 }
7589 7589
7590 7590 static int
7591 7591 mrsas_parse_devname(char *devnm, int *tgt, int *lun)
7592 7592 {
7593 7593 char devbuf[SCSI_MAXNAMELEN];
7594 7594 char *addr;
7595 7595 char *p, *tp, *lp;
7596 7596 long num;
7597 7597
7598 7598 /* Parse dev name and address */
7599 7599 (void) strcpy(devbuf, devnm);
7600 7600 addr = "";
7601 7601 for (p = devbuf; *p != '\0'; p++) {
7602 7602 if (*p == '@') {
7603 7603 addr = p + 1;
7604 7604 *p = '\0';
7605 7605 } else if (*p == ':') {
7606 7606 *p = '\0';
7607 7607 break;
7608 7608 }
7609 7609 }
7610 7610
7611 7611 /* Parse target and lun */
7612 7612 for (p = tp = addr, lp = NULL; *p != '\0'; p++) {
7613 7613 if (*p == ',') {
7614 7614 lp = p + 1;
7615 7615 *p = '\0';
7616 7616 break;
7617 7617 }
7618 7618 }
7619 7619 if (tgt && tp) {
7620 7620 if (ddi_strtol(tp, NULL, 0x10, &num)) {
7621 7621 return (DDI_FAILURE); /* Can declare this as constant */
7622 7622 }
7623 7623 *tgt = (int)num;
7624 7624 }
7625 7625 if (lun && lp) {
7626 7626 if (ddi_strtol(lp, NULL, 0x10, &num)) {
7627 7627 return (DDI_FAILURE);
7628 7628 }
7629 7629 *lun = (int)num;
7630 7630 }
7631 7631 return (DDI_SUCCESS); /* Success case */
7632 7632 }
7633 7633
7634 7634 static int
7635 7635 mrsas_config_ld(struct mrsas_instance *instance, uint16_t tgt,
7636 7636 uint8_t lun, dev_info_t **ldip)
7637 7637 {
7638 7638 struct scsi_device *sd;
7639 7639 dev_info_t *child;
7640 7640 int rval;
7641 7641
7642 7642 con_log(CL_DLEVEL1, (CE_NOTE, "mrsas_config_ld: t = %d l = %d",
7643 7643 tgt, lun));
7644 7644
7645 7645 if ((child = mrsas_find_child(instance, tgt, lun)) != NULL) {
7646 7646 if (ldip) {
7647 7647 *ldip = child;
7648 7648 }
7649 7649 if (instance->mr_ld_list[tgt].flag != MRDRV_TGT_VALID) {
7650 7650 rval = mrsas_service_evt(instance, tgt, 0,
7651 7651 MRSAS_EVT_UNCONFIG_TGT, NULL);
7652 7652 con_log(CL_ANN1, (CE_WARN,
7653 7653 "mr_sas: DELETING STALE ENTRY rval = %d "
7654 7654 "tgt id = %d ", rval, tgt));
7655 7655 return (NDI_FAILURE);
7656 7656 }
7657 7657 return (NDI_SUCCESS);
7658 7658 }
7659 7659
7660 7660 sd = kmem_zalloc(sizeof (struct scsi_device), KM_SLEEP);
7661 7661 sd->sd_address.a_hba_tran = instance->tran;
7662 7662 sd->sd_address.a_target = (uint16_t)tgt;
7663 7663 sd->sd_address.a_lun = (uint8_t)lun;
7664 7664
7665 7665 if (scsi_hba_probe(sd, NULL) == SCSIPROBE_EXISTS)
7666 7666 rval = mrsas_config_scsi_device(instance, sd, ldip);
7667 7667 else
7668 7668 rval = NDI_FAILURE;
7669 7669
7670 7670 /* sd_unprobe is blank now. Free buffer manually */
7671 7671 if (sd->sd_inq) {
7672 7672 kmem_free(sd->sd_inq, SUN_INQSIZE);
7673 7673 sd->sd_inq = (struct scsi_inquiry *)NULL;
7674 7674 }
7675 7675
7676 7676 kmem_free(sd, sizeof (struct scsi_device));
7677 7677 con_log(CL_DLEVEL1, (CE_NOTE, "mrsas_config_ld: return rval = %d",
7678 7678 rval));
7679 7679 return (rval);
7680 7680 }
7681 7681
7682 7682 int
7683 7683 mrsas_config_scsi_device(struct mrsas_instance *instance,
7684 7684 struct scsi_device *sd, dev_info_t **dipp)
7685 7685 {
7686 7686 char *nodename = NULL;
7687 7687 char **compatible = NULL;
7688 7688 int ncompatible = 0;
7689 7689 char *childname;
7690 7690 dev_info_t *ldip = NULL;
7691 7691 int tgt = sd->sd_address.a_target;
7692 7692 int lun = sd->sd_address.a_lun;
7693 7693 int dtype = sd->sd_inq->inq_dtype & DTYPE_MASK;
7694 7694 int rval;
7695 7695
7696 7696 con_log(CL_DLEVEL1, (CE_NOTE, "mr_sas: scsi_device t%dL%d", tgt, lun));
7697 7697 scsi_hba_nodename_compatible_get(sd->sd_inq, NULL, dtype,
7698 7698 NULL, &nodename, &compatible, &ncompatible);
7699 7699
7700 7700 if (nodename == NULL) {
7701 7701 con_log(CL_ANN1, (CE_WARN, "mr_sas: Found no compatible driver "
7702 7702 "for t%dL%d", tgt, lun));
7703 7703 rval = NDI_FAILURE;
7704 7704 goto finish;
7705 7705 }
7706 7706
7707 7707 childname = (dtype == DTYPE_DIRECT) ? "sd" : nodename;
7708 7708 con_log(CL_DLEVEL1, (CE_NOTE,
7709 7709 "mr_sas: Childname = %2s nodename = %s", childname, nodename));
7710 7710
7711 7711 /* Create a dev node */
7712 7712 rval = ndi_devi_alloc(instance->dip, childname, DEVI_SID_NODEID, &ldip);
7713 7713 con_log(CL_DLEVEL1, (CE_NOTE,
7714 7714 "mr_sas_config_scsi_device: ndi_devi_alloc rval = %x", rval));
7715 7715 if (rval == NDI_SUCCESS) {
7716 7716 if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "target", tgt) !=
7717 7717 DDI_PROP_SUCCESS) {
7718 7718 con_log(CL_ANN1, (CE_WARN, "mr_sas: unable to create "
7719 7719 "property for t%dl%d target", tgt, lun));
7720 7720 rval = NDI_FAILURE;
7721 7721 goto finish;
7722 7722 }
7723 7723 if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "lun", lun) !=
7724 7724 DDI_PROP_SUCCESS) {
7725 7725 con_log(CL_ANN1, (CE_WARN, "mr_sas: unable to create "
7726 7726 "property for t%dl%d lun", tgt, lun));
7727 7727 rval = NDI_FAILURE;
7728 7728 goto finish;
7729 7729 }
7730 7730
7731 7731 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, ldip,
7732 7732 "compatible", compatible, ncompatible) !=
7733 7733 DDI_PROP_SUCCESS) {
7734 7734 con_log(CL_ANN1, (CE_WARN, "mr_sas: unable to create "
7735 7735 "property for t%dl%d compatible", tgt, lun));
7736 7736 rval = NDI_FAILURE;
7737 7737 goto finish;
7738 7738 }
7739 7739
7740 7740 rval = ndi_devi_online(ldip, NDI_ONLINE_ATTACH);
7741 7741 if (rval != NDI_SUCCESS) {
7742 7742 con_log(CL_ANN1, (CE_WARN, "mr_sas: unable to online "
7743 7743 "t%dl%d", tgt, lun));
7744 7744 ndi_prop_remove_all(ldip);
7745 7745 (void) ndi_devi_free(ldip);
7746 7746 } else {
7747 7747 con_log(CL_ANN1, (CE_CONT, "mr_sas: online Done :"
7748 7748 "0 t%dl%d", tgt, lun));
7749 7749 }
7750 7750
7751 7751 }
7752 7752 finish:
7753 7753 if (dipp) {
7754 7754 *dipp = ldip;
7755 7755 }
7756 7756
7757 7757 con_log(CL_DLEVEL1, (CE_NOTE,
7758 7758 "mr_sas: config_scsi_device rval = %d t%dL%d",
7759 7759 rval, tgt, lun));
7760 7760 scsi_hba_nodename_compatible_free(nodename, compatible);
7761 7761 return (rval);
7762 7762 }
7763 7763
7764 7764 /*ARGSUSED*/
7765 7765 int
7766 7766 mrsas_service_evt(struct mrsas_instance *instance, int tgt, int lun, int event,
7767 7767 uint64_t wwn)
7768 7768 {
7769 7769 struct mrsas_eventinfo *mrevt = NULL;
7770 7770
7771 7771 con_log(CL_ANN1, (CE_NOTE,
7772 7772 "mrsas_service_evt called for t%dl%d event = %d",
7773 7773 tgt, lun, event));
7774 7774
7775 7775 if ((instance->taskq == NULL) || (mrevt =
7776 7776 kmem_zalloc(sizeof (struct mrsas_eventinfo), KM_NOSLEEP)) == NULL) {
7777 7777 return (ENOMEM);
7778 7778 }
7779 7779
7780 7780 mrevt->instance = instance;
7781 7781 mrevt->tgt = tgt;
7782 7782 mrevt->lun = lun;
7783 7783 mrevt->event = event;
7784 7784 mrevt->wwn = wwn;
7785 7785
7786 7786 if ((ddi_taskq_dispatch(instance->taskq,
7787 7787 (void (*)(void *))mrsas_issue_evt_taskq, mrevt, DDI_NOSLEEP)) !=
7788 7788 DDI_SUCCESS) {
7789 7789 con_log(CL_ANN1, (CE_NOTE,
7790 7790 "mr_sas: Event task failed for t%dl%d event = %d",
7791 7791 tgt, lun, event));
7792 7792 kmem_free(mrevt, sizeof (struct mrsas_eventinfo));
7793 7793 return (DDI_FAILURE);
7794 7794 }
7795 7795 DTRACE_PROBE3(service_evt, int, tgt, int, lun, int, event);
7796 7796 return (DDI_SUCCESS);
7797 7797 }
7798 7798
7799 7799 static void
7800 7800 mrsas_issue_evt_taskq(struct mrsas_eventinfo *mrevt)
7801 7801 {
7802 7802 struct mrsas_instance *instance = mrevt->instance;
7803 7803 dev_info_t *dip, *pdip;
7804 7804 int circ1 = 0;
7805 7805 char *devname;
7806 7806
7807 7807 con_log(CL_ANN1, (CE_NOTE, "mrsas_issue_evt_taskq: called for"
7808 7808 " tgt %d lun %d event %d",
7809 7809 mrevt->tgt, mrevt->lun, mrevt->event));
7810 7810
7811 7811 if (mrevt->tgt < MRDRV_MAX_LD && mrevt->lun == 0) {
7812 7812 mutex_enter(&instance->config_dev_mtx);
7813 7813 dip = instance->mr_ld_list[mrevt->tgt].dip;
7814 7814 mutex_exit(&instance->config_dev_mtx);
7815 7815 #ifdef PDSUPPORT
7816 7816 } else {
7817 7817 mutex_enter(&instance->config_dev_mtx);
7818 7818 dip = instance->mr_tbolt_pd_list[mrevt->tgt].dip;
7819 7819 mutex_exit(&instance->config_dev_mtx);
7820 7820 #endif
7821 7821 }
7822 7822
7823 7823
7824 7824 ndi_devi_enter(instance->dip, &circ1);
7825 7825 switch (mrevt->event) {
7826 7826 case MRSAS_EVT_CONFIG_TGT:
7827 7827 if (dip == NULL) {
7828 7828
7829 7829 if (mrevt->lun == 0) {
7830 7830 (void) mrsas_config_ld(instance, mrevt->tgt,
7831 7831 0, NULL);
7832 7832 #ifdef PDSUPPORT
7833 7833 } else if (instance->tbolt || instance->skinny) {
7834 7834 (void) mrsas_tbolt_config_pd(instance,
7835 7835 mrevt->tgt,
7836 7836 1, NULL);
7837 7837 #endif
7838 7838 }
7839 7839 con_log(CL_ANN1, (CE_NOTE,
7840 7840 "mr_sas: EVT_CONFIG_TGT called:"
7841 7841 " for tgt %d lun %d event %d",
7842 7842 mrevt->tgt, mrevt->lun, mrevt->event));
7843 7843
7844 7844 } else {
7845 7845 con_log(CL_ANN1, (CE_NOTE,
7846 7846 "mr_sas: EVT_CONFIG_TGT dip != NULL:"
7847 7847 " for tgt %d lun %d event %d",
7848 7848 mrevt->tgt, mrevt->lun, mrevt->event));
7849 7849 }
7850 7850 break;
7851 7851 case MRSAS_EVT_UNCONFIG_TGT:
7852 7852 if (dip) {
7853 7853 if (i_ddi_devi_attached(dip)) {
7854 7854
7855 7855 pdip = ddi_get_parent(dip);
7856 7856
7857 7857 devname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
7858 7858 (void) ddi_deviname(dip, devname);
7859 7859
7860 7860 (void) devfs_clean(pdip, devname + 1,
7861 7861 DV_CLEAN_FORCE);
7862 7862 kmem_free(devname, MAXNAMELEN + 1);
7863 7863 }
7864 7864 (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
7865 7865 con_log(CL_ANN1, (CE_NOTE,
7866 7866 "mr_sas: EVT_UNCONFIG_TGT called:"
7867 7867 " for tgt %d lun %d event %d",
7868 7868 mrevt->tgt, mrevt->lun, mrevt->event));
7869 7869 } else {
7870 7870 con_log(CL_ANN1, (CE_NOTE,
7871 7871 "mr_sas: EVT_UNCONFIG_TGT dip == NULL:"
7872 7872 " for tgt %d lun %d event %d",
7873 7873 mrevt->tgt, mrevt->lun, mrevt->event));
7874 7874 }
7875 7875 break;
7876 7876 }
7877 7877 kmem_free(mrevt, sizeof (struct mrsas_eventinfo));
7878 7878 ndi_devi_exit(instance->dip, circ1);
7879 7879 }
7880 7880
7881 7881
7882 7882 int
7883 7883 mrsas_mode_sense_build(struct scsi_pkt *pkt)
7884 7884 {
7885 7885 union scsi_cdb *cdbp;
7886 7886 uint16_t page_code;
7887 7887 struct scsa_cmd *acmd;
7888 7888 struct buf *bp;
7889 7889 struct mode_header *modehdrp;
7890 7890
7891 7891 cdbp = (void *)pkt->pkt_cdbp;
7892 7892 page_code = cdbp->cdb_un.sg.scsi[0];
7893 7893 acmd = PKT2CMD(pkt);
7894 7894 bp = acmd->cmd_buf;
7895 7895 if ((!bp) && bp->b_un.b_addr && bp->b_bcount && acmd->cmd_dmacount) {
7896 7896 con_log(CL_ANN1, (CE_WARN, "Failing MODESENSE Command"));
7897 7897 /* ADD pkt statistics as Command failed. */
7898 7898 return (NULL);
7899 7899 }
7900 7900
7901 7901 bp_mapin(bp);
7902 7902 bzero(bp->b_un.b_addr, bp->b_bcount);
7903 7903
7904 7904 switch (page_code) {
7905 7905 case 0x3: {
7906 7906 struct mode_format *page3p = NULL;
7907 7907 modehdrp = (struct mode_header *)(bp->b_un.b_addr);
7908 7908 modehdrp->bdesc_length = MODE_BLK_DESC_LENGTH;
7909 7909
7910 7910 page3p = (void *)((caddr_t)modehdrp +
7911 7911 MODE_HEADER_LENGTH + MODE_BLK_DESC_LENGTH);
7912 7912 page3p->mode_page.code = 0x3;
7913 7913 page3p->mode_page.length =
7914 7914 (uchar_t)(sizeof (struct mode_format));
7915 7915 page3p->data_bytes_sect = 512;
7916 7916 page3p->sect_track = 63;
7917 7917 break;
7918 7918 }
7919 7919 case 0x4: {
7920 7920 struct mode_geometry *page4p = NULL;
7921 7921 modehdrp = (struct mode_header *)(bp->b_un.b_addr);
7922 7922 modehdrp->bdesc_length = MODE_BLK_DESC_LENGTH;
7923 7923
7924 7924 page4p = (void *)((caddr_t)modehdrp +
7925 7925 MODE_HEADER_LENGTH + MODE_BLK_DESC_LENGTH);
7926 7926 page4p->mode_page.code = 0x4;
7927 7927 page4p->mode_page.length =
7928 7928 (uchar_t)(sizeof (struct mode_geometry));
7929 7929 page4p->heads = 255;
7930 7930 page4p->rpm = 10000;
7931 7931 break;
7932 7932 }
7933 7933 default:
7934 7934 break;
7935 7935 }
7936 7936 return (NULL);
7937 7937 }
↓ open down ↓ |
1190 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX