Print this page
4403 mpt_sas panic when pulling a drive
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
+++ new/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
25 25 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * Copyright (c) 2000 to 2010, LSI Corporation.
30 30 * All rights reserved.
31 31 *
32 32 * Redistribution and use in source and binary forms of all code within
33 33 * this file that is exclusively owned by LSI, with or without
34 34 * modification, is permitted provided that, in addition to the CDDL 1.0
35 35 * License requirements, the following conditions are met:
36 36 *
37 37 * Neither the name of the author nor the names of its contributors may be
38 38 * used to endorse or promote products derived from this software without
39 39 * specific prior written permission.
40 40 *
41 41 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
42 42 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
43 43 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
44 44 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
45 45 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
46 46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
47 47 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
48 48 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
49 49 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51 51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
52 52 * DAMAGE.
53 53 */
54 54
55 55 /*
56 56 * mptsas - This is a driver based on LSI Logic's MPT2.0 interface.
57 57 *
58 58 */
59 59
60 60 #if defined(lint) || defined(DEBUG)
61 61 #define MPTSAS_DEBUG
62 62 #endif
63 63
64 64 /*
65 65 * standard header files.
66 66 */
67 67 #include <sys/note.h>
68 68 #include <sys/scsi/scsi.h>
69 69 #include <sys/pci.h>
70 70 #include <sys/file.h>
71 71 #include <sys/policy.h>
72 72 #include <sys/model.h>
73 73 #include <sys/sysevent.h>
74 74 #include <sys/sysevent/eventdefs.h>
75 75 #include <sys/sysevent/dr.h>
76 76 #include <sys/sata/sata_defs.h>
77 77 #include <sys/scsi/generic/sas.h>
78 78 #include <sys/scsi/impl/scsi_sas.h>
79 79
80 80 #pragma pack(1)
81 81 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
82 82 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
83 83 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
84 84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
85 85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
86 86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
87 87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
88 88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
89 89 #pragma pack()
90 90
91 91 /*
92 92 * private header files.
93 93 *
94 94 */
95 95 #include <sys/scsi/impl/scsi_reset_notify.h>
96 96 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
97 97 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
98 98 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
99 99 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
100 100 #include <sys/raidioctl.h>
101 101
102 102 #include <sys/fs/dv_node.h> /* devfs_clean */
103 103
104 104 /*
105 105 * FMA header files
106 106 */
107 107 #include <sys/ddifm.h>
108 108 #include <sys/fm/protocol.h>
109 109 #include <sys/fm/util.h>
110 110 #include <sys/fm/io/ddi.h>
111 111
112 112 /*
113 113 * autoconfiguration data and routines.
114 114 */
115 115 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
116 116 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
117 117 static int mptsas_power(dev_info_t *dip, int component, int level);
118 118
119 119 /*
120 120 * cb_ops function
121 121 */
122 122 static int mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
123 123 cred_t *credp, int *rval);
124 124 #ifdef __sparc
125 125 static int mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd);
126 126 #else /* __sparc */
127 127 static int mptsas_quiesce(dev_info_t *devi);
128 128 #endif /* __sparc */
129 129
130 130 /*
131 131 * Resource initilaization for hardware
132 132 */
133 133 static void mptsas_setup_cmd_reg(mptsas_t *mpt);
134 134 static void mptsas_disable_bus_master(mptsas_t *mpt);
135 135 static void mptsas_hba_fini(mptsas_t *mpt);
136 136 static void mptsas_cfg_fini(mptsas_t *mptsas_blkp);
137 137 static int mptsas_hba_setup(mptsas_t *mpt);
138 138 static void mptsas_hba_teardown(mptsas_t *mpt);
139 139 static int mptsas_config_space_init(mptsas_t *mpt);
140 140 static void mptsas_config_space_fini(mptsas_t *mpt);
141 141 static void mptsas_iport_register(mptsas_t *mpt);
142 142 static int mptsas_smp_setup(mptsas_t *mpt);
143 143 static void mptsas_smp_teardown(mptsas_t *mpt);
144 144 static int mptsas_cache_create(mptsas_t *mpt);
145 145 static void mptsas_cache_destroy(mptsas_t *mpt);
146 146 static int mptsas_alloc_request_frames(mptsas_t *mpt);
147 147 static int mptsas_alloc_reply_frames(mptsas_t *mpt);
148 148 static int mptsas_alloc_free_queue(mptsas_t *mpt);
149 149 static int mptsas_alloc_post_queue(mptsas_t *mpt);
150 150 static void mptsas_alloc_reply_args(mptsas_t *mpt);
151 151 static int mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
152 152 static void mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
153 153 static int mptsas_init_chip(mptsas_t *mpt, int first_time);
154 154
155 155 /*
156 156 * SCSA function prototypes
157 157 */
158 158 static int mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
159 159 static int mptsas_scsi_reset(struct scsi_address *ap, int level);
160 160 static int mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
161 161 static int mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly);
162 162 static int mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value,
163 163 int tgtonly);
164 164 static void mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
165 165 static struct scsi_pkt *mptsas_scsi_init_pkt(struct scsi_address *ap,
166 166 struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
167 167 int tgtlen, int flags, int (*callback)(), caddr_t arg);
168 168 static void mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
169 169 static void mptsas_scsi_destroy_pkt(struct scsi_address *ap,
170 170 struct scsi_pkt *pkt);
171 171 static int mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
172 172 scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
173 173 static void mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
174 174 scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
175 175 static int mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
176 176 void (*callback)(caddr_t), caddr_t arg);
177 177 static int mptsas_get_name(struct scsi_device *sd, char *name, int len);
178 178 static int mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len);
179 179 static int mptsas_scsi_quiesce(dev_info_t *dip);
180 180 static int mptsas_scsi_unquiesce(dev_info_t *dip);
181 181 static int mptsas_bus_config(dev_info_t *pdip, uint_t flags,
182 182 ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
183 183
184 184 /*
185 185 * SMP functions
186 186 */
187 187 static int mptsas_smp_start(struct smp_pkt *smp_pkt);
188 188
189 189 /*
190 190 * internal function prototypes.
191 191 */
192 192 static void mptsas_list_add(mptsas_t *mpt);
193 193 static void mptsas_list_del(mptsas_t *mpt);
194 194
195 195 static int mptsas_quiesce_bus(mptsas_t *mpt);
196 196 static int mptsas_unquiesce_bus(mptsas_t *mpt);
197 197
198 198 static int mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size);
199 199 static void mptsas_free_handshake_msg(mptsas_t *mpt);
200 200
201 201 static void mptsas_ncmds_checkdrain(void *arg);
202 202
203 203 static int mptsas_prepare_pkt(mptsas_cmd_t *cmd);
204 204 static int mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
205 205 static int mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
206 206 static void mptsas_accept_tx_waitq(mptsas_t *mpt);
207 207
208 208 static int mptsas_do_detach(dev_info_t *dev);
209 209 static int mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl);
210 210 static int mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun,
211 211 struct scsi_pkt *pkt);
212 212 static int mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp);
213 213
214 214 static void mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd);
215 215 static void mptsas_handle_event(void *args);
216 216 static int mptsas_handle_event_sync(void *args);
217 217 static void mptsas_handle_dr(void *args);
218 218 static void mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
219 219 dev_info_t *pdip);
220 220
221 221 static void mptsas_restart_cmd(void *);
222 222
223 223 static void mptsas_flush_hba(mptsas_t *mpt);
224 224 static void mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun,
225 225 uint8_t tasktype);
226 226 static void mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd,
227 227 uchar_t reason, uint_t stat);
228 228
229 229 static uint_t mptsas_intr(caddr_t arg1, caddr_t arg2);
230 230 static void mptsas_process_intr(mptsas_t *mpt,
231 231 pMpi2ReplyDescriptorsUnion_t reply_desc_union);
232 232 static void mptsas_handle_scsi_io_success(mptsas_t *mpt,
233 233 pMpi2ReplyDescriptorsUnion_t reply_desc);
234 234 static void mptsas_handle_address_reply(mptsas_t *mpt,
235 235 pMpi2ReplyDescriptorsUnion_t reply_desc);
236 236 static int mptsas_wait_intr(mptsas_t *mpt, int polltime);
237 237 static void mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd,
238 238 uint32_t *control, pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl);
239 239
240 240 static void mptsas_watch(void *arg);
241 241 static void mptsas_watchsubr(mptsas_t *mpt);
242 242 static void mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl);
243 243
244 244 static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
245 245 static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
246 246 uint8_t *data, uint32_t request_size, uint32_t reply_size,
247 247 uint32_t data_size, uint32_t direction, uint8_t *dataout,
248 248 uint32_t dataout_size, short timeout, int mode);
249 249 static int mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl);
250 250
251 251 static uint8_t mptsas_get_fw_diag_buffer_number(mptsas_t *mpt,
252 252 uint32_t unique_id);
253 253 static void mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd);
254 254 static int mptsas_post_fw_diag_buffer(mptsas_t *mpt,
255 255 mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
256 256 static int mptsas_release_fw_diag_buffer(mptsas_t *mpt,
257 257 mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
258 258 uint32_t diag_type);
259 259 static int mptsas_diag_register(mptsas_t *mpt,
260 260 mptsas_fw_diag_register_t *diag_register, uint32_t *return_code);
261 261 static int mptsas_diag_unregister(mptsas_t *mpt,
262 262 mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
263 263 static int mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
264 264 uint32_t *return_code);
265 265 static int mptsas_diag_read_buffer(mptsas_t *mpt,
266 266 mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
267 267 uint32_t *return_code, int ioctl_mode);
268 268 static int mptsas_diag_release(mptsas_t *mpt,
269 269 mptsas_fw_diag_release_t *diag_release, uint32_t *return_code);
270 270 static int mptsas_do_diag_action(mptsas_t *mpt, uint32_t action,
271 271 uint8_t *diag_action, uint32_t length, uint32_t *return_code,
272 272 int ioctl_mode);
273 273 static int mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *data,
274 274 int mode);
275 275
276 276 static int mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
277 277 int cmdlen, int tgtlen, int statuslen, int kf);
278 278 static void mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd);
279 279
280 280 static int mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags);
281 281 static void mptsas_kmem_cache_destructor(void *buf, void *cdrarg);
282 282
283 283 static int mptsas_cache_frames_constructor(void *buf, void *cdrarg,
284 284 int kmflags);
285 285 static void mptsas_cache_frames_destructor(void *buf, void *cdrarg);
286 286
287 287 static void mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
288 288 mptsas_cmd_t *cmd);
289 289 static void mptsas_check_task_mgt(mptsas_t *mpt,
290 290 pMpi2SCSIManagementReply_t reply, mptsas_cmd_t *cmd);
291 291 static int mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
292 292 mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
293 293 int *resid);
294 294
295 295 static int mptsas_alloc_active_slots(mptsas_t *mpt, int flag);
296 296 static void mptsas_free_active_slots(mptsas_t *mpt);
297 297 static int mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
298 298
299 299 static void mptsas_restart_hba(mptsas_t *mpt);
300 300 static void mptsas_restart_waitq(mptsas_t *mpt);
301 301
302 302 static void mptsas_deliver_doneq_thread(mptsas_t *mpt);
303 303 static void mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd);
304 304 static void mptsas_doneq_mv(mptsas_t *mpt, uint64_t t);
305 305
306 306 static mptsas_cmd_t *mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t);
307 307 static void mptsas_doneq_empty(mptsas_t *mpt);
308 308 static void mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg);
309 309
310 310 static mptsas_cmd_t *mptsas_waitq_rm(mptsas_t *mpt);
311 311 static void mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
312 312 static mptsas_cmd_t *mptsas_tx_waitq_rm(mptsas_t *mpt);
313 313 static void mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
314 314
315 315
316 316 static void mptsas_start_watch_reset_delay();
317 317 static void mptsas_setup_bus_reset_delay(mptsas_t *mpt);
318 318 static void mptsas_watch_reset_delay(void *arg);
319 319 static int mptsas_watch_reset_delay_subr(mptsas_t *mpt);
320 320
321 321 /*
322 322 * helper functions
323 323 */
324 324 static void mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
325 325
326 326 static dev_info_t *mptsas_find_child(dev_info_t *pdip, char *name);
327 327 static dev_info_t *mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy);
328 328 static dev_info_t *mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr,
329 329 int lun);
330 330 static mdi_pathinfo_t *mptsas_find_path_addr(dev_info_t *pdip, uint64_t sasaddr,
331 331 int lun);
332 332 static mdi_pathinfo_t *mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy);
333 333 static dev_info_t *mptsas_find_smp_child(dev_info_t *pdip, char *str_wwn);
334 334
335 335 static int mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy,
336 336 int *lun);
337 337 static int mptsas_parse_smp_name(char *name, uint64_t *wwn);
338 338
339 339 static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt,
340 340 mptsas_phymask_t phymask, uint8_t phy);
341 341 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt,
342 342 mptsas_phymask_t phymask, uint64_t wwid);
343 343 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt,
344 344 mptsas_phymask_t phymask, uint64_t wwid);
345 345
346 346 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
347 347 uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
348 348
349 349 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
350 350 uint16_t *handle, mptsas_target_t **pptgt);
351 351 static void mptsas_update_phymask(mptsas_t *mpt);
352 352
353 353 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
354 354 uint32_t *status, uint8_t cmd);
355 355 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
356 356 mptsas_phymask_t *phymask);
357 357 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
358 358 mptsas_phymask_t phymask);
359 359 static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt);
360 360
361 361
362 362 /*
363 363 * Enumeration / DR functions
364 364 */
365 365 static void mptsas_config_all(dev_info_t *pdip);
366 366 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
367 367 dev_info_t **lundip);
368 368 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
369 369 dev_info_t **lundip);
370 370
371 371 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
372 372 static int mptsas_offline_target(dev_info_t *pdip, char *name);
373 373
374 374 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
375 375 dev_info_t **dip);
376 376
377 377 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
378 378 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
379 379 dev_info_t **dip, mptsas_target_t *ptgt);
380 380
381 381 static int mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
382 382 dev_info_t **dip, mptsas_target_t *ptgt, int lun);
383 383
384 384 static int mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
385 385 char *guid, dev_info_t **dip, mptsas_target_t *ptgt, int lun);
386 386 static int mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
387 387 char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt,
388 388 int lun);
389 389
390 390 static void mptsas_offline_missed_luns(dev_info_t *pdip,
391 391 uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
392 392 static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
393 393 mdi_pathinfo_t *rpip, uint_t flags);
394 394
395 395 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
396 396 dev_info_t **smp_dip);
397 397 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
398 398 uint_t flags);
399 399
400 400 static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data,
401 401 int mode, int *rval);
402 402 static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data,
403 403 int mode, int *rval);
404 404 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
405 405 int mode, int *rval);
406 406 static void mptsas_record_event(void *args);
407 407 static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
408 408 int mode);
409 409
410 410 mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, uint64_t,
411 411 uint32_t, mptsas_phymask_t, uint8_t);
412 412 static mptsas_smp_t *mptsas_smp_alloc(mptsas_t *, mptsas_smp_t *);
413 413 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
414 414 dev_info_t **smp_dip);
415 415
416 416 /*
417 417 * Power management functions
418 418 */
419 419 static int mptsas_get_pci_cap(mptsas_t *mpt);
420 420 static int mptsas_init_pm(mptsas_t *mpt);
421 421
422 422 /*
423 423 * MPT MSI tunable:
424 424 *
425 425 * By default MSI is enabled on all supported platforms.
426 426 */
427 427 boolean_t mptsas_enable_msi = B_TRUE;
428 428 boolean_t mptsas_physical_bind_failed_page_83 = B_FALSE;
429 429
430 430 static int mptsas_register_intrs(mptsas_t *);
431 431 static void mptsas_unregister_intrs(mptsas_t *);
432 432 static int mptsas_add_intrs(mptsas_t *, int);
433 433 static void mptsas_rem_intrs(mptsas_t *);
434 434
435 435 /*
436 436 * FMA Prototypes
437 437 */
438 438 static void mptsas_fm_init(mptsas_t *mpt);
439 439 static void mptsas_fm_fini(mptsas_t *mpt);
440 440 static int mptsas_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
441 441
442 442 extern pri_t minclsyspri, maxclsyspri;
443 443
444 444 /*
445 445 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI). It is
446 446 * under this device that the paths to a physical device are created when
447 447 * MPxIO is used.
448 448 */
449 449 extern dev_info_t *scsi_vhci_dip;
450 450
451 451 /*
452 452 * Tunable timeout value for Inquiry VPD page 0x83
453 453 * By default the value is 30 seconds.
454 454 */
455 455 int mptsas_inq83_retry_timeout = 30;
456 456
457 457 /*
458 458 * This is used to allocate memory for message frame storage, not for
459 459 * data I/O DMA. All message frames must be stored in the first 4G of
460 460 * physical memory.
461 461 */
462 462 ddi_dma_attr_t mptsas_dma_attrs = {
463 463 DMA_ATTR_V0, /* attribute layout version */
464 464 0x0ull, /* address low - should be 0 (longlong) */
465 465 0xffffffffull, /* address high - 32-bit max range */
466 466 0x00ffffffull, /* count max - max DMA object size */
467 467 4, /* allocation alignment requirements */
468 468 0x78, /* burstsizes - binary encoded values */
469 469 1, /* minxfer - gran. of DMA engine */
470 470 0x00ffffffull, /* maxxfer - gran. of DMA engine */
471 471 0xffffffffull, /* max segment size (DMA boundary) */
472 472 MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length */
473 473 512, /* granularity - device transfer size */
474 474 0 /* flags, set to 0 */
475 475 };
476 476
477 477 /*
478 478 * This is used for data I/O DMA memory allocation. (full 64-bit DMA
479 479 * physical addresses are supported.)
480 480 */
481 481 ddi_dma_attr_t mptsas_dma_attrs64 = {
482 482 DMA_ATTR_V0, /* attribute layout version */
483 483 0x0ull, /* address low - should be 0 (longlong) */
484 484 0xffffffffffffffffull, /* address high - 64-bit max */
485 485 0x00ffffffull, /* count max - max DMA object size */
486 486 4, /* allocation alignment requirements */
487 487 0x78, /* burstsizes - binary encoded values */
488 488 1, /* minxfer - gran. of DMA engine */
489 489 0x00ffffffull, /* maxxfer - gran. of DMA engine */
490 490 0xffffffffull, /* max segment size (DMA boundary) */
491 491 MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length */
492 492 512, /* granularity - device transfer size */
493 493 DDI_DMA_RELAXED_ORDERING /* flags, enable relaxed ordering */
494 494 };
495 495
496 496 ddi_device_acc_attr_t mptsas_dev_attr = {
497 497 DDI_DEVICE_ATTR_V1,
498 498 DDI_STRUCTURE_LE_ACC,
499 499 DDI_STRICTORDER_ACC,
500 500 DDI_DEFAULT_ACC
501 501 };
502 502
503 503 static struct cb_ops mptsas_cb_ops = {
504 504 scsi_hba_open, /* open */
505 505 scsi_hba_close, /* close */
506 506 nodev, /* strategy */
507 507 nodev, /* print */
508 508 nodev, /* dump */
509 509 nodev, /* read */
510 510 nodev, /* write */
511 511 mptsas_ioctl, /* ioctl */
512 512 nodev, /* devmap */
513 513 nodev, /* mmap */
514 514 nodev, /* segmap */
515 515 nochpoll, /* chpoll */
516 516 ddi_prop_op, /* cb_prop_op */
517 517 NULL, /* streamtab */
518 518 D_MP, /* cb_flag */
519 519 CB_REV, /* rev */
520 520 nodev, /* aread */
521 521 nodev /* awrite */
522 522 };
523 523
524 524 static struct dev_ops mptsas_ops = {
525 525 DEVO_REV, /* devo_rev, */
526 526 0, /* refcnt */
527 527 ddi_no_info, /* info */
528 528 nulldev, /* identify */
529 529 nulldev, /* probe */
530 530 mptsas_attach, /* attach */
531 531 mptsas_detach, /* detach */
532 532 #ifdef __sparc
533 533 mptsas_reset,
534 534 #else
535 535 nodev, /* reset */
536 536 #endif /* __sparc */
537 537 &mptsas_cb_ops, /* driver operations */
538 538 NULL, /* bus operations */
539 539 mptsas_power, /* power management */
540 540 #ifdef __sparc
541 541 ddi_quiesce_not_needed
542 542 #else
543 543 mptsas_quiesce /* quiesce */
544 544 #endif /* __sparc */
545 545 };
546 546
547 547
548 548 #define MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.24"
549 549
550 550 static struct modldrv modldrv = {
551 551 &mod_driverops, /* Type of module. This one is a driver */
552 552 MPTSAS_MOD_STRING, /* Name of the module. */
553 553 &mptsas_ops, /* driver ops */
554 554 };
555 555
556 556 static struct modlinkage modlinkage = {
557 557 MODREV_1, &modldrv, NULL
558 558 };
559 559 #define TARGET_PROP "target"
560 560 #define LUN_PROP "lun"
561 561 #define LUN64_PROP "lun64"
562 562 #define SAS_PROP "sas-mpt"
563 563 #define MDI_GUID "wwn"
564 564 #define NDI_GUID "guid"
565 565 #define MPTSAS_DEV_GONE "mptsas_dev_gone"
566 566
567 567 /*
568 568 * Local static data
569 569 */
570 570 #if defined(MPTSAS_DEBUG)
571 571 uint32_t mptsas_debug_flags = 0;
572 572 #endif /* defined(MPTSAS_DEBUG) */
573 573 uint32_t mptsas_debug_resets = 0;
574 574
575 575 static kmutex_t mptsas_global_mutex;
576 576 static void *mptsas_state; /* soft state ptr */
577 577 static krwlock_t mptsas_global_rwlock;
578 578
579 579 static kmutex_t mptsas_log_mutex;
580 580 static char mptsas_log_buf[256];
581 581 _NOTE(MUTEX_PROTECTS_DATA(mptsas_log_mutex, mptsas_log_buf))
582 582
583 583 static mptsas_t *mptsas_head, *mptsas_tail;
584 584 static clock_t mptsas_scsi_watchdog_tick;
585 585 static clock_t mptsas_tick;
586 586 static timeout_id_t mptsas_reset_watch;
587 587 static timeout_id_t mptsas_timeout_id;
588 588 static int mptsas_timeouts_enabled = 0;
589 589 /*
590 590 * warlock directives
591 591 */
592 592 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt \
593 593 mptsas_cmd NcrTableIndirect buf scsi_cdb scsi_status))
594 594 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", smp_pkt))
595 595 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
596 596 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mptsas_tgt_private))
597 597 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran::tran_tgt_private))
598 598
599 599 /*
600 600 * SM - HBA statics
601 601 */
602 602 char *mptsas_driver_rev = MPTSAS_MOD_STRING;
603 603
604 604 #ifdef MPTSAS_DEBUG
605 605 void debug_enter(char *);
606 606 #endif
607 607
608 608 /*
609 609 * Notes:
610 610 * - scsi_hba_init(9F) initializes SCSI HBA modules
611 611 * - must call scsi_hba_fini(9F) if modload() fails
612 612 */
613 613 int
614 614 _init(void)
615 615 {
616 616 int status;
617 617 /* CONSTCOND */
618 618 ASSERT(NO_COMPETING_THREADS);
619 619
620 620 NDBG0(("_init"));
621 621
622 622 status = ddi_soft_state_init(&mptsas_state, MPTSAS_SIZE,
623 623 MPTSAS_INITIAL_SOFT_SPACE);
624 624 if (status != 0) {
625 625 return (status);
626 626 }
627 627
628 628 if ((status = scsi_hba_init(&modlinkage)) != 0) {
629 629 ddi_soft_state_fini(&mptsas_state);
630 630 return (status);
631 631 }
632 632
633 633 mutex_init(&mptsas_global_mutex, NULL, MUTEX_DRIVER, NULL);
634 634 rw_init(&mptsas_global_rwlock, NULL, RW_DRIVER, NULL);
635 635 mutex_init(&mptsas_log_mutex, NULL, MUTEX_DRIVER, NULL);
636 636
637 637 if ((status = mod_install(&modlinkage)) != 0) {
638 638 mutex_destroy(&mptsas_log_mutex);
639 639 rw_destroy(&mptsas_global_rwlock);
640 640 mutex_destroy(&mptsas_global_mutex);
641 641 ddi_soft_state_fini(&mptsas_state);
642 642 scsi_hba_fini(&modlinkage);
643 643 }
644 644
645 645 return (status);
646 646 }
647 647
648 648 /*
649 649 * Notes:
650 650 * - scsi_hba_fini(9F) uninitializes SCSI HBA modules
651 651 */
652 652 int
653 653 _fini(void)
654 654 {
655 655 int status;
656 656 /* CONSTCOND */
657 657 ASSERT(NO_COMPETING_THREADS);
658 658
659 659 NDBG0(("_fini"));
660 660
661 661 if ((status = mod_remove(&modlinkage)) == 0) {
662 662 ddi_soft_state_fini(&mptsas_state);
663 663 scsi_hba_fini(&modlinkage);
664 664 mutex_destroy(&mptsas_global_mutex);
665 665 rw_destroy(&mptsas_global_rwlock);
666 666 mutex_destroy(&mptsas_log_mutex);
667 667 }
668 668 return (status);
669 669 }
670 670
671 671 /*
672 672 * The loadable-module _info(9E) entry point
673 673 */
674 674 int
675 675 _info(struct modinfo *modinfop)
676 676 {
677 677 /* CONSTCOND */
678 678 ASSERT(NO_COMPETING_THREADS);
679 679 NDBG0(("mptsas _info"));
680 680
681 681 return (mod_info(&modlinkage, modinfop));
682 682 }
683 683
684 684 static int
685 685 mptsas_target_eval_devhdl(const void *op, void *arg)
686 686 {
687 687 uint16_t dh = *(uint16_t *)arg;
688 688 const mptsas_target_t *tp = op;
689 689
690 690 return ((int)tp->m_devhdl - (int)dh);
691 691 }
692 692
693 693 static int
694 694 mptsas_target_eval_slot(const void *op, void *arg)
695 695 {
696 696 mptsas_led_control_t *lcp = arg;
697 697 const mptsas_target_t *tp = op;
698 698
699 699 if (tp->m_enclosure != lcp->Enclosure)
700 700 return ((int)tp->m_enclosure - (int)lcp->Enclosure);
701 701
702 702 return ((int)tp->m_slot_num - (int)lcp->Slot);
703 703 }
704 704
705 705 static int
706 706 mptsas_target_eval_nowwn(const void *op, void *arg)
707 707 {
708 708 uint8_t phy = *(uint8_t *)arg;
709 709 const mptsas_target_t *tp = op;
710 710
711 711 if (tp->m_addr.mta_wwn != 0)
712 712 return (-1);
713 713
714 714 return ((int)tp->m_phynum - (int)phy);
715 715 }
716 716
717 717 static int
718 718 mptsas_smp_eval_devhdl(const void *op, void *arg)
719 719 {
720 720 uint16_t dh = *(uint16_t *)arg;
721 721 const mptsas_smp_t *sp = op;
722 722
723 723 return ((int)sp->m_devhdl - (int)dh);
724 724 }
725 725
726 726 static uint64_t
727 727 mptsas_target_addr_hash(const void *tp)
728 728 {
729 729 const mptsas_target_addr_t *tap = tp;
730 730
731 731 return ((tap->mta_wwn & 0xffffffffffffULL) |
732 732 ((uint64_t)tap->mta_phymask << 48));
733 733 }
734 734
735 735 static int
736 736 mptsas_target_addr_cmp(const void *a, const void *b)
737 737 {
738 738 const mptsas_target_addr_t *aap = a;
739 739 const mptsas_target_addr_t *bap = b;
740 740
741 741 if (aap->mta_wwn < bap->mta_wwn)
742 742 return (-1);
743 743 if (aap->mta_wwn > bap->mta_wwn)
744 744 return (1);
745 745 return ((int)bap->mta_phymask - (int)aap->mta_phymask);
746 746 }
747 747
748 748 static void
749 749 mptsas_target_free(void *op)
750 750 {
751 751 kmem_free(op, sizeof (mptsas_target_t));
752 752 }
753 753
754 754 static void
755 755 mptsas_smp_free(void *op)
756 756 {
757 757 kmem_free(op, sizeof (mptsas_smp_t));
758 758 }
759 759
760 760 static void
761 761 mptsas_destroy_hashes(mptsas_t *mpt)
762 762 {
763 763 mptsas_target_t *tp;
764 764 mptsas_smp_t *sp;
765 765
766 766 for (tp = refhash_first(mpt->m_targets); tp != NULL;
767 767 tp = refhash_next(mpt->m_targets, tp)) {
768 768 refhash_remove(mpt->m_targets, tp);
769 769 }
770 770 for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
771 771 sp = refhash_next(mpt->m_smp_targets, sp)) {
772 772 refhash_remove(mpt->m_smp_targets, sp);
773 773 }
774 774 refhash_destroy(mpt->m_targets);
775 775 refhash_destroy(mpt->m_smp_targets);
776 776 mpt->m_targets = NULL;
777 777 mpt->m_smp_targets = NULL;
778 778 }
779 779
780 780 static int
781 781 mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
782 782 {
783 783 dev_info_t *pdip;
784 784 mptsas_t *mpt;
785 785 scsi_hba_tran_t *hba_tran;
786 786 char *iport = NULL;
787 787 char phymask[MPTSAS_MAX_PHYS];
788 788 mptsas_phymask_t phy_mask = 0;
789 789 int dynamic_port = 0;
790 790 uint32_t page_address;
791 791 char initiator_wwnstr[MPTSAS_WWN_STRLEN];
792 792 int rval = DDI_FAILURE;
793 793 int i = 0;
794 794 uint8_t numphys = 0;
795 795 uint8_t phy_id;
796 796 uint8_t phy_port = 0;
797 797 uint16_t attached_devhdl = 0;
798 798 uint32_t dev_info;
799 799 uint64_t attached_sas_wwn;
800 800 uint16_t dev_hdl;
801 801 uint16_t pdev_hdl;
802 802 uint16_t bay_num, enclosure;
803 803 char attached_wwnstr[MPTSAS_WWN_STRLEN];
804 804
805 805 /* CONSTCOND */
806 806 ASSERT(NO_COMPETING_THREADS);
807 807
808 808 switch (cmd) {
809 809 case DDI_ATTACH:
810 810 break;
811 811
812 812 case DDI_RESUME:
813 813 /*
814 814 * If this a scsi-iport node, nothing to do here.
815 815 */
816 816 return (DDI_SUCCESS);
817 817
818 818 default:
819 819 return (DDI_FAILURE);
820 820 }
821 821
822 822 pdip = ddi_get_parent(dip);
823 823
824 824 if ((hba_tran = ndi_flavorv_get(pdip, SCSA_FLAVOR_SCSI_DEVICE)) ==
825 825 NULL) {
826 826 cmn_err(CE_WARN, "Failed attach iport because fail to "
827 827 "get tran vector for the HBA node");
828 828 return (DDI_FAILURE);
829 829 }
830 830
831 831 mpt = TRAN2MPT(hba_tran);
832 832 ASSERT(mpt != NULL);
833 833 if (mpt == NULL)
834 834 return (DDI_FAILURE);
835 835
836 836 if ((hba_tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) ==
837 837 NULL) {
838 838 mptsas_log(mpt, CE_WARN, "Failed attach iport because fail to "
839 839 "get tran vector for the iport node");
840 840 return (DDI_FAILURE);
841 841 }
842 842
843 843 /*
844 844 * Overwrite parent's tran_hba_private to iport's tran vector
845 845 */
846 846 hba_tran->tran_hba_private = mpt;
847 847
848 848 ddi_report_dev(dip);
849 849
850 850 /*
851 851 * Get SAS address for initiator port according dev_handle
852 852 */
853 853 iport = ddi_get_name_addr(dip);
854 854 if (iport && strncmp(iport, "v0", 2) == 0) {
855 855 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
856 856 MPTSAS_VIRTUAL_PORT, 1) !=
857 857 DDI_PROP_SUCCESS) {
858 858 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
859 859 MPTSAS_VIRTUAL_PORT);
860 860 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
861 861 "prop update failed");
862 862 return (DDI_FAILURE);
863 863 }
864 864 return (DDI_SUCCESS);
865 865 }
866 866
867 867 mutex_enter(&mpt->m_mutex);
868 868 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
869 869 bzero(phymask, sizeof (phymask));
870 870 (void) sprintf(phymask,
871 871 "%x", mpt->m_phy_info[i].phy_mask);
872 872 if (strcmp(phymask, iport) == 0) {
873 873 break;
874 874 }
875 875 }
876 876
877 877 if (i == MPTSAS_MAX_PHYS) {
878 878 mptsas_log(mpt, CE_WARN, "Failed attach port %s because port"
879 879 "seems not exist", iport);
880 880 mutex_exit(&mpt->m_mutex);
881 881 return (DDI_FAILURE);
882 882 }
883 883
884 884 phy_mask = mpt->m_phy_info[i].phy_mask;
885 885
886 886 if (mpt->m_phy_info[i].port_flags & AUTO_PORT_CONFIGURATION)
887 887 dynamic_port = 1;
888 888 else
889 889 dynamic_port = 0;
890 890
891 891 /*
892 892 * Update PHY info for smhba
893 893 */
894 894 if (mptsas_smhba_phy_init(mpt)) {
895 895 mutex_exit(&mpt->m_mutex);
896 896 mptsas_log(mpt, CE_WARN, "mptsas phy update "
897 897 "failed");
898 898 return (DDI_FAILURE);
899 899 }
900 900
901 901 mutex_exit(&mpt->m_mutex);
902 902
903 903 numphys = 0;
904 904 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
905 905 if ((phy_mask >> i) & 0x01) {
906 906 numphys++;
907 907 }
908 908 }
909 909
910 910 bzero(initiator_wwnstr, sizeof (initiator_wwnstr));
911 911 (void) sprintf(initiator_wwnstr, "w%016"PRIx64,
912 912 mpt->un.m_base_wwid);
913 913
914 914 if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
915 915 SCSI_ADDR_PROP_INITIATOR_PORT, initiator_wwnstr) !=
916 916 DDI_PROP_SUCCESS) {
917 917 (void) ddi_prop_remove(DDI_DEV_T_NONE,
918 918 dip, SCSI_ADDR_PROP_INITIATOR_PORT);
919 919 mptsas_log(mpt, CE_WARN, "mptsas Initiator port "
920 920 "prop update failed");
921 921 return (DDI_FAILURE);
922 922 }
923 923 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
924 924 MPTSAS_NUM_PHYS, numphys) !=
925 925 DDI_PROP_SUCCESS) {
926 926 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, MPTSAS_NUM_PHYS);
927 927 return (DDI_FAILURE);
928 928 }
929 929
930 930 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
931 931 "phymask", phy_mask) !=
932 932 DDI_PROP_SUCCESS) {
933 933 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "phymask");
934 934 mptsas_log(mpt, CE_WARN, "mptsas phy mask "
935 935 "prop update failed");
936 936 return (DDI_FAILURE);
937 937 }
938 938
939 939 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
940 940 "dynamic-port", dynamic_port) !=
941 941 DDI_PROP_SUCCESS) {
942 942 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "dynamic-port");
943 943 mptsas_log(mpt, CE_WARN, "mptsas dynamic port "
944 944 "prop update failed");
945 945 return (DDI_FAILURE);
946 946 }
947 947 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
948 948 MPTSAS_VIRTUAL_PORT, 0) !=
949 949 DDI_PROP_SUCCESS) {
950 950 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
951 951 MPTSAS_VIRTUAL_PORT);
952 952 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
953 953 "prop update failed");
954 954 return (DDI_FAILURE);
955 955 }
956 956 mptsas_smhba_set_all_phy_props(mpt, dip, numphys, phy_mask,
957 957 &attached_devhdl);
958 958
959 959 mutex_enter(&mpt->m_mutex);
960 960 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
961 961 MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)attached_devhdl;
962 962 rval = mptsas_get_sas_device_page0(mpt, page_address, &dev_hdl,
963 963 &attached_sas_wwn, &dev_info, &phy_port, &phy_id,
964 964 &pdev_hdl, &bay_num, &enclosure);
965 965 if (rval != DDI_SUCCESS) {
966 966 mptsas_log(mpt, CE_WARN,
967 967 "Failed to get device page0 for handle:%d",
968 968 attached_devhdl);
969 969 mutex_exit(&mpt->m_mutex);
970 970 return (DDI_FAILURE);
971 971 }
972 972
973 973 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
974 974 bzero(phymask, sizeof (phymask));
975 975 (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
976 976 if (strcmp(phymask, iport) == 0) {
977 977 (void) sprintf(&mpt->m_phy_info[i].smhba_info.path[0],
978 978 "%x",
979 979 mpt->m_phy_info[i].phy_mask);
980 980 }
981 981 }
982 982 mutex_exit(&mpt->m_mutex);
983 983
984 984 bzero(attached_wwnstr, sizeof (attached_wwnstr));
985 985 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
986 986 attached_sas_wwn);
987 987 if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
988 988 SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
989 989 DDI_PROP_SUCCESS) {
990 990 (void) ddi_prop_remove(DDI_DEV_T_NONE,
991 991 dip, SCSI_ADDR_PROP_ATTACHED_PORT);
992 992 return (DDI_FAILURE);
993 993 }
994 994
995 995 /* Create kstats for each phy on this iport */
996 996
997 997 mptsas_create_phy_stats(mpt, iport, dip);
998 998
999 999 /*
1000 1000 * register sas hba iport with mdi (MPxIO/vhci)
1001 1001 */
1002 1002 if (mdi_phci_register(MDI_HCI_CLASS_SCSI,
1003 1003 dip, 0) == MDI_SUCCESS) {
1004 1004 mpt->m_mpxio_enable = TRUE;
1005 1005 }
1006 1006 return (DDI_SUCCESS);
1007 1007 }
1008 1008
1009 1009 /*
1010 1010 * Notes:
1011 1011 * Set up all device state and allocate data structures,
1012 1012 * mutexes, condition variables, etc. for device operation.
1013 1013 * Add interrupts needed.
1014 1014 * Return DDI_SUCCESS if device is ready, else return DDI_FAILURE.
1015 1015 */
1016 1016 static int
1017 1017 mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1018 1018 {
1019 1019 mptsas_t *mpt = NULL;
1020 1020 int instance, i, j;
1021 1021 int doneq_thread_num;
1022 1022 char intr_added = 0;
1023 1023 char map_setup = 0;
1024 1024 char config_setup = 0;
1025 1025 char hba_attach_setup = 0;
1026 1026 char smp_attach_setup = 0;
1027 1027 char mutex_init_done = 0;
1028 1028 char event_taskq_create = 0;
1029 1029 char dr_taskq_create = 0;
1030 1030 char doneq_thread_create = 0;
1031 1031 scsi_hba_tran_t *hba_tran;
1032 1032 uint_t mem_bar = MEM_SPACE;
1033 1033 int rval = DDI_FAILURE;
1034 1034
1035 1035 /* CONSTCOND */
1036 1036 ASSERT(NO_COMPETING_THREADS);
1037 1037
1038 1038 if (scsi_hba_iport_unit_address(dip)) {
1039 1039 return (mptsas_iport_attach(dip, cmd));
1040 1040 }
1041 1041
1042 1042 switch (cmd) {
1043 1043 case DDI_ATTACH:
1044 1044 break;
1045 1045
1046 1046 case DDI_RESUME:
1047 1047 if ((hba_tran = ddi_get_driver_private(dip)) == NULL)
1048 1048 return (DDI_FAILURE);
1049 1049
1050 1050 mpt = TRAN2MPT(hba_tran);
1051 1051
1052 1052 if (!mpt) {
1053 1053 return (DDI_FAILURE);
1054 1054 }
1055 1055
1056 1056 /*
1057 1057 * Reset hardware and softc to "no outstanding commands"
1058 1058 * Note that a check condition can result on first command
1059 1059 * to a target.
1060 1060 */
1061 1061 mutex_enter(&mpt->m_mutex);
1062 1062
1063 1063 /*
1064 1064 * raise power.
1065 1065 */
1066 1066 if (mpt->m_options & MPTSAS_OPT_PM) {
1067 1067 mutex_exit(&mpt->m_mutex);
1068 1068 (void) pm_busy_component(dip, 0);
1069 1069 rval = pm_power_has_changed(dip, 0, PM_LEVEL_D0);
1070 1070 if (rval == DDI_SUCCESS) {
1071 1071 mutex_enter(&mpt->m_mutex);
1072 1072 } else {
1073 1073 /*
1074 1074 * The pm_raise_power() call above failed,
1075 1075 * and that can only occur if we were unable
1076 1076 * to reset the hardware. This is probably
1077 1077 * due to unhealty hardware, and because
1078 1078 * important filesystems(such as the root
1079 1079 * filesystem) could be on the attached disks,
1080 1080 * it would not be a good idea to continue,
1081 1081 * as we won't be entirely certain we are
1082 1082 * writing correct data. So we panic() here
1083 1083 * to not only prevent possible data corruption,
1084 1084 * but to give developers or end users a hope
1085 1085 * of identifying and correcting any problems.
1086 1086 */
1087 1087 fm_panic("mptsas could not reset hardware "
1088 1088 "during resume");
1089 1089 }
1090 1090 }
1091 1091
1092 1092 mpt->m_suspended = 0;
1093 1093
1094 1094 /*
1095 1095 * Reinitialize ioc
1096 1096 */
1097 1097 mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1098 1098 if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
1099 1099 mutex_exit(&mpt->m_mutex);
1100 1100 if (mpt->m_options & MPTSAS_OPT_PM) {
1101 1101 (void) pm_idle_component(dip, 0);
1102 1102 }
1103 1103 fm_panic("mptsas init chip fail during resume");
1104 1104 }
1105 1105 /*
1106 1106 * mptsas_update_driver_data needs interrupts so enable them
1107 1107 * first.
1108 1108 */
1109 1109 MPTSAS_ENABLE_INTR(mpt);
1110 1110 mptsas_update_driver_data(mpt);
1111 1111
1112 1112 /* start requests, if possible */
1113 1113 mptsas_restart_hba(mpt);
1114 1114
1115 1115 mutex_exit(&mpt->m_mutex);
1116 1116
1117 1117 /*
1118 1118 * Restart watch thread
1119 1119 */
1120 1120 mutex_enter(&mptsas_global_mutex);
1121 1121 if (mptsas_timeout_id == 0) {
1122 1122 mptsas_timeout_id = timeout(mptsas_watch, NULL,
1123 1123 mptsas_tick);
1124 1124 mptsas_timeouts_enabled = 1;
1125 1125 }
1126 1126 mutex_exit(&mptsas_global_mutex);
1127 1127
1128 1128 /* report idle status to pm framework */
1129 1129 if (mpt->m_options & MPTSAS_OPT_PM) {
1130 1130 (void) pm_idle_component(dip, 0);
1131 1131 }
1132 1132
1133 1133 return (DDI_SUCCESS);
1134 1134
1135 1135 default:
1136 1136 return (DDI_FAILURE);
1137 1137
1138 1138 }
1139 1139
1140 1140 instance = ddi_get_instance(dip);
1141 1141
1142 1142 /*
1143 1143 * Allocate softc information.
1144 1144 */
1145 1145 if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) {
1146 1146 mptsas_log(NULL, CE_WARN,
1147 1147 "mptsas%d: cannot allocate soft state", instance);
1148 1148 goto fail;
1149 1149 }
1150 1150
1151 1151 mpt = ddi_get_soft_state(mptsas_state, instance);
1152 1152
1153 1153 if (mpt == NULL) {
1154 1154 mptsas_log(NULL, CE_WARN,
1155 1155 "mptsas%d: cannot get soft state", instance);
1156 1156 goto fail;
1157 1157 }
1158 1158
1159 1159 /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1160 1160 scsi_size_clean(dip);
1161 1161
1162 1162 mpt->m_dip = dip;
1163 1163 mpt->m_instance = instance;
1164 1164
1165 1165 /* Make a per-instance copy of the structures */
1166 1166 mpt->m_io_dma_attr = mptsas_dma_attrs64;
1167 1167 mpt->m_msg_dma_attr = mptsas_dma_attrs;
1168 1168 mpt->m_reg_acc_attr = mptsas_dev_attr;
1169 1169 mpt->m_dev_acc_attr = mptsas_dev_attr;
1170 1170
1171 1171 /*
1172 1172 * Initialize FMA
1173 1173 */
1174 1174 mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1175 1175 DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1176 1176 DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1177 1177 DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1178 1178
1179 1179 mptsas_fm_init(mpt);
1180 1180
1181 1181 if (mptsas_alloc_handshake_msg(mpt,
1182 1182 sizeof (Mpi2SCSITaskManagementRequest_t)) == DDI_FAILURE) {
1183 1183 mptsas_log(mpt, CE_WARN, "cannot initialize handshake msg.");
1184 1184 goto fail;
1185 1185 }
1186 1186
1187 1187 /*
1188 1188 * Setup configuration space
1189 1189 */
1190 1190 if (mptsas_config_space_init(mpt) == FALSE) {
1191 1191 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init failed");
1192 1192 goto fail;
1193 1193 }
1194 1194 config_setup++;
1195 1195
1196 1196 if (ddi_regs_map_setup(dip, mem_bar, (caddr_t *)&mpt->m_reg,
1197 1197 0, 0, &mpt->m_reg_acc_attr, &mpt->m_datap) != DDI_SUCCESS) {
1198 1198 mptsas_log(mpt, CE_WARN, "map setup failed");
1199 1199 goto fail;
1200 1200 }
1201 1201 map_setup++;
1202 1202
1203 1203 /*
1204 1204 * A taskq is created for dealing with the event handler
1205 1205 */
1206 1206 if ((mpt->m_event_taskq = ddi_taskq_create(dip, "mptsas_event_taskq",
1207 1207 1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1208 1208 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create failed");
1209 1209 goto fail;
1210 1210 }
1211 1211 event_taskq_create++;
1212 1212
1213 1213 /*
1214 1214 * A taskq is created for dealing with dr events
1215 1215 */
1216 1216 if ((mpt->m_dr_taskq = ddi_taskq_create(dip,
1217 1217 "mptsas_dr_taskq",
1218 1218 1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1219 1219 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create for discovery "
1220 1220 "failed");
1221 1221 goto fail;
1222 1222 }
1223 1223 dr_taskq_create++;
1224 1224
1225 1225 mpt->m_doneq_thread_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1226 1226 0, "mptsas_doneq_thread_threshold_prop", 10);
1227 1227 mpt->m_doneq_length_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1228 1228 0, "mptsas_doneq_length_threshold_prop", 8);
1229 1229 mpt->m_doneq_thread_n = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1230 1230 0, "mptsas_doneq_thread_n_prop", 8);
1231 1231
1232 1232 if (mpt->m_doneq_thread_n) {
1233 1233 cv_init(&mpt->m_doneq_thread_cv, NULL, CV_DRIVER, NULL);
1234 1234 mutex_init(&mpt->m_doneq_mutex, NULL, MUTEX_DRIVER, NULL);
1235 1235
1236 1236 mutex_enter(&mpt->m_doneq_mutex);
1237 1237 mpt->m_doneq_thread_id =
1238 1238 kmem_zalloc(sizeof (mptsas_doneq_thread_list_t)
1239 1239 * mpt->m_doneq_thread_n, KM_SLEEP);
1240 1240
1241 1241 for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1242 1242 cv_init(&mpt->m_doneq_thread_id[j].cv, NULL,
1243 1243 CV_DRIVER, NULL);
1244 1244 mutex_init(&mpt->m_doneq_thread_id[j].mutex, NULL,
1245 1245 MUTEX_DRIVER, NULL);
1246 1246 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1247 1247 mpt->m_doneq_thread_id[j].flag |=
1248 1248 MPTSAS_DONEQ_THREAD_ACTIVE;
1249 1249 mpt->m_doneq_thread_id[j].arg.mpt = mpt;
1250 1250 mpt->m_doneq_thread_id[j].arg.t = j;
1251 1251 mpt->m_doneq_thread_id[j].threadp =
1252 1252 thread_create(NULL, 0, mptsas_doneq_thread,
1253 1253 &mpt->m_doneq_thread_id[j].arg,
1254 1254 0, &p0, TS_RUN, minclsyspri);
1255 1255 mpt->m_doneq_thread_id[j].donetail =
1256 1256 &mpt->m_doneq_thread_id[j].doneq;
1257 1257 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1258 1258 }
1259 1259 mutex_exit(&mpt->m_doneq_mutex);
1260 1260 doneq_thread_create++;
1261 1261 }
1262 1262
1263 1263 /* Initialize mutex used in interrupt handler */
1264 1264 mutex_init(&mpt->m_mutex, NULL, MUTEX_DRIVER,
1265 1265 DDI_INTR_PRI(mpt->m_intr_pri));
1266 1266 mutex_init(&mpt->m_passthru_mutex, NULL, MUTEX_DRIVER, NULL);
1267 1267 mutex_init(&mpt->m_tx_waitq_mutex, NULL, MUTEX_DRIVER,
1268 1268 DDI_INTR_PRI(mpt->m_intr_pri));
1269 1269 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1270 1270 mutex_init(&mpt->m_phy_info[i].smhba_info.phy_mutex,
1271 1271 NULL, MUTEX_DRIVER,
1272 1272 DDI_INTR_PRI(mpt->m_intr_pri));
1273 1273 }
1274 1274
1275 1275 cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL);
1276 1276 cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL);
1277 1277 cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL);
1278 1278 cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL);
1279 1279 cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL);
1280 1280 mutex_init_done++;
1281 1281
1282 1282 /*
1283 1283 * Disable hardware interrupt since we're not ready to
1284 1284 * handle it yet.
1285 1285 */
1286 1286 MPTSAS_DISABLE_INTR(mpt);
1287 1287 if (mptsas_register_intrs(mpt) == FALSE)
1288 1288 goto fail;
1289 1289 intr_added++;
1290 1290
1291 1291 mutex_enter(&mpt->m_mutex);
1292 1292 /*
1293 1293 * Initialize power management component
1294 1294 */
1295 1295 if (mpt->m_options & MPTSAS_OPT_PM) {
1296 1296 if (mptsas_init_pm(mpt)) {
1297 1297 mutex_exit(&mpt->m_mutex);
1298 1298 mptsas_log(mpt, CE_WARN, "mptsas pm initialization "
1299 1299 "failed");
1300 1300 goto fail;
1301 1301 }
1302 1302 }
1303 1303
1304 1304 /*
1305 1305 * Initialize chip using Message Unit Reset, if allowed
1306 1306 */
1307 1307 mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1308 1308 if (mptsas_init_chip(mpt, TRUE) == DDI_FAILURE) {
1309 1309 mutex_exit(&mpt->m_mutex);
1310 1310 mptsas_log(mpt, CE_WARN, "mptsas chip initialization failed");
1311 1311 goto fail;
1312 1312 }
1313 1313
1314 1314 /*
1315 1315 * Fill in the phy_info structure and get the base WWID
1316 1316 */
1317 1317 if (mptsas_get_manufacture_page5(mpt) == DDI_FAILURE) {
1318 1318 mptsas_log(mpt, CE_WARN,
1319 1319 "mptsas_get_manufacture_page5 failed!");
1320 1320 goto fail;
1321 1321 }
1322 1322
1323 1323 if (mptsas_get_sas_io_unit_page_hndshk(mpt)) {
1324 1324 mptsas_log(mpt, CE_WARN,
1325 1325 "mptsas_get_sas_io_unit_page_hndshk failed!");
1326 1326 goto fail;
1327 1327 }
1328 1328
1329 1329 if (mptsas_get_manufacture_page0(mpt) == DDI_FAILURE) {
1330 1330 mptsas_log(mpt, CE_WARN,
1331 1331 "mptsas_get_manufacture_page0 failed!");
1332 1332 goto fail;
1333 1333 }
1334 1334
1335 1335 mutex_exit(&mpt->m_mutex);
1336 1336
1337 1337 /*
1338 1338 * Register the iport for multiple port HBA
1339 1339 */
1340 1340 mptsas_iport_register(mpt);
1341 1341
1342 1342 /*
1343 1343 * initialize SCSI HBA transport structure
1344 1344 */
1345 1345 if (mptsas_hba_setup(mpt) == FALSE)
1346 1346 goto fail;
1347 1347 hba_attach_setup++;
1348 1348
1349 1349 if (mptsas_smp_setup(mpt) == FALSE)
1350 1350 goto fail;
1351 1351 smp_attach_setup++;
1352 1352
1353 1353 if (mptsas_cache_create(mpt) == FALSE)
1354 1354 goto fail;
1355 1355
1356 1356 mpt->m_scsi_reset_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1357 1357 dip, 0, "scsi-reset-delay", SCSI_DEFAULT_RESET_DELAY);
1358 1358 if (mpt->m_scsi_reset_delay == 0) {
1359 1359 mptsas_log(mpt, CE_NOTE,
1360 1360 "scsi_reset_delay of 0 is not recommended,"
1361 1361 " resetting to SCSI_DEFAULT_RESET_DELAY\n");
1362 1362 mpt->m_scsi_reset_delay = SCSI_DEFAULT_RESET_DELAY;
1363 1363 }
1364 1364
1365 1365 /*
1366 1366 * Initialize the wait and done FIFO queue
1367 1367 */
1368 1368 mpt->m_donetail = &mpt->m_doneq;
1369 1369 mpt->m_waitqtail = &mpt->m_waitq;
1370 1370 mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
1371 1371 mpt->m_tx_draining = 0;
1372 1372
1373 1373 /*
1374 1374 * ioc cmd queue initialize
1375 1375 */
1376 1376 mpt->m_ioc_event_cmdtail = &mpt->m_ioc_event_cmdq;
1377 1377 mpt->m_dev_handle = 0xFFFF;
1378 1378
1379 1379 MPTSAS_ENABLE_INTR(mpt);
1380 1380
1381 1381 /*
1382 1382 * enable event notification
1383 1383 */
1384 1384 mutex_enter(&mpt->m_mutex);
1385 1385 if (mptsas_ioc_enable_event_notification(mpt)) {
1386 1386 mutex_exit(&mpt->m_mutex);
1387 1387 goto fail;
1388 1388 }
1389 1389 mutex_exit(&mpt->m_mutex);
1390 1390
1391 1391 /*
1392 1392 * Initialize PHY info for smhba
1393 1393 */
1394 1394 if (mptsas_smhba_setup(mpt)) {
1395 1395 mptsas_log(mpt, CE_WARN, "mptsas phy initialization "
1396 1396 "failed");
1397 1397 goto fail;
1398 1398 }
1399 1399
1400 1400 /* Check all dma handles allocated in attach */
1401 1401 if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl)
1402 1402 != DDI_SUCCESS) ||
1403 1403 (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl)
1404 1404 != DDI_SUCCESS) ||
1405 1405 (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl)
1406 1406 != DDI_SUCCESS) ||
1407 1407 (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl)
1408 1408 != DDI_SUCCESS) ||
1409 1409 (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl)
1410 1410 != DDI_SUCCESS)) {
1411 1411 goto fail;
1412 1412 }
1413 1413
1414 1414 /* Check all acc handles allocated in attach */
1415 1415 if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
1416 1416 (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl)
1417 1417 != DDI_SUCCESS) ||
1418 1418 (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl)
1419 1419 != DDI_SUCCESS) ||
1420 1420 (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl)
1421 1421 != DDI_SUCCESS) ||
1422 1422 (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl)
1423 1423 != DDI_SUCCESS) ||
1424 1424 (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl)
1425 1425 != DDI_SUCCESS) ||
1426 1426 (mptsas_check_acc_handle(mpt->m_config_handle)
1427 1427 != DDI_SUCCESS)) {
1428 1428 goto fail;
1429 1429 }
1430 1430
1431 1431 /*
1432 1432 * After this point, we are not going to fail the attach.
1433 1433 */
1434 1434 /*
1435 1435 * used for mptsas_watch
1436 1436 */
1437 1437 mptsas_list_add(mpt);
1438 1438
1439 1439 mutex_enter(&mptsas_global_mutex);
1440 1440 if (mptsas_timeouts_enabled == 0) {
1441 1441 mptsas_scsi_watchdog_tick = ddi_prop_get_int(DDI_DEV_T_ANY,
1442 1442 dip, 0, "scsi-watchdog-tick", DEFAULT_WD_TICK);
1443 1443
1444 1444 mptsas_tick = mptsas_scsi_watchdog_tick *
1445 1445 drv_usectohz((clock_t)1000000);
1446 1446
1447 1447 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
1448 1448 mptsas_timeouts_enabled = 1;
1449 1449 }
1450 1450 mutex_exit(&mptsas_global_mutex);
1451 1451
1452 1452 /* Print message of HBA present */
1453 1453 ddi_report_dev(dip);
1454 1454
1455 1455 /* report idle status to pm framework */
1456 1456 if (mpt->m_options & MPTSAS_OPT_PM) {
1457 1457 (void) pm_idle_component(dip, 0);
1458 1458 }
1459 1459
1460 1460 return (DDI_SUCCESS);
1461 1461
1462 1462 fail:
1463 1463 mptsas_log(mpt, CE_WARN, "attach failed");
1464 1464 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
1465 1465 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
1466 1466 if (mpt) {
1467 1467 mutex_enter(&mptsas_global_mutex);
1468 1468
1469 1469 if (mptsas_timeout_id && (mptsas_head == NULL)) {
1470 1470 timeout_id_t tid = mptsas_timeout_id;
1471 1471 mptsas_timeouts_enabled = 0;
1472 1472 mptsas_timeout_id = 0;
1473 1473 mutex_exit(&mptsas_global_mutex);
1474 1474 (void) untimeout(tid);
1475 1475 mutex_enter(&mptsas_global_mutex);
1476 1476 }
1477 1477 mutex_exit(&mptsas_global_mutex);
1478 1478 /* deallocate in reverse order */
1479 1479 mptsas_cache_destroy(mpt);
1480 1480
1481 1481 if (smp_attach_setup) {
1482 1482 mptsas_smp_teardown(mpt);
1483 1483 }
1484 1484 if (hba_attach_setup) {
1485 1485 mptsas_hba_teardown(mpt);
1486 1486 }
1487 1487
1488 1488 if (mpt->m_targets)
1489 1489 refhash_destroy(mpt->m_targets);
1490 1490 if (mpt->m_smp_targets)
1491 1491 refhash_destroy(mpt->m_smp_targets);
1492 1492
1493 1493 if (mpt->m_active) {
1494 1494 mptsas_free_active_slots(mpt);
1495 1495 }
1496 1496 if (intr_added) {
1497 1497 mptsas_unregister_intrs(mpt);
1498 1498 }
1499 1499
1500 1500 if (doneq_thread_create) {
1501 1501 mutex_enter(&mpt->m_doneq_mutex);
1502 1502 doneq_thread_num = mpt->m_doneq_thread_n;
1503 1503 for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1504 1504 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1505 1505 mpt->m_doneq_thread_id[j].flag &=
1506 1506 (~MPTSAS_DONEQ_THREAD_ACTIVE);
1507 1507 cv_signal(&mpt->m_doneq_thread_id[j].cv);
1508 1508 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1509 1509 }
1510 1510 while (mpt->m_doneq_thread_n) {
1511 1511 cv_wait(&mpt->m_doneq_thread_cv,
1512 1512 &mpt->m_doneq_mutex);
1513 1513 }
1514 1514 for (j = 0; j < doneq_thread_num; j++) {
1515 1515 cv_destroy(&mpt->m_doneq_thread_id[j].cv);
1516 1516 mutex_destroy(&mpt->m_doneq_thread_id[j].mutex);
1517 1517 }
1518 1518 kmem_free(mpt->m_doneq_thread_id,
1519 1519 sizeof (mptsas_doneq_thread_list_t)
1520 1520 * doneq_thread_num);
1521 1521 mutex_exit(&mpt->m_doneq_mutex);
1522 1522 cv_destroy(&mpt->m_doneq_thread_cv);
1523 1523 mutex_destroy(&mpt->m_doneq_mutex);
1524 1524 }
1525 1525 if (event_taskq_create) {
1526 1526 ddi_taskq_destroy(mpt->m_event_taskq);
1527 1527 }
1528 1528 if (dr_taskq_create) {
1529 1529 ddi_taskq_destroy(mpt->m_dr_taskq);
1530 1530 }
1531 1531 if (mutex_init_done) {
1532 1532 mutex_destroy(&mpt->m_tx_waitq_mutex);
1533 1533 mutex_destroy(&mpt->m_passthru_mutex);
1534 1534 mutex_destroy(&mpt->m_mutex);
1535 1535 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1536 1536 mutex_destroy(
1537 1537 &mpt->m_phy_info[i].smhba_info.phy_mutex);
1538 1538 }
1539 1539 cv_destroy(&mpt->m_cv);
1540 1540 cv_destroy(&mpt->m_passthru_cv);
1541 1541 cv_destroy(&mpt->m_fw_cv);
1542 1542 cv_destroy(&mpt->m_config_cv);
1543 1543 cv_destroy(&mpt->m_fw_diag_cv);
1544 1544 }
1545 1545
1546 1546 if (map_setup) {
1547 1547 mptsas_cfg_fini(mpt);
1548 1548 }
1549 1549 if (config_setup) {
1550 1550 mptsas_config_space_fini(mpt);
1551 1551 }
1552 1552 mptsas_free_handshake_msg(mpt);
1553 1553 mptsas_hba_fini(mpt);
1554 1554
1555 1555 mptsas_fm_fini(mpt);
1556 1556 ddi_soft_state_free(mptsas_state, instance);
1557 1557 ddi_prop_remove_all(dip);
1558 1558 }
1559 1559 return (DDI_FAILURE);
1560 1560 }
1561 1561
1562 1562 static int
1563 1563 mptsas_suspend(dev_info_t *devi)
1564 1564 {
1565 1565 mptsas_t *mpt, *g;
1566 1566 scsi_hba_tran_t *tran;
1567 1567
1568 1568 if (scsi_hba_iport_unit_address(devi)) {
1569 1569 return (DDI_SUCCESS);
1570 1570 }
1571 1571
1572 1572 if ((tran = ddi_get_driver_private(devi)) == NULL)
1573 1573 return (DDI_SUCCESS);
1574 1574
1575 1575 mpt = TRAN2MPT(tran);
1576 1576 if (!mpt) {
1577 1577 return (DDI_SUCCESS);
1578 1578 }
1579 1579
1580 1580 mutex_enter(&mpt->m_mutex);
1581 1581
1582 1582 if (mpt->m_suspended++) {
1583 1583 mutex_exit(&mpt->m_mutex);
1584 1584 return (DDI_SUCCESS);
1585 1585 }
1586 1586
1587 1587 /*
1588 1588 * Cancel timeout threads for this mpt
1589 1589 */
1590 1590 if (mpt->m_quiesce_timeid) {
1591 1591 timeout_id_t tid = mpt->m_quiesce_timeid;
1592 1592 mpt->m_quiesce_timeid = 0;
1593 1593 mutex_exit(&mpt->m_mutex);
1594 1594 (void) untimeout(tid);
1595 1595 mutex_enter(&mpt->m_mutex);
1596 1596 }
1597 1597
1598 1598 if (mpt->m_restart_cmd_timeid) {
1599 1599 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1600 1600 mpt->m_restart_cmd_timeid = 0;
1601 1601 mutex_exit(&mpt->m_mutex);
1602 1602 (void) untimeout(tid);
1603 1603 mutex_enter(&mpt->m_mutex);
1604 1604 }
1605 1605
1606 1606 mutex_exit(&mpt->m_mutex);
1607 1607
1608 1608 (void) pm_idle_component(mpt->m_dip, 0);
1609 1609
1610 1610 /*
1611 1611 * Cancel watch threads if all mpts suspended
1612 1612 */
1613 1613 rw_enter(&mptsas_global_rwlock, RW_WRITER);
1614 1614 for (g = mptsas_head; g != NULL; g = g->m_next) {
1615 1615 if (!g->m_suspended)
1616 1616 break;
1617 1617 }
1618 1618 rw_exit(&mptsas_global_rwlock);
1619 1619
1620 1620 mutex_enter(&mptsas_global_mutex);
1621 1621 if (g == NULL) {
1622 1622 timeout_id_t tid;
1623 1623
1624 1624 mptsas_timeouts_enabled = 0;
1625 1625 if (mptsas_timeout_id) {
1626 1626 tid = mptsas_timeout_id;
1627 1627 mptsas_timeout_id = 0;
1628 1628 mutex_exit(&mptsas_global_mutex);
1629 1629 (void) untimeout(tid);
1630 1630 mutex_enter(&mptsas_global_mutex);
1631 1631 }
1632 1632 if (mptsas_reset_watch) {
1633 1633 tid = mptsas_reset_watch;
1634 1634 mptsas_reset_watch = 0;
1635 1635 mutex_exit(&mptsas_global_mutex);
1636 1636 (void) untimeout(tid);
1637 1637 mutex_enter(&mptsas_global_mutex);
1638 1638 }
1639 1639 }
1640 1640 mutex_exit(&mptsas_global_mutex);
1641 1641
1642 1642 mutex_enter(&mpt->m_mutex);
1643 1643
1644 1644 /*
1645 1645 * If this mpt is not in full power(PM_LEVEL_D0), just return.
1646 1646 */
1647 1647 if ((mpt->m_options & MPTSAS_OPT_PM) &&
1648 1648 (mpt->m_power_level != PM_LEVEL_D0)) {
1649 1649 mutex_exit(&mpt->m_mutex);
1650 1650 return (DDI_SUCCESS);
1651 1651 }
1652 1652
1653 1653 /* Disable HBA interrupts in hardware */
1654 1654 MPTSAS_DISABLE_INTR(mpt);
1655 1655 /*
1656 1656 * Send RAID action system shutdown to sync IR
1657 1657 */
1658 1658 mptsas_raid_action_system_shutdown(mpt);
1659 1659
1660 1660 mutex_exit(&mpt->m_mutex);
1661 1661
1662 1662 /* drain the taskq */
1663 1663 ddi_taskq_wait(mpt->m_event_taskq);
1664 1664 ddi_taskq_wait(mpt->m_dr_taskq);
1665 1665
1666 1666 return (DDI_SUCCESS);
1667 1667 }
1668 1668
1669 1669 #ifdef __sparc
1670 1670 /*ARGSUSED*/
1671 1671 static int
1672 1672 mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd)
1673 1673 {
1674 1674 mptsas_t *mpt;
1675 1675 scsi_hba_tran_t *tran;
1676 1676
1677 1677 /*
1678 1678 * If this call is for iport, just return.
1679 1679 */
1680 1680 if (scsi_hba_iport_unit_address(devi))
1681 1681 return (DDI_SUCCESS);
1682 1682
1683 1683 if ((tran = ddi_get_driver_private(devi)) == NULL)
1684 1684 return (DDI_SUCCESS);
1685 1685
1686 1686 if ((mpt = TRAN2MPT(tran)) == NULL)
1687 1687 return (DDI_SUCCESS);
1688 1688
1689 1689 /*
1690 1690 * Send RAID action system shutdown to sync IR. Disable HBA
1691 1691 * interrupts in hardware first.
1692 1692 */
1693 1693 MPTSAS_DISABLE_INTR(mpt);
1694 1694 mptsas_raid_action_system_shutdown(mpt);
1695 1695
1696 1696 return (DDI_SUCCESS);
1697 1697 }
1698 1698 #else /* __sparc */
1699 1699 /*
1700 1700 * quiesce(9E) entry point.
1701 1701 *
1702 1702 * This function is called when the system is single-threaded at high
1703 1703 * PIL with preemption disabled. Therefore, this function must not be
1704 1704 * blocked.
1705 1705 *
1706 1706 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1707 1707 * DDI_FAILURE indicates an error condition and should almost never happen.
1708 1708 */
1709 1709 static int
1710 1710 mptsas_quiesce(dev_info_t *devi)
1711 1711 {
1712 1712 mptsas_t *mpt;
1713 1713 scsi_hba_tran_t *tran;
1714 1714
1715 1715 /*
1716 1716 * If this call is for iport, just return.
1717 1717 */
1718 1718 if (scsi_hba_iport_unit_address(devi))
1719 1719 return (DDI_SUCCESS);
1720 1720
1721 1721 if ((tran = ddi_get_driver_private(devi)) == NULL)
1722 1722 return (DDI_SUCCESS);
1723 1723
1724 1724 if ((mpt = TRAN2MPT(tran)) == NULL)
1725 1725 return (DDI_SUCCESS);
1726 1726
1727 1727 /* Disable HBA interrupts in hardware */
1728 1728 MPTSAS_DISABLE_INTR(mpt);
1729 1729 /* Send RAID action system shutdonw to sync IR */
1730 1730 mptsas_raid_action_system_shutdown(mpt);
1731 1731
1732 1732 return (DDI_SUCCESS);
1733 1733 }
1734 1734 #endif /* __sparc */
1735 1735
1736 1736 /*
1737 1737 * detach(9E). Remove all device allocations and system resources;
1738 1738 * disable device interrupts.
1739 1739 * Return DDI_SUCCESS if done; DDI_FAILURE if there's a problem.
1740 1740 */
1741 1741 static int
1742 1742 mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1743 1743 {
1744 1744 /* CONSTCOND */
1745 1745 ASSERT(NO_COMPETING_THREADS);
1746 1746 NDBG0(("mptsas_detach: dip=0x%p cmd=0x%p", (void *)devi, (void *)cmd));
1747 1747
1748 1748 switch (cmd) {
1749 1749 case DDI_DETACH:
1750 1750 return (mptsas_do_detach(devi));
1751 1751
1752 1752 case DDI_SUSPEND:
1753 1753 return (mptsas_suspend(devi));
1754 1754
1755 1755 default:
1756 1756 return (DDI_FAILURE);
1757 1757 }
1758 1758 /* NOTREACHED */
1759 1759 }
1760 1760
1761 1761 static int
1762 1762 mptsas_do_detach(dev_info_t *dip)
1763 1763 {
1764 1764 mptsas_t *mpt;
1765 1765 scsi_hba_tran_t *tran;
1766 1766 int circ = 0;
1767 1767 int circ1 = 0;
1768 1768 mdi_pathinfo_t *pip = NULL;
1769 1769 int i;
1770 1770 int doneq_thread_num = 0;
1771 1771
1772 1772 NDBG0(("mptsas_do_detach: dip=0x%p", (void *)dip));
1773 1773
1774 1774 if ((tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) == NULL)
1775 1775 return (DDI_FAILURE);
1776 1776
1777 1777 mpt = TRAN2MPT(tran);
1778 1778 if (!mpt) {
1779 1779 return (DDI_FAILURE);
1780 1780 }
1781 1781 /*
1782 1782 * Still have pathinfo child, should not detach mpt driver
1783 1783 */
1784 1784 if (scsi_hba_iport_unit_address(dip)) {
1785 1785 if (mpt->m_mpxio_enable) {
1786 1786 /*
1787 1787 * MPxIO enabled for the iport
1788 1788 */
1789 1789 ndi_devi_enter(scsi_vhci_dip, &circ1);
1790 1790 ndi_devi_enter(dip, &circ);
1791 1791 while (pip = mdi_get_next_client_path(dip, NULL)) {
1792 1792 if (mdi_pi_free(pip, 0) == MDI_SUCCESS) {
1793 1793 continue;
1794 1794 }
1795 1795 ndi_devi_exit(dip, circ);
1796 1796 ndi_devi_exit(scsi_vhci_dip, circ1);
1797 1797 NDBG12(("detach failed because of "
1798 1798 "outstanding path info"));
1799 1799 return (DDI_FAILURE);
1800 1800 }
1801 1801 ndi_devi_exit(dip, circ);
1802 1802 ndi_devi_exit(scsi_vhci_dip, circ1);
1803 1803 (void) mdi_phci_unregister(dip, 0);
1804 1804 }
1805 1805
1806 1806 ddi_prop_remove_all(dip);
1807 1807
1808 1808 return (DDI_SUCCESS);
1809 1809 }
1810 1810
1811 1811 /* Make sure power level is D0 before accessing registers */
1812 1812 if (mpt->m_options & MPTSAS_OPT_PM) {
1813 1813 (void) pm_busy_component(dip, 0);
1814 1814 if (mpt->m_power_level != PM_LEVEL_D0) {
1815 1815 if (pm_raise_power(dip, 0, PM_LEVEL_D0) !=
1816 1816 DDI_SUCCESS) {
1817 1817 mptsas_log(mpt, CE_WARN,
1818 1818 "mptsas%d: Raise power request failed.",
1819 1819 mpt->m_instance);
1820 1820 (void) pm_idle_component(dip, 0);
1821 1821 return (DDI_FAILURE);
1822 1822 }
1823 1823 }
1824 1824 }
1825 1825
1826 1826 /*
1827 1827 * Send RAID action system shutdown to sync IR. After action, send a
1828 1828 * Message Unit Reset. Since after that DMA resource will be freed,
1829 1829 * set ioc to READY state will avoid HBA initiated DMA operation.
1830 1830 */
1831 1831 mutex_enter(&mpt->m_mutex);
1832 1832 MPTSAS_DISABLE_INTR(mpt);
1833 1833 mptsas_raid_action_system_shutdown(mpt);
1834 1834 mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1835 1835 (void) mptsas_ioc_reset(mpt, FALSE);
1836 1836 mutex_exit(&mpt->m_mutex);
1837 1837 mptsas_rem_intrs(mpt);
1838 1838 ddi_taskq_destroy(mpt->m_event_taskq);
1839 1839 ddi_taskq_destroy(mpt->m_dr_taskq);
1840 1840
1841 1841 if (mpt->m_doneq_thread_n) {
1842 1842 mutex_enter(&mpt->m_doneq_mutex);
1843 1843 doneq_thread_num = mpt->m_doneq_thread_n;
1844 1844 for (i = 0; i < mpt->m_doneq_thread_n; i++) {
1845 1845 mutex_enter(&mpt->m_doneq_thread_id[i].mutex);
1846 1846 mpt->m_doneq_thread_id[i].flag &=
1847 1847 (~MPTSAS_DONEQ_THREAD_ACTIVE);
1848 1848 cv_signal(&mpt->m_doneq_thread_id[i].cv);
1849 1849 mutex_exit(&mpt->m_doneq_thread_id[i].mutex);
1850 1850 }
1851 1851 while (mpt->m_doneq_thread_n) {
1852 1852 cv_wait(&mpt->m_doneq_thread_cv,
1853 1853 &mpt->m_doneq_mutex);
1854 1854 }
1855 1855 for (i = 0; i < doneq_thread_num; i++) {
1856 1856 cv_destroy(&mpt->m_doneq_thread_id[i].cv);
1857 1857 mutex_destroy(&mpt->m_doneq_thread_id[i].mutex);
1858 1858 }
1859 1859 kmem_free(mpt->m_doneq_thread_id,
1860 1860 sizeof (mptsas_doneq_thread_list_t)
1861 1861 * doneq_thread_num);
1862 1862 mutex_exit(&mpt->m_doneq_mutex);
1863 1863 cv_destroy(&mpt->m_doneq_thread_cv);
1864 1864 mutex_destroy(&mpt->m_doneq_mutex);
1865 1865 }
1866 1866
1867 1867 scsi_hba_reset_notify_tear_down(mpt->m_reset_notify_listf);
1868 1868
1869 1869 mptsas_list_del(mpt);
1870 1870
1871 1871 /*
1872 1872 * Cancel timeout threads for this mpt
1873 1873 */
1874 1874 mutex_enter(&mpt->m_mutex);
1875 1875 if (mpt->m_quiesce_timeid) {
1876 1876 timeout_id_t tid = mpt->m_quiesce_timeid;
1877 1877 mpt->m_quiesce_timeid = 0;
1878 1878 mutex_exit(&mpt->m_mutex);
1879 1879 (void) untimeout(tid);
1880 1880 mutex_enter(&mpt->m_mutex);
1881 1881 }
1882 1882
1883 1883 if (mpt->m_restart_cmd_timeid) {
1884 1884 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1885 1885 mpt->m_restart_cmd_timeid = 0;
1886 1886 mutex_exit(&mpt->m_mutex);
1887 1887 (void) untimeout(tid);
1888 1888 mutex_enter(&mpt->m_mutex);
1889 1889 }
1890 1890
1891 1891 mutex_exit(&mpt->m_mutex);
1892 1892
1893 1893 /*
1894 1894 * last mpt? ... if active, CANCEL watch threads.
1895 1895 */
1896 1896 mutex_enter(&mptsas_global_mutex);
1897 1897 if (mptsas_head == NULL) {
1898 1898 timeout_id_t tid;
1899 1899 /*
1900 1900 * Clear mptsas_timeouts_enable so that the watch thread
1901 1901 * gets restarted on DDI_ATTACH
1902 1902 */
1903 1903 mptsas_timeouts_enabled = 0;
1904 1904 if (mptsas_timeout_id) {
1905 1905 tid = mptsas_timeout_id;
1906 1906 mptsas_timeout_id = 0;
1907 1907 mutex_exit(&mptsas_global_mutex);
1908 1908 (void) untimeout(tid);
1909 1909 mutex_enter(&mptsas_global_mutex);
1910 1910 }
1911 1911 if (mptsas_reset_watch) {
1912 1912 tid = mptsas_reset_watch;
1913 1913 mptsas_reset_watch = 0;
1914 1914 mutex_exit(&mptsas_global_mutex);
1915 1915 (void) untimeout(tid);
1916 1916 mutex_enter(&mptsas_global_mutex);
1917 1917 }
1918 1918 }
1919 1919 mutex_exit(&mptsas_global_mutex);
1920 1920
1921 1921 /*
1922 1922 * Delete Phy stats
1923 1923 */
1924 1924 mptsas_destroy_phy_stats(mpt);
1925 1925
1926 1926 mptsas_destroy_hashes(mpt);
1927 1927
1928 1928 /*
1929 1929 * Delete nt_active.
1930 1930 */
1931 1931 mutex_enter(&mpt->m_mutex);
1932 1932 mptsas_free_active_slots(mpt);
1933 1933 mutex_exit(&mpt->m_mutex);
1934 1934
1935 1935 /* deallocate everything that was allocated in mptsas_attach */
1936 1936 mptsas_cache_destroy(mpt);
1937 1937
1938 1938 mptsas_hba_fini(mpt);
1939 1939 mptsas_cfg_fini(mpt);
1940 1940
1941 1941 /* Lower the power informing PM Framework */
1942 1942 if (mpt->m_options & MPTSAS_OPT_PM) {
1943 1943 if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS)
1944 1944 mptsas_log(mpt, CE_WARN,
1945 1945 "!mptsas%d: Lower power request failed "
1946 1946 "during detach, ignoring.",
1947 1947 mpt->m_instance);
1948 1948 }
1949 1949
1950 1950 mutex_destroy(&mpt->m_tx_waitq_mutex);
1951 1951 mutex_destroy(&mpt->m_passthru_mutex);
1952 1952 mutex_destroy(&mpt->m_mutex);
1953 1953 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1954 1954 mutex_destroy(&mpt->m_phy_info[i].smhba_info.phy_mutex);
1955 1955 }
1956 1956 cv_destroy(&mpt->m_cv);
1957 1957 cv_destroy(&mpt->m_passthru_cv);
1958 1958 cv_destroy(&mpt->m_fw_cv);
1959 1959 cv_destroy(&mpt->m_config_cv);
1960 1960 cv_destroy(&mpt->m_fw_diag_cv);
1961 1961
1962 1962
1963 1963 mptsas_smp_teardown(mpt);
1964 1964 mptsas_hba_teardown(mpt);
1965 1965
1966 1966 mptsas_config_space_fini(mpt);
1967 1967
1968 1968 mptsas_free_handshake_msg(mpt);
1969 1969
1970 1970 mptsas_fm_fini(mpt);
1971 1971 ddi_soft_state_free(mptsas_state, ddi_get_instance(dip));
1972 1972 ddi_prop_remove_all(dip);
1973 1973
1974 1974 return (DDI_SUCCESS);
1975 1975 }
1976 1976
1977 1977 static void
1978 1978 mptsas_list_add(mptsas_t *mpt)
1979 1979 {
1980 1980 rw_enter(&mptsas_global_rwlock, RW_WRITER);
1981 1981
1982 1982 if (mptsas_head == NULL) {
1983 1983 mptsas_head = mpt;
1984 1984 } else {
1985 1985 mptsas_tail->m_next = mpt;
1986 1986 }
1987 1987 mptsas_tail = mpt;
1988 1988 rw_exit(&mptsas_global_rwlock);
1989 1989 }
1990 1990
1991 1991 static void
1992 1992 mptsas_list_del(mptsas_t *mpt)
1993 1993 {
1994 1994 mptsas_t *m;
1995 1995 /*
1996 1996 * Remove device instance from the global linked list
1997 1997 */
1998 1998 rw_enter(&mptsas_global_rwlock, RW_WRITER);
1999 1999 if (mptsas_head == mpt) {
2000 2000 m = mptsas_head = mpt->m_next;
2001 2001 } else {
2002 2002 for (m = mptsas_head; m != NULL; m = m->m_next) {
2003 2003 if (m->m_next == mpt) {
2004 2004 m->m_next = mpt->m_next;
2005 2005 break;
2006 2006 }
2007 2007 }
2008 2008 if (m == NULL) {
2009 2009 mptsas_log(mpt, CE_PANIC, "Not in softc list!");
2010 2010 }
2011 2011 }
2012 2012
2013 2013 if (mptsas_tail == mpt) {
|
↓ open down ↓ |
2013 lines elided |
↑ open up ↑ |
2014 2014 mptsas_tail = m;
2015 2015 }
2016 2016 rw_exit(&mptsas_global_rwlock);
2017 2017 }
2018 2018
2019 2019 static int
2020 2020 mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size)
2021 2021 {
2022 2022 ddi_dma_attr_t task_dma_attrs;
2023 2023
2024 + mpt->m_hshk_dma_size = 0;
2024 2025 task_dma_attrs = mpt->m_msg_dma_attr;
2025 2026 task_dma_attrs.dma_attr_sgllen = 1;
2026 2027 task_dma_attrs.dma_attr_granular = (uint32_t)(alloc_size);
2027 2028
2028 2029 /* allocate Task Management ddi_dma resources */
2029 2030 if (mptsas_dma_addr_create(mpt, task_dma_attrs,
2030 2031 &mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl, &mpt->m_hshk_memp,
2031 2032 alloc_size, NULL) == FALSE) {
2032 2033 return (DDI_FAILURE);
2033 2034 }
2034 2035 mpt->m_hshk_dma_size = alloc_size;
2035 2036
2036 2037 return (DDI_SUCCESS);
2037 2038 }
2038 2039
2039 2040 static void
2040 2041 mptsas_free_handshake_msg(mptsas_t *mpt)
2041 2042 {
2043 + if (mpt->m_hshk_dma_size == 0)
2044 + return;
2042 2045 mptsas_dma_addr_destroy(&mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl);
2043 2046 mpt->m_hshk_dma_size = 0;
2044 2047 }
2045 2048
2046 2049 static int
2047 2050 mptsas_hba_setup(mptsas_t *mpt)
2048 2051 {
2049 2052 scsi_hba_tran_t *hba_tran;
2050 2053 int tran_flags;
2051 2054
2052 2055 /* Allocate a transport structure */
2053 2056 hba_tran = mpt->m_tran = scsi_hba_tran_alloc(mpt->m_dip,
2054 2057 SCSI_HBA_CANSLEEP);
2055 2058 ASSERT(mpt->m_tran != NULL);
2056 2059
2057 2060 hba_tran->tran_hba_private = mpt;
2058 2061 hba_tran->tran_tgt_private = NULL;
2059 2062
2060 2063 hba_tran->tran_tgt_init = mptsas_scsi_tgt_init;
2061 2064 hba_tran->tran_tgt_free = mptsas_scsi_tgt_free;
2062 2065
2063 2066 hba_tran->tran_start = mptsas_scsi_start;
2064 2067 hba_tran->tran_reset = mptsas_scsi_reset;
2065 2068 hba_tran->tran_abort = mptsas_scsi_abort;
2066 2069 hba_tran->tran_getcap = mptsas_scsi_getcap;
2067 2070 hba_tran->tran_setcap = mptsas_scsi_setcap;
2068 2071 hba_tran->tran_init_pkt = mptsas_scsi_init_pkt;
2069 2072 hba_tran->tran_destroy_pkt = mptsas_scsi_destroy_pkt;
2070 2073
2071 2074 hba_tran->tran_dmafree = mptsas_scsi_dmafree;
2072 2075 hba_tran->tran_sync_pkt = mptsas_scsi_sync_pkt;
2073 2076 hba_tran->tran_reset_notify = mptsas_scsi_reset_notify;
2074 2077
2075 2078 hba_tran->tran_get_bus_addr = mptsas_get_bus_addr;
2076 2079 hba_tran->tran_get_name = mptsas_get_name;
2077 2080
2078 2081 hba_tran->tran_quiesce = mptsas_scsi_quiesce;
2079 2082 hba_tran->tran_unquiesce = mptsas_scsi_unquiesce;
2080 2083 hba_tran->tran_bus_reset = NULL;
2081 2084
2082 2085 hba_tran->tran_add_eventcall = NULL;
2083 2086 hba_tran->tran_get_eventcookie = NULL;
2084 2087 hba_tran->tran_post_event = NULL;
2085 2088 hba_tran->tran_remove_eventcall = NULL;
2086 2089
2087 2090 hba_tran->tran_bus_config = mptsas_bus_config;
2088 2091
2089 2092 hba_tran->tran_interconnect_type = INTERCONNECT_SAS;
2090 2093
2091 2094 /*
2092 2095 * All children of the HBA are iports. We need tran was cloned.
2093 2096 * So we pass the flags to SCSA. SCSI_HBA_TRAN_CLONE will be
2094 2097 * inherited to iport's tran vector.
2095 2098 */
2096 2099 tran_flags = (SCSI_HBA_HBA | SCSI_HBA_TRAN_CLONE);
2097 2100
2098 2101 if (scsi_hba_attach_setup(mpt->m_dip, &mpt->m_msg_dma_attr,
2099 2102 hba_tran, tran_flags) != DDI_SUCCESS) {
2100 2103 mptsas_log(mpt, CE_WARN, "hba attach setup failed");
2101 2104 scsi_hba_tran_free(hba_tran);
2102 2105 mpt->m_tran = NULL;
2103 2106 return (FALSE);
2104 2107 }
2105 2108 return (TRUE);
2106 2109 }
2107 2110
2108 2111 static void
2109 2112 mptsas_hba_teardown(mptsas_t *mpt)
2110 2113 {
2111 2114 (void) scsi_hba_detach(mpt->m_dip);
2112 2115 if (mpt->m_tran != NULL) {
2113 2116 scsi_hba_tran_free(mpt->m_tran);
2114 2117 mpt->m_tran = NULL;
2115 2118 }
2116 2119 }
2117 2120
2118 2121 static void
2119 2122 mptsas_iport_register(mptsas_t *mpt)
2120 2123 {
2121 2124 int i, j;
2122 2125 mptsas_phymask_t mask = 0x0;
2123 2126 /*
2124 2127 * initial value of mask is 0
2125 2128 */
2126 2129 mutex_enter(&mpt->m_mutex);
2127 2130 for (i = 0; i < mpt->m_num_phys; i++) {
2128 2131 mptsas_phymask_t phy_mask = 0x0;
2129 2132 char phy_mask_name[MPTSAS_MAX_PHYS];
2130 2133 uint8_t current_port;
2131 2134
2132 2135 if (mpt->m_phy_info[i].attached_devhdl == 0)
2133 2136 continue;
2134 2137
2135 2138 bzero(phy_mask_name, sizeof (phy_mask_name));
2136 2139
2137 2140 current_port = mpt->m_phy_info[i].port_num;
2138 2141
2139 2142 if ((mask & (1 << i)) != 0)
2140 2143 continue;
2141 2144
2142 2145 for (j = 0; j < mpt->m_num_phys; j++) {
2143 2146 if (mpt->m_phy_info[j].attached_devhdl &&
2144 2147 (mpt->m_phy_info[j].port_num == current_port)) {
2145 2148 phy_mask |= (1 << j);
2146 2149 }
2147 2150 }
2148 2151 mask = mask | phy_mask;
2149 2152
2150 2153 for (j = 0; j < mpt->m_num_phys; j++) {
2151 2154 if ((phy_mask >> j) & 0x01) {
2152 2155 mpt->m_phy_info[j].phy_mask = phy_mask;
2153 2156 }
2154 2157 }
2155 2158
2156 2159 (void) sprintf(phy_mask_name, "%x", phy_mask);
2157 2160
2158 2161 mutex_exit(&mpt->m_mutex);
2159 2162 /*
2160 2163 * register a iport
2161 2164 */
2162 2165 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
2163 2166 mutex_enter(&mpt->m_mutex);
2164 2167 }
2165 2168 mutex_exit(&mpt->m_mutex);
2166 2169 /*
2167 2170 * register a virtual port for RAID volume always
2168 2171 */
2169 2172 (void) scsi_hba_iport_register(mpt->m_dip, "v0");
2170 2173
2171 2174 }
2172 2175
2173 2176 static int
2174 2177 mptsas_smp_setup(mptsas_t *mpt)
2175 2178 {
2176 2179 mpt->m_smptran = smp_hba_tran_alloc(mpt->m_dip);
2177 2180 ASSERT(mpt->m_smptran != NULL);
2178 2181 mpt->m_smptran->smp_tran_hba_private = mpt;
2179 2182 mpt->m_smptran->smp_tran_start = mptsas_smp_start;
2180 2183 if (smp_hba_attach_setup(mpt->m_dip, mpt->m_smptran) != DDI_SUCCESS) {
2181 2184 mptsas_log(mpt, CE_WARN, "smp attach setup failed");
2182 2185 smp_hba_tran_free(mpt->m_smptran);
2183 2186 mpt->m_smptran = NULL;
2184 2187 return (FALSE);
2185 2188 }
2186 2189 /*
2187 2190 * Initialize smp hash table
2188 2191 */
2189 2192 mpt->m_smp_targets = refhash_create(MPTSAS_SMP_BUCKET_COUNT,
2190 2193 mptsas_target_addr_hash, mptsas_target_addr_cmp,
2191 2194 mptsas_smp_free, sizeof (mptsas_smp_t),
2192 2195 offsetof(mptsas_smp_t, m_link), offsetof(mptsas_smp_t, m_addr),
2193 2196 KM_SLEEP);
2194 2197 mpt->m_smp_devhdl = 0xFFFF;
2195 2198
2196 2199 return (TRUE);
2197 2200 }
2198 2201
2199 2202 static void
2200 2203 mptsas_smp_teardown(mptsas_t *mpt)
2201 2204 {
2202 2205 (void) smp_hba_detach(mpt->m_dip);
2203 2206 if (mpt->m_smptran != NULL) {
2204 2207 smp_hba_tran_free(mpt->m_smptran);
2205 2208 mpt->m_smptran = NULL;
2206 2209 }
2207 2210 mpt->m_smp_devhdl = 0;
2208 2211 }
2209 2212
2210 2213 static int
2211 2214 mptsas_cache_create(mptsas_t *mpt)
2212 2215 {
2213 2216 int instance = mpt->m_instance;
2214 2217 char buf[64];
2215 2218
2216 2219 /*
2217 2220 * create kmem cache for packets
2218 2221 */
2219 2222 (void) sprintf(buf, "mptsas%d_cache", instance);
2220 2223 mpt->m_kmem_cache = kmem_cache_create(buf,
2221 2224 sizeof (struct mptsas_cmd) + scsi_pkt_size(), 8,
2222 2225 mptsas_kmem_cache_constructor, mptsas_kmem_cache_destructor,
2223 2226 NULL, (void *)mpt, NULL, 0);
2224 2227
2225 2228 if (mpt->m_kmem_cache == NULL) {
2226 2229 mptsas_log(mpt, CE_WARN, "creating kmem cache failed");
2227 2230 return (FALSE);
2228 2231 }
2229 2232
2230 2233 /*
2231 2234 * create kmem cache for extra SGL frames if SGL cannot
2232 2235 * be accomodated into main request frame.
2233 2236 */
2234 2237 (void) sprintf(buf, "mptsas%d_cache_frames", instance);
2235 2238 mpt->m_cache_frames = kmem_cache_create(buf,
2236 2239 sizeof (mptsas_cache_frames_t), 8,
2237 2240 mptsas_cache_frames_constructor, mptsas_cache_frames_destructor,
2238 2241 NULL, (void *)mpt, NULL, 0);
2239 2242
2240 2243 if (mpt->m_cache_frames == NULL) {
2241 2244 mptsas_log(mpt, CE_WARN, "creating cache for frames failed");
2242 2245 return (FALSE);
2243 2246 }
2244 2247
2245 2248 return (TRUE);
2246 2249 }
2247 2250
2248 2251 static void
2249 2252 mptsas_cache_destroy(mptsas_t *mpt)
2250 2253 {
2251 2254 /* deallocate in reverse order */
2252 2255 if (mpt->m_cache_frames) {
2253 2256 kmem_cache_destroy(mpt->m_cache_frames);
2254 2257 mpt->m_cache_frames = NULL;
2255 2258 }
2256 2259 if (mpt->m_kmem_cache) {
2257 2260 kmem_cache_destroy(mpt->m_kmem_cache);
2258 2261 mpt->m_kmem_cache = NULL;
2259 2262 }
2260 2263 }
2261 2264
2262 2265 static int
2263 2266 mptsas_power(dev_info_t *dip, int component, int level)
2264 2267 {
2265 2268 #ifndef __lock_lint
2266 2269 _NOTE(ARGUNUSED(component))
2267 2270 #endif
2268 2271 mptsas_t *mpt;
2269 2272 int rval = DDI_SUCCESS;
2270 2273 int polls = 0;
2271 2274 uint32_t ioc_status;
2272 2275
2273 2276 if (scsi_hba_iport_unit_address(dip) != 0)
2274 2277 return (DDI_SUCCESS);
2275 2278
2276 2279 mpt = ddi_get_soft_state(mptsas_state, ddi_get_instance(dip));
2277 2280 if (mpt == NULL) {
2278 2281 return (DDI_FAILURE);
2279 2282 }
2280 2283
2281 2284 mutex_enter(&mpt->m_mutex);
2282 2285
2283 2286 /*
2284 2287 * If the device is busy, don't lower its power level
2285 2288 */
2286 2289 if (mpt->m_busy && (mpt->m_power_level > level)) {
2287 2290 mutex_exit(&mpt->m_mutex);
2288 2291 return (DDI_FAILURE);
2289 2292 }
2290 2293 switch (level) {
2291 2294 case PM_LEVEL_D0:
2292 2295 NDBG11(("mptsas%d: turning power ON.", mpt->m_instance));
2293 2296 MPTSAS_POWER_ON(mpt);
2294 2297 /*
2295 2298 * Wait up to 30 seconds for IOC to come out of reset.
2296 2299 */
2297 2300 while (((ioc_status = ddi_get32(mpt->m_datap,
2298 2301 &mpt->m_reg->Doorbell)) &
2299 2302 MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) {
2300 2303 if (polls++ > 3000) {
2301 2304 break;
2302 2305 }
2303 2306 delay(drv_usectohz(10000));
2304 2307 }
2305 2308 /*
2306 2309 * If IOC is not in operational state, try to hard reset it.
2307 2310 */
2308 2311 if ((ioc_status & MPI2_IOC_STATE_MASK) !=
2309 2312 MPI2_IOC_STATE_OPERATIONAL) {
2310 2313 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
2311 2314 if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
2312 2315 mptsas_log(mpt, CE_WARN,
2313 2316 "mptsas_power: hard reset failed");
2314 2317 mutex_exit(&mpt->m_mutex);
2315 2318 return (DDI_FAILURE);
2316 2319 }
2317 2320 }
2318 2321 mpt->m_power_level = PM_LEVEL_D0;
2319 2322 break;
2320 2323 case PM_LEVEL_D3:
2321 2324 NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance));
2322 2325 MPTSAS_POWER_OFF(mpt);
2323 2326 break;
2324 2327 default:
2325 2328 mptsas_log(mpt, CE_WARN, "mptsas%d: unknown power level <%x>.",
2326 2329 mpt->m_instance, level);
2327 2330 rval = DDI_FAILURE;
2328 2331 break;
2329 2332 }
2330 2333 mutex_exit(&mpt->m_mutex);
2331 2334 return (rval);
2332 2335 }
2333 2336
2334 2337 /*
2335 2338 * Initialize configuration space and figure out which
2336 2339 * chip and revison of the chip the mpt driver is using.
2337 2340 */
2338 2341 static int
2339 2342 mptsas_config_space_init(mptsas_t *mpt)
2340 2343 {
2341 2344 NDBG0(("mptsas_config_space_init"));
2342 2345
2343 2346 if (mpt->m_config_handle != NULL)
2344 2347 return (TRUE);
2345 2348
2346 2349 if (pci_config_setup(mpt->m_dip,
2347 2350 &mpt->m_config_handle) != DDI_SUCCESS) {
2348 2351 mptsas_log(mpt, CE_WARN, "cannot map configuration space.");
2349 2352 return (FALSE);
2350 2353 }
2351 2354
2352 2355 /*
2353 2356 * This is a workaround for a XMITS ASIC bug which does not
2354 2357 * drive the CBE upper bits.
2355 2358 */
2356 2359 if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT) &
2357 2360 PCI_STAT_PERROR) {
2358 2361 pci_config_put16(mpt->m_config_handle, PCI_CONF_STAT,
2359 2362 PCI_STAT_PERROR);
2360 2363 }
2361 2364
2362 2365 mptsas_setup_cmd_reg(mpt);
2363 2366
2364 2367 /*
2365 2368 * Get the chip device id:
2366 2369 */
2367 2370 mpt->m_devid = pci_config_get16(mpt->m_config_handle, PCI_CONF_DEVID);
2368 2371
2369 2372 /*
2370 2373 * Save the revision.
2371 2374 */
2372 2375 mpt->m_revid = pci_config_get8(mpt->m_config_handle, PCI_CONF_REVID);
2373 2376
2374 2377 /*
2375 2378 * Save the SubSystem Vendor and Device IDs
2376 2379 */
2377 2380 mpt->m_svid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBVENID);
2378 2381 mpt->m_ssid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBSYSID);
2379 2382
2380 2383 /*
2381 2384 * Set the latency timer to 0x40 as specified by the upa -> pci
2382 2385 * bridge chip design team. This may be done by the sparc pci
2383 2386 * bus nexus driver, but the driver should make sure the latency
2384 2387 * timer is correct for performance reasons.
2385 2388 */
2386 2389 pci_config_put8(mpt->m_config_handle, PCI_CONF_LATENCY_TIMER,
2387 2390 MPTSAS_LATENCY_TIMER);
2388 2391
2389 2392 (void) mptsas_get_pci_cap(mpt);
2390 2393 return (TRUE);
2391 2394 }
2392 2395
2393 2396 static void
2394 2397 mptsas_config_space_fini(mptsas_t *mpt)
2395 2398 {
2396 2399 if (mpt->m_config_handle != NULL) {
2397 2400 mptsas_disable_bus_master(mpt);
2398 2401 pci_config_teardown(&mpt->m_config_handle);
2399 2402 mpt->m_config_handle = NULL;
2400 2403 }
2401 2404 }
2402 2405
2403 2406 static void
2404 2407 mptsas_setup_cmd_reg(mptsas_t *mpt)
2405 2408 {
2406 2409 ushort_t cmdreg;
2407 2410
2408 2411 /*
2409 2412 * Set the command register to the needed values.
2410 2413 */
2411 2414 cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2412 2415 cmdreg |= (PCI_COMM_ME | PCI_COMM_SERR_ENABLE |
2413 2416 PCI_COMM_PARITY_DETECT | PCI_COMM_MAE);
2414 2417 cmdreg &= ~PCI_COMM_IO;
2415 2418 pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2416 2419 }
2417 2420
2418 2421 static void
2419 2422 mptsas_disable_bus_master(mptsas_t *mpt)
2420 2423 {
2421 2424 ushort_t cmdreg;
2422 2425
2423 2426 /*
2424 2427 * Clear the master enable bit in the PCI command register.
2425 2428 * This prevents any bus mastering activity like DMA.
2426 2429 */
2427 2430 cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2428 2431 cmdreg &= ~PCI_COMM_ME;
2429 2432 pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2430 2433 }
2431 2434
2432 2435 int
2433 2436 mptsas_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep)
2434 2437 {
2435 2438 ddi_dma_attr_t attrs;
2436 2439
2437 2440 attrs = mpt->m_io_dma_attr;
2438 2441 attrs.dma_attr_sgllen = 1;
2439 2442
2440 2443 ASSERT(dma_statep != NULL);
2441 2444
2442 2445 if (mptsas_dma_addr_create(mpt, attrs, &dma_statep->handle,
2443 2446 &dma_statep->accessp, &dma_statep->memp, dma_statep->size,
2444 2447 &dma_statep->cookie) == FALSE) {
2445 2448 return (DDI_FAILURE);
2446 2449 }
2447 2450
2448 2451 return (DDI_SUCCESS);
2449 2452 }
2450 2453
2451 2454 void
2452 2455 mptsas_dma_free(mptsas_dma_alloc_state_t *dma_statep)
2453 2456 {
2454 2457 ASSERT(dma_statep != NULL);
2455 2458 mptsas_dma_addr_destroy(&dma_statep->handle, &dma_statep->accessp);
2456 2459 dma_statep->size = 0;
2457 2460 }
2458 2461
2459 2462 int
2460 2463 mptsas_do_dma(mptsas_t *mpt, uint32_t size, int var, int (*callback)())
2461 2464 {
2462 2465 ddi_dma_attr_t attrs;
2463 2466 ddi_dma_handle_t dma_handle;
2464 2467 caddr_t memp;
2465 2468 ddi_acc_handle_t accessp;
2466 2469 int rval;
2467 2470
2468 2471 ASSERT(mutex_owned(&mpt->m_mutex));
2469 2472
2470 2473 attrs = mpt->m_msg_dma_attr;
2471 2474 attrs.dma_attr_sgllen = 1;
2472 2475 attrs.dma_attr_granular = size;
2473 2476
2474 2477 if (mptsas_dma_addr_create(mpt, attrs, &dma_handle,
2475 2478 &accessp, &memp, size, NULL) == FALSE) {
2476 2479 return (DDI_FAILURE);
2477 2480 }
2478 2481
2479 2482 rval = (*callback) (mpt, memp, var, accessp);
2480 2483
2481 2484 if ((mptsas_check_dma_handle(dma_handle) != DDI_SUCCESS) ||
2482 2485 (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
2483 2486 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2484 2487 rval = DDI_FAILURE;
2485 2488 }
2486 2489
2487 2490 mptsas_dma_addr_destroy(&dma_handle, &accessp);
2488 2491 return (rval);
2489 2492
2490 2493 }
2491 2494
2492 2495 static int
2493 2496 mptsas_alloc_request_frames(mptsas_t *mpt)
2494 2497 {
2495 2498 ddi_dma_attr_t frame_dma_attrs;
2496 2499 caddr_t memp;
2497 2500 ddi_dma_cookie_t cookie;
2498 2501 size_t mem_size;
2499 2502
2500 2503 /*
2501 2504 * re-alloc when it has already alloced
2502 2505 */
2503 2506 mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2504 2507 &mpt->m_acc_req_frame_hdl);
2505 2508
2506 2509 /*
2507 2510 * The size of the request frame pool is:
2508 2511 * Number of Request Frames * Request Frame Size
2509 2512 */
2510 2513 mem_size = mpt->m_max_requests * mpt->m_req_frame_size;
2511 2514
2512 2515 /*
2513 2516 * set the DMA attributes. System Request Message Frames must be
2514 2517 * aligned on a 16-byte boundry.
2515 2518 */
2516 2519 frame_dma_attrs = mpt->m_msg_dma_attr;
2517 2520 frame_dma_attrs.dma_attr_align = 16;
2518 2521 frame_dma_attrs.dma_attr_sgllen = 1;
2519 2522
2520 2523 /*
2521 2524 * allocate the request frame pool.
2522 2525 */
2523 2526 if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2524 2527 &mpt->m_dma_req_frame_hdl, &mpt->m_acc_req_frame_hdl, &memp,
2525 2528 mem_size, &cookie) == FALSE) {
2526 2529 return (DDI_FAILURE);
2527 2530 }
2528 2531
2529 2532 /*
2530 2533 * Store the request frame memory address. This chip uses this
2531 2534 * address to dma to and from the driver's frame. The second
2532 2535 * address is the address mpt uses to fill in the frame.
2533 2536 */
2534 2537 mpt->m_req_frame_dma_addr = cookie.dmac_laddress;
2535 2538 mpt->m_req_frame = memp;
2536 2539
2537 2540 /*
2538 2541 * Clear the request frame pool.
2539 2542 */
2540 2543 bzero(mpt->m_req_frame, mem_size);
2541 2544
2542 2545 return (DDI_SUCCESS);
2543 2546 }
2544 2547
2545 2548 static int
2546 2549 mptsas_alloc_reply_frames(mptsas_t *mpt)
2547 2550 {
2548 2551 ddi_dma_attr_t frame_dma_attrs;
2549 2552 caddr_t memp;
2550 2553 ddi_dma_cookie_t cookie;
2551 2554 size_t mem_size;
2552 2555
2553 2556 /*
2554 2557 * re-alloc when it has already alloced
2555 2558 */
2556 2559 mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2557 2560 &mpt->m_acc_reply_frame_hdl);
2558 2561
2559 2562 /*
2560 2563 * The size of the reply frame pool is:
2561 2564 * Number of Reply Frames * Reply Frame Size
2562 2565 */
2563 2566 mem_size = mpt->m_max_replies * mpt->m_reply_frame_size;
2564 2567
2565 2568 /*
2566 2569 * set the DMA attributes. System Reply Message Frames must be
2567 2570 * aligned on a 4-byte boundry. This is the default.
2568 2571 */
2569 2572 frame_dma_attrs = mpt->m_msg_dma_attr;
2570 2573 frame_dma_attrs.dma_attr_sgllen = 1;
2571 2574
2572 2575 /*
2573 2576 * allocate the reply frame pool
2574 2577 */
2575 2578 if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2576 2579 &mpt->m_dma_reply_frame_hdl, &mpt->m_acc_reply_frame_hdl, &memp,
2577 2580 mem_size, &cookie) == FALSE) {
2578 2581 return (DDI_FAILURE);
2579 2582 }
2580 2583
2581 2584 /*
2582 2585 * Store the reply frame memory address. This chip uses this
2583 2586 * address to dma to and from the driver's frame. The second
2584 2587 * address is the address mpt uses to process the frame.
2585 2588 */
2586 2589 mpt->m_reply_frame_dma_addr = cookie.dmac_laddress;
2587 2590 mpt->m_reply_frame = memp;
2588 2591
2589 2592 /*
2590 2593 * Clear the reply frame pool.
2591 2594 */
2592 2595 bzero(mpt->m_reply_frame, mem_size);
2593 2596
2594 2597 return (DDI_SUCCESS);
2595 2598 }
2596 2599
2597 2600 static int
2598 2601 mptsas_alloc_free_queue(mptsas_t *mpt)
2599 2602 {
2600 2603 ddi_dma_attr_t frame_dma_attrs;
2601 2604 caddr_t memp;
2602 2605 ddi_dma_cookie_t cookie;
2603 2606 size_t mem_size;
2604 2607
2605 2608 /*
2606 2609 * re-alloc when it has already alloced
2607 2610 */
2608 2611 mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2609 2612 &mpt->m_acc_free_queue_hdl);
2610 2613
2611 2614 /*
2612 2615 * The reply free queue size is:
2613 2616 * Reply Free Queue Depth * 4
2614 2617 * The "4" is the size of one 32 bit address (low part of 64-bit
2615 2618 * address)
2616 2619 */
2617 2620 mem_size = mpt->m_free_queue_depth * 4;
2618 2621
2619 2622 /*
2620 2623 * set the DMA attributes The Reply Free Queue must be aligned on a
2621 2624 * 16-byte boundry.
2622 2625 */
2623 2626 frame_dma_attrs = mpt->m_msg_dma_attr;
2624 2627 frame_dma_attrs.dma_attr_align = 16;
2625 2628 frame_dma_attrs.dma_attr_sgllen = 1;
2626 2629
2627 2630 /*
2628 2631 * allocate the reply free queue
2629 2632 */
2630 2633 if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2631 2634 &mpt->m_dma_free_queue_hdl, &mpt->m_acc_free_queue_hdl, &memp,
2632 2635 mem_size, &cookie) == FALSE) {
2633 2636 return (DDI_FAILURE);
2634 2637 }
2635 2638
2636 2639 /*
2637 2640 * Store the reply free queue memory address. This chip uses this
2638 2641 * address to read from the reply free queue. The second address
2639 2642 * is the address mpt uses to manage the queue.
2640 2643 */
2641 2644 mpt->m_free_queue_dma_addr = cookie.dmac_laddress;
2642 2645 mpt->m_free_queue = memp;
2643 2646
2644 2647 /*
2645 2648 * Clear the reply free queue memory.
2646 2649 */
2647 2650 bzero(mpt->m_free_queue, mem_size);
2648 2651
2649 2652 return (DDI_SUCCESS);
2650 2653 }
2651 2654
2652 2655 static int
2653 2656 mptsas_alloc_post_queue(mptsas_t *mpt)
2654 2657 {
2655 2658 ddi_dma_attr_t frame_dma_attrs;
2656 2659 caddr_t memp;
2657 2660 ddi_dma_cookie_t cookie;
2658 2661 size_t mem_size;
2659 2662
2660 2663 /*
2661 2664 * re-alloc when it has already alloced
2662 2665 */
2663 2666 mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2664 2667 &mpt->m_acc_post_queue_hdl);
2665 2668
2666 2669 /*
2667 2670 * The reply descriptor post queue size is:
2668 2671 * Reply Descriptor Post Queue Depth * 8
2669 2672 * The "8" is the size of each descriptor (8 bytes or 64 bits).
2670 2673 */
2671 2674 mem_size = mpt->m_post_queue_depth * 8;
2672 2675
2673 2676 /*
2674 2677 * set the DMA attributes. The Reply Descriptor Post Queue must be
2675 2678 * aligned on a 16-byte boundry.
2676 2679 */
2677 2680 frame_dma_attrs = mpt->m_msg_dma_attr;
2678 2681 frame_dma_attrs.dma_attr_align = 16;
2679 2682 frame_dma_attrs.dma_attr_sgllen = 1;
2680 2683
2681 2684 /*
2682 2685 * allocate the reply post queue
2683 2686 */
2684 2687 if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2685 2688 &mpt->m_dma_post_queue_hdl, &mpt->m_acc_post_queue_hdl, &memp,
2686 2689 mem_size, &cookie) == FALSE) {
2687 2690 return (DDI_FAILURE);
2688 2691 }
2689 2692
2690 2693 /*
2691 2694 * Store the reply descriptor post queue memory address. This chip
2692 2695 * uses this address to write to the reply descriptor post queue. The
2693 2696 * second address is the address mpt uses to manage the queue.
2694 2697 */
2695 2698 mpt->m_post_queue_dma_addr = cookie.dmac_laddress;
2696 2699 mpt->m_post_queue = memp;
2697 2700
2698 2701 /*
2699 2702 * Clear the reply post queue memory.
2700 2703 */
2701 2704 bzero(mpt->m_post_queue, mem_size);
2702 2705
2703 2706 return (DDI_SUCCESS);
2704 2707 }
2705 2708
2706 2709 static void
2707 2710 mptsas_alloc_reply_args(mptsas_t *mpt)
2708 2711 {
2709 2712 if (mpt->m_replyh_args == NULL) {
2710 2713 mpt->m_replyh_args = kmem_zalloc(sizeof (m_replyh_arg_t) *
2711 2714 mpt->m_max_replies, KM_SLEEP);
2712 2715 }
2713 2716 }
2714 2717
2715 2718 static int
2716 2719 mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2717 2720 {
2718 2721 mptsas_cache_frames_t *frames = NULL;
2719 2722 if (cmd->cmd_extra_frames == NULL) {
2720 2723 frames = kmem_cache_alloc(mpt->m_cache_frames, KM_NOSLEEP);
2721 2724 if (frames == NULL) {
2722 2725 return (DDI_FAILURE);
2723 2726 }
2724 2727 cmd->cmd_extra_frames = frames;
2725 2728 }
2726 2729 return (DDI_SUCCESS);
2727 2730 }
2728 2731
2729 2732 static void
2730 2733 mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2731 2734 {
2732 2735 if (cmd->cmd_extra_frames) {
2733 2736 kmem_cache_free(mpt->m_cache_frames,
2734 2737 (void *)cmd->cmd_extra_frames);
2735 2738 cmd->cmd_extra_frames = NULL;
2736 2739 }
2737 2740 }
2738 2741
2739 2742 static void
2740 2743 mptsas_cfg_fini(mptsas_t *mpt)
2741 2744 {
2742 2745 NDBG0(("mptsas_cfg_fini"));
2743 2746 ddi_regs_map_free(&mpt->m_datap);
2744 2747 }
2745 2748
2746 2749 static void
2747 2750 mptsas_hba_fini(mptsas_t *mpt)
2748 2751 {
2749 2752 NDBG0(("mptsas_hba_fini"));
2750 2753
2751 2754 /*
2752 2755 * Free up any allocated memory
2753 2756 */
2754 2757 mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2755 2758 &mpt->m_acc_req_frame_hdl);
2756 2759
2757 2760 mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2758 2761 &mpt->m_acc_reply_frame_hdl);
2759 2762
2760 2763 mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2761 2764 &mpt->m_acc_free_queue_hdl);
2762 2765
2763 2766 mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2764 2767 &mpt->m_acc_post_queue_hdl);
2765 2768
2766 2769 if (mpt->m_replyh_args != NULL) {
2767 2770 kmem_free(mpt->m_replyh_args, sizeof (m_replyh_arg_t)
2768 2771 * mpt->m_max_replies);
2769 2772 }
2770 2773 }
2771 2774
2772 2775 static int
2773 2776 mptsas_name_child(dev_info_t *lun_dip, char *name, int len)
2774 2777 {
2775 2778 int lun = 0;
2776 2779 char *sas_wwn = NULL;
2777 2780 int phynum = -1;
2778 2781 int reallen = 0;
2779 2782
2780 2783 /* Get the target num */
2781 2784 lun = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip, DDI_PROP_DONTPASS,
2782 2785 LUN_PROP, 0);
2783 2786
2784 2787 if ((phynum = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip,
2785 2788 DDI_PROP_DONTPASS, "sata-phy", -1)) != -1) {
2786 2789 /*
2787 2790 * Stick in the address of form "pPHY,LUN"
2788 2791 */
2789 2792 reallen = snprintf(name, len, "p%x,%x", phynum, lun);
2790 2793 } else if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip,
2791 2794 DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &sas_wwn)
2792 2795 == DDI_PROP_SUCCESS) {
2793 2796 /*
2794 2797 * Stick in the address of the form "wWWN,LUN"
2795 2798 */
2796 2799 reallen = snprintf(name, len, "%s,%x", sas_wwn, lun);
2797 2800 ddi_prop_free(sas_wwn);
2798 2801 } else {
2799 2802 return (DDI_FAILURE);
2800 2803 }
2801 2804
2802 2805 ASSERT(reallen < len);
2803 2806 if (reallen >= len) {
2804 2807 mptsas_log(0, CE_WARN, "!mptsas_get_name: name parameter "
2805 2808 "length too small, it needs to be %d bytes", reallen + 1);
2806 2809 }
2807 2810 return (DDI_SUCCESS);
2808 2811 }
2809 2812
2810 2813 /*
2811 2814 * tran_tgt_init(9E) - target device instance initialization
2812 2815 */
2813 2816 static int
2814 2817 mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
2815 2818 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
2816 2819 {
2817 2820 #ifndef __lock_lint
2818 2821 _NOTE(ARGUNUSED(hba_tran))
2819 2822 #endif
2820 2823
2821 2824 /*
2822 2825 * At this point, the scsi_device structure already exists
2823 2826 * and has been initialized.
2824 2827 *
2825 2828 * Use this function to allocate target-private data structures,
2826 2829 * if needed by this HBA. Add revised flow-control and queue
2827 2830 * properties for child here, if desired and if you can tell they
2828 2831 * support tagged queueing by now.
2829 2832 */
2830 2833 mptsas_t *mpt;
2831 2834 int lun = sd->sd_address.a_lun;
2832 2835 mdi_pathinfo_t *pip = NULL;
2833 2836 mptsas_tgt_private_t *tgt_private = NULL;
2834 2837 mptsas_target_t *ptgt = NULL;
2835 2838 char *psas_wwn = NULL;
2836 2839 mptsas_phymask_t phymask = 0;
2837 2840 uint64_t sas_wwn = 0;
2838 2841 mptsas_target_addr_t addr;
2839 2842 mpt = SDEV2MPT(sd);
2840 2843
2841 2844 ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
2842 2845
2843 2846 NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
2844 2847 (void *)hba_dip, (void *)tgt_dip, lun));
2845 2848
2846 2849 if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
2847 2850 (void) ndi_merge_node(tgt_dip, mptsas_name_child);
2848 2851 ddi_set_name_addr(tgt_dip, NULL);
2849 2852 return (DDI_FAILURE);
2850 2853 }
2851 2854 /*
2852 2855 * phymask is 0 means the virtual port for RAID
2853 2856 */
2854 2857 phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
2855 2858 "phymask", 0);
2856 2859 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2857 2860 if ((pip = (void *)(sd->sd_private)) == NULL) {
2858 2861 /*
2859 2862 * Very bad news if this occurs. Somehow scsi_vhci has
2860 2863 * lost the pathinfo node for this target.
2861 2864 */
2862 2865 return (DDI_NOT_WELL_FORMED);
2863 2866 }
2864 2867
2865 2868 if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) !=
2866 2869 DDI_PROP_SUCCESS) {
2867 2870 mptsas_log(mpt, CE_WARN, "Get lun property failed\n");
2868 2871 return (DDI_FAILURE);
2869 2872 }
2870 2873
2871 2874 if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
2872 2875 &psas_wwn) == MDI_SUCCESS) {
2873 2876 if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2874 2877 sas_wwn = 0;
2875 2878 }
2876 2879 (void) mdi_prop_free(psas_wwn);
2877 2880 }
2878 2881 } else {
2879 2882 lun = ddi_prop_get_int(DDI_DEV_T_ANY, tgt_dip,
2880 2883 DDI_PROP_DONTPASS, LUN_PROP, 0);
2881 2884 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
2882 2885 DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) ==
2883 2886 DDI_PROP_SUCCESS) {
2884 2887 if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2885 2888 sas_wwn = 0;
2886 2889 }
2887 2890 ddi_prop_free(psas_wwn);
2888 2891 } else {
2889 2892 sas_wwn = 0;
2890 2893 }
2891 2894 }
2892 2895
2893 2896 ASSERT((sas_wwn != 0) || (phymask != 0));
2894 2897 addr.mta_wwn = sas_wwn;
2895 2898 addr.mta_phymask = phymask;
2896 2899 mutex_enter(&mpt->m_mutex);
2897 2900 ptgt = refhash_lookup(mpt->m_targets, &addr);
2898 2901 mutex_exit(&mpt->m_mutex);
2899 2902 if (ptgt == NULL) {
2900 2903 mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or "
2901 2904 "gone already! phymask:%x, saswwn %"PRIx64, phymask,
2902 2905 sas_wwn);
2903 2906 return (DDI_FAILURE);
2904 2907 }
2905 2908 if (hba_tran->tran_tgt_private == NULL) {
2906 2909 tgt_private = kmem_zalloc(sizeof (mptsas_tgt_private_t),
2907 2910 KM_SLEEP);
2908 2911 tgt_private->t_lun = lun;
2909 2912 tgt_private->t_private = ptgt;
2910 2913 hba_tran->tran_tgt_private = tgt_private;
2911 2914 }
2912 2915
2913 2916 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2914 2917 return (DDI_SUCCESS);
2915 2918 }
2916 2919 mutex_enter(&mpt->m_mutex);
2917 2920
2918 2921 if (ptgt->m_deviceinfo &
2919 2922 (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
2920 2923 MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
2921 2924 uchar_t *inq89 = NULL;
2922 2925 int inq89_len = 0x238;
2923 2926 int reallen = 0;
2924 2927 int rval = 0;
2925 2928 struct sata_id *sid = NULL;
2926 2929 char model[SATA_ID_MODEL_LEN + 1];
2927 2930 char fw[SATA_ID_FW_LEN + 1];
2928 2931 char *vid, *pid;
2929 2932 int i;
2930 2933
2931 2934 mutex_exit(&mpt->m_mutex);
2932 2935 /*
2933 2936 * According SCSI/ATA Translation -2 (SAT-2) revision 01a
2934 2937 * chapter 12.4.2 VPD page 89h includes 512 bytes ATA IDENTIFY
2935 2938 * DEVICE data or ATA IDENTIFY PACKET DEVICE data.
2936 2939 */
2937 2940 inq89 = kmem_zalloc(inq89_len, KM_SLEEP);
2938 2941 rval = mptsas_inquiry(mpt, ptgt, 0, 0x89,
2939 2942 inq89, inq89_len, &reallen, 1);
2940 2943
2941 2944 if (rval != 0) {
2942 2945 if (inq89 != NULL) {
2943 2946 kmem_free(inq89, inq89_len);
2944 2947 }
2945 2948
2946 2949 mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
2947 2950 "0x89 for SATA target:%x failed!", ptgt->m_devhdl);
2948 2951 return (DDI_SUCCESS);
2949 2952 }
2950 2953 sid = (void *)(&inq89[60]);
2951 2954
2952 2955 swab(sid->ai_model, model, SATA_ID_MODEL_LEN);
2953 2956 swab(sid->ai_fw, fw, SATA_ID_FW_LEN);
2954 2957
2955 2958 model[SATA_ID_MODEL_LEN] = 0;
2956 2959 fw[SATA_ID_FW_LEN] = 0;
2957 2960
2958 2961 /*
2959 2962 * split model into into vid/pid
2960 2963 */
2961 2964 for (i = 0, pid = model; i < SATA_ID_MODEL_LEN; i++, pid++)
2962 2965 if ((*pid == ' ') || (*pid == '\t'))
2963 2966 break;
2964 2967 if (i < SATA_ID_MODEL_LEN) {
2965 2968 vid = model;
2966 2969 /*
2967 2970 * terminate vid, establish pid
2968 2971 */
2969 2972 *pid++ = 0;
2970 2973 } else {
2971 2974 /*
2972 2975 * vid will stay "ATA ", the rule is same
2973 2976 * as sata framework implementation.
2974 2977 */
2975 2978 vid = NULL;
2976 2979 /*
2977 2980 * model is all pid
2978 2981 */
2979 2982 pid = model;
2980 2983 }
2981 2984
2982 2985 /*
2983 2986 * override SCSA "inquiry-*" properties
2984 2987 */
2985 2988 if (vid)
2986 2989 (void) scsi_device_prop_update_inqstring(sd,
2987 2990 INQUIRY_VENDOR_ID, vid, strlen(vid));
2988 2991 if (pid)
2989 2992 (void) scsi_device_prop_update_inqstring(sd,
2990 2993 INQUIRY_PRODUCT_ID, pid, strlen(pid));
2991 2994 (void) scsi_device_prop_update_inqstring(sd,
2992 2995 INQUIRY_REVISION_ID, fw, strlen(fw));
2993 2996
2994 2997 if (inq89 != NULL) {
2995 2998 kmem_free(inq89, inq89_len);
2996 2999 }
2997 3000 } else {
2998 3001 mutex_exit(&mpt->m_mutex);
2999 3002 }
3000 3003
3001 3004 return (DDI_SUCCESS);
3002 3005 }
3003 3006 /*
3004 3007 * tran_tgt_free(9E) - target device instance deallocation
3005 3008 */
3006 3009 static void
3007 3010 mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3008 3011 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
3009 3012 {
3010 3013 #ifndef __lock_lint
3011 3014 _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran, sd))
3012 3015 #endif
3013 3016
3014 3017 mptsas_tgt_private_t *tgt_private = hba_tran->tran_tgt_private;
3015 3018
3016 3019 if (tgt_private != NULL) {
3017 3020 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
3018 3021 hba_tran->tran_tgt_private = NULL;
3019 3022 }
3020 3023 }
3021 3024
3022 3025 /*
3023 3026 * scsi_pkt handling
3024 3027 *
3025 3028 * Visible to the external world via the transport structure.
3026 3029 */
3027 3030
3028 3031 /*
3029 3032 * Notes:
3030 3033 * - transport the command to the addressed SCSI target/lun device
3031 3034 * - normal operation is to schedule the command to be transported,
3032 3035 * and return TRAN_ACCEPT if this is successful.
3033 3036 * - if NO_INTR, tran_start must poll device for command completion
3034 3037 */
3035 3038 static int
3036 3039 mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
3037 3040 {
3038 3041 #ifndef __lock_lint
3039 3042 _NOTE(ARGUNUSED(ap))
3040 3043 #endif
3041 3044 mptsas_t *mpt = PKT2MPT(pkt);
3042 3045 mptsas_cmd_t *cmd = PKT2CMD(pkt);
3043 3046 int rval;
3044 3047 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3045 3048
3046 3049 NDBG1(("mptsas_scsi_start: pkt=0x%p", (void *)pkt));
3047 3050 ASSERT(ptgt);
3048 3051 if (ptgt == NULL)
3049 3052 return (TRAN_FATAL_ERROR);
3050 3053
3051 3054 /*
3052 3055 * prepare the pkt before taking mutex.
3053 3056 */
3054 3057 rval = mptsas_prepare_pkt(cmd);
3055 3058 if (rval != TRAN_ACCEPT) {
3056 3059 return (rval);
3057 3060 }
3058 3061
3059 3062 /*
3060 3063 * Send the command to target/lun, however your HBA requires it.
3061 3064 * If busy, return TRAN_BUSY; if there's some other formatting error
3062 3065 * in the packet, return TRAN_BADPKT; otherwise, fall through to the
3063 3066 * return of TRAN_ACCEPT.
3064 3067 *
3065 3068 * Remember that access to shared resources, including the mptsas_t
3066 3069 * data structure and the HBA hardware registers, must be protected
3067 3070 * with mutexes, here and everywhere.
3068 3071 *
3069 3072 * Also remember that at interrupt time, you'll get an argument
3070 3073 * to the interrupt handler which is a pointer to your mptsas_t
3071 3074 * structure; you'll have to remember which commands are outstanding
3072 3075 * and which scsi_pkt is the currently-running command so the
3073 3076 * interrupt handler can refer to the pkt to set completion
3074 3077 * status, call the target driver back through pkt_comp, etc.
3075 3078 *
3076 3079 * If the instance lock is held by other thread, don't spin to wait
3077 3080 * for it. Instead, queue the cmd and next time when the instance lock
3078 3081 * is not held, accept all the queued cmd. A extra tx_waitq is
3079 3082 * introduced to protect the queue.
3080 3083 *
3081 3084 * The polled cmd will not be queud and accepted as usual.
3082 3085 *
3083 3086 * Under the tx_waitq mutex, record whether a thread is draining
3084 3087 * the tx_waitq. An IO requesting thread that finds the instance
3085 3088 * mutex contended appends to the tx_waitq and while holding the
3086 3089 * tx_wait mutex, if the draining flag is not set, sets it and then
3087 3090 * proceeds to spin for the instance mutex. This scheme ensures that
3088 3091 * the last cmd in a burst be processed.
3089 3092 *
3090 3093 * we enable this feature only when the helper threads are enabled,
3091 3094 * at which we think the loads are heavy.
3092 3095 *
3093 3096 * per instance mutex m_tx_waitq_mutex is introduced to protect the
3094 3097 * m_tx_waitqtail, m_tx_waitq, m_tx_draining.
3095 3098 */
3096 3099
3097 3100 if (mpt->m_doneq_thread_n) {
3098 3101 if (mutex_tryenter(&mpt->m_mutex) != 0) {
3099 3102 rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3100 3103 mutex_exit(&mpt->m_mutex);
3101 3104 } else if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3102 3105 mutex_enter(&mpt->m_mutex);
3103 3106 rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3104 3107 mutex_exit(&mpt->m_mutex);
3105 3108 } else {
3106 3109 mutex_enter(&mpt->m_tx_waitq_mutex);
3107 3110 /*
3108 3111 * ptgt->m_dr_flag is protected by m_mutex or
3109 3112 * m_tx_waitq_mutex. In this case, m_tx_waitq_mutex
3110 3113 * is acquired.
3111 3114 */
3112 3115 if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3113 3116 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3114 3117 /*
3115 3118 * The command should be allowed to
3116 3119 * retry by returning TRAN_BUSY to
3117 3120 * to stall the I/O's which come from
3118 3121 * scsi_vhci since the device/path is
3119 3122 * in unstable state now.
3120 3123 */
3121 3124 mutex_exit(&mpt->m_tx_waitq_mutex);
3122 3125 return (TRAN_BUSY);
3123 3126 } else {
3124 3127 /*
3125 3128 * The device is offline, just fail the
3126 3129 * command by returning
3127 3130 * TRAN_FATAL_ERROR.
3128 3131 */
3129 3132 mutex_exit(&mpt->m_tx_waitq_mutex);
3130 3133 return (TRAN_FATAL_ERROR);
3131 3134 }
3132 3135 }
3133 3136 if (mpt->m_tx_draining) {
3134 3137 cmd->cmd_flags |= CFLAG_TXQ;
3135 3138 *mpt->m_tx_waitqtail = cmd;
3136 3139 mpt->m_tx_waitqtail = &cmd->cmd_linkp;
3137 3140 mutex_exit(&mpt->m_tx_waitq_mutex);
3138 3141 } else { /* drain the queue */
3139 3142 mpt->m_tx_draining = 1;
3140 3143 mutex_exit(&mpt->m_tx_waitq_mutex);
3141 3144 mutex_enter(&mpt->m_mutex);
3142 3145 rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3143 3146 mutex_exit(&mpt->m_mutex);
3144 3147 }
3145 3148 }
3146 3149 } else {
3147 3150 mutex_enter(&mpt->m_mutex);
3148 3151 /*
3149 3152 * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3150 3153 * in this case, m_mutex is acquired.
3151 3154 */
3152 3155 if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3153 3156 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3154 3157 /*
3155 3158 * commands should be allowed to retry by
3156 3159 * returning TRAN_BUSY to stall the I/O's
3157 3160 * which come from scsi_vhci since the device/
3158 3161 * path is in unstable state now.
3159 3162 */
3160 3163 mutex_exit(&mpt->m_mutex);
3161 3164 return (TRAN_BUSY);
3162 3165 } else {
3163 3166 /*
3164 3167 * The device is offline, just fail the
3165 3168 * command by returning TRAN_FATAL_ERROR.
3166 3169 */
3167 3170 mutex_exit(&mpt->m_mutex);
3168 3171 return (TRAN_FATAL_ERROR);
3169 3172 }
3170 3173 }
3171 3174 rval = mptsas_accept_pkt(mpt, cmd);
3172 3175 mutex_exit(&mpt->m_mutex);
3173 3176 }
3174 3177
3175 3178 return (rval);
3176 3179 }
3177 3180
3178 3181 /*
3179 3182 * Accept all the queued cmds(if any) before accept the current one.
3180 3183 */
3181 3184 static int
3182 3185 mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3183 3186 {
3184 3187 int rval;
3185 3188 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3186 3189
3187 3190 ASSERT(mutex_owned(&mpt->m_mutex));
3188 3191 /*
3189 3192 * The call to mptsas_accept_tx_waitq() must always be performed
3190 3193 * because that is where mpt->m_tx_draining is cleared.
3191 3194 */
3192 3195 mutex_enter(&mpt->m_tx_waitq_mutex);
3193 3196 mptsas_accept_tx_waitq(mpt);
3194 3197 mutex_exit(&mpt->m_tx_waitq_mutex);
3195 3198 /*
3196 3199 * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3197 3200 * in this case, m_mutex is acquired.
3198 3201 */
3199 3202 if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3200 3203 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3201 3204 /*
3202 3205 * The command should be allowed to retry by returning
3203 3206 * TRAN_BUSY to stall the I/O's which come from
3204 3207 * scsi_vhci since the device/path is in unstable state
3205 3208 * now.
3206 3209 */
3207 3210 return (TRAN_BUSY);
3208 3211 } else {
3209 3212 /*
3210 3213 * The device is offline, just fail the command by
3211 3214 * return TRAN_FATAL_ERROR.
3212 3215 */
3213 3216 return (TRAN_FATAL_ERROR);
3214 3217 }
3215 3218 }
3216 3219 rval = mptsas_accept_pkt(mpt, cmd);
3217 3220
3218 3221 return (rval);
3219 3222 }
3220 3223
3221 3224 static int
3222 3225 mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3223 3226 {
3224 3227 int rval = TRAN_ACCEPT;
3225 3228 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3226 3229
3227 3230 NDBG1(("mptsas_accept_pkt: cmd=0x%p", (void *)cmd));
3228 3231
3229 3232 ASSERT(mutex_owned(&mpt->m_mutex));
3230 3233
3231 3234 if ((cmd->cmd_flags & CFLAG_PREPARED) == 0) {
3232 3235 rval = mptsas_prepare_pkt(cmd);
3233 3236 if (rval != TRAN_ACCEPT) {
3234 3237 cmd->cmd_flags &= ~CFLAG_TRANFLAG;
3235 3238 return (rval);
3236 3239 }
3237 3240 }
3238 3241
3239 3242 /*
3240 3243 * reset the throttle if we were draining
3241 3244 */
3242 3245 if ((ptgt->m_t_ncmds == 0) &&
3243 3246 (ptgt->m_t_throttle == DRAIN_THROTTLE)) {
3244 3247 NDBG23(("reset throttle"));
3245 3248 ASSERT(ptgt->m_reset_delay == 0);
3246 3249 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
3247 3250 }
3248 3251
3249 3252 /*
3250 3253 * If HBA is being reset, the DevHandles are being re-initialized,
3251 3254 * which means that they could be invalid even if the target is still
3252 3255 * attached. Check if being reset and if DevHandle is being
3253 3256 * re-initialized. If this is the case, return BUSY so the I/O can be
3254 3257 * retried later.
3255 3258 */
3256 3259 if ((ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) && mpt->m_in_reset) {
3257 3260 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
3258 3261 if (cmd->cmd_flags & CFLAG_TXQ) {
3259 3262 mptsas_doneq_add(mpt, cmd);
3260 3263 mptsas_doneq_empty(mpt);
3261 3264 return (rval);
3262 3265 } else {
3263 3266 return (TRAN_BUSY);
3264 3267 }
3265 3268 }
3266 3269
3267 3270 /*
3268 3271 * If device handle has already been invalidated, just
3269 3272 * fail the command. In theory, command from scsi_vhci
3270 3273 * client is impossible send down command with invalid
3271 3274 * devhdl since devhdl is set after path offline, target
3272 3275 * driver is not suppose to select a offlined path.
3273 3276 */
3274 3277 if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) {
3275 3278 NDBG20(("rejecting command, it might because invalid devhdl "
3276 3279 "request."));
3277 3280 mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED);
3278 3281 if (cmd->cmd_flags & CFLAG_TXQ) {
3279 3282 mptsas_doneq_add(mpt, cmd);
3280 3283 mptsas_doneq_empty(mpt);
3281 3284 return (rval);
3282 3285 } else {
3283 3286 return (TRAN_FATAL_ERROR);
3284 3287 }
3285 3288 }
3286 3289 /*
3287 3290 * The first case is the normal case. mpt gets a command from the
3288 3291 * target driver and starts it.
3289 3292 * Since SMID 0 is reserved and the TM slot is reserved, the actual max
3290 3293 * commands is m_max_requests - 2.
3291 3294 */
3292 3295 if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
3293 3296 (ptgt->m_t_throttle > HOLD_THROTTLE) &&
3294 3297 (ptgt->m_t_ncmds < ptgt->m_t_throttle) &&
3295 3298 (ptgt->m_reset_delay == 0) &&
3296 3299 (ptgt->m_t_nwait == 0) &&
3297 3300 ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0)) {
3298 3301 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
3299 3302 (void) mptsas_start_cmd(mpt, cmd);
3300 3303 } else {
3301 3304 mptsas_waitq_add(mpt, cmd);
3302 3305 }
3303 3306 } else {
3304 3307 /*
3305 3308 * Add this pkt to the work queue
3306 3309 */
3307 3310 mptsas_waitq_add(mpt, cmd);
3308 3311
3309 3312 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3310 3313 (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
3311 3314
3312 3315 /*
3313 3316 * Only flush the doneq if this is not a TM
3314 3317 * cmd. For TM cmds the flushing of the
3315 3318 * doneq will be done in those routines.
3316 3319 */
3317 3320 if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
3318 3321 mptsas_doneq_empty(mpt);
3319 3322 }
3320 3323 }
3321 3324 }
3322 3325 return (rval);
3323 3326 }
3324 3327
3325 3328 int
3326 3329 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
3327 3330 {
3328 3331 mptsas_slots_t *slots = mpt->m_active;
3329 3332 uint_t slot, start_rotor;
3330 3333 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3331 3334
3332 3335 ASSERT(MUTEX_HELD(&mpt->m_mutex));
3333 3336
3334 3337 /*
3335 3338 * Account for reserved TM request slot and reserved SMID of 0.
3336 3339 */
3337 3340 ASSERT(slots->m_n_normal == (mpt->m_max_requests - 2));
3338 3341
3339 3342 /*
3340 3343 * Find the next available slot, beginning at m_rotor. If no slot is
3341 3344 * available, we'll return FALSE to indicate that. This mechanism
3342 3345 * considers only the normal slots, not the reserved slot 0 nor the
3343 3346 * task management slot m_n_normal + 1. The rotor is left to point to
3344 3347 * the normal slot after the one we select, unless we select the last
3345 3348 * normal slot in which case it returns to slot 1.
3346 3349 */
3347 3350 start_rotor = slots->m_rotor;
3348 3351 do {
3349 3352 slot = slots->m_rotor++;
3350 3353 if (slots->m_rotor > slots->m_n_normal)
3351 3354 slots->m_rotor = 1;
3352 3355
3353 3356 if (slots->m_rotor == start_rotor)
3354 3357 break;
3355 3358 } while (slots->m_slot[slot] != NULL);
3356 3359
3357 3360 if (slots->m_slot[slot] != NULL)
3358 3361 return (FALSE);
3359 3362
3360 3363 ASSERT(slot != 0 && slot <= slots->m_n_normal);
3361 3364
3362 3365 cmd->cmd_slot = slot;
3363 3366 slots->m_slot[slot] = cmd;
3364 3367 mpt->m_ncmds++;
3365 3368
3366 3369 /*
3367 3370 * only increment per target ncmds if this is not a
3368 3371 * command that has no target associated with it (i.e. a
3369 3372 * event acknoledgment)
3370 3373 */
3371 3374 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
3372 3375 ptgt->m_t_ncmds++;
3373 3376 }
3374 3377 cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
3375 3378
3376 3379 /*
3377 3380 * If initial timout is less than or equal to one tick, bump
3378 3381 * the timeout by a tick so that command doesn't timeout before
3379 3382 * its allotted time.
3380 3383 */
3381 3384 if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
3382 3385 cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
3383 3386 }
3384 3387 return (TRUE);
3385 3388 }
3386 3389
3387 3390 /*
3388 3391 * prepare the pkt:
3389 3392 * the pkt may have been resubmitted or just reused so
3390 3393 * initialize some fields and do some checks.
3391 3394 */
3392 3395 static int
3393 3396 mptsas_prepare_pkt(mptsas_cmd_t *cmd)
3394 3397 {
3395 3398 struct scsi_pkt *pkt = CMD2PKT(cmd);
3396 3399
3397 3400 NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd));
3398 3401
3399 3402 /*
3400 3403 * Reinitialize some fields that need it; the packet may
3401 3404 * have been resubmitted
3402 3405 */
3403 3406 pkt->pkt_reason = CMD_CMPLT;
3404 3407 pkt->pkt_state = 0;
3405 3408 pkt->pkt_statistics = 0;
3406 3409 pkt->pkt_resid = 0;
3407 3410 cmd->cmd_age = 0;
3408 3411 cmd->cmd_pkt_flags = pkt->pkt_flags;
3409 3412
3410 3413 /*
3411 3414 * zero status byte.
3412 3415 */
3413 3416 *(pkt->pkt_scbp) = 0;
3414 3417
3415 3418 if (cmd->cmd_flags & CFLAG_DMAVALID) {
3416 3419 pkt->pkt_resid = cmd->cmd_dmacount;
3417 3420
3418 3421 /*
3419 3422 * consistent packets need to be sync'ed first
3420 3423 * (only for data going out)
3421 3424 */
3422 3425 if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
3423 3426 (cmd->cmd_flags & CFLAG_DMASEND)) {
3424 3427 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
3425 3428 DDI_DMA_SYNC_FORDEV);
3426 3429 }
3427 3430 }
3428 3431
3429 3432 cmd->cmd_flags =
3430 3433 (cmd->cmd_flags & ~(CFLAG_TRANFLAG)) |
3431 3434 CFLAG_PREPARED | CFLAG_IN_TRANSPORT;
3432 3435
3433 3436 return (TRAN_ACCEPT);
3434 3437 }
3435 3438
3436 3439 /*
3437 3440 * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command
3438 3441 *
3439 3442 * One of three possibilities:
3440 3443 * - allocate scsi_pkt
3441 3444 * - allocate scsi_pkt and DMA resources
3442 3445 * - allocate DMA resources to an already-allocated pkt
3443 3446 */
3444 3447 static struct scsi_pkt *
3445 3448 mptsas_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
3446 3449 struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
3447 3450 int (*callback)(), caddr_t arg)
3448 3451 {
3449 3452 mptsas_cmd_t *cmd, *new_cmd;
3450 3453 mptsas_t *mpt = ADDR2MPT(ap);
3451 3454 int failure = 1;
3452 3455 uint_t oldcookiec;
3453 3456 mptsas_target_t *ptgt = NULL;
3454 3457 int rval;
3455 3458 mptsas_tgt_private_t *tgt_private;
3456 3459 int kf;
3457 3460
3458 3461 kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
3459 3462
3460 3463 tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
3461 3464 tran_tgt_private;
3462 3465 ASSERT(tgt_private != NULL);
3463 3466 if (tgt_private == NULL) {
3464 3467 return (NULL);
3465 3468 }
3466 3469 ptgt = tgt_private->t_private;
3467 3470 ASSERT(ptgt != NULL);
3468 3471 if (ptgt == NULL)
3469 3472 return (NULL);
3470 3473 ap->a_target = ptgt->m_devhdl;
3471 3474 ap->a_lun = tgt_private->t_lun;
3472 3475
3473 3476 ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
3474 3477 #ifdef MPTSAS_TEST_EXTRN_ALLOC
3475 3478 statuslen *= 100; tgtlen *= 4;
3476 3479 #endif
3477 3480 NDBG3(("mptsas_scsi_init_pkt:\n"
3478 3481 "\ttgt=%d in=0x%p bp=0x%p clen=%d slen=%d tlen=%d flags=%x",
3479 3482 ap->a_target, (void *)pkt, (void *)bp,
3480 3483 cmdlen, statuslen, tgtlen, flags));
3481 3484
3482 3485 /*
3483 3486 * Allocate the new packet.
3484 3487 */
3485 3488 if (pkt == NULL) {
3486 3489 ddi_dma_handle_t save_dma_handle;
3487 3490 ddi_dma_handle_t save_arq_dma_handle;
3488 3491 struct buf *save_arq_bp;
3489 3492 ddi_dma_cookie_t save_arqcookie;
3490 3493
3491 3494 cmd = kmem_cache_alloc(mpt->m_kmem_cache, kf);
3492 3495
3493 3496 if (cmd) {
3494 3497 save_dma_handle = cmd->cmd_dmahandle;
3495 3498 save_arq_dma_handle = cmd->cmd_arqhandle;
3496 3499 save_arq_bp = cmd->cmd_arq_buf;
3497 3500 save_arqcookie = cmd->cmd_arqcookie;
3498 3501 bzero(cmd, sizeof (*cmd) + scsi_pkt_size());
3499 3502 cmd->cmd_dmahandle = save_dma_handle;
3500 3503 cmd->cmd_arqhandle = save_arq_dma_handle;
3501 3504 cmd->cmd_arq_buf = save_arq_bp;
3502 3505 cmd->cmd_arqcookie = save_arqcookie;
3503 3506
3504 3507 pkt = (void *)((uchar_t *)cmd +
3505 3508 sizeof (struct mptsas_cmd));
3506 3509 pkt->pkt_ha_private = (opaque_t)cmd;
3507 3510 pkt->pkt_address = *ap;
3508 3511 pkt->pkt_private = (opaque_t)cmd->cmd_pkt_private;
3509 3512 pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
3510 3513 pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb;
3511 3514 cmd->cmd_pkt = (struct scsi_pkt *)pkt;
3512 3515 cmd->cmd_cdblen = (uchar_t)cmdlen;
3513 3516 cmd->cmd_scblen = statuslen;
3514 3517 cmd->cmd_rqslen = SENSE_LENGTH;
3515 3518 cmd->cmd_tgt_addr = ptgt;
3516 3519 failure = 0;
3517 3520 }
3518 3521
3519 3522 if (failure || (cmdlen > sizeof (cmd->cmd_cdb)) ||
3520 3523 (tgtlen > PKT_PRIV_LEN) ||
3521 3524 (statuslen > EXTCMDS_STATUS_SIZE)) {
3522 3525 if (failure == 0) {
3523 3526 /*
3524 3527 * if extern alloc fails, all will be
3525 3528 * deallocated, including cmd
3526 3529 */
3527 3530 failure = mptsas_pkt_alloc_extern(mpt, cmd,
3528 3531 cmdlen, tgtlen, statuslen, kf);
3529 3532 }
3530 3533 if (failure) {
3531 3534 /*
3532 3535 * if extern allocation fails, it will
3533 3536 * deallocate the new pkt as well
3534 3537 */
3535 3538 return (NULL);
3536 3539 }
3537 3540 }
3538 3541 new_cmd = cmd;
3539 3542
3540 3543 } else {
3541 3544 cmd = PKT2CMD(pkt);
3542 3545 new_cmd = NULL;
3543 3546 }
3544 3547
3545 3548
3546 3549 /* grab cmd->cmd_cookiec here as oldcookiec */
3547 3550
3548 3551 oldcookiec = cmd->cmd_cookiec;
3549 3552
3550 3553 /*
3551 3554 * If the dma was broken up into PARTIAL transfers cmd_nwin will be
3552 3555 * greater than 0 and we'll need to grab the next dma window
3553 3556 */
3554 3557 /*
3555 3558 * SLM-not doing extra command frame right now; may add later
3556 3559 */
3557 3560
3558 3561 if (cmd->cmd_nwin > 0) {
3559 3562
3560 3563 /*
3561 3564 * Make sure we havn't gone past the the total number
3562 3565 * of windows
3563 3566 */
3564 3567 if (++cmd->cmd_winindex >= cmd->cmd_nwin) {
3565 3568 return (NULL);
3566 3569 }
3567 3570 if (ddi_dma_getwin(cmd->cmd_dmahandle, cmd->cmd_winindex,
3568 3571 &cmd->cmd_dma_offset, &cmd->cmd_dma_len,
3569 3572 &cmd->cmd_cookie, &cmd->cmd_cookiec) == DDI_FAILURE) {
3570 3573 return (NULL);
3571 3574 }
3572 3575 goto get_dma_cookies;
3573 3576 }
3574 3577
3575 3578
3576 3579 if (flags & PKT_XARQ) {
3577 3580 cmd->cmd_flags |= CFLAG_XARQ;
3578 3581 }
3579 3582
3580 3583 /*
3581 3584 * DMA resource allocation. This version assumes your
3582 3585 * HBA has some sort of bus-mastering or onboard DMA capability, with a
3583 3586 * scatter-gather list of length MPTSAS_MAX_DMA_SEGS, as given in the
3584 3587 * ddi_dma_attr_t structure and passed to scsi_impl_dmaget.
3585 3588 */
3586 3589 if (bp && (bp->b_bcount != 0) &&
3587 3590 (cmd->cmd_flags & CFLAG_DMAVALID) == 0) {
3588 3591
3589 3592 int cnt, dma_flags;
3590 3593 mptti_t *dmap; /* ptr to the S/G list */
3591 3594
3592 3595 /*
3593 3596 * Set up DMA memory and position to the next DMA segment.
3594 3597 */
3595 3598 ASSERT(cmd->cmd_dmahandle != NULL);
3596 3599
3597 3600 if (bp->b_flags & B_READ) {
3598 3601 dma_flags = DDI_DMA_READ;
3599 3602 cmd->cmd_flags &= ~CFLAG_DMASEND;
3600 3603 } else {
3601 3604 dma_flags = DDI_DMA_WRITE;
3602 3605 cmd->cmd_flags |= CFLAG_DMASEND;
3603 3606 }
3604 3607 if (flags & PKT_CONSISTENT) {
3605 3608 cmd->cmd_flags |= CFLAG_CMDIOPB;
3606 3609 dma_flags |= DDI_DMA_CONSISTENT;
3607 3610 }
3608 3611
3609 3612 if (flags & PKT_DMA_PARTIAL) {
3610 3613 dma_flags |= DDI_DMA_PARTIAL;
3611 3614 }
3612 3615
3613 3616 /*
3614 3617 * workaround for byte hole issue on psycho and
3615 3618 * schizo pre 2.1
3616 3619 */
3617 3620 if ((bp->b_flags & B_READ) && ((bp->b_flags &
3618 3621 (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
3619 3622 ((uintptr_t)bp->b_un.b_addr & 0x7)) {
3620 3623 dma_flags |= DDI_DMA_CONSISTENT;
3621 3624 }
3622 3625
3623 3626 rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
3624 3627 dma_flags, callback, arg,
3625 3628 &cmd->cmd_cookie, &cmd->cmd_cookiec);
3626 3629 if (rval == DDI_DMA_PARTIAL_MAP) {
3627 3630 (void) ddi_dma_numwin(cmd->cmd_dmahandle,
3628 3631 &cmd->cmd_nwin);
3629 3632 cmd->cmd_winindex = 0;
3630 3633 (void) ddi_dma_getwin(cmd->cmd_dmahandle,
3631 3634 cmd->cmd_winindex, &cmd->cmd_dma_offset,
3632 3635 &cmd->cmd_dma_len, &cmd->cmd_cookie,
3633 3636 &cmd->cmd_cookiec);
3634 3637 } else if (rval && (rval != DDI_DMA_MAPPED)) {
3635 3638 switch (rval) {
3636 3639 case DDI_DMA_NORESOURCES:
3637 3640 bioerror(bp, 0);
3638 3641 break;
3639 3642 case DDI_DMA_BADATTR:
3640 3643 case DDI_DMA_NOMAPPING:
3641 3644 bioerror(bp, EFAULT);
3642 3645 break;
3643 3646 case DDI_DMA_TOOBIG:
3644 3647 default:
3645 3648 bioerror(bp, EINVAL);
3646 3649 break;
3647 3650 }
3648 3651 cmd->cmd_flags &= ~CFLAG_DMAVALID;
3649 3652 if (new_cmd) {
3650 3653 mptsas_scsi_destroy_pkt(ap, pkt);
3651 3654 }
3652 3655 return ((struct scsi_pkt *)NULL);
3653 3656 }
3654 3657
3655 3658 get_dma_cookies:
3656 3659 cmd->cmd_flags |= CFLAG_DMAVALID;
3657 3660 ASSERT(cmd->cmd_cookiec > 0);
3658 3661
3659 3662 if (cmd->cmd_cookiec > MPTSAS_MAX_CMD_SEGS) {
3660 3663 mptsas_log(mpt, CE_NOTE, "large cookiec received %d\n",
3661 3664 cmd->cmd_cookiec);
3662 3665 bioerror(bp, EINVAL);
3663 3666 if (new_cmd) {
3664 3667 mptsas_scsi_destroy_pkt(ap, pkt);
3665 3668 }
3666 3669 return ((struct scsi_pkt *)NULL);
3667 3670 }
3668 3671
3669 3672 /*
3670 3673 * Allocate extra SGL buffer if needed.
3671 3674 */
3672 3675 if ((cmd->cmd_cookiec > MPTSAS_MAX_FRAME_SGES64(mpt)) &&
3673 3676 (cmd->cmd_extra_frames == NULL)) {
3674 3677 if (mptsas_alloc_extra_sgl_frame(mpt, cmd) ==
3675 3678 DDI_FAILURE) {
3676 3679 mptsas_log(mpt, CE_WARN, "MPT SGL mem alloc "
3677 3680 "failed");
3678 3681 bioerror(bp, ENOMEM);
3679 3682 if (new_cmd) {
3680 3683 mptsas_scsi_destroy_pkt(ap, pkt);
3681 3684 }
3682 3685 return ((struct scsi_pkt *)NULL);
3683 3686 }
3684 3687 }
3685 3688
3686 3689 /*
3687 3690 * Always use scatter-gather transfer
3688 3691 * Use the loop below to store physical addresses of
3689 3692 * DMA segments, from the DMA cookies, into your HBA's
3690 3693 * scatter-gather list.
3691 3694 * We need to ensure we have enough kmem alloc'd
3692 3695 * for the sg entries since we are no longer using an
3693 3696 * array inside mptsas_cmd_t.
3694 3697 *
3695 3698 * We check cmd->cmd_cookiec against oldcookiec so
3696 3699 * the scatter-gather list is correctly allocated
3697 3700 */
3698 3701
3699 3702 if (oldcookiec != cmd->cmd_cookiec) {
3700 3703 if (cmd->cmd_sg != (mptti_t *)NULL) {
3701 3704 kmem_free(cmd->cmd_sg, sizeof (mptti_t) *
3702 3705 oldcookiec);
3703 3706 cmd->cmd_sg = NULL;
3704 3707 }
3705 3708 }
3706 3709
3707 3710 if (cmd->cmd_sg == (mptti_t *)NULL) {
3708 3711 cmd->cmd_sg = kmem_alloc((size_t)(sizeof (mptti_t)*
3709 3712 cmd->cmd_cookiec), kf);
3710 3713
3711 3714 if (cmd->cmd_sg == (mptti_t *)NULL) {
3712 3715 mptsas_log(mpt, CE_WARN,
3713 3716 "unable to kmem_alloc enough memory "
3714 3717 "for scatter/gather list");
3715 3718 /*
3716 3719 * if we have an ENOMEM condition we need to behave
3717 3720 * the same way as the rest of this routine
3718 3721 */
3719 3722
3720 3723 bioerror(bp, ENOMEM);
3721 3724 if (new_cmd) {
3722 3725 mptsas_scsi_destroy_pkt(ap, pkt);
3723 3726 }
3724 3727 return ((struct scsi_pkt *)NULL);
3725 3728 }
3726 3729 }
3727 3730
3728 3731 dmap = cmd->cmd_sg;
3729 3732
3730 3733 ASSERT(cmd->cmd_cookie.dmac_size != 0);
3731 3734
3732 3735 /*
3733 3736 * store the first segment into the S/G list
3734 3737 */
3735 3738 dmap->count = cmd->cmd_cookie.dmac_size;
3736 3739 dmap->addr.address64.Low = (uint32_t)
3737 3740 (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3738 3741 dmap->addr.address64.High = (uint32_t)
3739 3742 (cmd->cmd_cookie.dmac_laddress >> 32);
3740 3743
3741 3744 /*
3742 3745 * dmacount counts the size of the dma for this window
3743 3746 * (if partial dma is being used). totaldmacount
3744 3747 * keeps track of the total amount of dma we have
3745 3748 * transferred for all the windows (needed to calculate
3746 3749 * the resid value below).
3747 3750 */
3748 3751 cmd->cmd_dmacount = cmd->cmd_cookie.dmac_size;
3749 3752 cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3750 3753
3751 3754 /*
3752 3755 * We already stored the first DMA scatter gather segment,
3753 3756 * start at 1 if we need to store more.
3754 3757 */
3755 3758 for (cnt = 1; cnt < cmd->cmd_cookiec; cnt++) {
3756 3759 /*
3757 3760 * Get next DMA cookie
3758 3761 */
3759 3762 ddi_dma_nextcookie(cmd->cmd_dmahandle,
3760 3763 &cmd->cmd_cookie);
3761 3764 dmap++;
3762 3765
3763 3766 cmd->cmd_dmacount += cmd->cmd_cookie.dmac_size;
3764 3767 cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3765 3768
3766 3769 /*
3767 3770 * store the segment parms into the S/G list
3768 3771 */
3769 3772 dmap->count = cmd->cmd_cookie.dmac_size;
3770 3773 dmap->addr.address64.Low = (uint32_t)
3771 3774 (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3772 3775 dmap->addr.address64.High = (uint32_t)
3773 3776 (cmd->cmd_cookie.dmac_laddress >> 32);
3774 3777 }
3775 3778
3776 3779 /*
3777 3780 * If this was partially allocated we set the resid
3778 3781 * the amount of data NOT transferred in this window
3779 3782 * If there is only one window, the resid will be 0
3780 3783 */
3781 3784 pkt->pkt_resid = (bp->b_bcount - cmd->cmd_totaldmacount);
3782 3785 NDBG16(("mptsas_dmaget: cmd_dmacount=%d.", cmd->cmd_dmacount));
3783 3786 }
3784 3787 return (pkt);
3785 3788 }
3786 3789
3787 3790 /*
3788 3791 * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation
3789 3792 *
3790 3793 * Notes:
3791 3794 * - also frees DMA resources if allocated
3792 3795 * - implicit DMA synchonization
3793 3796 */
3794 3797 static void
3795 3798 mptsas_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
3796 3799 {
3797 3800 mptsas_cmd_t *cmd = PKT2CMD(pkt);
3798 3801 mptsas_t *mpt = ADDR2MPT(ap);
3799 3802
3800 3803 NDBG3(("mptsas_scsi_destroy_pkt: target=%d pkt=0x%p",
3801 3804 ap->a_target, (void *)pkt));
3802 3805
3803 3806 if (cmd->cmd_flags & CFLAG_DMAVALID) {
3804 3807 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
3805 3808 cmd->cmd_flags &= ~CFLAG_DMAVALID;
3806 3809 }
3807 3810
3808 3811 if (cmd->cmd_sg) {
3809 3812 kmem_free(cmd->cmd_sg, sizeof (mptti_t) * cmd->cmd_cookiec);
3810 3813 cmd->cmd_sg = NULL;
3811 3814 }
3812 3815
3813 3816 mptsas_free_extra_sgl_frame(mpt, cmd);
3814 3817
3815 3818 if ((cmd->cmd_flags &
3816 3819 (CFLAG_FREE | CFLAG_CDBEXTERN | CFLAG_PRIVEXTERN |
3817 3820 CFLAG_SCBEXTERN)) == 0) {
3818 3821 cmd->cmd_flags = CFLAG_FREE;
3819 3822 kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
3820 3823 } else {
3821 3824 mptsas_pkt_destroy_extern(mpt, cmd);
3822 3825 }
3823 3826 }
3824 3827
3825 3828 /*
3826 3829 * kmem cache constructor and destructor:
3827 3830 * When constructing, we bzero the cmd and allocate the dma handle
3828 3831 * When destructing, just free the dma handle
3829 3832 */
3830 3833 static int
3831 3834 mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags)
3832 3835 {
3833 3836 mptsas_cmd_t *cmd = buf;
3834 3837 mptsas_t *mpt = cdrarg;
3835 3838 struct scsi_address ap;
3836 3839 uint_t cookiec;
3837 3840 ddi_dma_attr_t arq_dma_attr;
3838 3841 int (*callback)(caddr_t);
3839 3842
3840 3843 callback = (kmflags == KM_SLEEP)? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3841 3844
3842 3845 NDBG4(("mptsas_kmem_cache_constructor"));
3843 3846
3844 3847 ap.a_hba_tran = mpt->m_tran;
3845 3848 ap.a_target = 0;
3846 3849 ap.a_lun = 0;
3847 3850
3848 3851 /*
3849 3852 * allocate a dma handle
3850 3853 */
3851 3854 if ((ddi_dma_alloc_handle(mpt->m_dip, &mpt->m_io_dma_attr, callback,
3852 3855 NULL, &cmd->cmd_dmahandle)) != DDI_SUCCESS) {
3853 3856 cmd->cmd_dmahandle = NULL;
3854 3857 return (-1);
3855 3858 }
3856 3859
3857 3860 cmd->cmd_arq_buf = scsi_alloc_consistent_buf(&ap, (struct buf *)NULL,
3858 3861 SENSE_LENGTH, B_READ, callback, NULL);
3859 3862 if (cmd->cmd_arq_buf == NULL) {
3860 3863 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3861 3864 cmd->cmd_dmahandle = NULL;
3862 3865 return (-1);
3863 3866 }
3864 3867
3865 3868 /*
3866 3869 * allocate a arq handle
3867 3870 */
3868 3871 arq_dma_attr = mpt->m_msg_dma_attr;
3869 3872 arq_dma_attr.dma_attr_sgllen = 1;
3870 3873 if ((ddi_dma_alloc_handle(mpt->m_dip, &arq_dma_attr, callback,
3871 3874 NULL, &cmd->cmd_arqhandle)) != DDI_SUCCESS) {
3872 3875 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3873 3876 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3874 3877 cmd->cmd_dmahandle = NULL;
3875 3878 cmd->cmd_arqhandle = NULL;
3876 3879 return (-1);
3877 3880 }
3878 3881
3879 3882 if (ddi_dma_buf_bind_handle(cmd->cmd_arqhandle,
3880 3883 cmd->cmd_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
3881 3884 callback, NULL, &cmd->cmd_arqcookie, &cookiec) != DDI_SUCCESS) {
3882 3885 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3883 3886 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3884 3887 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3885 3888 cmd->cmd_dmahandle = NULL;
3886 3889 cmd->cmd_arqhandle = NULL;
3887 3890 cmd->cmd_arq_buf = NULL;
3888 3891 return (-1);
3889 3892 }
3890 3893
3891 3894 return (0);
3892 3895 }
3893 3896
3894 3897 static void
3895 3898 mptsas_kmem_cache_destructor(void *buf, void *cdrarg)
3896 3899 {
3897 3900 #ifndef __lock_lint
3898 3901 _NOTE(ARGUNUSED(cdrarg))
3899 3902 #endif
3900 3903 mptsas_cmd_t *cmd = buf;
3901 3904
3902 3905 NDBG4(("mptsas_kmem_cache_destructor"));
3903 3906
3904 3907 if (cmd->cmd_arqhandle) {
3905 3908 (void) ddi_dma_unbind_handle(cmd->cmd_arqhandle);
3906 3909 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3907 3910 cmd->cmd_arqhandle = NULL;
3908 3911 }
3909 3912 if (cmd->cmd_arq_buf) {
3910 3913 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3911 3914 cmd->cmd_arq_buf = NULL;
3912 3915 }
3913 3916 if (cmd->cmd_dmahandle) {
3914 3917 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3915 3918 cmd->cmd_dmahandle = NULL;
3916 3919 }
3917 3920 }
3918 3921
3919 3922 static int
3920 3923 mptsas_cache_frames_constructor(void *buf, void *cdrarg, int kmflags)
3921 3924 {
3922 3925 mptsas_cache_frames_t *p = buf;
3923 3926 mptsas_t *mpt = cdrarg;
3924 3927 ddi_dma_attr_t frame_dma_attr;
3925 3928 size_t mem_size, alloc_len;
3926 3929 ddi_dma_cookie_t cookie;
3927 3930 uint_t ncookie;
3928 3931 int (*callback)(caddr_t) = (kmflags == KM_SLEEP)
3929 3932 ? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3930 3933
3931 3934 frame_dma_attr = mpt->m_msg_dma_attr;
3932 3935 frame_dma_attr.dma_attr_align = 0x10;
3933 3936 frame_dma_attr.dma_attr_sgllen = 1;
3934 3937
3935 3938 if (ddi_dma_alloc_handle(mpt->m_dip, &frame_dma_attr, callback, NULL,
3936 3939 &p->m_dma_hdl) != DDI_SUCCESS) {
3937 3940 mptsas_log(mpt, CE_WARN, "Unable to allocate dma handle for"
3938 3941 " extra SGL.");
3939 3942 return (DDI_FAILURE);
3940 3943 }
3941 3944
3942 3945 mem_size = (mpt->m_max_request_frames - 1) * mpt->m_req_frame_size;
3943 3946
3944 3947 if (ddi_dma_mem_alloc(p->m_dma_hdl, mem_size, &mpt->m_dev_acc_attr,
3945 3948 DDI_DMA_CONSISTENT, callback, NULL, (caddr_t *)&p->m_frames_addr,
3946 3949 &alloc_len, &p->m_acc_hdl) != DDI_SUCCESS) {
3947 3950 ddi_dma_free_handle(&p->m_dma_hdl);
3948 3951 p->m_dma_hdl = NULL;
3949 3952 mptsas_log(mpt, CE_WARN, "Unable to allocate dma memory for"
3950 3953 " extra SGL.");
3951 3954 return (DDI_FAILURE);
3952 3955 }
3953 3956
3954 3957 if (ddi_dma_addr_bind_handle(p->m_dma_hdl, NULL, p->m_frames_addr,
3955 3958 alloc_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL,
3956 3959 &cookie, &ncookie) != DDI_DMA_MAPPED) {
3957 3960 (void) ddi_dma_mem_free(&p->m_acc_hdl);
3958 3961 ddi_dma_free_handle(&p->m_dma_hdl);
3959 3962 p->m_dma_hdl = NULL;
3960 3963 mptsas_log(mpt, CE_WARN, "Unable to bind DMA resources for"
3961 3964 " extra SGL");
3962 3965 return (DDI_FAILURE);
3963 3966 }
3964 3967
3965 3968 /*
3966 3969 * Store the SGL memory address. This chip uses this
3967 3970 * address to dma to and from the driver. The second
3968 3971 * address is the address mpt uses to fill in the SGL.
3969 3972 */
3970 3973 p->m_phys_addr = cookie.dmac_address;
3971 3974
3972 3975 return (DDI_SUCCESS);
3973 3976 }
3974 3977
3975 3978 static void
3976 3979 mptsas_cache_frames_destructor(void *buf, void *cdrarg)
3977 3980 {
3978 3981 #ifndef __lock_lint
3979 3982 _NOTE(ARGUNUSED(cdrarg))
3980 3983 #endif
3981 3984 mptsas_cache_frames_t *p = buf;
3982 3985 if (p->m_dma_hdl != NULL) {
3983 3986 (void) ddi_dma_unbind_handle(p->m_dma_hdl);
3984 3987 (void) ddi_dma_mem_free(&p->m_acc_hdl);
3985 3988 ddi_dma_free_handle(&p->m_dma_hdl);
3986 3989 p->m_phys_addr = NULL;
3987 3990 p->m_frames_addr = NULL;
3988 3991 p->m_dma_hdl = NULL;
3989 3992 p->m_acc_hdl = NULL;
3990 3993 }
3991 3994
3992 3995 }
3993 3996
3994 3997 /*
3995 3998 * allocate and deallocate external pkt space (ie. not part of mptsas_cmd)
3996 3999 * for non-standard length cdb, pkt_private, status areas
3997 4000 * if allocation fails, then deallocate all external space and the pkt
3998 4001 */
3999 4002 /* ARGSUSED */
4000 4003 static int
4001 4004 mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
4002 4005 int cmdlen, int tgtlen, int statuslen, int kf)
4003 4006 {
4004 4007 caddr_t cdbp, scbp, tgt;
4005 4008 int (*callback)(caddr_t) = (kf == KM_SLEEP) ?
4006 4009 DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
4007 4010 struct scsi_address ap;
4008 4011 size_t senselength;
4009 4012 ddi_dma_attr_t ext_arq_dma_attr;
4010 4013 uint_t cookiec;
4011 4014
4012 4015 NDBG3(("mptsas_pkt_alloc_extern: "
4013 4016 "cmd=0x%p cmdlen=%d tgtlen=%d statuslen=%d kf=%x",
4014 4017 (void *)cmd, cmdlen, tgtlen, statuslen, kf));
4015 4018
4016 4019 tgt = cdbp = scbp = NULL;
4017 4020 cmd->cmd_scblen = statuslen;
4018 4021 cmd->cmd_privlen = (uchar_t)tgtlen;
4019 4022
4020 4023 if (cmdlen > sizeof (cmd->cmd_cdb)) {
4021 4024 if ((cdbp = kmem_zalloc((size_t)cmdlen, kf)) == NULL) {
4022 4025 goto fail;
4023 4026 }
4024 4027 cmd->cmd_pkt->pkt_cdbp = (opaque_t)cdbp;
4025 4028 cmd->cmd_flags |= CFLAG_CDBEXTERN;
4026 4029 }
4027 4030 if (tgtlen > PKT_PRIV_LEN) {
4028 4031 if ((tgt = kmem_zalloc((size_t)tgtlen, kf)) == NULL) {
4029 4032 goto fail;
4030 4033 }
4031 4034 cmd->cmd_flags |= CFLAG_PRIVEXTERN;
4032 4035 cmd->cmd_pkt->pkt_private = tgt;
4033 4036 }
4034 4037 if (statuslen > EXTCMDS_STATUS_SIZE) {
4035 4038 if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
4036 4039 goto fail;
4037 4040 }
4038 4041 cmd->cmd_flags |= CFLAG_SCBEXTERN;
4039 4042 cmd->cmd_pkt->pkt_scbp = (opaque_t)scbp;
4040 4043
4041 4044 /* allocate sense data buf for DMA */
4042 4045
4043 4046 senselength = statuslen - MPTSAS_GET_ITEM_OFF(
4044 4047 struct scsi_arq_status, sts_sensedata);
4045 4048 cmd->cmd_rqslen = (uchar_t)senselength;
4046 4049
4047 4050 ap.a_hba_tran = mpt->m_tran;
4048 4051 ap.a_target = 0;
4049 4052 ap.a_lun = 0;
4050 4053
4051 4054 cmd->cmd_ext_arq_buf = scsi_alloc_consistent_buf(&ap,
4052 4055 (struct buf *)NULL, senselength, B_READ,
4053 4056 callback, NULL);
4054 4057
4055 4058 if (cmd->cmd_ext_arq_buf == NULL) {
4056 4059 goto fail;
4057 4060 }
4058 4061 /*
4059 4062 * allocate a extern arq handle and bind the buf
4060 4063 */
4061 4064 ext_arq_dma_attr = mpt->m_msg_dma_attr;
4062 4065 ext_arq_dma_attr.dma_attr_sgllen = 1;
4063 4066 if ((ddi_dma_alloc_handle(mpt->m_dip,
4064 4067 &ext_arq_dma_attr, callback,
4065 4068 NULL, &cmd->cmd_ext_arqhandle)) != DDI_SUCCESS) {
4066 4069 goto fail;
4067 4070 }
4068 4071
4069 4072 if (ddi_dma_buf_bind_handle(cmd->cmd_ext_arqhandle,
4070 4073 cmd->cmd_ext_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
4071 4074 callback, NULL, &cmd->cmd_ext_arqcookie,
4072 4075 &cookiec)
4073 4076 != DDI_SUCCESS) {
4074 4077 goto fail;
4075 4078 }
4076 4079 cmd->cmd_flags |= CFLAG_EXTARQBUFVALID;
4077 4080 }
4078 4081 return (0);
4079 4082 fail:
4080 4083 mptsas_pkt_destroy_extern(mpt, cmd);
4081 4084 return (1);
4082 4085 }
4083 4086
4084 4087 /*
4085 4088 * deallocate external pkt space and deallocate the pkt
4086 4089 */
4087 4090 static void
4088 4091 mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd)
4089 4092 {
4090 4093 NDBG3(("mptsas_pkt_destroy_extern: cmd=0x%p", (void *)cmd));
4091 4094
4092 4095 if (cmd->cmd_flags & CFLAG_FREE) {
4093 4096 mptsas_log(mpt, CE_PANIC,
4094 4097 "mptsas_pkt_destroy_extern: freeing free packet");
4095 4098 _NOTE(NOT_REACHED)
4096 4099 /* NOTREACHED */
4097 4100 }
4098 4101 if (cmd->cmd_flags & CFLAG_CDBEXTERN) {
4099 4102 kmem_free(cmd->cmd_pkt->pkt_cdbp, (size_t)cmd->cmd_cdblen);
4100 4103 }
4101 4104 if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
4102 4105 kmem_free(cmd->cmd_pkt->pkt_scbp, (size_t)cmd->cmd_scblen);
4103 4106 if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4104 4107 (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4105 4108 }
4106 4109 if (cmd->cmd_ext_arqhandle) {
4107 4110 ddi_dma_free_handle(&cmd->cmd_ext_arqhandle);
4108 4111 cmd->cmd_ext_arqhandle = NULL;
4109 4112 }
4110 4113 if (cmd->cmd_ext_arq_buf)
4111 4114 scsi_free_consistent_buf(cmd->cmd_ext_arq_buf);
4112 4115 }
4113 4116 if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
4114 4117 kmem_free(cmd->cmd_pkt->pkt_private, (size_t)cmd->cmd_privlen);
4115 4118 }
4116 4119 cmd->cmd_flags = CFLAG_FREE;
4117 4120 kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
4118 4121 }
4119 4122
4120 4123 /*
4121 4124 * tran_sync_pkt(9E) - explicit DMA synchronization
4122 4125 */
4123 4126 /*ARGSUSED*/
4124 4127 static void
4125 4128 mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
4126 4129 {
4127 4130 mptsas_cmd_t *cmd = PKT2CMD(pkt);
4128 4131
4129 4132 NDBG3(("mptsas_scsi_sync_pkt: target=%d, pkt=0x%p",
4130 4133 ap->a_target, (void *)pkt));
4131 4134
4132 4135 if (cmd->cmd_dmahandle) {
4133 4136 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4134 4137 (cmd->cmd_flags & CFLAG_DMASEND) ?
4135 4138 DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
4136 4139 }
4137 4140 }
4138 4141
4139 4142 /*
4140 4143 * tran_dmafree(9E) - deallocate DMA resources allocated for command
4141 4144 */
4142 4145 /*ARGSUSED*/
4143 4146 static void
4144 4147 mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
4145 4148 {
4146 4149 mptsas_cmd_t *cmd = PKT2CMD(pkt);
4147 4150 mptsas_t *mpt = ADDR2MPT(ap);
4148 4151
4149 4152 NDBG3(("mptsas_scsi_dmafree: target=%d pkt=0x%p",
4150 4153 ap->a_target, (void *)pkt));
4151 4154
4152 4155 if (cmd->cmd_flags & CFLAG_DMAVALID) {
4153 4156 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
4154 4157 cmd->cmd_flags &= ~CFLAG_DMAVALID;
4155 4158 }
4156 4159
4157 4160 if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4158 4161 (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4159 4162 cmd->cmd_flags &= ~CFLAG_EXTARQBUFVALID;
4160 4163 }
4161 4164
4162 4165 mptsas_free_extra_sgl_frame(mpt, cmd);
4163 4166 }
4164 4167
4165 4168 static void
4166 4169 mptsas_pkt_comp(struct scsi_pkt *pkt, mptsas_cmd_t *cmd)
4167 4170 {
4168 4171 if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
4169 4172 (!(cmd->cmd_flags & CFLAG_DMASEND))) {
4170 4173 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4171 4174 DDI_DMA_SYNC_FORCPU);
4172 4175 }
4173 4176 (*pkt->pkt_comp)(pkt);
4174 4177 }
4175 4178
4176 4179 static void
4177 4180 mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd, uint32_t *control,
4178 4181 pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4179 4182 {
4180 4183 uint_t cookiec;
4181 4184 mptti_t *dmap;
4182 4185 uint32_t flags;
4183 4186 pMpi2SGESimple64_t sge;
4184 4187 pMpi2SGEChain64_t sgechain;
4185 4188 ASSERT(cmd->cmd_flags & CFLAG_DMAVALID);
4186 4189
4187 4190 /*
4188 4191 * Save the number of entries in the DMA
4189 4192 * Scatter/Gather list
4190 4193 */
4191 4194 cookiec = cmd->cmd_cookiec;
4192 4195
4193 4196 NDBG1(("mptsas_sge_setup: cookiec=%d", cookiec));
4194 4197
4195 4198 /*
4196 4199 * Set read/write bit in control.
4197 4200 */
4198 4201 if (cmd->cmd_flags & CFLAG_DMASEND) {
4199 4202 *control |= MPI2_SCSIIO_CONTROL_WRITE;
4200 4203 } else {
4201 4204 *control |= MPI2_SCSIIO_CONTROL_READ;
4202 4205 }
4203 4206
4204 4207 ddi_put32(acc_hdl, &frame->DataLength, cmd->cmd_dmacount);
4205 4208
4206 4209 /*
4207 4210 * We have 2 cases here. First where we can fit all the
4208 4211 * SG elements into the main frame, and the case
4209 4212 * where we can't.
4210 4213 * If we have more cookies than we can attach to a frame
4211 4214 * we will need to use a chain element to point
4212 4215 * a location of memory where the rest of the S/G
4213 4216 * elements reside.
4214 4217 */
4215 4218 if (cookiec <= MPTSAS_MAX_FRAME_SGES64(mpt)) {
4216 4219 dmap = cmd->cmd_sg;
4217 4220 sge = (pMpi2SGESimple64_t)(&frame->SGL);
4218 4221 while (cookiec--) {
4219 4222 ddi_put32(acc_hdl,
4220 4223 &sge->Address.Low, dmap->addr.address64.Low);
4221 4224 ddi_put32(acc_hdl,
4222 4225 &sge->Address.High, dmap->addr.address64.High);
4223 4226 ddi_put32(acc_hdl, &sge->FlagsLength,
4224 4227 dmap->count);
4225 4228 flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4226 4229 flags |= ((uint32_t)
4227 4230 (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4228 4231 MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4229 4232 MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4230 4233 MPI2_SGE_FLAGS_SHIFT);
4231 4234
4232 4235 /*
4233 4236 * If this is the last cookie, we set the flags
4234 4237 * to indicate so
4235 4238 */
4236 4239 if (cookiec == 0) {
4237 4240 flags |=
4238 4241 ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT
4239 4242 | MPI2_SGE_FLAGS_END_OF_BUFFER
4240 4243 | MPI2_SGE_FLAGS_END_OF_LIST) <<
4241 4244 MPI2_SGE_FLAGS_SHIFT);
4242 4245 }
4243 4246 if (cmd->cmd_flags & CFLAG_DMASEND) {
4244 4247 flags |= (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4245 4248 MPI2_SGE_FLAGS_SHIFT);
4246 4249 } else {
4247 4250 flags |= (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4248 4251 MPI2_SGE_FLAGS_SHIFT);
4249 4252 }
4250 4253 ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4251 4254 dmap++;
4252 4255 sge++;
4253 4256 }
4254 4257 } else {
4255 4258 /*
4256 4259 * Hereby we start to deal with multiple frames.
4257 4260 * The process is as follows:
4258 4261 * 1. Determine how many frames are needed for SGL element
4259 4262 * storage; Note that all frames are stored in contiguous
4260 4263 * memory space and in 64-bit DMA mode each element is
4261 4264 * 3 double-words (12 bytes) long.
4262 4265 * 2. Fill up the main frame. We need to do this separately
4263 4266 * since it contains the SCSI IO request header and needs
4264 4267 * dedicated processing. Note that the last 4 double-words
4265 4268 * of the SCSI IO header is for SGL element storage
4266 4269 * (MPI2_SGE_IO_UNION).
4267 4270 * 3. Fill the chain element in the main frame, so the DMA
4268 4271 * engine can use the following frames.
4269 4272 * 4. Enter a loop to fill the remaining frames. Note that the
4270 4273 * last frame contains no chain element. The remaining
4271 4274 * frames go into the mpt SGL buffer allocated on the fly,
4272 4275 * not immediately following the main message frame, as in
4273 4276 * Gen1.
4274 4277 * Some restrictions:
4275 4278 * 1. For 64-bit DMA, the simple element and chain element
4276 4279 * are both of 3 double-words (12 bytes) in size, even
4277 4280 * though all frames are stored in the first 4G of mem
4278 4281 * range and the higher 32-bits of the address are always 0.
4279 4282 * 2. On some controllers (like the 1064/1068), a frame can
4280 4283 * hold SGL elements with the last 1 or 2 double-words
4281 4284 * (4 or 8 bytes) un-used. On these controllers, we should
4282 4285 * recognize that there's not enough room for another SGL
4283 4286 * element and move the sge pointer to the next frame.
4284 4287 */
4285 4288 int i, j, k, l, frames, sgemax;
4286 4289 int temp;
4287 4290 uint8_t chainflags;
4288 4291 uint16_t chainlength;
4289 4292 mptsas_cache_frames_t *p;
4290 4293
4291 4294 /*
4292 4295 * Sgemax is the number of SGE's that will fit
4293 4296 * each extra frame and frames is total
4294 4297 * number of frames we'll need. 1 sge entry per
4295 4298 * frame is reseverd for the chain element thus the -1 below.
4296 4299 */
4297 4300 sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_SGE_SIMPLE64))
4298 4301 - 1);
4299 4302 temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4300 4303
4301 4304 /*
4302 4305 * A little check to see if we need to round up the number
4303 4306 * of frames we need
4304 4307 */
4305 4308 if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4306 4309 sgemax) > 1) {
4307 4310 frames = (temp + 1);
4308 4311 } else {
4309 4312 frames = temp;
4310 4313 }
4311 4314 dmap = cmd->cmd_sg;
4312 4315 sge = (pMpi2SGESimple64_t)(&frame->SGL);
4313 4316
4314 4317 /*
4315 4318 * First fill in the main frame
4316 4319 */
4317 4320 for (j = 1; j < MPTSAS_MAX_FRAME_SGES64(mpt); j++) {
4318 4321 ddi_put32(acc_hdl, &sge->Address.Low,
4319 4322 dmap->addr.address64.Low);
4320 4323 ddi_put32(acc_hdl, &sge->Address.High,
4321 4324 dmap->addr.address64.High);
4322 4325 ddi_put32(acc_hdl, &sge->FlagsLength, dmap->count);
4323 4326 flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4324 4327 flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4325 4328 MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4326 4329 MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4327 4330 MPI2_SGE_FLAGS_SHIFT);
4328 4331
4329 4332 /*
4330 4333 * If this is the last SGE of this frame
4331 4334 * we set the end of list flag
4332 4335 */
4333 4336 if (j == (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) {
4334 4337 flags |= ((uint32_t)
4335 4338 (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4336 4339 MPI2_SGE_FLAGS_SHIFT);
4337 4340 }
4338 4341 if (cmd->cmd_flags & CFLAG_DMASEND) {
4339 4342 flags |=
4340 4343 (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4341 4344 MPI2_SGE_FLAGS_SHIFT);
4342 4345 } else {
4343 4346 flags |=
4344 4347 (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4345 4348 MPI2_SGE_FLAGS_SHIFT);
4346 4349 }
4347 4350 ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4348 4351 dmap++;
4349 4352 sge++;
4350 4353 }
4351 4354
4352 4355 /*
4353 4356 * Fill in the chain element in the main frame.
4354 4357 * About calculation on ChainOffset:
4355 4358 * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4356 4359 * in the end reserved for SGL element storage
4357 4360 * (MPI2_SGE_IO_UNION); we should count it in our
4358 4361 * calculation. See its definition in the header file.
4359 4362 * 2. Constant j is the counter of the current SGL element
4360 4363 * that will be processed, and (j - 1) is the number of
4361 4364 * SGL elements that have been processed (stored in the
4362 4365 * main frame).
4363 4366 * 3. ChainOffset value should be in units of double-words (4
4364 4367 * bytes) so the last value should be divided by 4.
4365 4368 */
4366 4369 ddi_put8(acc_hdl, &frame->ChainOffset,
4367 4370 (sizeof (MPI2_SCSI_IO_REQUEST) -
4368 4371 sizeof (MPI2_SGE_IO_UNION) +
4369 4372 (j - 1) * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4370 4373 sgechain = (pMpi2SGEChain64_t)sge;
4371 4374 chainflags = (MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4372 4375 MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4373 4376 MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4374 4377 ddi_put8(acc_hdl, &sgechain->Flags, chainflags);
4375 4378
4376 4379 /*
4377 4380 * The size of the next frame is the accurate size of space
4378 4381 * (in bytes) used to store the SGL elements. j is the counter
4379 4382 * of SGL elements. (j - 1) is the number of SGL elements that
4380 4383 * have been processed (stored in frames).
4381 4384 */
4382 4385 if (frames >= 2) {
4383 4386 chainlength = mpt->m_req_frame_size /
4384 4387 sizeof (MPI2_SGE_SIMPLE64) *
4385 4388 sizeof (MPI2_SGE_SIMPLE64);
4386 4389 } else {
4387 4390 chainlength = ((cookiec - (j - 1)) *
4388 4391 sizeof (MPI2_SGE_SIMPLE64));
4389 4392 }
4390 4393
4391 4394 p = cmd->cmd_extra_frames;
4392 4395
4393 4396 ddi_put16(acc_hdl, &sgechain->Length, chainlength);
4394 4397 ddi_put32(acc_hdl, &sgechain->Address.Low,
4395 4398 p->m_phys_addr);
4396 4399 /* SGL is allocated in the first 4G mem range */
4397 4400 ddi_put32(acc_hdl, &sgechain->Address.High, 0);
4398 4401
4399 4402 /*
4400 4403 * If there are more than 2 frames left we have to
4401 4404 * fill in the next chain offset to the location of
4402 4405 * the chain element in the next frame.
4403 4406 * sgemax is the number of simple elements in an extra
4404 4407 * frame. Note that the value NextChainOffset should be
4405 4408 * in double-words (4 bytes).
4406 4409 */
4407 4410 if (frames >= 2) {
4408 4411 ddi_put8(acc_hdl, &sgechain->NextChainOffset,
4409 4412 (sgemax * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4410 4413 } else {
4411 4414 ddi_put8(acc_hdl, &sgechain->NextChainOffset, 0);
4412 4415 }
4413 4416
4414 4417 /*
4415 4418 * Jump to next frame;
4416 4419 * Starting here, chain buffers go into the per command SGL.
4417 4420 * This buffer is allocated when chain buffers are needed.
4418 4421 */
4419 4422 sge = (pMpi2SGESimple64_t)p->m_frames_addr;
4420 4423 i = cookiec;
4421 4424
4422 4425 /*
4423 4426 * Start filling in frames with SGE's. If we
4424 4427 * reach the end of frame and still have SGE's
4425 4428 * to fill we need to add a chain element and
4426 4429 * use another frame. j will be our counter
4427 4430 * for what cookie we are at and i will be
4428 4431 * the total cookiec. k is the current frame
4429 4432 */
4430 4433 for (k = 1; k <= frames; k++) {
4431 4434 for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4432 4435
4433 4436 /*
4434 4437 * If we have reached the end of frame
4435 4438 * and we have more SGE's to fill in
4436 4439 * we have to fill the final entry
4437 4440 * with a chain element and then
4438 4441 * continue to the next frame
4439 4442 */
4440 4443 if ((l == (sgemax + 1)) && (k != frames)) {
4441 4444 sgechain = (pMpi2SGEChain64_t)sge;
4442 4445 j--;
4443 4446 chainflags = (
4444 4447 MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4445 4448 MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4446 4449 MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4447 4450 ddi_put8(p->m_acc_hdl,
4448 4451 &sgechain->Flags, chainflags);
4449 4452 /*
4450 4453 * k is the frame counter and (k + 1)
4451 4454 * is the number of the next frame.
4452 4455 * Note that frames are in contiguous
4453 4456 * memory space.
4454 4457 */
4455 4458 ddi_put32(p->m_acc_hdl,
4456 4459 &sgechain->Address.Low,
4457 4460 (p->m_phys_addr +
4458 4461 (mpt->m_req_frame_size * k)));
4459 4462 ddi_put32(p->m_acc_hdl,
4460 4463 &sgechain->Address.High, 0);
4461 4464
4462 4465 /*
4463 4466 * If there are more than 2 frames left
4464 4467 * we have to next chain offset to
4465 4468 * the location of the chain element
4466 4469 * in the next frame and fill in the
4467 4470 * length of the next chain
4468 4471 */
4469 4472 if ((frames - k) >= 2) {
4470 4473 ddi_put8(p->m_acc_hdl,
4471 4474 &sgechain->NextChainOffset,
4472 4475 (sgemax *
4473 4476 sizeof (MPI2_SGE_SIMPLE64))
4474 4477 >> 2);
4475 4478 ddi_put16(p->m_acc_hdl,
4476 4479 &sgechain->Length,
4477 4480 mpt->m_req_frame_size /
4478 4481 sizeof (MPI2_SGE_SIMPLE64) *
4479 4482 sizeof (MPI2_SGE_SIMPLE64));
4480 4483 } else {
4481 4484 /*
4482 4485 * This is the last frame. Set
4483 4486 * the NextChainOffset to 0 and
4484 4487 * Length is the total size of
4485 4488 * all remaining simple elements
4486 4489 */
4487 4490 ddi_put8(p->m_acc_hdl,
4488 4491 &sgechain->NextChainOffset,
4489 4492 0);
4490 4493 ddi_put16(p->m_acc_hdl,
4491 4494 &sgechain->Length,
4492 4495 (cookiec - j) *
4493 4496 sizeof (MPI2_SGE_SIMPLE64));
4494 4497 }
4495 4498
4496 4499 /* Jump to the next frame */
4497 4500 sge = (pMpi2SGESimple64_t)
4498 4501 ((char *)p->m_frames_addr +
4499 4502 (int)mpt->m_req_frame_size * k);
4500 4503
4501 4504 continue;
4502 4505 }
4503 4506
4504 4507 ddi_put32(p->m_acc_hdl,
4505 4508 &sge->Address.Low,
4506 4509 dmap->addr.address64.Low);
4507 4510 ddi_put32(p->m_acc_hdl,
4508 4511 &sge->Address.High,
4509 4512 dmap->addr.address64.High);
4510 4513 ddi_put32(p->m_acc_hdl,
4511 4514 &sge->FlagsLength, dmap->count);
4512 4515 flags = ddi_get32(p->m_acc_hdl,
4513 4516 &sge->FlagsLength);
4514 4517 flags |= ((uint32_t)(
4515 4518 MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4516 4519 MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4517 4520 MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4518 4521 MPI2_SGE_FLAGS_SHIFT);
4519 4522
4520 4523 /*
4521 4524 * If we are at the end of the frame and
4522 4525 * there is another frame to fill in
4523 4526 * we set the last simple element as last
4524 4527 * element
4525 4528 */
4526 4529 if ((l == sgemax) && (k != frames)) {
4527 4530 flags |= ((uint32_t)
4528 4531 (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4529 4532 MPI2_SGE_FLAGS_SHIFT);
4530 4533 }
4531 4534
4532 4535 /*
4533 4536 * If this is the final cookie we
4534 4537 * indicate it by setting the flags
4535 4538 */
4536 4539 if (j == i) {
4537 4540 flags |= ((uint32_t)
4538 4541 (MPI2_SGE_FLAGS_LAST_ELEMENT |
4539 4542 MPI2_SGE_FLAGS_END_OF_BUFFER |
4540 4543 MPI2_SGE_FLAGS_END_OF_LIST) <<
4541 4544 MPI2_SGE_FLAGS_SHIFT);
4542 4545 }
4543 4546 if (cmd->cmd_flags & CFLAG_DMASEND) {
4544 4547 flags |=
4545 4548 (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4546 4549 MPI2_SGE_FLAGS_SHIFT);
4547 4550 } else {
4548 4551 flags |=
4549 4552 (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4550 4553 MPI2_SGE_FLAGS_SHIFT);
4551 4554 }
4552 4555 ddi_put32(p->m_acc_hdl,
4553 4556 &sge->FlagsLength, flags);
4554 4557 dmap++;
4555 4558 sge++;
4556 4559 }
4557 4560 }
4558 4561
4559 4562 /*
4560 4563 * Sync DMA with the chain buffers that were just created
4561 4564 */
4562 4565 (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4563 4566 }
4564 4567 }
4565 4568
4566 4569 /*
4567 4570 * Interrupt handling
4568 4571 * Utility routine. Poll for status of a command sent to HBA
4569 4572 * without interrupts (a FLAG_NOINTR command).
4570 4573 */
4571 4574 int
4572 4575 mptsas_poll(mptsas_t *mpt, mptsas_cmd_t *poll_cmd, int polltime)
4573 4576 {
4574 4577 int rval = TRUE;
4575 4578
4576 4579 NDBG5(("mptsas_poll: cmd=0x%p", (void *)poll_cmd));
4577 4580
4578 4581 if ((poll_cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
4579 4582 mptsas_restart_hba(mpt);
4580 4583 }
4581 4584
4582 4585 /*
4583 4586 * Wait, using drv_usecwait(), long enough for the command to
4584 4587 * reasonably return from the target if the target isn't
4585 4588 * "dead". A polled command may well be sent from scsi_poll, and
4586 4589 * there are retries built in to scsi_poll if the transport
4587 4590 * accepted the packet (TRAN_ACCEPT). scsi_poll waits 1 second
4588 4591 * and retries the transport up to scsi_poll_busycnt times
4589 4592 * (currently 60) if
4590 4593 * 1. pkt_reason is CMD_INCOMPLETE and pkt_state is 0, or
4591 4594 * 2. pkt_reason is CMD_CMPLT and *pkt_scbp has STATUS_BUSY
4592 4595 *
4593 4596 * limit the waiting to avoid a hang in the event that the
4594 4597 * cmd never gets started but we are still receiving interrupts
4595 4598 */
4596 4599 while (!(poll_cmd->cmd_flags & CFLAG_FINISHED)) {
4597 4600 if (mptsas_wait_intr(mpt, polltime) == FALSE) {
4598 4601 NDBG5(("mptsas_poll: command incomplete"));
4599 4602 rval = FALSE;
4600 4603 break;
4601 4604 }
4602 4605 }
4603 4606
4604 4607 if (rval == FALSE) {
4605 4608
4606 4609 /*
4607 4610 * this isn't supposed to happen, the hba must be wedged
4608 4611 * Mark this cmd as a timeout.
4609 4612 */
4610 4613 mptsas_set_pkt_reason(mpt, poll_cmd, CMD_TIMEOUT,
4611 4614 (STAT_TIMEOUT|STAT_ABORTED));
4612 4615
4613 4616 if (poll_cmd->cmd_queued == FALSE) {
4614 4617
4615 4618 NDBG5(("mptsas_poll: not on waitq"));
4616 4619
4617 4620 poll_cmd->cmd_pkt->pkt_state |=
4618 4621 (STATE_GOT_BUS|STATE_GOT_TARGET|STATE_SENT_CMD);
4619 4622 } else {
4620 4623
4621 4624 /* find and remove it from the waitq */
4622 4625 NDBG5(("mptsas_poll: delete from waitq"));
4623 4626 mptsas_waitq_delete(mpt, poll_cmd);
4624 4627 }
4625 4628
4626 4629 }
4627 4630 mptsas_fma_check(mpt, poll_cmd);
4628 4631 NDBG5(("mptsas_poll: done"));
4629 4632 return (rval);
4630 4633 }
4631 4634
4632 4635 /*
4633 4636 * Used for polling cmds and TM function
4634 4637 */
4635 4638 static int
4636 4639 mptsas_wait_intr(mptsas_t *mpt, int polltime)
4637 4640 {
4638 4641 int cnt;
4639 4642 pMpi2ReplyDescriptorsUnion_t reply_desc_union;
4640 4643 uint32_t int_mask;
4641 4644
4642 4645 NDBG5(("mptsas_wait_intr"));
4643 4646
4644 4647 mpt->m_polled_intr = 1;
4645 4648
4646 4649 /*
4647 4650 * Get the current interrupt mask and disable interrupts. When
4648 4651 * re-enabling ints, set mask to saved value.
4649 4652 */
4650 4653 int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
4651 4654 MPTSAS_DISABLE_INTR(mpt);
4652 4655
4653 4656 /*
4654 4657 * Keep polling for at least (polltime * 1000) seconds
4655 4658 */
4656 4659 for (cnt = 0; cnt < polltime; cnt++) {
4657 4660 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
4658 4661 DDI_DMA_SYNC_FORCPU);
4659 4662
4660 4663 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
4661 4664 MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
4662 4665
4663 4666 if (ddi_get32(mpt->m_acc_post_queue_hdl,
4664 4667 &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
4665 4668 ddi_get32(mpt->m_acc_post_queue_hdl,
4666 4669 &reply_desc_union->Words.High) == 0xFFFFFFFF) {
4667 4670 drv_usecwait(1000);
4668 4671 continue;
4669 4672 }
4670 4673
4671 4674 /*
4672 4675 * The reply is valid, process it according to its
4673 4676 * type.
4674 4677 */
4675 4678 mptsas_process_intr(mpt, reply_desc_union);
4676 4679
4677 4680 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
4678 4681 mpt->m_post_index = 0;
4679 4682 }
4680 4683
4681 4684 /*
4682 4685 * Update the global reply index
4683 4686 */
4684 4687 ddi_put32(mpt->m_datap,
4685 4688 &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
4686 4689 mpt->m_polled_intr = 0;
4687 4690
4688 4691 /*
4689 4692 * Re-enable interrupts and quit.
4690 4693 */
4691 4694 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask,
4692 4695 int_mask);
4693 4696 return (TRUE);
4694 4697
4695 4698 }
4696 4699
4697 4700 /*
4698 4701 * Clear polling flag, re-enable interrupts and quit.
4699 4702 */
4700 4703 mpt->m_polled_intr = 0;
4701 4704 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
4702 4705 return (FALSE);
4703 4706 }
4704 4707
4705 4708 static void
4706 4709 mptsas_handle_scsi_io_success(mptsas_t *mpt,
4707 4710 pMpi2ReplyDescriptorsUnion_t reply_desc)
4708 4711 {
4709 4712 pMpi2SCSIIOSuccessReplyDescriptor_t scsi_io_success;
4710 4713 uint16_t SMID;
4711 4714 mptsas_slots_t *slots = mpt->m_active;
4712 4715 mptsas_cmd_t *cmd = NULL;
4713 4716 struct scsi_pkt *pkt;
4714 4717
4715 4718 ASSERT(mutex_owned(&mpt->m_mutex));
4716 4719
4717 4720 scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
4718 4721 SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &scsi_io_success->SMID);
4719 4722
4720 4723 /*
4721 4724 * This is a success reply so just complete the IO. First, do a sanity
4722 4725 * check on the SMID. The final slot is used for TM requests, which
4723 4726 * would not come into this reply handler.
4724 4727 */
4725 4728 if ((SMID == 0) || (SMID > slots->m_n_normal)) {
4726 4729 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
4727 4730 SMID);
4728 4731 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4729 4732 return;
4730 4733 }
4731 4734
4732 4735 cmd = slots->m_slot[SMID];
4733 4736
4734 4737 /*
4735 4738 * print warning and return if the slot is empty
4736 4739 */
4737 4740 if (cmd == NULL) {
4738 4741 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
4739 4742 "in slot %d", SMID);
4740 4743 return;
4741 4744 }
4742 4745
4743 4746 pkt = CMD2PKT(cmd);
4744 4747 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
4745 4748 STATE_GOT_STATUS);
4746 4749 if (cmd->cmd_flags & CFLAG_DMAVALID) {
4747 4750 pkt->pkt_state |= STATE_XFERRED_DATA;
4748 4751 }
4749 4752 pkt->pkt_resid = 0;
4750 4753
4751 4754 if (cmd->cmd_flags & CFLAG_PASSTHRU) {
4752 4755 cmd->cmd_flags |= CFLAG_FINISHED;
4753 4756 cv_broadcast(&mpt->m_passthru_cv);
4754 4757 return;
4755 4758 } else {
4756 4759 mptsas_remove_cmd(mpt, cmd);
4757 4760 }
4758 4761
4759 4762 if (cmd->cmd_flags & CFLAG_RETRY) {
4760 4763 /*
4761 4764 * The target returned QFULL or busy, do not add tihs
4762 4765 * pkt to the doneq since the hba will retry
4763 4766 * this cmd.
4764 4767 *
4765 4768 * The pkt has already been resubmitted in
4766 4769 * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
4767 4770 * Remove this cmd_flag here.
4768 4771 */
4769 4772 cmd->cmd_flags &= ~CFLAG_RETRY;
4770 4773 } else {
4771 4774 mptsas_doneq_add(mpt, cmd);
4772 4775 }
4773 4776 }
4774 4777
4775 4778 static void
4776 4779 mptsas_handle_address_reply(mptsas_t *mpt,
4777 4780 pMpi2ReplyDescriptorsUnion_t reply_desc)
4778 4781 {
4779 4782 pMpi2AddressReplyDescriptor_t address_reply;
4780 4783 pMPI2DefaultReply_t reply;
4781 4784 mptsas_fw_diagnostic_buffer_t *pBuffer;
4782 4785 uint32_t reply_addr;
4783 4786 uint16_t SMID, iocstatus;
4784 4787 mptsas_slots_t *slots = mpt->m_active;
4785 4788 mptsas_cmd_t *cmd = NULL;
4786 4789 uint8_t function, buffer_type;
4787 4790 m_replyh_arg_t *args;
4788 4791 int reply_frame_no;
4789 4792
4790 4793 ASSERT(mutex_owned(&mpt->m_mutex));
4791 4794
4792 4795 address_reply = (pMpi2AddressReplyDescriptor_t)reply_desc;
4793 4796 reply_addr = ddi_get32(mpt->m_acc_post_queue_hdl,
4794 4797 &address_reply->ReplyFrameAddress);
4795 4798 SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &address_reply->SMID);
4796 4799
4797 4800 /*
4798 4801 * If reply frame is not in the proper range we should ignore this
4799 4802 * message and exit the interrupt handler.
4800 4803 */
4801 4804 if ((reply_addr < mpt->m_reply_frame_dma_addr) ||
4802 4805 (reply_addr >= (mpt->m_reply_frame_dma_addr +
4803 4806 (mpt->m_reply_frame_size * mpt->m_max_replies))) ||
4804 4807 ((reply_addr - mpt->m_reply_frame_dma_addr) %
4805 4808 mpt->m_reply_frame_size != 0)) {
4806 4809 mptsas_log(mpt, CE_WARN, "?Received invalid reply frame "
4807 4810 "address 0x%x\n", reply_addr);
4808 4811 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4809 4812 return;
4810 4813 }
4811 4814
4812 4815 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
4813 4816 DDI_DMA_SYNC_FORCPU);
4814 4817 reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + (reply_addr -
4815 4818 mpt->m_reply_frame_dma_addr));
4816 4819 function = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->Function);
4817 4820
4818 4821 /*
4819 4822 * don't get slot information and command for events since these values
4820 4823 * don't exist
4821 4824 */
4822 4825 if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
4823 4826 (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
4824 4827 /*
4825 4828 * This could be a TM reply, which use the last allocated SMID,
4826 4829 * so allow for that.
4827 4830 */
4828 4831 if ((SMID == 0) || (SMID > (slots->m_n_normal + 1))) {
4829 4832 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of "
4830 4833 "%d\n", SMID);
4831 4834 ddi_fm_service_impact(mpt->m_dip,
4832 4835 DDI_SERVICE_UNAFFECTED);
4833 4836 return;
4834 4837 }
4835 4838
4836 4839 cmd = slots->m_slot[SMID];
4837 4840
4838 4841 /*
4839 4842 * print warning and return if the slot is empty
4840 4843 */
4841 4844 if (cmd == NULL) {
4842 4845 mptsas_log(mpt, CE_WARN, "?NULL command for address "
4843 4846 "reply in slot %d", SMID);
4844 4847 return;
4845 4848 }
4846 4849 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
4847 4850 (cmd->cmd_flags & CFLAG_CONFIG) ||
4848 4851 (cmd->cmd_flags & CFLAG_FW_DIAG)) {
4849 4852 cmd->cmd_rfm = reply_addr;
4850 4853 cmd->cmd_flags |= CFLAG_FINISHED;
4851 4854 cv_broadcast(&mpt->m_passthru_cv);
4852 4855 cv_broadcast(&mpt->m_config_cv);
4853 4856 cv_broadcast(&mpt->m_fw_diag_cv);
4854 4857 return;
4855 4858 } else if (!(cmd->cmd_flags & CFLAG_FW_CMD)) {
4856 4859 mptsas_remove_cmd(mpt, cmd);
4857 4860 }
4858 4861 NDBG31(("\t\tmptsas_process_intr: slot=%d", SMID));
4859 4862 }
4860 4863 /*
4861 4864 * Depending on the function, we need to handle
4862 4865 * the reply frame (and cmd) differently.
4863 4866 */
4864 4867 switch (function) {
4865 4868 case MPI2_FUNCTION_SCSI_IO_REQUEST:
4866 4869 mptsas_check_scsi_io_error(mpt, (pMpi2SCSIIOReply_t)reply, cmd);
4867 4870 break;
4868 4871 case MPI2_FUNCTION_SCSI_TASK_MGMT:
4869 4872 cmd->cmd_rfm = reply_addr;
4870 4873 mptsas_check_task_mgt(mpt, (pMpi2SCSIManagementReply_t)reply,
4871 4874 cmd);
4872 4875 break;
4873 4876 case MPI2_FUNCTION_FW_DOWNLOAD:
4874 4877 cmd->cmd_flags |= CFLAG_FINISHED;
4875 4878 cv_signal(&mpt->m_fw_cv);
4876 4879 break;
4877 4880 case MPI2_FUNCTION_EVENT_NOTIFICATION:
4878 4881 reply_frame_no = (reply_addr - mpt->m_reply_frame_dma_addr) /
4879 4882 mpt->m_reply_frame_size;
4880 4883 args = &mpt->m_replyh_args[reply_frame_no];
4881 4884 args->mpt = (void *)mpt;
4882 4885 args->rfm = reply_addr;
4883 4886
4884 4887 /*
4885 4888 * Record the event if its type is enabled in
4886 4889 * this mpt instance by ioctl.
4887 4890 */
4888 4891 mptsas_record_event(args);
4889 4892
4890 4893 /*
4891 4894 * Handle time critical events
4892 4895 * NOT_RESPONDING/ADDED only now
4893 4896 */
4894 4897 if (mptsas_handle_event_sync(args) == DDI_SUCCESS) {
4895 4898 /*
4896 4899 * Would not return main process,
4897 4900 * just let taskq resolve ack action
4898 4901 * and ack would be sent in taskq thread
4899 4902 */
4900 4903 NDBG20(("send mptsas_handle_event_sync success"));
4901 4904 }
4902 4905
4903 4906 if (mpt->m_in_reset) {
4904 4907 NDBG20(("dropping event received during reset"));
4905 4908 return;
4906 4909 }
4907 4910
4908 4911 if ((ddi_taskq_dispatch(mpt->m_event_taskq, mptsas_handle_event,
4909 4912 (void *)args, DDI_NOSLEEP)) != DDI_SUCCESS) {
4910 4913 mptsas_log(mpt, CE_WARN, "No memory available"
4911 4914 "for dispatch taskq");
4912 4915 /*
4913 4916 * Return the reply frame to the free queue.
4914 4917 */
4915 4918 ddi_put32(mpt->m_acc_free_queue_hdl,
4916 4919 &((uint32_t *)(void *)
4917 4920 mpt->m_free_queue)[mpt->m_free_index], reply_addr);
4918 4921 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
4919 4922 DDI_DMA_SYNC_FORDEV);
4920 4923 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
4921 4924 mpt->m_free_index = 0;
4922 4925 }
4923 4926
4924 4927 ddi_put32(mpt->m_datap,
4925 4928 &mpt->m_reg->ReplyFreeHostIndex, mpt->m_free_index);
4926 4929 }
4927 4930 return;
4928 4931 case MPI2_FUNCTION_DIAG_BUFFER_POST:
4929 4932 /*
4930 4933 * If SMID is 0, this implies that the reply is due to a
4931 4934 * release function with a status that the buffer has been
4932 4935 * released. Set the buffer flags accordingly.
4933 4936 */
4934 4937 if (SMID == 0) {
4935 4938 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
4936 4939 &reply->IOCStatus);
4937 4940 buffer_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
4938 4941 &(((pMpi2DiagBufferPostReply_t)reply)->BufferType));
4939 4942 if (iocstatus == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) {
4940 4943 pBuffer =
4941 4944 &mpt->m_fw_diag_buffer_list[buffer_type];
4942 4945 pBuffer->valid_data = TRUE;
4943 4946 pBuffer->owned_by_firmware = FALSE;
4944 4947 pBuffer->immediate = FALSE;
4945 4948 }
4946 4949 } else {
4947 4950 /*
4948 4951 * Normal handling of diag post reply with SMID.
4949 4952 */
4950 4953 cmd = slots->m_slot[SMID];
4951 4954
4952 4955 /*
4953 4956 * print warning and return if the slot is empty
4954 4957 */
4955 4958 if (cmd == NULL) {
4956 4959 mptsas_log(mpt, CE_WARN, "?NULL command for "
4957 4960 "address reply in slot %d", SMID);
4958 4961 return;
4959 4962 }
4960 4963 cmd->cmd_rfm = reply_addr;
4961 4964 cmd->cmd_flags |= CFLAG_FINISHED;
4962 4965 cv_broadcast(&mpt->m_fw_diag_cv);
4963 4966 }
4964 4967 return;
4965 4968 default:
4966 4969 mptsas_log(mpt, CE_WARN, "Unknown function 0x%x ", function);
4967 4970 break;
4968 4971 }
4969 4972
4970 4973 /*
4971 4974 * Return the reply frame to the free queue.
4972 4975 */
4973 4976 ddi_put32(mpt->m_acc_free_queue_hdl,
4974 4977 &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
4975 4978 reply_addr);
4976 4979 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
4977 4980 DDI_DMA_SYNC_FORDEV);
4978 4981 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
4979 4982 mpt->m_free_index = 0;
4980 4983 }
4981 4984 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
4982 4985 mpt->m_free_index);
4983 4986
4984 4987 if (cmd->cmd_flags & CFLAG_FW_CMD)
4985 4988 return;
4986 4989
4987 4990 if (cmd->cmd_flags & CFLAG_RETRY) {
4988 4991 /*
4989 4992 * The target returned QFULL or busy, do not add tihs
4990 4993 * pkt to the doneq since the hba will retry
4991 4994 * this cmd.
4992 4995 *
4993 4996 * The pkt has already been resubmitted in
4994 4997 * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
4995 4998 * Remove this cmd_flag here.
4996 4999 */
4997 5000 cmd->cmd_flags &= ~CFLAG_RETRY;
4998 5001 } else {
4999 5002 mptsas_doneq_add(mpt, cmd);
5000 5003 }
5001 5004 }
5002 5005
5003 5006 static void
5004 5007 mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
5005 5008 mptsas_cmd_t *cmd)
5006 5009 {
5007 5010 uint8_t scsi_status, scsi_state;
5008 5011 uint16_t ioc_status;
5009 5012 uint32_t xferred, sensecount, responsedata, loginfo = 0;
5010 5013 struct scsi_pkt *pkt;
5011 5014 struct scsi_arq_status *arqstat;
5012 5015 struct buf *bp;
5013 5016 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
5014 5017 uint8_t *sensedata = NULL;
5015 5018
5016 5019 if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
5017 5020 (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
5018 5021 bp = cmd->cmd_ext_arq_buf;
5019 5022 } else {
5020 5023 bp = cmd->cmd_arq_buf;
5021 5024 }
5022 5025
5023 5026 scsi_status = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIStatus);
5024 5027 ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5025 5028 scsi_state = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIState);
5026 5029 xferred = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->TransferCount);
5027 5030 sensecount = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->SenseCount);
5028 5031 responsedata = ddi_get32(mpt->m_acc_reply_frame_hdl,
5029 5032 &reply->ResponseInfo);
5030 5033
5031 5034 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
5032 5035 loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
5033 5036 &reply->IOCLogInfo);
5034 5037 mptsas_log(mpt, CE_NOTE,
5035 5038 "?Log info 0x%x received for target %d.\n"
5036 5039 "\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5037 5040 loginfo, Tgt(cmd), scsi_status, ioc_status,
5038 5041 scsi_state);
5039 5042 }
5040 5043
5041 5044 NDBG31(("\t\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5042 5045 scsi_status, ioc_status, scsi_state));
5043 5046
5044 5047 pkt = CMD2PKT(cmd);
5045 5048 *(pkt->pkt_scbp) = scsi_status;
5046 5049
5047 5050 if (loginfo == 0x31170000) {
5048 5051 /*
5049 5052 * if loginfo PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY
5050 5053 * 0x31170000 comes, that means the device missing delay
5051 5054 * is in progressing, the command need retry later.
5052 5055 */
5053 5056 *(pkt->pkt_scbp) = STATUS_BUSY;
5054 5057 return;
5055 5058 }
5056 5059
5057 5060 if ((scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) &&
5058 5061 ((ioc_status & MPI2_IOCSTATUS_MASK) ==
5059 5062 MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE)) {
5060 5063 pkt->pkt_reason = CMD_INCOMPLETE;
5061 5064 pkt->pkt_state |= STATE_GOT_BUS;
5062 5065 if (ptgt->m_reset_delay == 0) {
5063 5066 mptsas_set_throttle(mpt, ptgt,
5064 5067 DRAIN_THROTTLE);
5065 5068 }
5066 5069 return;
5067 5070 }
5068 5071
5069 5072 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
5070 5073 responsedata &= 0x000000FF;
5071 5074 if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) {
5072 5075 mptsas_log(mpt, CE_NOTE, "Do not support the TLR\n");
5073 5076 pkt->pkt_reason = CMD_TLR_OFF;
5074 5077 return;
5075 5078 }
5076 5079 }
5077 5080
5078 5081
5079 5082 switch (scsi_status) {
5080 5083 case MPI2_SCSI_STATUS_CHECK_CONDITION:
5081 5084 pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5082 5085 arqstat = (void*)(pkt->pkt_scbp);
5083 5086 arqstat->sts_rqpkt_status = *((struct scsi_status *)
5084 5087 (pkt->pkt_scbp));
5085 5088 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
5086 5089 STATE_SENT_CMD | STATE_GOT_STATUS | STATE_ARQ_DONE);
5087 5090 if (cmd->cmd_flags & CFLAG_XARQ) {
5088 5091 pkt->pkt_state |= STATE_XARQ_DONE;
5089 5092 }
5090 5093 if (pkt->pkt_resid != cmd->cmd_dmacount) {
5091 5094 pkt->pkt_state |= STATE_XFERRED_DATA;
5092 5095 }
5093 5096 arqstat->sts_rqpkt_reason = pkt->pkt_reason;
5094 5097 arqstat->sts_rqpkt_state = pkt->pkt_state;
5095 5098 arqstat->sts_rqpkt_state |= STATE_XFERRED_DATA;
5096 5099 arqstat->sts_rqpkt_statistics = pkt->pkt_statistics;
5097 5100 sensedata = (uint8_t *)&arqstat->sts_sensedata;
5098 5101
5099 5102 bcopy((uchar_t *)bp->b_un.b_addr, sensedata,
5100 5103 ((cmd->cmd_rqslen >= sensecount) ? sensecount :
5101 5104 cmd->cmd_rqslen));
5102 5105 arqstat->sts_rqpkt_resid = (cmd->cmd_rqslen - sensecount);
5103 5106 cmd->cmd_flags |= CFLAG_CMDARQ;
5104 5107 /*
5105 5108 * Set proper status for pkt if autosense was valid
5106 5109 */
5107 5110 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
5108 5111 struct scsi_status zero_status = { 0 };
5109 5112 arqstat->sts_rqpkt_status = zero_status;
5110 5113 }
5111 5114
5112 5115 /*
5113 5116 * ASC=0x47 is parity error
5114 5117 * ASC=0x48 is initiator detected error received
5115 5118 */
5116 5119 if ((scsi_sense_key(sensedata) == KEY_ABORTED_COMMAND) &&
5117 5120 ((scsi_sense_asc(sensedata) == 0x47) ||
5118 5121 (scsi_sense_asc(sensedata) == 0x48))) {
5119 5122 mptsas_log(mpt, CE_NOTE, "Aborted_command!");
5120 5123 }
5121 5124
5122 5125 /*
5123 5126 * ASC/ASCQ=0x3F/0x0E means report_luns data changed
5124 5127 * ASC/ASCQ=0x25/0x00 means invalid lun
5125 5128 */
5126 5129 if (((scsi_sense_key(sensedata) == KEY_UNIT_ATTENTION) &&
5127 5130 (scsi_sense_asc(sensedata) == 0x3F) &&
5128 5131 (scsi_sense_ascq(sensedata) == 0x0E)) ||
5129 5132 ((scsi_sense_key(sensedata) == KEY_ILLEGAL_REQUEST) &&
5130 5133 (scsi_sense_asc(sensedata) == 0x25) &&
5131 5134 (scsi_sense_ascq(sensedata) == 0x00))) {
5132 5135 mptsas_topo_change_list_t *topo_node = NULL;
5133 5136
5134 5137 topo_node = kmem_zalloc(
5135 5138 sizeof (mptsas_topo_change_list_t),
5136 5139 KM_NOSLEEP);
5137 5140 if (topo_node == NULL) {
5138 5141 mptsas_log(mpt, CE_NOTE, "No memory"
5139 5142 "resource for handle SAS dynamic"
5140 5143 "reconfigure.\n");
5141 5144 break;
5142 5145 }
5143 5146 topo_node->mpt = mpt;
5144 5147 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
5145 5148 topo_node->un.phymask = ptgt->m_addr.mta_phymask;
5146 5149 topo_node->devhdl = ptgt->m_devhdl;
5147 5150 topo_node->object = (void *)ptgt;
5148 5151 topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
5149 5152
5150 5153 if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
5151 5154 mptsas_handle_dr,
5152 5155 (void *)topo_node,
5153 5156 DDI_NOSLEEP)) != DDI_SUCCESS) {
5154 5157 mptsas_log(mpt, CE_NOTE, "mptsas start taskq"
5155 5158 "for handle SAS dynamic reconfigure"
5156 5159 "failed. \n");
5157 5160 }
5158 5161 }
5159 5162 break;
5160 5163 case MPI2_SCSI_STATUS_GOOD:
5161 5164 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
5162 5165 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
5163 5166 pkt->pkt_reason = CMD_DEV_GONE;
5164 5167 pkt->pkt_state |= STATE_GOT_BUS;
5165 5168 if (ptgt->m_reset_delay == 0) {
5166 5169 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5167 5170 }
5168 5171 NDBG31(("lost disk for target%d, command:%x",
5169 5172 Tgt(cmd), pkt->pkt_cdbp[0]));
5170 5173 break;
5171 5174 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
5172 5175 NDBG31(("data overrun: xferred=%d", xferred));
5173 5176 NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5174 5177 pkt->pkt_reason = CMD_DATA_OVR;
5175 5178 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5176 5179 | STATE_SENT_CMD | STATE_GOT_STATUS
5177 5180 | STATE_XFERRED_DATA);
5178 5181 pkt->pkt_resid = 0;
5179 5182 break;
5180 5183 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
5181 5184 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
5182 5185 NDBG31(("data underrun: xferred=%d", xferred));
5183 5186 NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5184 5187 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5185 5188 | STATE_SENT_CMD | STATE_GOT_STATUS);
5186 5189 pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5187 5190 if (pkt->pkt_resid != cmd->cmd_dmacount) {
5188 5191 pkt->pkt_state |= STATE_XFERRED_DATA;
5189 5192 }
5190 5193 break;
5191 5194 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
5192 5195 mptsas_set_pkt_reason(mpt,
5193 5196 cmd, CMD_RESET, STAT_BUS_RESET);
5194 5197 break;
5195 5198 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
5196 5199 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
5197 5200 mptsas_set_pkt_reason(mpt,
5198 5201 cmd, CMD_RESET, STAT_DEV_RESET);
5199 5202 break;
5200 5203 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
5201 5204 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5202 5205 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
5203 5206 mptsas_set_pkt_reason(mpt,
5204 5207 cmd, CMD_TERMINATED, STAT_TERMINATED);
5205 5208 break;
5206 5209 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
5207 5210 case MPI2_IOCSTATUS_BUSY:
5208 5211 /*
5209 5212 * set throttles to drain
5210 5213 */
5211 5214 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
5212 5215 ptgt = refhash_next(mpt->m_targets, ptgt)) {
5213 5216 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5214 5217 }
5215 5218
5216 5219 /*
5217 5220 * retry command
5218 5221 */
5219 5222 cmd->cmd_flags |= CFLAG_RETRY;
5220 5223 cmd->cmd_pkt_flags |= FLAG_HEAD;
5221 5224
5222 5225 (void) mptsas_accept_pkt(mpt, cmd);
5223 5226 break;
5224 5227 default:
5225 5228 mptsas_log(mpt, CE_WARN,
5226 5229 "unknown ioc_status = %x\n", ioc_status);
5227 5230 mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "
5228 5231 "count = %x, scsi_status = %x", scsi_state,
5229 5232 xferred, scsi_status);
5230 5233 break;
5231 5234 }
5232 5235 break;
5233 5236 case MPI2_SCSI_STATUS_TASK_SET_FULL:
5234 5237 mptsas_handle_qfull(mpt, cmd);
5235 5238 break;
5236 5239 case MPI2_SCSI_STATUS_BUSY:
5237 5240 NDBG31(("scsi_status busy received"));
5238 5241 break;
5239 5242 case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
5240 5243 NDBG31(("scsi_status reservation conflict received"));
5241 5244 break;
5242 5245 default:
5243 5246 mptsas_log(mpt, CE_WARN, "scsi_status=%x, ioc_status=%x\n",
5244 5247 scsi_status, ioc_status);
5245 5248 mptsas_log(mpt, CE_WARN,
5246 5249 "mptsas_process_intr: invalid scsi status\n");
5247 5250 break;
5248 5251 }
5249 5252 }
5250 5253
5251 5254 static void
5252 5255 mptsas_check_task_mgt(mptsas_t *mpt, pMpi2SCSIManagementReply_t reply,
5253 5256 mptsas_cmd_t *cmd)
5254 5257 {
5255 5258 uint8_t task_type;
5256 5259 uint16_t ioc_status;
5257 5260 uint32_t log_info;
5258 5261 uint16_t dev_handle;
5259 5262 struct scsi_pkt *pkt = CMD2PKT(cmd);
5260 5263
5261 5264 task_type = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->TaskType);
5262 5265 ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5263 5266 log_info = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo);
5264 5267 dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->DevHandle);
5265 5268
5266 5269 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5267 5270 mptsas_log(mpt, CE_WARN, "mptsas_check_task_mgt: Task 0x%x "
5268 5271 "failed. IOCStatus=0x%x IOCLogInfo=0x%x target=%d\n",
5269 5272 task_type, ioc_status, log_info, dev_handle);
5270 5273 pkt->pkt_reason = CMD_INCOMPLETE;
5271 5274 return;
5272 5275 }
5273 5276
5274 5277 switch (task_type) {
5275 5278 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
5276 5279 case MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
5277 5280 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
5278 5281 case MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA:
5279 5282 case MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET:
5280 5283 case MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION:
5281 5284 break;
5282 5285 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
5283 5286 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
5284 5287 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
5285 5288 /*
5286 5289 * Check for invalid DevHandle of 0 in case application
5287 5290 * sends bad command. DevHandle of 0 could cause problems.
5288 5291 */
5289 5292 if (dev_handle == 0) {
5290 5293 mptsas_log(mpt, CE_WARN, "!Can't flush target with"
5291 5294 " DevHandle of 0.");
5292 5295 } else {
5293 5296 mptsas_flush_target(mpt, dev_handle, Lun(cmd),
5294 5297 task_type);
5295 5298 }
5296 5299 break;
5297 5300 default:
5298 5301 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
5299 5302 task_type);
5300 5303 mptsas_log(mpt, CE_WARN, "ioc status = %x", ioc_status);
5301 5304 break;
5302 5305 }
5303 5306 }
5304 5307
5305 5308 static void
5306 5309 mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg)
5307 5310 {
5308 5311 mptsas_t *mpt = arg->mpt;
5309 5312 uint64_t t = arg->t;
5310 5313 mptsas_cmd_t *cmd;
5311 5314 struct scsi_pkt *pkt;
5312 5315 mptsas_doneq_thread_list_t *item = &mpt->m_doneq_thread_id[t];
5313 5316
5314 5317 mutex_enter(&item->mutex);
5315 5318 while (item->flag & MPTSAS_DONEQ_THREAD_ACTIVE) {
5316 5319 if (!item->doneq) {
5317 5320 cv_wait(&item->cv, &item->mutex);
5318 5321 }
5319 5322 pkt = NULL;
5320 5323 if ((cmd = mptsas_doneq_thread_rm(mpt, t)) != NULL) {
5321 5324 cmd->cmd_flags |= CFLAG_COMPLETED;
5322 5325 pkt = CMD2PKT(cmd);
5323 5326 }
5324 5327 mutex_exit(&item->mutex);
5325 5328 if (pkt) {
5326 5329 mptsas_pkt_comp(pkt, cmd);
5327 5330 }
5328 5331 mutex_enter(&item->mutex);
5329 5332 }
5330 5333 mutex_exit(&item->mutex);
5331 5334 mutex_enter(&mpt->m_doneq_mutex);
5332 5335 mpt->m_doneq_thread_n--;
5333 5336 cv_broadcast(&mpt->m_doneq_thread_cv);
5334 5337 mutex_exit(&mpt->m_doneq_mutex);
5335 5338 }
5336 5339
5337 5340
5338 5341 /*
5339 5342 * mpt interrupt handler.
5340 5343 */
5341 5344 static uint_t
5342 5345 mptsas_intr(caddr_t arg1, caddr_t arg2)
5343 5346 {
5344 5347 mptsas_t *mpt = (void *)arg1;
5345 5348 pMpi2ReplyDescriptorsUnion_t reply_desc_union;
5346 5349 uchar_t did_reply = FALSE;
5347 5350
5348 5351 NDBG1(("mptsas_intr: arg1 0x%p arg2 0x%p", (void *)arg1, (void *)arg2));
5349 5352
5350 5353 mutex_enter(&mpt->m_mutex);
5351 5354
5352 5355 /*
5353 5356 * If interrupts are shared by two channels then check whether this
5354 5357 * interrupt is genuinely for this channel by making sure first the
5355 5358 * chip is in high power state.
5356 5359 */
5357 5360 if ((mpt->m_options & MPTSAS_OPT_PM) &&
5358 5361 (mpt->m_power_level != PM_LEVEL_D0)) {
5359 5362 mutex_exit(&mpt->m_mutex);
5360 5363 return (DDI_INTR_UNCLAIMED);
5361 5364 }
5362 5365
5363 5366 /*
5364 5367 * If polling, interrupt was triggered by some shared interrupt because
5365 5368 * IOC interrupts are disabled during polling, so polling routine will
5366 5369 * handle any replies. Considering this, if polling is happening,
5367 5370 * return with interrupt unclaimed.
5368 5371 */
5369 5372 if (mpt->m_polled_intr) {
5370 5373 mutex_exit(&mpt->m_mutex);
5371 5374 mptsas_log(mpt, CE_WARN, "mpt_sas: Unclaimed interrupt");
5372 5375 return (DDI_INTR_UNCLAIMED);
5373 5376 }
5374 5377
5375 5378 /*
5376 5379 * Read the istat register.
5377 5380 */
5378 5381 if ((INTPENDING(mpt)) != 0) {
5379 5382 /*
5380 5383 * read fifo until empty.
5381 5384 */
5382 5385 #ifndef __lock_lint
5383 5386 _NOTE(CONSTCOND)
5384 5387 #endif
5385 5388 while (TRUE) {
5386 5389 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5387 5390 DDI_DMA_SYNC_FORCPU);
5388 5391 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5389 5392 MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5390 5393
5391 5394 if (ddi_get32(mpt->m_acc_post_queue_hdl,
5392 5395 &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5393 5396 ddi_get32(mpt->m_acc_post_queue_hdl,
5394 5397 &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5395 5398 break;
5396 5399 }
5397 5400
5398 5401 /*
5399 5402 * The reply is valid, process it according to its
5400 5403 * type. Also, set a flag for updating the reply index
5401 5404 * after they've all been processed.
5402 5405 */
5403 5406 did_reply = TRUE;
5404 5407
5405 5408 mptsas_process_intr(mpt, reply_desc_union);
5406 5409
5407 5410 /*
5408 5411 * Increment post index and roll over if needed.
5409 5412 */
5410 5413 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5411 5414 mpt->m_post_index = 0;
5412 5415 }
5413 5416 }
5414 5417
5415 5418 /*
5416 5419 * Update the global reply index if at least one reply was
5417 5420 * processed.
5418 5421 */
5419 5422 if (did_reply) {
5420 5423 ddi_put32(mpt->m_datap,
5421 5424 &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5422 5425 }
5423 5426 } else {
5424 5427 mutex_exit(&mpt->m_mutex);
5425 5428 return (DDI_INTR_UNCLAIMED);
5426 5429 }
5427 5430 NDBG1(("mptsas_intr complete"));
5428 5431
5429 5432 /*
5430 5433 * If no helper threads are created, process the doneq in ISR. If
5431 5434 * helpers are created, use the doneq length as a metric to measure the
5432 5435 * load on the interrupt CPU. If it is long enough, which indicates the
5433 5436 * load is heavy, then we deliver the IO completions to the helpers.
5434 5437 * This measurement has some limitations, although it is simple and
5435 5438 * straightforward and works well for most of the cases at present.
5436 5439 */
5437 5440 if (!mpt->m_doneq_thread_n ||
5438 5441 (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)) {
5439 5442 mptsas_doneq_empty(mpt);
5440 5443 } else {
5441 5444 mptsas_deliver_doneq_thread(mpt);
5442 5445 }
5443 5446
5444 5447 /*
5445 5448 * If there are queued cmd, start them now.
5446 5449 */
5447 5450 if (mpt->m_waitq != NULL) {
5448 5451 mptsas_restart_waitq(mpt);
5449 5452 }
5450 5453
5451 5454 mutex_exit(&mpt->m_mutex);
5452 5455 return (DDI_INTR_CLAIMED);
5453 5456 }
5454 5457
5455 5458 static void
5456 5459 mptsas_process_intr(mptsas_t *mpt,
5457 5460 pMpi2ReplyDescriptorsUnion_t reply_desc_union)
5458 5461 {
5459 5462 uint8_t reply_type;
5460 5463
5461 5464 ASSERT(mutex_owned(&mpt->m_mutex));
5462 5465
5463 5466 /*
5464 5467 * The reply is valid, process it according to its
5465 5468 * type. Also, set a flag for updated the reply index
5466 5469 * after they've all been processed.
5467 5470 */
5468 5471 reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
5469 5472 &reply_desc_union->Default.ReplyFlags);
5470 5473 reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
5471 5474 if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
5472 5475 mptsas_handle_scsi_io_success(mpt, reply_desc_union);
5473 5476 } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
5474 5477 mptsas_handle_address_reply(mpt, reply_desc_union);
5475 5478 } else {
5476 5479 mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type);
5477 5480 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5478 5481 }
5479 5482
5480 5483 /*
5481 5484 * Clear the reply descriptor for re-use and increment
5482 5485 * index.
5483 5486 */
5484 5487 ddi_put64(mpt->m_acc_post_queue_hdl,
5485 5488 &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
5486 5489 0xFFFFFFFFFFFFFFFF);
5487 5490 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5488 5491 DDI_DMA_SYNC_FORDEV);
5489 5492 }
5490 5493
5491 5494 /*
5492 5495 * handle qfull condition
5493 5496 */
5494 5497 static void
5495 5498 mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd)
5496 5499 {
5497 5500 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
5498 5501
5499 5502 if ((++cmd->cmd_qfull_retries > ptgt->m_qfull_retries) ||
5500 5503 (ptgt->m_qfull_retries == 0)) {
5501 5504 /*
5502 5505 * We have exhausted the retries on QFULL, or,
5503 5506 * the target driver has indicated that it
5504 5507 * wants to handle QFULL itself by setting
5505 5508 * qfull-retries capability to 0. In either case
5506 5509 * we want the target driver's QFULL handling
5507 5510 * to kick in. We do this by having pkt_reason
5508 5511 * as CMD_CMPLT and pkt_scbp as STATUS_QFULL.
5509 5512 */
5510 5513 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5511 5514 } else {
5512 5515 if (ptgt->m_reset_delay == 0) {
5513 5516 ptgt->m_t_throttle =
5514 5517 max((ptgt->m_t_ncmds - 2), 0);
5515 5518 }
5516 5519
5517 5520 cmd->cmd_pkt_flags |= FLAG_HEAD;
5518 5521 cmd->cmd_flags &= ~(CFLAG_TRANFLAG);
5519 5522 cmd->cmd_flags |= CFLAG_RETRY;
5520 5523
5521 5524 (void) mptsas_accept_pkt(mpt, cmd);
5522 5525
5523 5526 /*
5524 5527 * when target gives queue full status with no commands
5525 5528 * outstanding (m_t_ncmds == 0), throttle is set to 0
5526 5529 * (HOLD_THROTTLE), and the queue full handling start
5527 5530 * (see psarc/1994/313); if there are commands outstanding,
5528 5531 * throttle is set to (m_t_ncmds - 2)
5529 5532 */
5530 5533 if (ptgt->m_t_throttle == HOLD_THROTTLE) {
5531 5534 /*
5532 5535 * By setting throttle to QFULL_THROTTLE, we
5533 5536 * avoid submitting new commands and in
5534 5537 * mptsas_restart_cmd find out slots which need
5535 5538 * their throttles to be cleared.
5536 5539 */
5537 5540 mptsas_set_throttle(mpt, ptgt, QFULL_THROTTLE);
5538 5541 if (mpt->m_restart_cmd_timeid == 0) {
5539 5542 mpt->m_restart_cmd_timeid =
5540 5543 timeout(mptsas_restart_cmd, mpt,
5541 5544 ptgt->m_qfull_retry_interval);
5542 5545 }
5543 5546 }
5544 5547 }
5545 5548 }
5546 5549
5547 5550 mptsas_phymask_t
5548 5551 mptsas_physport_to_phymask(mptsas_t *mpt, uint8_t physport)
5549 5552 {
5550 5553 mptsas_phymask_t phy_mask = 0;
5551 5554 uint8_t i = 0;
5552 5555
5553 5556 NDBG20(("mptsas%d physport_to_phymask enter", mpt->m_instance));
5554 5557
5555 5558 ASSERT(mutex_owned(&mpt->m_mutex));
5556 5559
5557 5560 /*
5558 5561 * If physport is 0xFF, this is a RAID volume. Use phymask of 0.
5559 5562 */
5560 5563 if (physport == 0xFF) {
5561 5564 return (0);
5562 5565 }
5563 5566
5564 5567 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
5565 5568 if (mpt->m_phy_info[i].attached_devhdl &&
5566 5569 (mpt->m_phy_info[i].phy_mask != 0) &&
5567 5570 (mpt->m_phy_info[i].port_num == physport)) {
5568 5571 phy_mask = mpt->m_phy_info[i].phy_mask;
5569 5572 break;
5570 5573 }
5571 5574 }
5572 5575 NDBG20(("mptsas%d physport_to_phymask:physport :%x phymask :%x, ",
5573 5576 mpt->m_instance, physport, phy_mask));
5574 5577 return (phy_mask);
5575 5578 }
5576 5579
5577 5580 /*
5578 5581 * mpt free device handle after device gone, by use of passthrough
5579 5582 */
5580 5583 static int
5581 5584 mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl)
5582 5585 {
5583 5586 Mpi2SasIoUnitControlRequest_t req;
5584 5587 Mpi2SasIoUnitControlReply_t rep;
5585 5588 int ret;
5586 5589
5587 5590 ASSERT(mutex_owned(&mpt->m_mutex));
5588 5591
5589 5592 /*
5590 5593 * Need to compose a SAS IO Unit Control request message
5591 5594 * and call mptsas_do_passthru() function
5592 5595 */
5593 5596 bzero(&req, sizeof (req));
5594 5597 bzero(&rep, sizeof (rep));
5595 5598
5596 5599 req.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
5597 5600 req.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
5598 5601 req.DevHandle = LE_16(devhdl);
5599 5602
5600 5603 ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
5601 5604 sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
5602 5605 if (ret != 0) {
5603 5606 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5604 5607 "Control error %d", ret);
5605 5608 return (DDI_FAILURE);
5606 5609 }
5607 5610
5608 5611 /* do passthrough success, check the ioc status */
5609 5612 if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
5610 5613 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5611 5614 "Control IOCStatus %d", LE_16(rep.IOCStatus));
5612 5615 return (DDI_FAILURE);
5613 5616 }
5614 5617
5615 5618 return (DDI_SUCCESS);
5616 5619 }
5617 5620
5618 5621 static void
5619 5622 mptsas_update_phymask(mptsas_t *mpt)
5620 5623 {
5621 5624 mptsas_phymask_t mask = 0, phy_mask;
5622 5625 char *phy_mask_name;
5623 5626 uint8_t current_port;
5624 5627 int i, j;
5625 5628
5626 5629 NDBG20(("mptsas%d update phymask ", mpt->m_instance));
5627 5630
5628 5631 ASSERT(mutex_owned(&mpt->m_mutex));
5629 5632
5630 5633 (void) mptsas_get_sas_io_unit_page(mpt);
5631 5634
5632 5635 phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5633 5636
5634 5637 for (i = 0; i < mpt->m_num_phys; i++) {
5635 5638 phy_mask = 0x00;
5636 5639
5637 5640 if (mpt->m_phy_info[i].attached_devhdl == 0)
5638 5641 continue;
5639 5642
5640 5643 bzero(phy_mask_name, sizeof (phy_mask_name));
5641 5644
5642 5645 current_port = mpt->m_phy_info[i].port_num;
5643 5646
5644 5647 if ((mask & (1 << i)) != 0)
5645 5648 continue;
5646 5649
5647 5650 for (j = 0; j < mpt->m_num_phys; j++) {
5648 5651 if (mpt->m_phy_info[j].attached_devhdl &&
5649 5652 (mpt->m_phy_info[j].port_num == current_port)) {
5650 5653 phy_mask |= (1 << j);
5651 5654 }
5652 5655 }
5653 5656 mask = mask | phy_mask;
5654 5657
5655 5658 for (j = 0; j < mpt->m_num_phys; j++) {
5656 5659 if ((phy_mask >> j) & 0x01) {
5657 5660 mpt->m_phy_info[j].phy_mask = phy_mask;
5658 5661 }
5659 5662 }
5660 5663
5661 5664 (void) sprintf(phy_mask_name, "%x", phy_mask);
5662 5665
5663 5666 mutex_exit(&mpt->m_mutex);
5664 5667 /*
5665 5668 * register a iport, if the port has already been existed
5666 5669 * SCSA will do nothing and just return.
5667 5670 */
5668 5671 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
5669 5672 mutex_enter(&mpt->m_mutex);
5670 5673 }
5671 5674 kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5672 5675 NDBG20(("mptsas%d update phymask return", mpt->m_instance));
5673 5676 }
5674 5677
5675 5678 /*
5676 5679 * mptsas_handle_dr is a task handler for DR, the DR action includes:
5677 5680 * 1. Directly attched Device Added/Removed.
5678 5681 * 2. Expander Device Added/Removed.
5679 5682 * 3. Indirectly Attached Device Added/Expander.
5680 5683 * 4. LUNs of a existing device status change.
5681 5684 * 5. RAID volume created/deleted.
5682 5685 * 6. Member of RAID volume is released because of RAID deletion.
5683 5686 * 7. Physical disks are removed because of RAID creation.
5684 5687 */
5685 5688 static void
5686 5689 mptsas_handle_dr(void *args) {
5687 5690 mptsas_topo_change_list_t *topo_node = NULL;
5688 5691 mptsas_topo_change_list_t *save_node = NULL;
5689 5692 mptsas_t *mpt;
5690 5693 dev_info_t *parent = NULL;
5691 5694 mptsas_phymask_t phymask = 0;
5692 5695 char *phy_mask_name;
5693 5696 uint8_t flags = 0, physport = 0xff;
5694 5697 uint8_t port_update = 0;
5695 5698 uint_t event;
5696 5699
5697 5700 topo_node = (mptsas_topo_change_list_t *)args;
5698 5701
5699 5702 mpt = topo_node->mpt;
5700 5703 event = topo_node->event;
5701 5704 flags = topo_node->flags;
5702 5705
5703 5706 phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5704 5707
5705 5708 NDBG20(("mptsas%d handle_dr enter", mpt->m_instance));
5706 5709
5707 5710 switch (event) {
5708 5711 case MPTSAS_DR_EVENT_RECONFIG_TARGET:
5709 5712 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
5710 5713 (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE) ||
5711 5714 (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
5712 5715 /*
5713 5716 * Direct attached or expander attached device added
5714 5717 * into system or a Phys Disk that is being unhidden.
5715 5718 */
5716 5719 port_update = 1;
5717 5720 }
5718 5721 break;
5719 5722 case MPTSAS_DR_EVENT_RECONFIG_SMP:
5720 5723 /*
5721 5724 * New expander added into system, it must be the head
5722 5725 * of topo_change_list_t
5723 5726 */
5724 5727 port_update = 1;
5725 5728 break;
5726 5729 default:
5727 5730 port_update = 0;
5728 5731 break;
5729 5732 }
5730 5733 /*
5731 5734 * All cases port_update == 1 may cause initiator port form change
5732 5735 */
5733 5736 mutex_enter(&mpt->m_mutex);
5734 5737 if (mpt->m_port_chng && port_update) {
5735 5738 /*
5736 5739 * mpt->m_port_chng flag indicates some PHYs of initiator
5737 5740 * port have changed to online. So when expander added or
5738 5741 * directly attached device online event come, we force to
5739 5742 * update port information by issueing SAS IO Unit Page and
5740 5743 * update PHYMASKs.
5741 5744 */
5742 5745 (void) mptsas_update_phymask(mpt);
5743 5746 mpt->m_port_chng = 0;
5744 5747
5745 5748 }
5746 5749 mutex_exit(&mpt->m_mutex);
5747 5750 while (topo_node) {
5748 5751 phymask = 0;
5749 5752 if (parent == NULL) {
5750 5753 physport = topo_node->un.physport;
5751 5754 event = topo_node->event;
5752 5755 flags = topo_node->flags;
5753 5756 if (event & (MPTSAS_DR_EVENT_OFFLINE_TARGET |
5754 5757 MPTSAS_DR_EVENT_OFFLINE_SMP)) {
5755 5758 /*
5756 5759 * For all offline events, phymask is known
5757 5760 */
5758 5761 phymask = topo_node->un.phymask;
5759 5762 goto find_parent;
5760 5763 }
5761 5764 if (event & MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
5762 5765 goto handle_topo_change;
5763 5766 }
5764 5767 if (flags & MPTSAS_TOPO_FLAG_LUN_ASSOCIATED) {
5765 5768 phymask = topo_node->un.phymask;
5766 5769 goto find_parent;
5767 5770 }
5768 5771
5769 5772 if ((flags ==
5770 5773 MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) &&
5771 5774 (event == MPTSAS_DR_EVENT_RECONFIG_TARGET)) {
5772 5775 /*
5773 5776 * There is no any field in IR_CONFIG_CHANGE
5774 5777 * event indicate physport/phynum, let's get
5775 5778 * parent after SAS Device Page0 request.
5776 5779 */
5777 5780 goto handle_topo_change;
5778 5781 }
5779 5782
5780 5783 mutex_enter(&mpt->m_mutex);
5781 5784 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
5782 5785 /*
5783 5786 * If the direct attached device added or a
5784 5787 * phys disk is being unhidden, argument
5785 5788 * physport actually is PHY#, so we have to get
5786 5789 * phymask according PHY#.
5787 5790 */
5788 5791 physport = mpt->m_phy_info[physport].port_num;
5789 5792 }
5790 5793
5791 5794 /*
5792 5795 * Translate physport to phymask so that we can search
5793 5796 * parent dip.
5794 5797 */
5795 5798 phymask = mptsas_physport_to_phymask(mpt,
5796 5799 physport);
5797 5800 mutex_exit(&mpt->m_mutex);
5798 5801
5799 5802 find_parent:
5800 5803 bzero(phy_mask_name, MPTSAS_MAX_PHYS);
5801 5804 /*
5802 5805 * For RAID topology change node, write the iport name
5803 5806 * as v0.
5804 5807 */
5805 5808 if (flags & MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5806 5809 (void) sprintf(phy_mask_name, "v0");
5807 5810 } else {
5808 5811 /*
5809 5812 * phymask can bo 0 if the drive has been
5810 5813 * pulled by the time an add event is
5811 5814 * processed. If phymask is 0, just skip this
5812 5815 * event and continue.
5813 5816 */
5814 5817 if (phymask == 0) {
5815 5818 mutex_enter(&mpt->m_mutex);
5816 5819 save_node = topo_node;
5817 5820 topo_node = topo_node->next;
5818 5821 ASSERT(save_node);
5819 5822 kmem_free(save_node,
5820 5823 sizeof (mptsas_topo_change_list_t));
5821 5824 mutex_exit(&mpt->m_mutex);
5822 5825
5823 5826 parent = NULL;
5824 5827 continue;
5825 5828 }
5826 5829 (void) sprintf(phy_mask_name, "%x", phymask);
5827 5830 }
5828 5831 parent = scsi_hba_iport_find(mpt->m_dip,
5829 5832 phy_mask_name);
5830 5833 if (parent == NULL) {
5831 5834 mptsas_log(mpt, CE_WARN, "Failed to find an "
5832 5835 "iport, should not happen!");
5833 5836 goto out;
5834 5837 }
5835 5838
5836 5839 }
5837 5840 ASSERT(parent);
5838 5841 handle_topo_change:
5839 5842
5840 5843 mutex_enter(&mpt->m_mutex);
5841 5844 /*
5842 5845 * If HBA is being reset, don't perform operations depending
5843 5846 * on the IOC. We must free the topo list, however.
5844 5847 */
5845 5848 if (!mpt->m_in_reset)
5846 5849 mptsas_handle_topo_change(topo_node, parent);
5847 5850 else
5848 5851 NDBG20(("skipping topo change received during reset"));
5849 5852 save_node = topo_node;
5850 5853 topo_node = topo_node->next;
5851 5854 ASSERT(save_node);
5852 5855 kmem_free(save_node, sizeof (mptsas_topo_change_list_t));
5853 5856 mutex_exit(&mpt->m_mutex);
5854 5857
5855 5858 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
5856 5859 (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) ||
5857 5860 (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED)) {
5858 5861 /*
5859 5862 * If direct attached device associated, make sure
5860 5863 * reset the parent before start the next one. But
5861 5864 * all devices associated with expander shares the
5862 5865 * parent. Also, reset parent if this is for RAID.
5863 5866 */
5864 5867 parent = NULL;
5865 5868 }
5866 5869 }
5867 5870 out:
5868 5871 kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5869 5872 }
5870 5873
5871 5874 static void
5872 5875 mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
5873 5876 dev_info_t *parent)
5874 5877 {
5875 5878 mptsas_target_t *ptgt = NULL;
5876 5879 mptsas_smp_t *psmp = NULL;
5877 5880 mptsas_t *mpt = (void *)topo_node->mpt;
5878 5881 uint16_t devhdl;
5879 5882 uint16_t attached_devhdl;
5880 5883 uint64_t sas_wwn = 0;
5881 5884 int rval = 0;
5882 5885 uint32_t page_address;
5883 5886 uint8_t phy, flags;
5884 5887 char *addr = NULL;
5885 5888 dev_info_t *lundip;
5886 5889 int circ = 0, circ1 = 0;
5887 5890 char attached_wwnstr[MPTSAS_WWN_STRLEN];
5888 5891
5889 5892 NDBG20(("mptsas%d handle_topo_change enter", mpt->m_instance));
5890 5893
5891 5894 ASSERT(mutex_owned(&mpt->m_mutex));
5892 5895
5893 5896 switch (topo_node->event) {
5894 5897 case MPTSAS_DR_EVENT_RECONFIG_TARGET:
5895 5898 {
5896 5899 char *phy_mask_name;
5897 5900 mptsas_phymask_t phymask = 0;
5898 5901
5899 5902 if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5900 5903 /*
5901 5904 * Get latest RAID info.
5902 5905 */
5903 5906 (void) mptsas_get_raid_info(mpt);
5904 5907 ptgt = refhash_linear_search(mpt->m_targets,
5905 5908 mptsas_target_eval_devhdl, &topo_node->devhdl);
5906 5909 if (ptgt == NULL)
5907 5910 break;
5908 5911 } else {
5909 5912 ptgt = (void *)topo_node->object;
5910 5913 }
5911 5914
5912 5915 if (ptgt == NULL) {
5913 5916 /*
5914 5917 * If a Phys Disk was deleted, RAID info needs to be
5915 5918 * updated to reflect the new topology.
5916 5919 */
5917 5920 (void) mptsas_get_raid_info(mpt);
5918 5921
5919 5922 /*
5920 5923 * Get sas device page 0 by DevHandle to make sure if
5921 5924 * SSP/SATA end device exist.
5922 5925 */
5923 5926 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
5924 5927 MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
5925 5928 topo_node->devhdl;
5926 5929
5927 5930 rval = mptsas_get_target_device_info(mpt, page_address,
5928 5931 &devhdl, &ptgt);
5929 5932 if (rval == DEV_INFO_WRONG_DEVICE_TYPE) {
5930 5933 mptsas_log(mpt, CE_NOTE,
5931 5934 "mptsas_handle_topo_change: target %d is "
5932 5935 "not a SAS/SATA device. \n",
5933 5936 topo_node->devhdl);
5934 5937 } else if (rval == DEV_INFO_FAIL_ALLOC) {
5935 5938 mptsas_log(mpt, CE_NOTE,
5936 5939 "mptsas_handle_topo_change: could not "
5937 5940 "allocate memory. \n");
5938 5941 }
5939 5942 /*
5940 5943 * If rval is DEV_INFO_PHYS_DISK than there is nothing
5941 5944 * else to do, just leave.
5942 5945 */
5943 5946 if (rval != DEV_INFO_SUCCESS) {
5944 5947 return;
5945 5948 }
5946 5949 }
5947 5950
5948 5951 ASSERT(ptgt->m_devhdl == topo_node->devhdl);
5949 5952
5950 5953 mutex_exit(&mpt->m_mutex);
5951 5954 flags = topo_node->flags;
5952 5955
5953 5956 if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
5954 5957 phymask = ptgt->m_addr.mta_phymask;
5955 5958 phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5956 5959 (void) sprintf(phy_mask_name, "%x", phymask);
5957 5960 parent = scsi_hba_iport_find(mpt->m_dip,
5958 5961 phy_mask_name);
5959 5962 kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5960 5963 if (parent == NULL) {
5961 5964 mptsas_log(mpt, CE_WARN, "Failed to find a "
5962 5965 "iport for PD, should not happen!");
5963 5966 mutex_enter(&mpt->m_mutex);
5964 5967 break;
5965 5968 }
5966 5969 }
5967 5970
5968 5971 if (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5969 5972 ndi_devi_enter(parent, &circ1);
5970 5973 (void) mptsas_config_raid(parent, topo_node->devhdl,
5971 5974 &lundip);
5972 5975 ndi_devi_exit(parent, circ1);
5973 5976 } else {
5974 5977 /*
5975 5978 * hold nexus for bus configure
5976 5979 */
5977 5980 ndi_devi_enter(scsi_vhci_dip, &circ);
5978 5981 ndi_devi_enter(parent, &circ1);
5979 5982 rval = mptsas_config_target(parent, ptgt);
5980 5983 /*
5981 5984 * release nexus for bus configure
5982 5985 */
5983 5986 ndi_devi_exit(parent, circ1);
5984 5987 ndi_devi_exit(scsi_vhci_dip, circ);
5985 5988
5986 5989 /*
5987 5990 * Add parent's props for SMHBA support
5988 5991 */
5989 5992 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
5990 5993 bzero(attached_wwnstr,
5991 5994 sizeof (attached_wwnstr));
5992 5995 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
5993 5996 ptgt->m_addr.mta_wwn);
5994 5997 if (ddi_prop_update_string(DDI_DEV_T_NONE,
5995 5998 parent,
5996 5999 SCSI_ADDR_PROP_ATTACHED_PORT,
5997 6000 attached_wwnstr)
5998 6001 != DDI_PROP_SUCCESS) {
5999 6002 (void) ddi_prop_remove(DDI_DEV_T_NONE,
6000 6003 parent,
6001 6004 SCSI_ADDR_PROP_ATTACHED_PORT);
6002 6005 mptsas_log(mpt, CE_WARN, "Failed to"
6003 6006 "attached-port props");
6004 6007 return;
6005 6008 }
6006 6009 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6007 6010 MPTSAS_NUM_PHYS, 1) !=
6008 6011 DDI_PROP_SUCCESS) {
6009 6012 (void) ddi_prop_remove(DDI_DEV_T_NONE,
6010 6013 parent, MPTSAS_NUM_PHYS);
6011 6014 mptsas_log(mpt, CE_WARN, "Failed to"
6012 6015 " create num-phys props");
6013 6016 return;
6014 6017 }
6015 6018
6016 6019 /*
6017 6020 * Update PHY info for smhba
6018 6021 */
6019 6022 mutex_enter(&mpt->m_mutex);
6020 6023 if (mptsas_smhba_phy_init(mpt)) {
6021 6024 mutex_exit(&mpt->m_mutex);
6022 6025 mptsas_log(mpt, CE_WARN, "mptsas phy"
6023 6026 " update failed");
6024 6027 return;
6025 6028 }
6026 6029 mutex_exit(&mpt->m_mutex);
6027 6030
6028 6031 /*
6029 6032 * topo_node->un.physport is really the PHY#
6030 6033 * for direct attached devices
6031 6034 */
6032 6035 mptsas_smhba_set_one_phy_props(mpt, parent,
6033 6036 topo_node->un.physport, &attached_devhdl);
6034 6037
6035 6038 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6036 6039 MPTSAS_VIRTUAL_PORT, 0) !=
6037 6040 DDI_PROP_SUCCESS) {
6038 6041 (void) ddi_prop_remove(DDI_DEV_T_NONE,
6039 6042 parent, MPTSAS_VIRTUAL_PORT);
6040 6043 mptsas_log(mpt, CE_WARN,
6041 6044 "mptsas virtual-port"
6042 6045 "port prop update failed");
6043 6046 return;
6044 6047 }
6045 6048 }
6046 6049 }
6047 6050 mutex_enter(&mpt->m_mutex);
6048 6051
6049 6052 NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
6050 6053 "phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
6051 6054 ptgt->m_addr.mta_phymask));
6052 6055 break;
6053 6056 }
6054 6057 case MPTSAS_DR_EVENT_OFFLINE_TARGET:
6055 6058 {
6056 6059 devhdl = topo_node->devhdl;
6057 6060 ptgt = refhash_linear_search(mpt->m_targets,
6058 6061 mptsas_target_eval_devhdl, &devhdl);
6059 6062 if (ptgt == NULL)
6060 6063 break;
6061 6064
6062 6065 sas_wwn = ptgt->m_addr.mta_wwn;
6063 6066 phy = ptgt->m_phynum;
6064 6067
6065 6068 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
6066 6069
6067 6070 if (sas_wwn) {
6068 6071 (void) sprintf(addr, "w%016"PRIx64, sas_wwn);
6069 6072 } else {
6070 6073 (void) sprintf(addr, "p%x", phy);
6071 6074 }
6072 6075 ASSERT(ptgt->m_devhdl == devhdl);
6073 6076
6074 6077 if ((topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) ||
6075 6078 (topo_node->flags ==
6076 6079 MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6077 6080 /*
6078 6081 * Get latest RAID info if RAID volume status changes
6079 6082 * or Phys Disk status changes
6080 6083 */
6081 6084 (void) mptsas_get_raid_info(mpt);
6082 6085 }
6083 6086 /*
6084 6087 * Abort all outstanding command on the device
6085 6088 */
6086 6089 rval = mptsas_do_scsi_reset(mpt, devhdl);
6087 6090 if (rval) {
6088 6091 NDBG20(("mptsas%d handle_topo_change to reset target "
6089 6092 "before offline devhdl:%x, phymask:%x, rval:%x",
6090 6093 mpt->m_instance, ptgt->m_devhdl,
6091 6094 ptgt->m_addr.mta_phymask, rval));
6092 6095 }
6093 6096
6094 6097 mutex_exit(&mpt->m_mutex);
6095 6098
6096 6099 ndi_devi_enter(scsi_vhci_dip, &circ);
6097 6100 ndi_devi_enter(parent, &circ1);
6098 6101 rval = mptsas_offline_target(parent, addr);
6099 6102 ndi_devi_exit(parent, circ1);
6100 6103 ndi_devi_exit(scsi_vhci_dip, circ);
6101 6104 NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
6102 6105 "phymask:%x, rval:%x", mpt->m_instance,
6103 6106 ptgt->m_devhdl, ptgt->m_addr.mta_phymask, rval));
6104 6107
6105 6108 kmem_free(addr, SCSI_MAXNAMELEN);
6106 6109
6107 6110 /*
6108 6111 * Clear parent's props for SMHBA support
6109 6112 */
6110 6113 flags = topo_node->flags;
6111 6114 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6112 6115 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6113 6116 if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6114 6117 SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6115 6118 DDI_PROP_SUCCESS) {
6116 6119 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6117 6120 SCSI_ADDR_PROP_ATTACHED_PORT);
6118 6121 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6119 6122 "prop update failed");
6120 6123 break;
6121 6124 }
6122 6125 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6123 6126 MPTSAS_NUM_PHYS, 0) !=
6124 6127 DDI_PROP_SUCCESS) {
6125 6128 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6126 6129 MPTSAS_NUM_PHYS);
6127 6130 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6128 6131 "prop update failed");
6129 6132 break;
6130 6133 }
6131 6134 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6132 6135 MPTSAS_VIRTUAL_PORT, 1) !=
6133 6136 DDI_PROP_SUCCESS) {
6134 6137 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6135 6138 MPTSAS_VIRTUAL_PORT);
6136 6139 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6137 6140 "prop update failed");
6138 6141 break;
6139 6142 }
6140 6143 }
6141 6144
6142 6145 mutex_enter(&mpt->m_mutex);
6143 6146 ptgt->m_led_status = 0;
6144 6147 (void) mptsas_flush_led_status(mpt, ptgt);
6145 6148 if (rval == DDI_SUCCESS) {
6146 6149 refhash_remove(mpt->m_targets, ptgt);
6147 6150 ptgt = NULL;
6148 6151 } else {
6149 6152 /*
6150 6153 * clean DR_INTRANSITION flag to allow I/O down to
6151 6154 * PHCI driver since failover finished.
6152 6155 * Invalidate the devhdl
6153 6156 */
6154 6157 ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6155 6158 ptgt->m_tgt_unconfigured = 0;
6156 6159 mutex_enter(&mpt->m_tx_waitq_mutex);
6157 6160 ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6158 6161 mutex_exit(&mpt->m_tx_waitq_mutex);
6159 6162 }
6160 6163
6161 6164 /*
6162 6165 * Send SAS IO Unit Control to free the dev handle
6163 6166 */
6164 6167 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6165 6168 (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE)) {
6166 6169 rval = mptsas_free_devhdl(mpt, devhdl);
6167 6170
6168 6171 NDBG20(("mptsas%d handle_topo_change to remove "
6169 6172 "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6170 6173 rval));
6171 6174 }
6172 6175
6173 6176 break;
6174 6177 }
6175 6178 case MPTSAS_TOPO_FLAG_REMOVE_HANDLE:
6176 6179 {
6177 6180 devhdl = topo_node->devhdl;
6178 6181 /*
6179 6182 * If this is the remove handle event, do a reset first.
6180 6183 */
6181 6184 if (topo_node->event == MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6182 6185 rval = mptsas_do_scsi_reset(mpt, devhdl);
6183 6186 if (rval) {
6184 6187 NDBG20(("mpt%d reset target before remove "
6185 6188 "devhdl:%x, rval:%x", mpt->m_instance,
6186 6189 devhdl, rval));
6187 6190 }
6188 6191 }
6189 6192
6190 6193 /*
6191 6194 * Send SAS IO Unit Control to free the dev handle
6192 6195 */
6193 6196 rval = mptsas_free_devhdl(mpt, devhdl);
6194 6197 NDBG20(("mptsas%d handle_topo_change to remove "
6195 6198 "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6196 6199 rval));
6197 6200 break;
6198 6201 }
6199 6202 case MPTSAS_DR_EVENT_RECONFIG_SMP:
6200 6203 {
6201 6204 mptsas_smp_t smp;
6202 6205 dev_info_t *smpdip;
6203 6206
6204 6207 devhdl = topo_node->devhdl;
6205 6208
6206 6209 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
6207 6210 MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
6208 6211 rval = mptsas_get_sas_expander_page0(mpt, page_address, &smp);
6209 6212 if (rval != DDI_SUCCESS) {
6210 6213 mptsas_log(mpt, CE_WARN, "failed to online smp, "
6211 6214 "handle %x", devhdl);
6212 6215 return;
6213 6216 }
6214 6217
6215 6218 psmp = mptsas_smp_alloc(mpt, &smp);
6216 6219 if (psmp == NULL) {
6217 6220 return;
6218 6221 }
6219 6222
6220 6223 mutex_exit(&mpt->m_mutex);
6221 6224 ndi_devi_enter(parent, &circ1);
6222 6225 (void) mptsas_online_smp(parent, psmp, &smpdip);
6223 6226 ndi_devi_exit(parent, circ1);
6224 6227
6225 6228 mutex_enter(&mpt->m_mutex);
6226 6229 break;
6227 6230 }
6228 6231 case MPTSAS_DR_EVENT_OFFLINE_SMP:
6229 6232 {
6230 6233 devhdl = topo_node->devhdl;
6231 6234 uint32_t dev_info;
6232 6235
6233 6236 psmp = refhash_linear_search(mpt->m_smp_targets,
6234 6237 mptsas_smp_eval_devhdl, &devhdl);
6235 6238 if (psmp == NULL)
6236 6239 break;
6237 6240 /*
6238 6241 * The mptsas_smp_t data is released only if the dip is offlined
6239 6242 * successfully.
6240 6243 */
6241 6244 mutex_exit(&mpt->m_mutex);
6242 6245
6243 6246 ndi_devi_enter(parent, &circ1);
6244 6247 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6245 6248 ndi_devi_exit(parent, circ1);
6246 6249
6247 6250 dev_info = psmp->m_deviceinfo;
6248 6251 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6249 6252 DEVINFO_DIRECT_ATTACHED) {
6250 6253 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6251 6254 MPTSAS_VIRTUAL_PORT, 1) !=
6252 6255 DDI_PROP_SUCCESS) {
6253 6256 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6254 6257 MPTSAS_VIRTUAL_PORT);
6255 6258 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6256 6259 "prop update failed");
6257 6260 return;
6258 6261 }
6259 6262 /*
6260 6263 * Check whether the smp connected to the iport,
6261 6264 */
6262 6265 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6263 6266 MPTSAS_NUM_PHYS, 0) !=
6264 6267 DDI_PROP_SUCCESS) {
6265 6268 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6266 6269 MPTSAS_NUM_PHYS);
6267 6270 mptsas_log(mpt, CE_WARN, "mptsas num phys"
6268 6271 "prop update failed");
6269 6272 return;
6270 6273 }
6271 6274 /*
6272 6275 * Clear parent's attached-port props
6273 6276 */
6274 6277 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6275 6278 if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6276 6279 SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6277 6280 DDI_PROP_SUCCESS) {
6278 6281 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6279 6282 SCSI_ADDR_PROP_ATTACHED_PORT);
6280 6283 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6281 6284 "prop update failed");
6282 6285 return;
6283 6286 }
6284 6287 }
6285 6288
6286 6289 mutex_enter(&mpt->m_mutex);
6287 6290 NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
6288 6291 "rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
6289 6292 if (rval == DDI_SUCCESS) {
6290 6293 refhash_remove(mpt->m_smp_targets, psmp);
6291 6294 } else {
6292 6295 psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
6293 6296 }
6294 6297
6295 6298 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6296 6299
6297 6300 break;
6298 6301 }
6299 6302 default:
6300 6303 return;
6301 6304 }
6302 6305 }
6303 6306
6304 6307 /*
6305 6308 * Record the event if its type is enabled in mpt instance by ioctl.
6306 6309 */
6307 6310 static void
6308 6311 mptsas_record_event(void *args)
6309 6312 {
6310 6313 m_replyh_arg_t *replyh_arg;
6311 6314 pMpi2EventNotificationReply_t eventreply;
6312 6315 uint32_t event, rfm;
6313 6316 mptsas_t *mpt;
6314 6317 int i, j;
6315 6318 uint16_t event_data_len;
6316 6319 boolean_t sendAEN = FALSE;
6317 6320
6318 6321 replyh_arg = (m_replyh_arg_t *)args;
6319 6322 rfm = replyh_arg->rfm;
6320 6323 mpt = replyh_arg->mpt;
6321 6324
6322 6325 eventreply = (pMpi2EventNotificationReply_t)
6323 6326 (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6324 6327 event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6325 6328
6326 6329
6327 6330 /*
6328 6331 * Generate a system event to let anyone who cares know that a
6329 6332 * LOG_ENTRY_ADDED event has occurred. This is sent no matter what the
6330 6333 * event mask is set to.
6331 6334 */
6332 6335 if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
6333 6336 sendAEN = TRUE;
6334 6337 }
6335 6338
6336 6339 /*
6337 6340 * Record the event only if it is not masked. Determine which dword
6338 6341 * and bit of event mask to test.
6339 6342 */
6340 6343 i = (uint8_t)(event / 32);
6341 6344 j = (uint8_t)(event % 32);
6342 6345 if ((i < 4) && ((1 << j) & mpt->m_event_mask[i])) {
6343 6346 i = mpt->m_event_index;
6344 6347 mpt->m_events[i].Type = event;
6345 6348 mpt->m_events[i].Number = ++mpt->m_event_number;
6346 6349 bzero(mpt->m_events[i].Data, MPTSAS_MAX_EVENT_DATA_LENGTH * 4);
6347 6350 event_data_len = ddi_get16(mpt->m_acc_reply_frame_hdl,
6348 6351 &eventreply->EventDataLength);
6349 6352
6350 6353 if (event_data_len > 0) {
6351 6354 /*
6352 6355 * Limit data to size in m_event entry
6353 6356 */
6354 6357 if (event_data_len > MPTSAS_MAX_EVENT_DATA_LENGTH) {
6355 6358 event_data_len = MPTSAS_MAX_EVENT_DATA_LENGTH;
6356 6359 }
6357 6360 for (j = 0; j < event_data_len; j++) {
6358 6361 mpt->m_events[i].Data[j] =
6359 6362 ddi_get32(mpt->m_acc_reply_frame_hdl,
6360 6363 &(eventreply->EventData[j]));
6361 6364 }
6362 6365
6363 6366 /*
6364 6367 * check for index wrap-around
6365 6368 */
6366 6369 if (++i == MPTSAS_EVENT_QUEUE_SIZE) {
6367 6370 i = 0;
6368 6371 }
6369 6372 mpt->m_event_index = (uint8_t)i;
6370 6373
6371 6374 /*
6372 6375 * Set flag to send the event.
6373 6376 */
6374 6377 sendAEN = TRUE;
6375 6378 }
6376 6379 }
6377 6380
6378 6381 /*
6379 6382 * Generate a system event if flag is set to let anyone who cares know
6380 6383 * that an event has occurred.
6381 6384 */
6382 6385 if (sendAEN) {
6383 6386 (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
6384 6387 "SAS", NULL, NULL, DDI_NOSLEEP);
6385 6388 }
6386 6389 }
6387 6390
6388 6391 #define SMP_RESET_IN_PROGRESS MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS
6389 6392 /*
6390 6393 * handle sync events from ioc in interrupt
6391 6394 * return value:
6392 6395 * DDI_SUCCESS: The event is handled by this func
6393 6396 * DDI_FAILURE: Event is not handled
6394 6397 */
6395 6398 static int
6396 6399 mptsas_handle_event_sync(void *args)
6397 6400 {
6398 6401 m_replyh_arg_t *replyh_arg;
6399 6402 pMpi2EventNotificationReply_t eventreply;
6400 6403 uint32_t event, rfm;
6401 6404 mptsas_t *mpt;
6402 6405 uint_t iocstatus;
6403 6406
6404 6407 replyh_arg = (m_replyh_arg_t *)args;
6405 6408 rfm = replyh_arg->rfm;
6406 6409 mpt = replyh_arg->mpt;
6407 6410
6408 6411 ASSERT(mutex_owned(&mpt->m_mutex));
6409 6412
6410 6413 eventreply = (pMpi2EventNotificationReply_t)
6411 6414 (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6412 6415 event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6413 6416
6414 6417 if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
6415 6418 &eventreply->IOCStatus)) {
6416 6419 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
6417 6420 mptsas_log(mpt, CE_WARN,
6418 6421 "!mptsas_handle_event_sync: IOCStatus=0x%x, "
6419 6422 "IOCLogInfo=0x%x", iocstatus,
6420 6423 ddi_get32(mpt->m_acc_reply_frame_hdl,
6421 6424 &eventreply->IOCLogInfo));
6422 6425 } else {
6423 6426 mptsas_log(mpt, CE_WARN,
6424 6427 "mptsas_handle_event_sync: IOCStatus=0x%x, "
6425 6428 "IOCLogInfo=0x%x", iocstatus,
6426 6429 ddi_get32(mpt->m_acc_reply_frame_hdl,
6427 6430 &eventreply->IOCLogInfo));
6428 6431 }
6429 6432 }
6430 6433
6431 6434 /*
6432 6435 * figure out what kind of event we got and handle accordingly
6433 6436 */
6434 6437 switch (event) {
6435 6438 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
6436 6439 {
6437 6440 pMpi2EventDataSasTopologyChangeList_t sas_topo_change_list;
6438 6441 uint8_t num_entries, expstatus, phy;
6439 6442 uint8_t phystatus, physport, state, i;
6440 6443 uint8_t start_phy_num, link_rate;
6441 6444 uint16_t dev_handle, reason_code;
6442 6445 uint16_t enc_handle, expd_handle;
6443 6446 char string[80], curr[80], prev[80];
6444 6447 mptsas_topo_change_list_t *topo_head = NULL;
6445 6448 mptsas_topo_change_list_t *topo_tail = NULL;
6446 6449 mptsas_topo_change_list_t *topo_node = NULL;
6447 6450 mptsas_target_t *ptgt;
6448 6451 mptsas_smp_t *psmp;
6449 6452 uint8_t flags = 0, exp_flag;
6450 6453 smhba_info_t *pSmhba = NULL;
6451 6454
6452 6455 NDBG20(("mptsas_handle_event_sync: SAS topology change"));
6453 6456
6454 6457 sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
6455 6458 eventreply->EventData;
6456 6459
6457 6460 enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6458 6461 &sas_topo_change_list->EnclosureHandle);
6459 6462 expd_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6460 6463 &sas_topo_change_list->ExpanderDevHandle);
6461 6464 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6462 6465 &sas_topo_change_list->NumEntries);
6463 6466 start_phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
6464 6467 &sas_topo_change_list->StartPhyNum);
6465 6468 expstatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6466 6469 &sas_topo_change_list->ExpStatus);
6467 6470 physport = ddi_get8(mpt->m_acc_reply_frame_hdl,
6468 6471 &sas_topo_change_list->PhysicalPort);
6469 6472
6470 6473 string[0] = 0;
6471 6474 if (expd_handle) {
6472 6475 flags = MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED;
6473 6476 switch (expstatus) {
6474 6477 case MPI2_EVENT_SAS_TOPO_ES_ADDED:
6475 6478 (void) sprintf(string, " added");
6476 6479 /*
6477 6480 * New expander device added
6478 6481 */
6479 6482 mpt->m_port_chng = 1;
6480 6483 topo_node = kmem_zalloc(
6481 6484 sizeof (mptsas_topo_change_list_t),
6482 6485 KM_SLEEP);
6483 6486 topo_node->mpt = mpt;
6484 6487 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_SMP;
6485 6488 topo_node->un.physport = physport;
6486 6489 topo_node->devhdl = expd_handle;
6487 6490 topo_node->flags = flags;
6488 6491 topo_node->object = NULL;
6489 6492 if (topo_head == NULL) {
6490 6493 topo_head = topo_tail = topo_node;
6491 6494 } else {
6492 6495 topo_tail->next = topo_node;
6493 6496 topo_tail = topo_node;
6494 6497 }
6495 6498 break;
6496 6499 case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
6497 6500 (void) sprintf(string, " not responding, "
6498 6501 "removed");
6499 6502 psmp = refhash_linear_search(mpt->m_smp_targets,
6500 6503 mptsas_smp_eval_devhdl, &expd_handle);
6501 6504 if (psmp == NULL)
6502 6505 break;
6503 6506
6504 6507 topo_node = kmem_zalloc(
6505 6508 sizeof (mptsas_topo_change_list_t),
6506 6509 KM_SLEEP);
6507 6510 topo_node->mpt = mpt;
6508 6511 topo_node->un.phymask =
6509 6512 psmp->m_addr.mta_phymask;
6510 6513 topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
6511 6514 topo_node->devhdl = expd_handle;
6512 6515 topo_node->flags = flags;
6513 6516 topo_node->object = NULL;
6514 6517 if (topo_head == NULL) {
6515 6518 topo_head = topo_tail = topo_node;
6516 6519 } else {
6517 6520 topo_tail->next = topo_node;
6518 6521 topo_tail = topo_node;
6519 6522 }
6520 6523 break;
6521 6524 case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
6522 6525 break;
6523 6526 case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
6524 6527 (void) sprintf(string, " not responding, "
6525 6528 "delaying removal");
6526 6529 break;
6527 6530 default:
6528 6531 break;
6529 6532 }
6530 6533 } else {
6531 6534 flags = MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE;
6532 6535 }
6533 6536
6534 6537 NDBG20(("SAS TOPOLOGY CHANGE for enclosure %x expander %x%s\n",
6535 6538 enc_handle, expd_handle, string));
6536 6539 for (i = 0; i < num_entries; i++) {
6537 6540 phy = i + start_phy_num;
6538 6541 phystatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6539 6542 &sas_topo_change_list->PHY[i].PhyStatus);
6540 6543 dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6541 6544 &sas_topo_change_list->PHY[i].AttachedDevHandle);
6542 6545 reason_code = phystatus & MPI2_EVENT_SAS_TOPO_RC_MASK;
6543 6546 /*
6544 6547 * Filter out processing of Phy Vacant Status unless
6545 6548 * the reason code is "Not Responding". Process all
6546 6549 * other combinations of Phy Status and Reason Codes.
6547 6550 */
6548 6551 if ((phystatus &
6549 6552 MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) &&
6550 6553 (reason_code !=
6551 6554 MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) {
6552 6555 continue;
6553 6556 }
6554 6557 curr[0] = 0;
6555 6558 prev[0] = 0;
6556 6559 string[0] = 0;
6557 6560 switch (reason_code) {
6558 6561 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
6559 6562 {
6560 6563 NDBG20(("mptsas%d phy %d physical_port %d "
6561 6564 "dev_handle %d added", mpt->m_instance, phy,
6562 6565 physport, dev_handle));
6563 6566 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6564 6567 &sas_topo_change_list->PHY[i].LinkRate);
6565 6568 state = (link_rate &
6566 6569 MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6567 6570 MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6568 6571 switch (state) {
6569 6572 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6570 6573 (void) sprintf(curr, "is disabled");
6571 6574 break;
6572 6575 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6573 6576 (void) sprintf(curr, "is offline, "
6574 6577 "failed speed negotiation");
6575 6578 break;
6576 6579 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6577 6580 (void) sprintf(curr, "SATA OOB "
6578 6581 "complete");
6579 6582 break;
6580 6583 case SMP_RESET_IN_PROGRESS:
6581 6584 (void) sprintf(curr, "SMP reset in "
6582 6585 "progress");
6583 6586 break;
6584 6587 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6585 6588 (void) sprintf(curr, "is online at "
6586 6589 "1.5 Gbps");
6587 6590 break;
6588 6591 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6589 6592 (void) sprintf(curr, "is online at 3.0 "
6590 6593 "Gbps");
6591 6594 break;
6592 6595 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6593 6596 (void) sprintf(curr, "is online at 6.0 "
6594 6597 "Gbps");
6595 6598 break;
6596 6599 default:
6597 6600 (void) sprintf(curr, "state is "
6598 6601 "unknown");
6599 6602 break;
6600 6603 }
6601 6604 /*
6602 6605 * New target device added into the system.
6603 6606 * Set association flag according to if an
6604 6607 * expander is used or not.
6605 6608 */
6606 6609 exp_flag =
6607 6610 MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6608 6611 if (flags ==
6609 6612 MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6610 6613 flags = exp_flag;
6611 6614 }
6612 6615 topo_node = kmem_zalloc(
6613 6616 sizeof (mptsas_topo_change_list_t),
6614 6617 KM_SLEEP);
6615 6618 topo_node->mpt = mpt;
6616 6619 topo_node->event =
6617 6620 MPTSAS_DR_EVENT_RECONFIG_TARGET;
6618 6621 if (expd_handle == 0) {
6619 6622 /*
6620 6623 * Per MPI 2, if expander dev handle
6621 6624 * is 0, it's a directly attached
6622 6625 * device. So driver use PHY to decide
6623 6626 * which iport is associated
6624 6627 */
6625 6628 physport = phy;
6626 6629 mpt->m_port_chng = 1;
6627 6630 }
6628 6631 topo_node->un.physport = physport;
6629 6632 topo_node->devhdl = dev_handle;
6630 6633 topo_node->flags = flags;
6631 6634 topo_node->object = NULL;
6632 6635 if (topo_head == NULL) {
6633 6636 topo_head = topo_tail = topo_node;
6634 6637 } else {
6635 6638 topo_tail->next = topo_node;
6636 6639 topo_tail = topo_node;
6637 6640 }
6638 6641 break;
6639 6642 }
6640 6643 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
6641 6644 {
6642 6645 NDBG20(("mptsas%d phy %d physical_port %d "
6643 6646 "dev_handle %d removed", mpt->m_instance,
6644 6647 phy, physport, dev_handle));
6645 6648 /*
6646 6649 * Set association flag according to if an
6647 6650 * expander is used or not.
6648 6651 */
6649 6652 exp_flag =
6650 6653 MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6651 6654 if (flags ==
6652 6655 MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6653 6656 flags = exp_flag;
6654 6657 }
6655 6658 /*
6656 6659 * Target device is removed from the system
6657 6660 * Before the device is really offline from
6658 6661 * from system.
6659 6662 */
6660 6663 ptgt = refhash_linear_search(mpt->m_targets,
6661 6664 mptsas_target_eval_devhdl, &dev_handle);
6662 6665 /*
6663 6666 * If ptgt is NULL here, it means that the
6664 6667 * DevHandle is not in the hash table. This is
6665 6668 * reasonable sometimes. For example, if a
6666 6669 * disk was pulled, then added, then pulled
6667 6670 * again, the disk will not have been put into
6668 6671 * the hash table because the add event will
6669 6672 * have an invalid phymask. BUT, this does not
6670 6673 * mean that the DevHandle is invalid. The
6671 6674 * controller will still have a valid DevHandle
6672 6675 * that must be removed. To do this, use the
6673 6676 * MPTSAS_TOPO_FLAG_REMOVE_HANDLE event.
6674 6677 */
6675 6678 if (ptgt == NULL) {
6676 6679 topo_node = kmem_zalloc(
6677 6680 sizeof (mptsas_topo_change_list_t),
6678 6681 KM_SLEEP);
6679 6682 topo_node->mpt = mpt;
6680 6683 topo_node->un.phymask = 0;
6681 6684 topo_node->event =
6682 6685 MPTSAS_TOPO_FLAG_REMOVE_HANDLE;
6683 6686 topo_node->devhdl = dev_handle;
6684 6687 topo_node->flags = flags;
6685 6688 topo_node->object = NULL;
6686 6689 if (topo_head == NULL) {
6687 6690 topo_head = topo_tail =
6688 6691 topo_node;
6689 6692 } else {
6690 6693 topo_tail->next = topo_node;
6691 6694 topo_tail = topo_node;
6692 6695 }
6693 6696 break;
6694 6697 }
6695 6698
6696 6699 /*
6697 6700 * Update DR flag immediately avoid I/O failure
6698 6701 * before failover finish. Pay attention to the
6699 6702 * mutex protect, we need grab m_tx_waitq_mutex
6700 6703 * during set m_dr_flag because we won't add
6701 6704 * the following command into waitq, instead,
6702 6705 * we need return TRAN_BUSY in the tran_start
6703 6706 * context.
6704 6707 */
6705 6708 mutex_enter(&mpt->m_tx_waitq_mutex);
6706 6709 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6707 6710 mutex_exit(&mpt->m_tx_waitq_mutex);
6708 6711
6709 6712 topo_node = kmem_zalloc(
6710 6713 sizeof (mptsas_topo_change_list_t),
6711 6714 KM_SLEEP);
6712 6715 topo_node->mpt = mpt;
6713 6716 topo_node->un.phymask =
6714 6717 ptgt->m_addr.mta_phymask;
6715 6718 topo_node->event =
6716 6719 MPTSAS_DR_EVENT_OFFLINE_TARGET;
6717 6720 topo_node->devhdl = dev_handle;
6718 6721 topo_node->flags = flags;
6719 6722 topo_node->object = NULL;
6720 6723 if (topo_head == NULL) {
6721 6724 topo_head = topo_tail = topo_node;
6722 6725 } else {
6723 6726 topo_tail->next = topo_node;
6724 6727 topo_tail = topo_node;
6725 6728 }
6726 6729 break;
6727 6730 }
6728 6731 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
6729 6732 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6730 6733 &sas_topo_change_list->PHY[i].LinkRate);
6731 6734 state = (link_rate &
6732 6735 MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6733 6736 MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6734 6737 pSmhba = &mpt->m_phy_info[i].smhba_info;
6735 6738 pSmhba->negotiated_link_rate = state;
6736 6739 switch (state) {
6737 6740 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6738 6741 (void) sprintf(curr, "is disabled");
6739 6742 mptsas_smhba_log_sysevent(mpt,
6740 6743 ESC_SAS_PHY_EVENT,
6741 6744 SAS_PHY_REMOVE,
6742 6745 &mpt->m_phy_info[i].smhba_info);
6743 6746 mpt->m_phy_info[i].smhba_info.
6744 6747 negotiated_link_rate
6745 6748 = 0x1;
6746 6749 break;
6747 6750 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6748 6751 (void) sprintf(curr, "is offline, "
6749 6752 "failed speed negotiation");
6750 6753 mptsas_smhba_log_sysevent(mpt,
6751 6754 ESC_SAS_PHY_EVENT,
6752 6755 SAS_PHY_OFFLINE,
6753 6756 &mpt->m_phy_info[i].smhba_info);
6754 6757 break;
6755 6758 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6756 6759 (void) sprintf(curr, "SATA OOB "
6757 6760 "complete");
6758 6761 break;
6759 6762 case SMP_RESET_IN_PROGRESS:
6760 6763 (void) sprintf(curr, "SMP reset in "
6761 6764 "progress");
6762 6765 break;
6763 6766 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6764 6767 (void) sprintf(curr, "is online at "
6765 6768 "1.5 Gbps");
6766 6769 if ((expd_handle == 0) &&
6767 6770 (enc_handle == 1)) {
6768 6771 mpt->m_port_chng = 1;
6769 6772 }
6770 6773 mptsas_smhba_log_sysevent(mpt,
6771 6774 ESC_SAS_PHY_EVENT,
6772 6775 SAS_PHY_ONLINE,
6773 6776 &mpt->m_phy_info[i].smhba_info);
6774 6777 break;
6775 6778 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6776 6779 (void) sprintf(curr, "is online at 3.0 "
6777 6780 "Gbps");
6778 6781 if ((expd_handle == 0) &&
6779 6782 (enc_handle == 1)) {
6780 6783 mpt->m_port_chng = 1;
6781 6784 }
6782 6785 mptsas_smhba_log_sysevent(mpt,
6783 6786 ESC_SAS_PHY_EVENT,
6784 6787 SAS_PHY_ONLINE,
6785 6788 &mpt->m_phy_info[i].smhba_info);
6786 6789 break;
6787 6790 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6788 6791 (void) sprintf(curr, "is online at "
6789 6792 "6.0 Gbps");
6790 6793 if ((expd_handle == 0) &&
6791 6794 (enc_handle == 1)) {
6792 6795 mpt->m_port_chng = 1;
6793 6796 }
6794 6797 mptsas_smhba_log_sysevent(mpt,
6795 6798 ESC_SAS_PHY_EVENT,
6796 6799 SAS_PHY_ONLINE,
6797 6800 &mpt->m_phy_info[i].smhba_info);
6798 6801 break;
6799 6802 default:
6800 6803 (void) sprintf(curr, "state is "
6801 6804 "unknown");
6802 6805 break;
6803 6806 }
6804 6807
6805 6808 state = (link_rate &
6806 6809 MPI2_EVENT_SAS_TOPO_LR_PREV_MASK) >>
6807 6810 MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT;
6808 6811 switch (state) {
6809 6812 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6810 6813 (void) sprintf(prev, ", was disabled");
6811 6814 break;
6812 6815 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6813 6816 (void) sprintf(prev, ", was offline, "
6814 6817 "failed speed negotiation");
6815 6818 break;
6816 6819 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6817 6820 (void) sprintf(prev, ", was SATA OOB "
6818 6821 "complete");
6819 6822 break;
6820 6823 case SMP_RESET_IN_PROGRESS:
6821 6824 (void) sprintf(prev, ", was SMP reset "
6822 6825 "in progress");
6823 6826 break;
6824 6827 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6825 6828 (void) sprintf(prev, ", was online at "
6826 6829 "1.5 Gbps");
6827 6830 break;
6828 6831 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6829 6832 (void) sprintf(prev, ", was online at "
6830 6833 "3.0 Gbps");
6831 6834 break;
6832 6835 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6833 6836 (void) sprintf(prev, ", was online at "
6834 6837 "6.0 Gbps");
6835 6838 break;
6836 6839 default:
6837 6840 break;
6838 6841 }
6839 6842 (void) sprintf(&string[strlen(string)], "link "
6840 6843 "changed, ");
6841 6844 break;
6842 6845 case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
6843 6846 continue;
6844 6847 case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
6845 6848 (void) sprintf(&string[strlen(string)],
6846 6849 "target not responding, delaying "
6847 6850 "removal");
6848 6851 break;
6849 6852 }
6850 6853 NDBG20(("mptsas%d phy %d DevHandle %x, %s%s%s\n",
6851 6854 mpt->m_instance, phy, dev_handle, string, curr,
6852 6855 prev));
6853 6856 }
6854 6857 if (topo_head != NULL) {
6855 6858 /*
6856 6859 * Launch DR taskq to handle topology change
6857 6860 */
6858 6861 if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
6859 6862 mptsas_handle_dr, (void *)topo_head,
6860 6863 DDI_NOSLEEP)) != DDI_SUCCESS) {
6861 6864 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
6862 6865 "for handle SAS DR event failed. \n");
6863 6866 }
6864 6867 }
6865 6868 break;
6866 6869 }
6867 6870 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
6868 6871 {
6869 6872 Mpi2EventDataIrConfigChangeList_t *irChangeList;
6870 6873 mptsas_topo_change_list_t *topo_head = NULL;
6871 6874 mptsas_topo_change_list_t *topo_tail = NULL;
6872 6875 mptsas_topo_change_list_t *topo_node = NULL;
6873 6876 mptsas_target_t *ptgt;
6874 6877 uint8_t num_entries, i, reason;
6875 6878 uint16_t volhandle, diskhandle;
6876 6879
6877 6880 irChangeList = (pMpi2EventDataIrConfigChangeList_t)
6878 6881 eventreply->EventData;
6879 6882 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6880 6883 &irChangeList->NumElements);
6881 6884
6882 6885 NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
6883 6886 mpt->m_instance));
6884 6887
6885 6888 for (i = 0; i < num_entries; i++) {
6886 6889 reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
6887 6890 &irChangeList->ConfigElement[i].ReasonCode);
6888 6891 volhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6889 6892 &irChangeList->ConfigElement[i].VolDevHandle);
6890 6893 diskhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6891 6894 &irChangeList->ConfigElement[i].PhysDiskDevHandle);
6892 6895
6893 6896 switch (reason) {
6894 6897 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6895 6898 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6896 6899 {
6897 6900 NDBG20(("mptsas %d volume added\n",
6898 6901 mpt->m_instance));
6899 6902
6900 6903 topo_node = kmem_zalloc(
6901 6904 sizeof (mptsas_topo_change_list_t),
6902 6905 KM_SLEEP);
6903 6906
6904 6907 topo_node->mpt = mpt;
6905 6908 topo_node->event =
6906 6909 MPTSAS_DR_EVENT_RECONFIG_TARGET;
6907 6910 topo_node->un.physport = 0xff;
6908 6911 topo_node->devhdl = volhandle;
6909 6912 topo_node->flags =
6910 6913 MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6911 6914 topo_node->object = NULL;
6912 6915 if (topo_head == NULL) {
6913 6916 topo_head = topo_tail = topo_node;
6914 6917 } else {
6915 6918 topo_tail->next = topo_node;
6916 6919 topo_tail = topo_node;
6917 6920 }
6918 6921 break;
6919 6922 }
6920 6923 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6921 6924 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6922 6925 {
6923 6926 NDBG20(("mptsas %d volume deleted\n",
6924 6927 mpt->m_instance));
6925 6928 ptgt = refhash_linear_search(mpt->m_targets,
6926 6929 mptsas_target_eval_devhdl, &volhandle);
6927 6930 if (ptgt == NULL)
6928 6931 break;
6929 6932
6930 6933 /*
6931 6934 * Clear any flags related to volume
6932 6935 */
6933 6936 (void) mptsas_delete_volume(mpt, volhandle);
6934 6937
6935 6938 /*
6936 6939 * Update DR flag immediately avoid I/O failure
6937 6940 */
6938 6941 mutex_enter(&mpt->m_tx_waitq_mutex);
6939 6942 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6940 6943 mutex_exit(&mpt->m_tx_waitq_mutex);
6941 6944
6942 6945 topo_node = kmem_zalloc(
6943 6946 sizeof (mptsas_topo_change_list_t),
6944 6947 KM_SLEEP);
6945 6948 topo_node->mpt = mpt;
6946 6949 topo_node->un.phymask =
6947 6950 ptgt->m_addr.mta_phymask;
6948 6951 topo_node->event =
6949 6952 MPTSAS_DR_EVENT_OFFLINE_TARGET;
6950 6953 topo_node->devhdl = volhandle;
6951 6954 topo_node->flags =
6952 6955 MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6953 6956 topo_node->object = (void *)ptgt;
6954 6957 if (topo_head == NULL) {
6955 6958 topo_head = topo_tail = topo_node;
6956 6959 } else {
6957 6960 topo_tail->next = topo_node;
6958 6961 topo_tail = topo_node;
6959 6962 }
6960 6963 break;
6961 6964 }
6962 6965 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6963 6966 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6964 6967 {
6965 6968 ptgt = refhash_linear_search(mpt->m_targets,
6966 6969 mptsas_target_eval_devhdl, &diskhandle);
6967 6970 if (ptgt == NULL)
6968 6971 break;
6969 6972
6970 6973 /*
6971 6974 * Update DR flag immediately avoid I/O failure
6972 6975 */
6973 6976 mutex_enter(&mpt->m_tx_waitq_mutex);
6974 6977 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6975 6978 mutex_exit(&mpt->m_tx_waitq_mutex);
6976 6979
6977 6980 topo_node = kmem_zalloc(
6978 6981 sizeof (mptsas_topo_change_list_t),
6979 6982 KM_SLEEP);
6980 6983 topo_node->mpt = mpt;
6981 6984 topo_node->un.phymask =
6982 6985 ptgt->m_addr.mta_phymask;
6983 6986 topo_node->event =
6984 6987 MPTSAS_DR_EVENT_OFFLINE_TARGET;
6985 6988 topo_node->devhdl = diskhandle;
6986 6989 topo_node->flags =
6987 6990 MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
6988 6991 topo_node->object = (void *)ptgt;
6989 6992 if (topo_head == NULL) {
6990 6993 topo_head = topo_tail = topo_node;
6991 6994 } else {
6992 6995 topo_tail->next = topo_node;
6993 6996 topo_tail = topo_node;
6994 6997 }
6995 6998 break;
6996 6999 }
6997 7000 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
6998 7001 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
6999 7002 {
7000 7003 /*
7001 7004 * The physical drive is released by a IR
7002 7005 * volume. But we cannot get the the physport
7003 7006 * or phynum from the event data, so we only
7004 7007 * can get the physport/phynum after SAS
7005 7008 * Device Page0 request for the devhdl.
7006 7009 */
7007 7010 topo_node = kmem_zalloc(
7008 7011 sizeof (mptsas_topo_change_list_t),
7009 7012 KM_SLEEP);
7010 7013 topo_node->mpt = mpt;
7011 7014 topo_node->un.phymask = 0;
7012 7015 topo_node->event =
7013 7016 MPTSAS_DR_EVENT_RECONFIG_TARGET;
7014 7017 topo_node->devhdl = diskhandle;
7015 7018 topo_node->flags =
7016 7019 MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7017 7020 topo_node->object = NULL;
7018 7021 mpt->m_port_chng = 1;
7019 7022 if (topo_head == NULL) {
7020 7023 topo_head = topo_tail = topo_node;
7021 7024 } else {
7022 7025 topo_tail->next = topo_node;
7023 7026 topo_tail = topo_node;
7024 7027 }
7025 7028 break;
7026 7029 }
7027 7030 default:
7028 7031 break;
7029 7032 }
7030 7033 }
7031 7034
7032 7035 if (topo_head != NULL) {
7033 7036 /*
7034 7037 * Launch DR taskq to handle topology change
7035 7038 */
7036 7039 if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7037 7040 mptsas_handle_dr, (void *)topo_head,
7038 7041 DDI_NOSLEEP)) != DDI_SUCCESS) {
7039 7042 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7040 7043 "for handle SAS DR event failed. \n");
7041 7044 }
7042 7045 }
7043 7046 break;
7044 7047 }
7045 7048 default:
7046 7049 return (DDI_FAILURE);
7047 7050 }
7048 7051
7049 7052 return (DDI_SUCCESS);
7050 7053 }
7051 7054
7052 7055 /*
7053 7056 * handle events from ioc
7054 7057 */
7055 7058 static void
7056 7059 mptsas_handle_event(void *args)
7057 7060 {
7058 7061 m_replyh_arg_t *replyh_arg;
7059 7062 pMpi2EventNotificationReply_t eventreply;
7060 7063 uint32_t event, iocloginfo, rfm;
7061 7064 uint32_t status;
7062 7065 uint8_t port;
7063 7066 mptsas_t *mpt;
7064 7067 uint_t iocstatus;
7065 7068
7066 7069 replyh_arg = (m_replyh_arg_t *)args;
7067 7070 rfm = replyh_arg->rfm;
7068 7071 mpt = replyh_arg->mpt;
7069 7072
7070 7073 mutex_enter(&mpt->m_mutex);
7071 7074 /*
7072 7075 * If HBA is being reset, drop incoming event.
7073 7076 */
7074 7077 if (mpt->m_in_reset) {
7075 7078 NDBG20(("dropping event received prior to reset"));
7076 7079 mutex_exit(&mpt->m_mutex);
7077 7080 return;
7078 7081 }
7079 7082
7080 7083 eventreply = (pMpi2EventNotificationReply_t)
7081 7084 (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
7082 7085 event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
7083 7086
7084 7087 if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
7085 7088 &eventreply->IOCStatus)) {
7086 7089 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
7087 7090 mptsas_log(mpt, CE_WARN,
7088 7091 "!mptsas_handle_event: IOCStatus=0x%x, "
7089 7092 "IOCLogInfo=0x%x", iocstatus,
7090 7093 ddi_get32(mpt->m_acc_reply_frame_hdl,
7091 7094 &eventreply->IOCLogInfo));
7092 7095 } else {
7093 7096 mptsas_log(mpt, CE_WARN,
7094 7097 "mptsas_handle_event: IOCStatus=0x%x, "
7095 7098 "IOCLogInfo=0x%x", iocstatus,
7096 7099 ddi_get32(mpt->m_acc_reply_frame_hdl,
7097 7100 &eventreply->IOCLogInfo));
7098 7101 }
7099 7102 }
7100 7103
7101 7104 /*
7102 7105 * figure out what kind of event we got and handle accordingly
7103 7106 */
7104 7107 switch (event) {
7105 7108 case MPI2_EVENT_LOG_ENTRY_ADDED:
7106 7109 break;
7107 7110 case MPI2_EVENT_LOG_DATA:
7108 7111 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7109 7112 &eventreply->IOCLogInfo);
7110 7113 NDBG20(("mptsas %d log info %x received.\n", mpt->m_instance,
7111 7114 iocloginfo));
7112 7115 break;
7113 7116 case MPI2_EVENT_STATE_CHANGE:
7114 7117 NDBG20(("mptsas%d state change.", mpt->m_instance));
7115 7118 break;
7116 7119 case MPI2_EVENT_HARD_RESET_RECEIVED:
7117 7120 NDBG20(("mptsas%d event change.", mpt->m_instance));
7118 7121 break;
7119 7122 case MPI2_EVENT_SAS_DISCOVERY:
7120 7123 {
7121 7124 MPI2_EVENT_DATA_SAS_DISCOVERY *sasdiscovery;
7122 7125 char string[80];
7123 7126 uint8_t rc;
7124 7127
7125 7128 sasdiscovery =
7126 7129 (pMpi2EventDataSasDiscovery_t)eventreply->EventData;
7127 7130
7128 7131 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7129 7132 &sasdiscovery->ReasonCode);
7130 7133 port = ddi_get8(mpt->m_acc_reply_frame_hdl,
7131 7134 &sasdiscovery->PhysicalPort);
7132 7135 status = ddi_get32(mpt->m_acc_reply_frame_hdl,
7133 7136 &sasdiscovery->DiscoveryStatus);
7134 7137
7135 7138 string[0] = 0;
7136 7139 switch (rc) {
7137 7140 case MPI2_EVENT_SAS_DISC_RC_STARTED:
7138 7141 (void) sprintf(string, "STARTING");
7139 7142 break;
7140 7143 case MPI2_EVENT_SAS_DISC_RC_COMPLETED:
7141 7144 (void) sprintf(string, "COMPLETED");
7142 7145 break;
7143 7146 default:
7144 7147 (void) sprintf(string, "UNKNOWN");
7145 7148 break;
7146 7149 }
7147 7150
7148 7151 NDBG20(("SAS DISCOVERY is %s for port %d, status %x", string,
7149 7152 port, status));
7150 7153
7151 7154 break;
7152 7155 }
7153 7156 case MPI2_EVENT_EVENT_CHANGE:
7154 7157 NDBG20(("mptsas%d event change.", mpt->m_instance));
7155 7158 break;
7156 7159 case MPI2_EVENT_TASK_SET_FULL:
7157 7160 {
7158 7161 pMpi2EventDataTaskSetFull_t taskfull;
7159 7162
7160 7163 taskfull = (pMpi2EventDataTaskSetFull_t)eventreply->EventData;
7161 7164
7162 7165 NDBG20(("TASK_SET_FULL received for mptsas%d, depth %d\n",
7163 7166 mpt->m_instance, ddi_get16(mpt->m_acc_reply_frame_hdl,
7164 7167 &taskfull->CurrentDepth)));
7165 7168 break;
7166 7169 }
7167 7170 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7168 7171 {
7169 7172 /*
7170 7173 * SAS TOPOLOGY CHANGE LIST Event has already been handled
7171 7174 * in mptsas_handle_event_sync() of interrupt context
7172 7175 */
7173 7176 break;
7174 7177 }
7175 7178 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7176 7179 {
7177 7180 pMpi2EventDataSasEnclDevStatusChange_t encstatus;
7178 7181 uint8_t rc;
7179 7182 char string[80];
7180 7183
7181 7184 encstatus = (pMpi2EventDataSasEnclDevStatusChange_t)
7182 7185 eventreply->EventData;
7183 7186
7184 7187 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7185 7188 &encstatus->ReasonCode);
7186 7189 switch (rc) {
7187 7190 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
7188 7191 (void) sprintf(string, "added");
7189 7192 break;
7190 7193 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
7191 7194 (void) sprintf(string, ", not responding");
7192 7195 break;
7193 7196 default:
7194 7197 break;
7195 7198 }
7196 7199 NDBG20(("mptsas%d ENCLOSURE STATUS CHANGE for enclosure %x%s\n",
7197 7200 mpt->m_instance, ddi_get16(mpt->m_acc_reply_frame_hdl,
7198 7201 &encstatus->EnclosureHandle), string));
7199 7202 break;
7200 7203 }
7201 7204
7202 7205 /*
7203 7206 * MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE is handled by
7204 7207 * mptsas_handle_event_sync,in here just send ack message.
7205 7208 */
7206 7209 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7207 7210 {
7208 7211 pMpi2EventDataSasDeviceStatusChange_t statuschange;
7209 7212 uint8_t rc;
7210 7213 uint16_t devhdl;
7211 7214 uint64_t wwn = 0;
7212 7215 uint32_t wwn_lo, wwn_hi;
7213 7216
7214 7217 statuschange = (pMpi2EventDataSasDeviceStatusChange_t)
7215 7218 eventreply->EventData;
7216 7219 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7217 7220 &statuschange->ReasonCode);
7218 7221 wwn_lo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7219 7222 (uint32_t *)(void *)&statuschange->SASAddress);
7220 7223 wwn_hi = ddi_get32(mpt->m_acc_reply_frame_hdl,
7221 7224 (uint32_t *)(void *)&statuschange->SASAddress + 1);
7222 7225 wwn = ((uint64_t)wwn_hi << 32) | wwn_lo;
7223 7226 devhdl = ddi_get16(mpt->m_acc_reply_frame_hdl,
7224 7227 &statuschange->DevHandle);
7225 7228
7226 7229 NDBG13(("MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE wwn is %"PRIx64,
7227 7230 wwn));
7228 7231
7229 7232 switch (rc) {
7230 7233 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7231 7234 NDBG20(("SMART data received, ASC/ASCQ = %02x/%02x",
7232 7235 ddi_get8(mpt->m_acc_reply_frame_hdl,
7233 7236 &statuschange->ASC),
7234 7237 ddi_get8(mpt->m_acc_reply_frame_hdl,
7235 7238 &statuschange->ASCQ)));
7236 7239 break;
7237 7240
7238 7241 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7239 7242 NDBG20(("Device not supported"));
7240 7243 break;
7241 7244
7242 7245 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7243 7246 NDBG20(("IOC internally generated the Target Reset "
7244 7247 "for devhdl:%x", devhdl));
7245 7248 break;
7246 7249
7247 7250 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
7248 7251 NDBG20(("IOC's internally generated Target Reset "
7249 7252 "completed for devhdl:%x", devhdl));
7250 7253 break;
7251 7254
7252 7255 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7253 7256 NDBG20(("IOC internally generated Abort Task"));
7254 7257 break;
7255 7258
7256 7259 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
7257 7260 NDBG20(("IOC's internally generated Abort Task "
7258 7261 "completed"));
7259 7262 break;
7260 7263
7261 7264 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7262 7265 NDBG20(("IOC internally generated Abort Task Set"));
7263 7266 break;
7264 7267
7265 7268 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7266 7269 NDBG20(("IOC internally generated Clear Task Set"));
7267 7270 break;
7268 7271
7269 7272 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7270 7273 NDBG20(("IOC internally generated Query Task"));
7271 7274 break;
7272 7275
7273 7276 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
7274 7277 NDBG20(("Device sent an Asynchronous Notification"));
7275 7278 break;
7276 7279
7277 7280 default:
7278 7281 break;
7279 7282 }
7280 7283 break;
7281 7284 }
7282 7285 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7283 7286 {
7284 7287 /*
7285 7288 * IR TOPOLOGY CHANGE LIST Event has already been handled
7286 7289 * in mpt_handle_event_sync() of interrupt context
7287 7290 */
7288 7291 break;
7289 7292 }
7290 7293 case MPI2_EVENT_IR_OPERATION_STATUS:
7291 7294 {
7292 7295 Mpi2EventDataIrOperationStatus_t *irOpStatus;
7293 7296 char reason_str[80];
7294 7297 uint8_t rc, percent;
7295 7298 uint16_t handle;
7296 7299
7297 7300 irOpStatus = (pMpi2EventDataIrOperationStatus_t)
7298 7301 eventreply->EventData;
7299 7302 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7300 7303 &irOpStatus->RAIDOperation);
7301 7304 percent = ddi_get8(mpt->m_acc_reply_frame_hdl,
7302 7305 &irOpStatus->PercentComplete);
7303 7306 handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7304 7307 &irOpStatus->VolDevHandle);
7305 7308
7306 7309 switch (rc) {
7307 7310 case MPI2_EVENT_IR_RAIDOP_RESYNC:
7308 7311 (void) sprintf(reason_str, "resync");
7309 7312 break;
7310 7313 case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
7311 7314 (void) sprintf(reason_str, "online capacity "
7312 7315 "expansion");
7313 7316 break;
7314 7317 case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
7315 7318 (void) sprintf(reason_str, "consistency check");
7316 7319 break;
7317 7320 default:
7318 7321 (void) sprintf(reason_str, "unknown reason %x",
7319 7322 rc);
7320 7323 }
7321 7324
7322 7325 NDBG20(("mptsas%d raid operational status: (%s)"
7323 7326 "\thandle(0x%04x), percent complete(%d)\n",
7324 7327 mpt->m_instance, reason_str, handle, percent));
7325 7328 break;
7326 7329 }
7327 7330 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7328 7331 {
7329 7332 pMpi2EventDataSasBroadcastPrimitive_t sas_broadcast;
7330 7333 uint8_t phy_num;
7331 7334 uint8_t primitive;
7332 7335
7333 7336 sas_broadcast = (pMpi2EventDataSasBroadcastPrimitive_t)
7334 7337 eventreply->EventData;
7335 7338
7336 7339 phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
7337 7340 &sas_broadcast->PhyNum);
7338 7341 primitive = ddi_get8(mpt->m_acc_reply_frame_hdl,
7339 7342 &sas_broadcast->Primitive);
7340 7343
7341 7344 switch (primitive) {
7342 7345 case MPI2_EVENT_PRIMITIVE_CHANGE:
7343 7346 mptsas_smhba_log_sysevent(mpt,
7344 7347 ESC_SAS_HBA_PORT_BROADCAST,
7345 7348 SAS_PORT_BROADCAST_CHANGE,
7346 7349 &mpt->m_phy_info[phy_num].smhba_info);
7347 7350 break;
7348 7351 case MPI2_EVENT_PRIMITIVE_SES:
7349 7352 mptsas_smhba_log_sysevent(mpt,
7350 7353 ESC_SAS_HBA_PORT_BROADCAST,
7351 7354 SAS_PORT_BROADCAST_SES,
7352 7355 &mpt->m_phy_info[phy_num].smhba_info);
7353 7356 break;
7354 7357 case MPI2_EVENT_PRIMITIVE_EXPANDER:
7355 7358 mptsas_smhba_log_sysevent(mpt,
7356 7359 ESC_SAS_HBA_PORT_BROADCAST,
7357 7360 SAS_PORT_BROADCAST_D01_4,
7358 7361 &mpt->m_phy_info[phy_num].smhba_info);
7359 7362 break;
7360 7363 case MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT:
7361 7364 mptsas_smhba_log_sysevent(mpt,
7362 7365 ESC_SAS_HBA_PORT_BROADCAST,
7363 7366 SAS_PORT_BROADCAST_D04_7,
7364 7367 &mpt->m_phy_info[phy_num].smhba_info);
7365 7368 break;
7366 7369 case MPI2_EVENT_PRIMITIVE_RESERVED3:
7367 7370 mptsas_smhba_log_sysevent(mpt,
7368 7371 ESC_SAS_HBA_PORT_BROADCAST,
7369 7372 SAS_PORT_BROADCAST_D16_7,
7370 7373 &mpt->m_phy_info[phy_num].smhba_info);
7371 7374 break;
7372 7375 case MPI2_EVENT_PRIMITIVE_RESERVED4:
7373 7376 mptsas_smhba_log_sysevent(mpt,
7374 7377 ESC_SAS_HBA_PORT_BROADCAST,
7375 7378 SAS_PORT_BROADCAST_D29_7,
7376 7379 &mpt->m_phy_info[phy_num].smhba_info);
7377 7380 break;
7378 7381 case MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED:
7379 7382 mptsas_smhba_log_sysevent(mpt,
7380 7383 ESC_SAS_HBA_PORT_BROADCAST,
7381 7384 SAS_PORT_BROADCAST_D24_0,
7382 7385 &mpt->m_phy_info[phy_num].smhba_info);
7383 7386 break;
7384 7387 case MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED:
7385 7388 mptsas_smhba_log_sysevent(mpt,
7386 7389 ESC_SAS_HBA_PORT_BROADCAST,
7387 7390 SAS_PORT_BROADCAST_D27_4,
7388 7391 &mpt->m_phy_info[phy_num].smhba_info);
7389 7392 break;
7390 7393 default:
7391 7394 NDBG20(("mptsas%d: unknown BROADCAST PRIMITIVE"
7392 7395 " %x received",
7393 7396 mpt->m_instance, primitive));
7394 7397 break;
7395 7398 }
7396 7399 NDBG20(("mptsas%d sas broadcast primitive: "
7397 7400 "\tprimitive(0x%04x), phy(%d) complete\n",
7398 7401 mpt->m_instance, primitive, phy_num));
7399 7402 break;
7400 7403 }
7401 7404 case MPI2_EVENT_IR_VOLUME:
7402 7405 {
7403 7406 Mpi2EventDataIrVolume_t *irVolume;
7404 7407 uint16_t devhandle;
7405 7408 uint32_t state;
7406 7409 int config, vol;
7407 7410 uint8_t found = FALSE;
7408 7411
7409 7412 irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
7410 7413 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7411 7414 &irVolume->NewValue);
7412 7415 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7413 7416 &irVolume->VolDevHandle);
7414 7417
7415 7418 NDBG20(("EVENT_IR_VOLUME event is received"));
7416 7419
7417 7420 /*
7418 7421 * Get latest RAID info and then find the DevHandle for this
7419 7422 * event in the configuration. If the DevHandle is not found
7420 7423 * just exit the event.
7421 7424 */
7422 7425 (void) mptsas_get_raid_info(mpt);
7423 7426 for (config = 0; (config < mpt->m_num_raid_configs) &&
7424 7427 (!found); config++) {
7425 7428 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
7426 7429 if (mpt->m_raidconfig[config].m_raidvol[vol].
7427 7430 m_raidhandle == devhandle) {
7428 7431 found = TRUE;
7429 7432 break;
7430 7433 }
7431 7434 }
7432 7435 }
7433 7436 if (!found) {
7434 7437 break;
7435 7438 }
7436 7439
7437 7440 switch (irVolume->ReasonCode) {
7438 7441 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
7439 7442 {
7440 7443 uint32_t i;
7441 7444 mpt->m_raidconfig[config].m_raidvol[vol].m_settings =
7442 7445 state;
7443 7446
7444 7447 i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING;
7445 7448 mptsas_log(mpt, CE_NOTE, " Volume %d settings changed"
7446 7449 ", auto-config of hot-swap drives is %s"
7447 7450 ", write caching is %s"
7448 7451 ", hot-spare pool mask is %02x\n",
7449 7452 vol, state &
7450 7453 MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE
7451 7454 ? "disabled" : "enabled",
7452 7455 i == MPI2_RAIDVOL0_SETTING_UNCHANGED
7453 7456 ? "controlled by member disks" :
7454 7457 i == MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING
7455 7458 ? "disabled" :
7456 7459 i == MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING
7457 7460 ? "enabled" :
7458 7461 "incorrectly set",
7459 7462 (state >> 16) & 0xff);
7460 7463 break;
7461 7464 }
7462 7465 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
7463 7466 {
7464 7467 mpt->m_raidconfig[config].m_raidvol[vol].m_state =
7465 7468 (uint8_t)state;
7466 7469
7467 7470 mptsas_log(mpt, CE_NOTE,
7468 7471 "Volume %d is now %s\n", vol,
7469 7472 state == MPI2_RAID_VOL_STATE_OPTIMAL
7470 7473 ? "optimal" :
7471 7474 state == MPI2_RAID_VOL_STATE_DEGRADED
7472 7475 ? "degraded" :
7473 7476 state == MPI2_RAID_VOL_STATE_ONLINE
7474 7477 ? "online" :
7475 7478 state == MPI2_RAID_VOL_STATE_INITIALIZING
7476 7479 ? "initializing" :
7477 7480 state == MPI2_RAID_VOL_STATE_FAILED
7478 7481 ? "failed" :
7479 7482 state == MPI2_RAID_VOL_STATE_MISSING
7480 7483 ? "missing" :
7481 7484 "state unknown");
7482 7485 break;
7483 7486 }
7484 7487 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
7485 7488 {
7486 7489 mpt->m_raidconfig[config].m_raidvol[vol].
7487 7490 m_statusflags = state;
7488 7491
7489 7492 mptsas_log(mpt, CE_NOTE,
7490 7493 " Volume %d is now %s%s%s%s%s%s%s%s%s\n",
7491 7494 vol,
7492 7495 state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED
7493 7496 ? ", enabled" : ", disabled",
7494 7497 state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED
7495 7498 ? ", quiesced" : "",
7496 7499 state & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
7497 7500 ? ", inactive" : ", active",
7498 7501 state &
7499 7502 MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL
7500 7503 ? ", bad block table is full" : "",
7501 7504 state &
7502 7505 MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
7503 7506 ? ", resync in progress" : "",
7504 7507 state & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT
7505 7508 ? ", background initialization in progress" : "",
7506 7509 state &
7507 7510 MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION
7508 7511 ? ", capacity expansion in progress" : "",
7509 7512 state &
7510 7513 MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK
7511 7514 ? ", consistency check in progress" : "",
7512 7515 state & MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB
7513 7516 ? ", data scrub in progress" : "");
7514 7517 break;
7515 7518 }
7516 7519 default:
7517 7520 break;
7518 7521 }
7519 7522 break;
7520 7523 }
7521 7524 case MPI2_EVENT_IR_PHYSICAL_DISK:
7522 7525 {
7523 7526 Mpi2EventDataIrPhysicalDisk_t *irPhysDisk;
7524 7527 uint16_t devhandle, enchandle, slot;
7525 7528 uint32_t status, state;
7526 7529 uint8_t physdisknum, reason;
7527 7530
7528 7531 irPhysDisk = (Mpi2EventDataIrPhysicalDisk_t *)
7529 7532 eventreply->EventData;
7530 7533 physdisknum = ddi_get8(mpt->m_acc_reply_frame_hdl,
7531 7534 &irPhysDisk->PhysDiskNum);
7532 7535 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7533 7536 &irPhysDisk->PhysDiskDevHandle);
7534 7537 enchandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7535 7538 &irPhysDisk->EnclosureHandle);
7536 7539 slot = ddi_get16(mpt->m_acc_reply_frame_hdl,
7537 7540 &irPhysDisk->Slot);
7538 7541 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7539 7542 &irPhysDisk->NewValue);
7540 7543 reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
7541 7544 &irPhysDisk->ReasonCode);
7542 7545
7543 7546 NDBG20(("EVENT_IR_PHYSICAL_DISK event is received"));
7544 7547
7545 7548 switch (reason) {
7546 7549 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
7547 7550 mptsas_log(mpt, CE_NOTE,
7548 7551 " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7549 7552 "for enclosure with handle 0x%x is now in hot "
7550 7553 "spare pool %d",
7551 7554 physdisknum, devhandle, slot, enchandle,
7552 7555 (state >> 16) & 0xff);
7553 7556 break;
7554 7557
7555 7558 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
7556 7559 status = state;
7557 7560 mptsas_log(mpt, CE_NOTE,
7558 7561 " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7559 7562 "for enclosure with handle 0x%x is now "
7560 7563 "%s%s%s%s%s\n", physdisknum, devhandle, slot,
7561 7564 enchandle,
7562 7565 status & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME
7563 7566 ? ", inactive" : ", active",
7564 7567 status & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
7565 7568 ? ", out of sync" : "",
7566 7569 status & MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED
7567 7570 ? ", quiesced" : "",
7568 7571 status &
7569 7572 MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED
7570 7573 ? ", write cache enabled" : "",
7571 7574 status & MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET
7572 7575 ? ", capacity expansion target" : "");
7573 7576 break;
7574 7577
7575 7578 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
7576 7579 mptsas_log(mpt, CE_NOTE,
7577 7580 " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7578 7581 "for enclosure with handle 0x%x is now %s\n",
7579 7582 physdisknum, devhandle, slot, enchandle,
7580 7583 state == MPI2_RAID_PD_STATE_OPTIMAL
7581 7584 ? "optimal" :
7582 7585 state == MPI2_RAID_PD_STATE_REBUILDING
7583 7586 ? "rebuilding" :
7584 7587 state == MPI2_RAID_PD_STATE_DEGRADED
7585 7588 ? "degraded" :
7586 7589 state == MPI2_RAID_PD_STATE_HOT_SPARE
7587 7590 ? "a hot spare" :
7588 7591 state == MPI2_RAID_PD_STATE_ONLINE
7589 7592 ? "online" :
7590 7593 state == MPI2_RAID_PD_STATE_OFFLINE
7591 7594 ? "offline" :
7592 7595 state == MPI2_RAID_PD_STATE_NOT_COMPATIBLE
7593 7596 ? "not compatible" :
7594 7597 state == MPI2_RAID_PD_STATE_NOT_CONFIGURED
7595 7598 ? "not configured" :
7596 7599 "state unknown");
7597 7600 break;
7598 7601 }
7599 7602 break;
7600 7603 }
7601 7604 default:
7602 7605 NDBG20(("mptsas%d: unknown event %x received",
7603 7606 mpt->m_instance, event));
7604 7607 break;
7605 7608 }
7606 7609
7607 7610 /*
7608 7611 * Return the reply frame to the free queue.
7609 7612 */
7610 7613 ddi_put32(mpt->m_acc_free_queue_hdl,
7611 7614 &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index], rfm);
7612 7615 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
7613 7616 DDI_DMA_SYNC_FORDEV);
7614 7617 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
7615 7618 mpt->m_free_index = 0;
7616 7619 }
7617 7620 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
7618 7621 mpt->m_free_index);
7619 7622 mutex_exit(&mpt->m_mutex);
7620 7623 }
7621 7624
7622 7625 /*
7623 7626 * invoked from timeout() to restart qfull cmds with throttle == 0
7624 7627 */
7625 7628 static void
7626 7629 mptsas_restart_cmd(void *arg)
7627 7630 {
7628 7631 mptsas_t *mpt = arg;
7629 7632 mptsas_target_t *ptgt = NULL;
7630 7633
7631 7634 mutex_enter(&mpt->m_mutex);
7632 7635
7633 7636 mpt->m_restart_cmd_timeid = 0;
7634 7637
7635 7638 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
7636 7639 ptgt = refhash_next(mpt->m_targets, ptgt)) {
7637 7640 if (ptgt->m_reset_delay == 0) {
7638 7641 if (ptgt->m_t_throttle == QFULL_THROTTLE) {
7639 7642 mptsas_set_throttle(mpt, ptgt,
7640 7643 MAX_THROTTLE);
7641 7644 }
7642 7645 }
7643 7646 }
7644 7647 mptsas_restart_hba(mpt);
7645 7648 mutex_exit(&mpt->m_mutex);
7646 7649 }
7647 7650
7648 7651 void
7649 7652 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
7650 7653 {
7651 7654 int slot;
7652 7655 mptsas_slots_t *slots = mpt->m_active;
7653 7656 int t;
7654 7657 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
7655 7658
7656 7659 ASSERT(cmd != NULL);
7657 7660 ASSERT(cmd->cmd_queued == FALSE);
7658 7661
7659 7662 /*
7660 7663 * Task Management cmds are removed in their own routines. Also,
7661 7664 * we don't want to modify timeout based on TM cmds.
7662 7665 */
7663 7666 if (cmd->cmd_flags & CFLAG_TM_CMD) {
7664 7667 return;
7665 7668 }
7666 7669
7667 7670 t = Tgt(cmd);
7668 7671 slot = cmd->cmd_slot;
7669 7672
7670 7673 /*
7671 7674 * remove the cmd.
7672 7675 */
7673 7676 if (cmd == slots->m_slot[slot]) {
7674 7677 NDBG31(("mptsas_remove_cmd: removing cmd=0x%p", (void *)cmd));
7675 7678 slots->m_slot[slot] = NULL;
7676 7679 mpt->m_ncmds--;
7677 7680
7678 7681 /*
7679 7682 * only decrement per target ncmds if command
7680 7683 * has a target associated with it.
7681 7684 */
7682 7685 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
7683 7686 ptgt->m_t_ncmds--;
7684 7687 /*
7685 7688 * reset throttle if we just ran an untagged command
7686 7689 * to a tagged target
7687 7690 */
7688 7691 if ((ptgt->m_t_ncmds == 0) &&
7689 7692 ((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0)) {
7690 7693 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
7691 7694 }
7692 7695 }
7693 7696
7694 7697 }
7695 7698
7696 7699 /*
7697 7700 * This is all we need to do for ioc commands.
7698 7701 */
7699 7702 if (cmd->cmd_flags & CFLAG_CMDIOC) {
7700 7703 mptsas_return_to_pool(mpt, cmd);
7701 7704 return;
7702 7705 }
7703 7706
7704 7707 /*
7705 7708 * Figure out what to set tag Q timeout for...
7706 7709 *
7707 7710 * Optimize: If we have duplicate's of same timeout
7708 7711 * we're using, then we'll use it again until we run
7709 7712 * out of duplicates. This should be the normal case
7710 7713 * for block and raw I/O.
7711 7714 * If no duplicates, we have to scan through tag que and
7712 7715 * find the longest timeout value and use it. This is
7713 7716 * going to take a while...
7714 7717 * Add 1 to m_n_normal to account for TM request.
7715 7718 */
7716 7719 if (cmd->cmd_pkt->pkt_time == ptgt->m_timebase) {
7717 7720 if (--(ptgt->m_dups) == 0) {
7718 7721 if (ptgt->m_t_ncmds) {
7719 7722 mptsas_cmd_t *ssp;
7720 7723 uint_t n = 0;
7721 7724 ushort_t nslots = (slots->m_n_normal + 1);
7722 7725 ushort_t i;
7723 7726 /*
7724 7727 * This crude check assumes we don't do
7725 7728 * this too often which seems reasonable
7726 7729 * for block and raw I/O.
7727 7730 */
7728 7731 for (i = 0; i < nslots; i++) {
7729 7732 ssp = slots->m_slot[i];
7730 7733 if (ssp && (Tgt(ssp) == t) &&
7731 7734 (ssp->cmd_pkt->pkt_time > n)) {
7732 7735 n = ssp->cmd_pkt->pkt_time;
7733 7736 ptgt->m_dups = 1;
7734 7737 } else if (ssp && (Tgt(ssp) == t) &&
7735 7738 (ssp->cmd_pkt->pkt_time == n)) {
7736 7739 ptgt->m_dups++;
7737 7740 }
7738 7741 }
7739 7742 ptgt->m_timebase = n;
7740 7743 } else {
7741 7744 ptgt->m_dups = 0;
7742 7745 ptgt->m_timebase = 0;
7743 7746 }
7744 7747 }
7745 7748 }
7746 7749 ptgt->m_timeout = ptgt->m_timebase;
7747 7750
7748 7751 ASSERT(cmd != slots->m_slot[cmd->cmd_slot]);
7749 7752 }
7750 7753
7751 7754 /*
7752 7755 * accept all cmds on the tx_waitq if any and then
7753 7756 * start a fresh request from the top of the device queue.
7754 7757 *
7755 7758 * since there are always cmds queued on the tx_waitq, and rare cmds on
7756 7759 * the instance waitq, so this function should not be invoked in the ISR,
7757 7760 * the mptsas_restart_waitq() is invoked in the ISR instead. otherwise, the
7758 7761 * burden belongs to the IO dispatch CPUs is moved the interrupt CPU.
7759 7762 */
7760 7763 static void
7761 7764 mptsas_restart_hba(mptsas_t *mpt)
7762 7765 {
7763 7766 ASSERT(mutex_owned(&mpt->m_mutex));
7764 7767
7765 7768 mutex_enter(&mpt->m_tx_waitq_mutex);
7766 7769 if (mpt->m_tx_waitq) {
7767 7770 mptsas_accept_tx_waitq(mpt);
7768 7771 }
7769 7772 mutex_exit(&mpt->m_tx_waitq_mutex);
7770 7773 mptsas_restart_waitq(mpt);
7771 7774 }
7772 7775
7773 7776 /*
7774 7777 * start a fresh request from the top of the device queue
7775 7778 */
7776 7779 static void
7777 7780 mptsas_restart_waitq(mptsas_t *mpt)
7778 7781 {
7779 7782 mptsas_cmd_t *cmd, *next_cmd;
7780 7783 mptsas_target_t *ptgt = NULL;
7781 7784
7782 7785 NDBG1(("mptsas_restart_waitq: mpt=0x%p", (void *)mpt));
7783 7786
7784 7787 ASSERT(mutex_owned(&mpt->m_mutex));
7785 7788
7786 7789 /*
7787 7790 * If there is a reset delay, don't start any cmds. Otherwise, start
7788 7791 * as many cmds as possible.
7789 7792 * Since SMID 0 is reserved and the TM slot is reserved, the actual max
7790 7793 * commands is m_max_requests - 2.
7791 7794 */
7792 7795 cmd = mpt->m_waitq;
7793 7796
7794 7797 while (cmd != NULL) {
7795 7798 next_cmd = cmd->cmd_linkp;
7796 7799 if (cmd->cmd_flags & CFLAG_PASSTHRU) {
7797 7800 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7798 7801 /*
7799 7802 * passthru command get slot need
7800 7803 * set CFLAG_PREPARED.
7801 7804 */
7802 7805 cmd->cmd_flags |= CFLAG_PREPARED;
7803 7806 mptsas_waitq_delete(mpt, cmd);
7804 7807 mptsas_start_passthru(mpt, cmd);
7805 7808 }
7806 7809 cmd = next_cmd;
7807 7810 continue;
7808 7811 }
7809 7812 if (cmd->cmd_flags & CFLAG_CONFIG) {
7810 7813 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7811 7814 /*
7812 7815 * Send the config page request and delete it
7813 7816 * from the waitq.
7814 7817 */
7815 7818 cmd->cmd_flags |= CFLAG_PREPARED;
7816 7819 mptsas_waitq_delete(mpt, cmd);
7817 7820 mptsas_start_config_page_access(mpt, cmd);
7818 7821 }
7819 7822 cmd = next_cmd;
7820 7823 continue;
7821 7824 }
7822 7825 if (cmd->cmd_flags & CFLAG_FW_DIAG) {
7823 7826 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7824 7827 /*
7825 7828 * Send the FW Diag request and delete if from
7826 7829 * the waitq.
7827 7830 */
7828 7831 cmd->cmd_flags |= CFLAG_PREPARED;
7829 7832 mptsas_waitq_delete(mpt, cmd);
7830 7833 mptsas_start_diag(mpt, cmd);
7831 7834 }
7832 7835 cmd = next_cmd;
7833 7836 continue;
7834 7837 }
7835 7838
7836 7839 ptgt = cmd->cmd_tgt_addr;
7837 7840 if (ptgt && (ptgt->m_t_throttle == DRAIN_THROTTLE) &&
7838 7841 (ptgt->m_t_ncmds == 0)) {
7839 7842 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
7840 7843 }
7841 7844 if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
7842 7845 (ptgt && (ptgt->m_reset_delay == 0)) &&
7843 7846 (ptgt && (ptgt->m_t_ncmds <
7844 7847 ptgt->m_t_throttle))) {
7845 7848 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7846 7849 mptsas_waitq_delete(mpt, cmd);
7847 7850 (void) mptsas_start_cmd(mpt, cmd);
7848 7851 }
7849 7852 }
7850 7853 cmd = next_cmd;
7851 7854 }
7852 7855 }
7853 7856 /*
7854 7857 * Cmds are queued if tran_start() doesn't get the m_mutexlock(no wait).
7855 7858 * Accept all those queued cmds before new cmd is accept so that the
7856 7859 * cmds are sent in order.
7857 7860 */
7858 7861 static void
7859 7862 mptsas_accept_tx_waitq(mptsas_t *mpt)
7860 7863 {
7861 7864 mptsas_cmd_t *cmd;
7862 7865
7863 7866 ASSERT(mutex_owned(&mpt->m_mutex));
7864 7867 ASSERT(mutex_owned(&mpt->m_tx_waitq_mutex));
7865 7868
7866 7869 /*
7867 7870 * A Bus Reset could occur at any time and flush the tx_waitq,
7868 7871 * so we cannot count on the tx_waitq to contain even one cmd.
7869 7872 * And when the m_tx_waitq_mutex is released and run
7870 7873 * mptsas_accept_pkt(), the tx_waitq may be flushed.
7871 7874 */
7872 7875 cmd = mpt->m_tx_waitq;
7873 7876 for (;;) {
7874 7877 if ((cmd = mpt->m_tx_waitq) == NULL) {
7875 7878 mpt->m_tx_draining = 0;
7876 7879 break;
7877 7880 }
7878 7881 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL) {
7879 7882 mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
7880 7883 }
7881 7884 cmd->cmd_linkp = NULL;
7882 7885 mutex_exit(&mpt->m_tx_waitq_mutex);
7883 7886 if (mptsas_accept_pkt(mpt, cmd) != TRAN_ACCEPT)
7884 7887 cmn_err(CE_WARN, "mpt: mptsas_accept_tx_waitq: failed "
7885 7888 "to accept cmd on queue\n");
7886 7889 mutex_enter(&mpt->m_tx_waitq_mutex);
7887 7890 }
7888 7891 }
7889 7892
7890 7893
7891 7894 /*
7892 7895 * mpt tag type lookup
7893 7896 */
7894 7897 static char mptsas_tag_lookup[] =
7895 7898 {0, MSG_HEAD_QTAG, MSG_ORDERED_QTAG, 0, MSG_SIMPLE_QTAG};
7896 7899
7897 7900 static int
7898 7901 mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
7899 7902 {
7900 7903 struct scsi_pkt *pkt = CMD2PKT(cmd);
7901 7904 uint32_t control = 0;
7902 7905 int n;
7903 7906 caddr_t mem;
7904 7907 pMpi2SCSIIORequest_t io_request;
7905 7908 ddi_dma_handle_t dma_hdl = mpt->m_dma_req_frame_hdl;
7906 7909 ddi_acc_handle_t acc_hdl = mpt->m_acc_req_frame_hdl;
7907 7910 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
7908 7911 uint16_t SMID, io_flags = 0;
7909 7912 uint32_t request_desc_low, request_desc_high;
7910 7913
7911 7914 NDBG1(("mptsas_start_cmd: cmd=0x%p", (void *)cmd));
7912 7915
7913 7916 /*
7914 7917 * Set SMID and increment index. Rollover to 1 instead of 0 if index
7915 7918 * is at the max. 0 is an invalid SMID, so we call the first index 1.
7916 7919 */
7917 7920 SMID = cmd->cmd_slot;
7918 7921
7919 7922 /*
7920 7923 * It is possible for back to back device reset to
7921 7924 * happen before the reset delay has expired. That's
7922 7925 * ok, just let the device reset go out on the bus.
7923 7926 */
7924 7927 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
7925 7928 ASSERT(ptgt->m_reset_delay == 0);
7926 7929 }
7927 7930
7928 7931 /*
7929 7932 * if a non-tagged cmd is submitted to an active tagged target
7930 7933 * then drain before submitting this cmd; SCSI-2 allows RQSENSE
7931 7934 * to be untagged
7932 7935 */
7933 7936 if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
7934 7937 (ptgt->m_t_ncmds > 1) &&
7935 7938 ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
7936 7939 (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
7937 7940 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
7938 7941 NDBG23(("target=%d, untagged cmd, start draining\n",
7939 7942 ptgt->m_devhdl));
7940 7943
7941 7944 if (ptgt->m_reset_delay == 0) {
7942 7945 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
7943 7946 }
7944 7947
7945 7948 mptsas_remove_cmd(mpt, cmd);
7946 7949 cmd->cmd_pkt_flags |= FLAG_HEAD;
7947 7950 mptsas_waitq_add(mpt, cmd);
7948 7951 }
7949 7952 return (DDI_FAILURE);
7950 7953 }
7951 7954
7952 7955 /*
7953 7956 * Set correct tag bits.
7954 7957 */
7955 7958 if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {
7956 7959 switch (mptsas_tag_lookup[((cmd->cmd_pkt_flags &
7957 7960 FLAG_TAGMASK) >> 12)]) {
7958 7961 case MSG_SIMPLE_QTAG:
7959 7962 control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
7960 7963 break;
7961 7964 case MSG_HEAD_QTAG:
7962 7965 control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
7963 7966 break;
7964 7967 case MSG_ORDERED_QTAG:
7965 7968 control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
7966 7969 break;
7967 7970 default:
7968 7971 mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n");
7969 7972 break;
7970 7973 }
7971 7974 } else {
7972 7975 if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) {
7973 7976 ptgt->m_t_throttle = 1;
7974 7977 }
7975 7978 control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
7976 7979 }
7977 7980
7978 7981 if (cmd->cmd_pkt_flags & FLAG_TLR) {
7979 7982 control |= MPI2_SCSIIO_CONTROL_TLR_ON;
7980 7983 }
7981 7984
7982 7985 mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
7983 7986 io_request = (pMpi2SCSIIORequest_t)mem;
7984 7987
7985 7988 bzero(io_request, sizeof (Mpi2SCSIIORequest_t));
7986 7989 ddi_put8(acc_hdl, &io_request->SGLOffset0, offsetof
7987 7990 (MPI2_SCSI_IO_REQUEST, SGL) / 4);
7988 7991 mptsas_init_std_hdr(acc_hdl, io_request, ptgt->m_devhdl, Lun(cmd), 0,
7989 7992 MPI2_FUNCTION_SCSI_IO_REQUEST);
7990 7993
7991 7994 (void) ddi_rep_put8(acc_hdl, (uint8_t *)pkt->pkt_cdbp,
7992 7995 io_request->CDB.CDB32, cmd->cmd_cdblen, DDI_DEV_AUTOINCR);
7993 7996
7994 7997 io_flags = cmd->cmd_cdblen;
7995 7998 ddi_put16(acc_hdl, &io_request->IoFlags, io_flags);
7996 7999 /*
7997 8000 * setup the Scatter/Gather DMA list for this request
7998 8001 */
7999 8002 if (cmd->cmd_cookiec > 0) {
8000 8003 mptsas_sge_setup(mpt, cmd, &control, io_request, acc_hdl);
8001 8004 } else {
8002 8005 ddi_put32(acc_hdl, &io_request->SGL.MpiSimple.FlagsLength,
8003 8006 ((uint32_t)MPI2_SGE_FLAGS_LAST_ELEMENT |
8004 8007 MPI2_SGE_FLAGS_END_OF_BUFFER |
8005 8008 MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
8006 8009 MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
8007 8010 }
8008 8011
8009 8012 /*
8010 8013 * save ARQ information
8011 8014 */
8012 8015 ddi_put8(acc_hdl, &io_request->SenseBufferLength, cmd->cmd_rqslen);
8013 8016 if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
8014 8017 (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
8015 8018 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8016 8019 cmd->cmd_ext_arqcookie.dmac_address);
8017 8020 } else {
8018 8021 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8019 8022 cmd->cmd_arqcookie.dmac_address);
8020 8023 }
8021 8024
8022 8025 ddi_put32(acc_hdl, &io_request->Control, control);
8023 8026
8024 8027 NDBG31(("starting message=0x%p, with cmd=0x%p",
8025 8028 (void *)(uintptr_t)mpt->m_req_frame_dma_addr, (void *)cmd));
8026 8029
8027 8030 (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
8028 8031
8029 8032 /*
8030 8033 * Build request descriptor and write it to the request desc post reg.
8031 8034 */
8032 8035 request_desc_low = (SMID << 16) + MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
8033 8036 request_desc_high = ptgt->m_devhdl << 16;
8034 8037 MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
8035 8038
8036 8039 /*
8037 8040 * Start timeout.
8038 8041 */
8039 8042 #ifdef MPTSAS_TEST
8040 8043 /*
8041 8044 * Temporarily set timebase = 0; needed for
8042 8045 * timeout torture test.
8043 8046 */
8044 8047 if (mptsas_test_timeouts) {
8045 8048 ptgt->m_timebase = 0;
8046 8049 }
8047 8050 #endif
8048 8051 n = pkt->pkt_time - ptgt->m_timebase;
8049 8052
8050 8053 if (n == 0) {
8051 8054 (ptgt->m_dups)++;
8052 8055 ptgt->m_timeout = ptgt->m_timebase;
8053 8056 } else if (n > 0) {
8054 8057 ptgt->m_timeout =
8055 8058 ptgt->m_timebase = pkt->pkt_time;
8056 8059 ptgt->m_dups = 1;
8057 8060 } else if (n < 0) {
8058 8061 ptgt->m_timeout = ptgt->m_timebase;
8059 8062 }
8060 8063 #ifdef MPTSAS_TEST
8061 8064 /*
8062 8065 * Set back to a number higher than
8063 8066 * mptsas_scsi_watchdog_tick
8064 8067 * so timeouts will happen in mptsas_watchsubr
8065 8068 */
8066 8069 if (mptsas_test_timeouts) {
8067 8070 ptgt->m_timebase = 60;
8068 8071 }
8069 8072 #endif
8070 8073
8071 8074 if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
8072 8075 (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
8073 8076 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8074 8077 return (DDI_FAILURE);
8075 8078 }
8076 8079 return (DDI_SUCCESS);
8077 8080 }
8078 8081
8079 8082 /*
8080 8083 * Select a helper thread to handle current doneq
8081 8084 */
8082 8085 static void
8083 8086 mptsas_deliver_doneq_thread(mptsas_t *mpt)
8084 8087 {
8085 8088 uint64_t t, i;
8086 8089 uint32_t min = 0xffffffff;
8087 8090 mptsas_doneq_thread_list_t *item;
8088 8091
8089 8092 for (i = 0; i < mpt->m_doneq_thread_n; i++) {
8090 8093 item = &mpt->m_doneq_thread_id[i];
8091 8094 /*
8092 8095 * If the completed command on help thread[i] less than
8093 8096 * doneq_thread_threshold, then pick the thread[i]. Otherwise
8094 8097 * pick a thread which has least completed command.
8095 8098 */
8096 8099
8097 8100 mutex_enter(&item->mutex);
8098 8101 if (item->len < mpt->m_doneq_thread_threshold) {
8099 8102 t = i;
8100 8103 mutex_exit(&item->mutex);
8101 8104 break;
8102 8105 }
8103 8106 if (item->len < min) {
8104 8107 min = item->len;
8105 8108 t = i;
8106 8109 }
8107 8110 mutex_exit(&item->mutex);
8108 8111 }
8109 8112 mutex_enter(&mpt->m_doneq_thread_id[t].mutex);
8110 8113 mptsas_doneq_mv(mpt, t);
8111 8114 cv_signal(&mpt->m_doneq_thread_id[t].cv);
8112 8115 mutex_exit(&mpt->m_doneq_thread_id[t].mutex);
8113 8116 }
8114 8117
8115 8118 /*
8116 8119 * move the current global doneq to the doneq of thead[t]
8117 8120 */
8118 8121 static void
8119 8122 mptsas_doneq_mv(mptsas_t *mpt, uint64_t t)
8120 8123 {
8121 8124 mptsas_cmd_t *cmd;
8122 8125 mptsas_doneq_thread_list_t *item = &mpt->m_doneq_thread_id[t];
8123 8126
8124 8127 ASSERT(mutex_owned(&item->mutex));
8125 8128 while ((cmd = mpt->m_doneq) != NULL) {
8126 8129 if ((mpt->m_doneq = cmd->cmd_linkp) == NULL) {
8127 8130 mpt->m_donetail = &mpt->m_doneq;
8128 8131 }
8129 8132 cmd->cmd_linkp = NULL;
8130 8133 *item->donetail = cmd;
8131 8134 item->donetail = &cmd->cmd_linkp;
8132 8135 mpt->m_doneq_len--;
8133 8136 item->len++;
8134 8137 }
8135 8138 }
8136 8139
8137 8140 void
8138 8141 mptsas_fma_check(mptsas_t *mpt, mptsas_cmd_t *cmd)
8139 8142 {
8140 8143 struct scsi_pkt *pkt = CMD2PKT(cmd);
8141 8144
8142 8145 /* Check all acc and dma handles */
8143 8146 if ((mptsas_check_acc_handle(mpt->m_datap) !=
8144 8147 DDI_SUCCESS) ||
8145 8148 (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
8146 8149 DDI_SUCCESS) ||
8147 8150 (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
8148 8151 DDI_SUCCESS) ||
8149 8152 (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
8150 8153 DDI_SUCCESS) ||
8151 8154 (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
8152 8155 DDI_SUCCESS) ||
8153 8156 (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
8154 8157 DDI_SUCCESS) ||
8155 8158 (mptsas_check_acc_handle(mpt->m_config_handle) !=
8156 8159 DDI_SUCCESS)) {
8157 8160 ddi_fm_service_impact(mpt->m_dip,
8158 8161 DDI_SERVICE_UNAFFECTED);
8159 8162 ddi_fm_acc_err_clear(mpt->m_config_handle,
8160 8163 DDI_FME_VER0);
8161 8164 pkt->pkt_reason = CMD_TRAN_ERR;
8162 8165 pkt->pkt_statistics = 0;
8163 8166 }
8164 8167 if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
8165 8168 DDI_SUCCESS) ||
8166 8169 (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
8167 8170 DDI_SUCCESS) ||
8168 8171 (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
8169 8172 DDI_SUCCESS) ||
8170 8173 (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
8171 8174 DDI_SUCCESS) ||
8172 8175 (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
8173 8176 DDI_SUCCESS)) {
8174 8177 ddi_fm_service_impact(mpt->m_dip,
8175 8178 DDI_SERVICE_UNAFFECTED);
8176 8179 pkt->pkt_reason = CMD_TRAN_ERR;
8177 8180 pkt->pkt_statistics = 0;
8178 8181 }
8179 8182 if (cmd->cmd_dmahandle &&
8180 8183 (mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS)) {
8181 8184 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8182 8185 pkt->pkt_reason = CMD_TRAN_ERR;
8183 8186 pkt->pkt_statistics = 0;
8184 8187 }
8185 8188 if ((cmd->cmd_extra_frames &&
8186 8189 ((mptsas_check_dma_handle(cmd->cmd_extra_frames->m_dma_hdl) !=
8187 8190 DDI_SUCCESS) ||
8188 8191 (mptsas_check_acc_handle(cmd->cmd_extra_frames->m_acc_hdl) !=
8189 8192 DDI_SUCCESS)))) {
8190 8193 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8191 8194 pkt->pkt_reason = CMD_TRAN_ERR;
8192 8195 pkt->pkt_statistics = 0;
8193 8196 }
8194 8197 if (cmd->cmd_arqhandle &&
8195 8198 (mptsas_check_dma_handle(cmd->cmd_arqhandle) != DDI_SUCCESS)) {
8196 8199 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8197 8200 pkt->pkt_reason = CMD_TRAN_ERR;
8198 8201 pkt->pkt_statistics = 0;
8199 8202 }
8200 8203 if (cmd->cmd_ext_arqhandle &&
8201 8204 (mptsas_check_dma_handle(cmd->cmd_ext_arqhandle) != DDI_SUCCESS)) {
8202 8205 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8203 8206 pkt->pkt_reason = CMD_TRAN_ERR;
8204 8207 pkt->pkt_statistics = 0;
8205 8208 }
8206 8209 }
8207 8210
8208 8211 /*
8209 8212 * These routines manipulate the queue of commands that
8210 8213 * are waiting for their completion routines to be called.
8211 8214 * The queue is usually in FIFO order but on an MP system
8212 8215 * it's possible for the completion routines to get out
8213 8216 * of order. If that's a problem you need to add a global
8214 8217 * mutex around the code that calls the completion routine
8215 8218 * in the interrupt handler.
8216 8219 */
8217 8220 static void
8218 8221 mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8219 8222 {
8220 8223 struct scsi_pkt *pkt = CMD2PKT(cmd);
8221 8224
8222 8225 NDBG31(("mptsas_doneq_add: cmd=0x%p", (void *)cmd));
8223 8226
8224 8227 ASSERT((cmd->cmd_flags & CFLAG_COMPLETED) == 0);
8225 8228 cmd->cmd_linkp = NULL;
8226 8229 cmd->cmd_flags |= CFLAG_FINISHED;
8227 8230 cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT;
8228 8231
8229 8232 mptsas_fma_check(mpt, cmd);
8230 8233
8231 8234 /*
8232 8235 * only add scsi pkts that have completion routines to
8233 8236 * the doneq. no intr cmds do not have callbacks.
8234 8237 */
8235 8238 if (pkt && (pkt->pkt_comp)) {
8236 8239 *mpt->m_donetail = cmd;
8237 8240 mpt->m_donetail = &cmd->cmd_linkp;
8238 8241 mpt->m_doneq_len++;
8239 8242 }
8240 8243 }
8241 8244
8242 8245 static mptsas_cmd_t *
8243 8246 mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t)
8244 8247 {
8245 8248 mptsas_cmd_t *cmd;
8246 8249 mptsas_doneq_thread_list_t *item = &mpt->m_doneq_thread_id[t];
8247 8250
8248 8251 /* pop one off the done queue */
8249 8252 if ((cmd = item->doneq) != NULL) {
8250 8253 /* if the queue is now empty fix the tail pointer */
8251 8254 NDBG31(("mptsas_doneq_thread_rm: cmd=0x%p", (void *)cmd));
8252 8255 if ((item->doneq = cmd->cmd_linkp) == NULL) {
8253 8256 item->donetail = &item->doneq;
8254 8257 }
8255 8258 cmd->cmd_linkp = NULL;
8256 8259 item->len--;
8257 8260 }
8258 8261 return (cmd);
8259 8262 }
8260 8263
8261 8264 static void
8262 8265 mptsas_doneq_empty(mptsas_t *mpt)
8263 8266 {
8264 8267 if (mpt->m_doneq && !mpt->m_in_callback) {
8265 8268 mptsas_cmd_t *cmd, *next;
8266 8269 struct scsi_pkt *pkt;
8267 8270
8268 8271 mpt->m_in_callback = 1;
8269 8272 cmd = mpt->m_doneq;
8270 8273 mpt->m_doneq = NULL;
8271 8274 mpt->m_donetail = &mpt->m_doneq;
8272 8275 mpt->m_doneq_len = 0;
8273 8276
8274 8277 mutex_exit(&mpt->m_mutex);
8275 8278 /*
8276 8279 * run the completion routines of all the
8277 8280 * completed commands
8278 8281 */
8279 8282 while (cmd != NULL) {
8280 8283 next = cmd->cmd_linkp;
8281 8284 cmd->cmd_linkp = NULL;
8282 8285 /* run this command's completion routine */
8283 8286 cmd->cmd_flags |= CFLAG_COMPLETED;
8284 8287 pkt = CMD2PKT(cmd);
8285 8288 mptsas_pkt_comp(pkt, cmd);
8286 8289 cmd = next;
8287 8290 }
8288 8291 mutex_enter(&mpt->m_mutex);
8289 8292 mpt->m_in_callback = 0;
8290 8293 }
8291 8294 }
8292 8295
8293 8296 /*
8294 8297 * These routines manipulate the target's queue of pending requests
8295 8298 */
8296 8299 void
8297 8300 mptsas_waitq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8298 8301 {
8299 8302 NDBG7(("mptsas_waitq_add: cmd=0x%p", (void *)cmd));
8300 8303 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8301 8304 cmd->cmd_queued = TRUE;
8302 8305 if (ptgt)
8303 8306 ptgt->m_t_nwait++;
8304 8307 if (cmd->cmd_pkt_flags & FLAG_HEAD) {
8305 8308 if ((cmd->cmd_linkp = mpt->m_waitq) == NULL) {
8306 8309 mpt->m_waitqtail = &cmd->cmd_linkp;
8307 8310 }
8308 8311 mpt->m_waitq = cmd;
8309 8312 } else {
8310 8313 cmd->cmd_linkp = NULL;
8311 8314 *(mpt->m_waitqtail) = cmd;
8312 8315 mpt->m_waitqtail = &cmd->cmd_linkp;
8313 8316 }
8314 8317 }
8315 8318
8316 8319 static mptsas_cmd_t *
8317 8320 mptsas_waitq_rm(mptsas_t *mpt)
8318 8321 {
8319 8322 mptsas_cmd_t *cmd;
8320 8323 mptsas_target_t *ptgt;
8321 8324 NDBG7(("mptsas_waitq_rm"));
8322 8325
8323 8326 MPTSAS_WAITQ_RM(mpt, cmd);
8324 8327
8325 8328 NDBG7(("mptsas_waitq_rm: cmd=0x%p", (void *)cmd));
8326 8329 if (cmd) {
8327 8330 ptgt = cmd->cmd_tgt_addr;
8328 8331 if (ptgt) {
8329 8332 ptgt->m_t_nwait--;
8330 8333 ASSERT(ptgt->m_t_nwait >= 0);
8331 8334 }
8332 8335 }
8333 8336 return (cmd);
8334 8337 }
8335 8338
8336 8339 /*
8337 8340 * remove specified cmd from the middle of the wait queue.
8338 8341 */
8339 8342 static void
8340 8343 mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8341 8344 {
8342 8345 mptsas_cmd_t *prevp = mpt->m_waitq;
8343 8346 mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8344 8347
8345 8348 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8346 8349 (void *)mpt, (void *)cmd));
8347 8350 if (ptgt) {
8348 8351 ptgt->m_t_nwait--;
8349 8352 ASSERT(ptgt->m_t_nwait >= 0);
8350 8353 }
8351 8354
8352 8355 if (prevp == cmd) {
8353 8356 if ((mpt->m_waitq = cmd->cmd_linkp) == NULL)
8354 8357 mpt->m_waitqtail = &mpt->m_waitq;
8355 8358
8356 8359 cmd->cmd_linkp = NULL;
8357 8360 cmd->cmd_queued = FALSE;
8358 8361 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8359 8362 (void *)mpt, (void *)cmd));
8360 8363 return;
8361 8364 }
8362 8365
8363 8366 while (prevp != NULL) {
8364 8367 if (prevp->cmd_linkp == cmd) {
8365 8368 if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8366 8369 mpt->m_waitqtail = &prevp->cmd_linkp;
8367 8370
8368 8371 cmd->cmd_linkp = NULL;
8369 8372 cmd->cmd_queued = FALSE;
8370 8373 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8371 8374 (void *)mpt, (void *)cmd));
8372 8375 return;
8373 8376 }
8374 8377 prevp = prevp->cmd_linkp;
8375 8378 }
8376 8379 cmn_err(CE_PANIC, "mpt: mptsas_waitq_delete: queue botch");
8377 8380 }
8378 8381
8379 8382 static mptsas_cmd_t *
8380 8383 mptsas_tx_waitq_rm(mptsas_t *mpt)
8381 8384 {
8382 8385 mptsas_cmd_t *cmd;
8383 8386 NDBG7(("mptsas_tx_waitq_rm"));
8384 8387
8385 8388 MPTSAS_TX_WAITQ_RM(mpt, cmd);
8386 8389
8387 8390 NDBG7(("mptsas_tx_waitq_rm: cmd=0x%p", (void *)cmd));
8388 8391
8389 8392 return (cmd);
8390 8393 }
8391 8394
8392 8395 /*
8393 8396 * remove specified cmd from the middle of the tx_waitq.
8394 8397 */
8395 8398 static void
8396 8399 mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8397 8400 {
8398 8401 mptsas_cmd_t *prevp = mpt->m_tx_waitq;
8399 8402
8400 8403 NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8401 8404 (void *)mpt, (void *)cmd));
8402 8405
8403 8406 if (prevp == cmd) {
8404 8407 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL)
8405 8408 mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
8406 8409
8407 8410 cmd->cmd_linkp = NULL;
8408 8411 cmd->cmd_queued = FALSE;
8409 8412 NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8410 8413 (void *)mpt, (void *)cmd));
8411 8414 return;
8412 8415 }
8413 8416
8414 8417 while (prevp != NULL) {
8415 8418 if (prevp->cmd_linkp == cmd) {
8416 8419 if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8417 8420 mpt->m_tx_waitqtail = &prevp->cmd_linkp;
8418 8421
8419 8422 cmd->cmd_linkp = NULL;
8420 8423 cmd->cmd_queued = FALSE;
8421 8424 NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8422 8425 (void *)mpt, (void *)cmd));
8423 8426 return;
8424 8427 }
8425 8428 prevp = prevp->cmd_linkp;
8426 8429 }
8427 8430 cmn_err(CE_PANIC, "mpt: mptsas_tx_waitq_delete: queue botch");
8428 8431 }
8429 8432
8430 8433 /*
8431 8434 * device and bus reset handling
8432 8435 *
8433 8436 * Notes:
8434 8437 * - RESET_ALL: reset the controller
8435 8438 * - RESET_TARGET: reset the target specified in scsi_address
8436 8439 */
8437 8440 static int
8438 8441 mptsas_scsi_reset(struct scsi_address *ap, int level)
8439 8442 {
8440 8443 mptsas_t *mpt = ADDR2MPT(ap);
8441 8444 int rval;
8442 8445 mptsas_tgt_private_t *tgt_private;
8443 8446 mptsas_target_t *ptgt = NULL;
8444 8447
8445 8448 tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->tran_tgt_private;
8446 8449 ptgt = tgt_private->t_private;
8447 8450 if (ptgt == NULL) {
8448 8451 return (FALSE);
8449 8452 }
8450 8453 NDBG22(("mptsas_scsi_reset: target=%d level=%d", ptgt->m_devhdl,
8451 8454 level));
8452 8455
8453 8456 mutex_enter(&mpt->m_mutex);
8454 8457 /*
8455 8458 * if we are not in panic set up a reset delay for this target
8456 8459 */
8457 8460 if (!ddi_in_panic()) {
8458 8461 mptsas_setup_bus_reset_delay(mpt);
8459 8462 } else {
8460 8463 drv_usecwait(mpt->m_scsi_reset_delay * 1000);
8461 8464 }
8462 8465 rval = mptsas_do_scsi_reset(mpt, ptgt->m_devhdl);
8463 8466 mutex_exit(&mpt->m_mutex);
8464 8467
8465 8468 /*
8466 8469 * The transport layer expect to only see TRUE and
8467 8470 * FALSE. Therefore, we will adjust the return value
8468 8471 * if mptsas_do_scsi_reset returns FAILED.
8469 8472 */
8470 8473 if (rval == FAILED)
8471 8474 rval = FALSE;
8472 8475 return (rval);
8473 8476 }
8474 8477
8475 8478 static int
8476 8479 mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
8477 8480 {
8478 8481 int rval = FALSE;
8479 8482 uint8_t config, disk;
8480 8483
8481 8484 ASSERT(mutex_owned(&mpt->m_mutex));
8482 8485
8483 8486 if (mptsas_debug_resets) {
8484 8487 mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
8485 8488 devhdl);
8486 8489 }
8487 8490
8488 8491 /*
8489 8492 * Issue a Target Reset message to the target specified but not to a
8490 8493 * disk making up a raid volume. Just look through the RAID config
8491 8494 * Phys Disk list of DevHandles. If the target's DevHandle is in this
8492 8495 * list, then don't reset this target.
8493 8496 */
8494 8497 for (config = 0; config < mpt->m_num_raid_configs; config++) {
8495 8498 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
8496 8499 if (devhdl == mpt->m_raidconfig[config].
8497 8500 m_physdisk_devhdl[disk]) {
8498 8501 return (TRUE);
8499 8502 }
8500 8503 }
8501 8504 }
8502 8505
8503 8506 rval = mptsas_ioc_task_management(mpt,
8504 8507 MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, devhdl, 0, NULL, 0, 0);
8505 8508
8506 8509 mptsas_doneq_empty(mpt);
8507 8510 return (rval);
8508 8511 }
8509 8512
8510 8513 static int
8511 8514 mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
8512 8515 void (*callback)(caddr_t), caddr_t arg)
8513 8516 {
8514 8517 mptsas_t *mpt = ADDR2MPT(ap);
8515 8518
8516 8519 NDBG22(("mptsas_scsi_reset_notify: tgt=%d", ap->a_target));
8517 8520
8518 8521 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
8519 8522 &mpt->m_mutex, &mpt->m_reset_notify_listf));
8520 8523 }
8521 8524
8522 8525 static int
8523 8526 mptsas_get_name(struct scsi_device *sd, char *name, int len)
8524 8527 {
8525 8528 dev_info_t *lun_dip = NULL;
8526 8529
8527 8530 ASSERT(sd != NULL);
8528 8531 ASSERT(name != NULL);
8529 8532 lun_dip = sd->sd_dev;
8530 8533 ASSERT(lun_dip != NULL);
8531 8534
8532 8535 if (mptsas_name_child(lun_dip, name, len) == DDI_SUCCESS) {
8533 8536 return (1);
8534 8537 } else {
8535 8538 return (0);
8536 8539 }
8537 8540 }
8538 8541
8539 8542 static int
8540 8543 mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len)
8541 8544 {
8542 8545 return (mptsas_get_name(sd, name, len));
8543 8546 }
8544 8547
8545 8548 void
8546 8549 mptsas_set_throttle(mptsas_t *mpt, mptsas_target_t *ptgt, int what)
8547 8550 {
8548 8551
8549 8552 NDBG25(("mptsas_set_throttle: throttle=%x", what));
8550 8553
8551 8554 /*
8552 8555 * if the bus is draining/quiesced, no changes to the throttles
8553 8556 * are allowed. Not allowing change of throttles during draining
8554 8557 * limits error recovery but will reduce draining time
8555 8558 *
8556 8559 * all throttles should have been set to HOLD_THROTTLE
8557 8560 */
8558 8561 if (mpt->m_softstate & (MPTSAS_SS_QUIESCED | MPTSAS_SS_DRAINING)) {
8559 8562 return;
8560 8563 }
8561 8564
8562 8565 if (what == HOLD_THROTTLE) {
8563 8566 ptgt->m_t_throttle = HOLD_THROTTLE;
8564 8567 } else if (ptgt->m_reset_delay == 0) {
8565 8568 ptgt->m_t_throttle = what;
8566 8569 }
8567 8570 }
8568 8571
8569 8572 /*
8570 8573 * Clean up from a device reset.
8571 8574 * For the case of target reset, this function clears the waitq of all
8572 8575 * commands for a particular target. For the case of abort task set, this
8573 8576 * function clears the waitq of all commonds for a particular target/lun.
8574 8577 */
8575 8578 static void
8576 8579 mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
8577 8580 {
8578 8581 mptsas_slots_t *slots = mpt->m_active;
8579 8582 mptsas_cmd_t *cmd, *next_cmd;
8580 8583 int slot;
8581 8584 uchar_t reason;
8582 8585 uint_t stat;
8583 8586
8584 8587 NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
8585 8588
8586 8589 /*
8587 8590 * Make sure the I/O Controller has flushed all cmds
8588 8591 * that are associated with this target for a target reset
8589 8592 * and target/lun for abort task set.
8590 8593 * Account for TM requests, which use the last SMID.
8591 8594 */
8592 8595 for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
8593 8596 if ((cmd = slots->m_slot[slot]) == NULL)
8594 8597 continue;
8595 8598 reason = CMD_RESET;
8596 8599 stat = STAT_DEV_RESET;
8597 8600 switch (tasktype) {
8598 8601 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
8599 8602 if (Tgt(cmd) == target) {
8600 8603 NDBG25(("mptsas_flush_target discovered non-"
8601 8604 "NULL cmd in slot %d, tasktype 0x%x", slot,
8602 8605 tasktype));
8603 8606 mptsas_dump_cmd(mpt, cmd);
8604 8607 mptsas_remove_cmd(mpt, cmd);
8605 8608 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
8606 8609 mptsas_doneq_add(mpt, cmd);
8607 8610 }
8608 8611 break;
8609 8612 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
8610 8613 reason = CMD_ABORTED;
8611 8614 stat = STAT_ABORTED;
8612 8615 /*FALLTHROUGH*/
8613 8616 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
8614 8617 if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
8615 8618
8616 8619 NDBG25(("mptsas_flush_target discovered non-"
8617 8620 "NULL cmd in slot %d, tasktype 0x%x", slot,
8618 8621 tasktype));
8619 8622 mptsas_dump_cmd(mpt, cmd);
8620 8623 mptsas_remove_cmd(mpt, cmd);
8621 8624 mptsas_set_pkt_reason(mpt, cmd, reason,
8622 8625 stat);
8623 8626 mptsas_doneq_add(mpt, cmd);
8624 8627 }
8625 8628 break;
8626 8629 default:
8627 8630 break;
8628 8631 }
8629 8632 }
8630 8633
8631 8634 /*
8632 8635 * Flush the waitq and tx_waitq of this target's cmds
8633 8636 */
8634 8637 cmd = mpt->m_waitq;
8635 8638
8636 8639 reason = CMD_RESET;
8637 8640 stat = STAT_DEV_RESET;
8638 8641
8639 8642 switch (tasktype) {
8640 8643 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
8641 8644 while (cmd != NULL) {
8642 8645 next_cmd = cmd->cmd_linkp;
8643 8646 if (Tgt(cmd) == target) {
8644 8647 mptsas_waitq_delete(mpt, cmd);
8645 8648 mptsas_set_pkt_reason(mpt, cmd,
8646 8649 reason, stat);
8647 8650 mptsas_doneq_add(mpt, cmd);
8648 8651 }
8649 8652 cmd = next_cmd;
8650 8653 }
8651 8654 mutex_enter(&mpt->m_tx_waitq_mutex);
8652 8655 cmd = mpt->m_tx_waitq;
8653 8656 while (cmd != NULL) {
8654 8657 next_cmd = cmd->cmd_linkp;
8655 8658 if (Tgt(cmd) == target) {
8656 8659 mptsas_tx_waitq_delete(mpt, cmd);
8657 8660 mutex_exit(&mpt->m_tx_waitq_mutex);
8658 8661 mptsas_set_pkt_reason(mpt, cmd,
8659 8662 reason, stat);
8660 8663 mptsas_doneq_add(mpt, cmd);
8661 8664 mutex_enter(&mpt->m_tx_waitq_mutex);
8662 8665 }
8663 8666 cmd = next_cmd;
8664 8667 }
8665 8668 mutex_exit(&mpt->m_tx_waitq_mutex);
8666 8669 break;
8667 8670 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
8668 8671 reason = CMD_ABORTED;
8669 8672 stat = STAT_ABORTED;
8670 8673 /*FALLTHROUGH*/
8671 8674 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
8672 8675 while (cmd != NULL) {
8673 8676 next_cmd = cmd->cmd_linkp;
8674 8677 if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
8675 8678 mptsas_waitq_delete(mpt, cmd);
8676 8679 mptsas_set_pkt_reason(mpt, cmd,
8677 8680 reason, stat);
8678 8681 mptsas_doneq_add(mpt, cmd);
8679 8682 }
8680 8683 cmd = next_cmd;
8681 8684 }
8682 8685 mutex_enter(&mpt->m_tx_waitq_mutex);
8683 8686 cmd = mpt->m_tx_waitq;
8684 8687 while (cmd != NULL) {
8685 8688 next_cmd = cmd->cmd_linkp;
8686 8689 if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
8687 8690 mptsas_tx_waitq_delete(mpt, cmd);
8688 8691 mutex_exit(&mpt->m_tx_waitq_mutex);
8689 8692 mptsas_set_pkt_reason(mpt, cmd,
8690 8693 reason, stat);
8691 8694 mptsas_doneq_add(mpt, cmd);
8692 8695 mutex_enter(&mpt->m_tx_waitq_mutex);
8693 8696 }
8694 8697 cmd = next_cmd;
8695 8698 }
8696 8699 mutex_exit(&mpt->m_tx_waitq_mutex);
8697 8700 break;
8698 8701 default:
8699 8702 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
8700 8703 tasktype);
8701 8704 break;
8702 8705 }
8703 8706 }
8704 8707
8705 8708 /*
8706 8709 * Clean up hba state, abort all outstanding command and commands in waitq
8707 8710 * reset timeout of all targets.
8708 8711 */
8709 8712 static void
8710 8713 mptsas_flush_hba(mptsas_t *mpt)
8711 8714 {
8712 8715 mptsas_slots_t *slots = mpt->m_active;
8713 8716 mptsas_cmd_t *cmd;
8714 8717 int slot;
8715 8718
8716 8719 NDBG25(("mptsas_flush_hba"));
8717 8720
8718 8721 /*
8719 8722 * The I/O Controller should have already sent back
8720 8723 * all commands via the scsi I/O reply frame. Make
8721 8724 * sure all commands have been flushed.
8722 8725 * Account for TM request, which use the last SMID.
8723 8726 */
8724 8727 for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
8725 8728 if ((cmd = slots->m_slot[slot]) == NULL)
8726 8729 continue;
8727 8730
8728 8731 if (cmd->cmd_flags & CFLAG_CMDIOC) {
8729 8732 /*
8730 8733 * Need to make sure to tell everyone that might be
8731 8734 * waiting on this command that it's going to fail. If
8732 8735 * we get here, this command will never timeout because
8733 8736 * the active command table is going to be re-allocated,
8734 8737 * so there will be nothing to check against a time out.
8735 8738 * Instead, mark the command as failed due to reset.
8736 8739 */
8737 8740 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
8738 8741 STAT_BUS_RESET);
8739 8742 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
8740 8743 (cmd->cmd_flags & CFLAG_CONFIG) ||
8741 8744 (cmd->cmd_flags & CFLAG_FW_DIAG)) {
8742 8745 cmd->cmd_flags |= CFLAG_FINISHED;
8743 8746 cv_broadcast(&mpt->m_passthru_cv);
8744 8747 cv_broadcast(&mpt->m_config_cv);
8745 8748 cv_broadcast(&mpt->m_fw_diag_cv);
8746 8749 }
8747 8750 continue;
8748 8751 }
8749 8752
8750 8753 NDBG25(("mptsas_flush_hba discovered non-NULL cmd in slot %d",
8751 8754 slot));
8752 8755 mptsas_dump_cmd(mpt, cmd);
8753 8756
8754 8757 mptsas_remove_cmd(mpt, cmd);
8755 8758 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
8756 8759 mptsas_doneq_add(mpt, cmd);
8757 8760 }
8758 8761
8759 8762 /*
8760 8763 * Flush the waitq.
8761 8764 */
8762 8765 while ((cmd = mptsas_waitq_rm(mpt)) != NULL) {
8763 8766 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
8764 8767 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
8765 8768 (cmd->cmd_flags & CFLAG_CONFIG) ||
8766 8769 (cmd->cmd_flags & CFLAG_FW_DIAG)) {
8767 8770 cmd->cmd_flags |= CFLAG_FINISHED;
8768 8771 cv_broadcast(&mpt->m_passthru_cv);
8769 8772 cv_broadcast(&mpt->m_config_cv);
8770 8773 cv_broadcast(&mpt->m_fw_diag_cv);
8771 8774 } else {
8772 8775 mptsas_doneq_add(mpt, cmd);
8773 8776 }
8774 8777 }
8775 8778
8776 8779 /*
8777 8780 * Flush the tx_waitq
8778 8781 */
8779 8782 mutex_enter(&mpt->m_tx_waitq_mutex);
8780 8783 while ((cmd = mptsas_tx_waitq_rm(mpt)) != NULL) {
8781 8784 mutex_exit(&mpt->m_tx_waitq_mutex);
8782 8785 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
8783 8786 mptsas_doneq_add(mpt, cmd);
8784 8787 mutex_enter(&mpt->m_tx_waitq_mutex);
8785 8788 }
8786 8789 mutex_exit(&mpt->m_tx_waitq_mutex);
8787 8790
8788 8791 /*
8789 8792 * Drain the taskqs prior to reallocating resources.
8790 8793 */
8791 8794 mutex_exit(&mpt->m_mutex);
8792 8795 ddi_taskq_wait(mpt->m_event_taskq);
8793 8796 ddi_taskq_wait(mpt->m_dr_taskq);
8794 8797 mutex_enter(&mpt->m_mutex);
8795 8798 }
8796 8799
8797 8800 /*
8798 8801 * set pkt_reason and OR in pkt_statistics flag
8799 8802 */
8800 8803 static void
8801 8804 mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd, uchar_t reason,
8802 8805 uint_t stat)
8803 8806 {
8804 8807 #ifndef __lock_lint
8805 8808 _NOTE(ARGUNUSED(mpt))
8806 8809 #endif
8807 8810
8808 8811 NDBG25(("mptsas_set_pkt_reason: cmd=0x%p reason=%x stat=%x",
8809 8812 (void *)cmd, reason, stat));
8810 8813
8811 8814 if (cmd) {
8812 8815 if (cmd->cmd_pkt->pkt_reason == CMD_CMPLT) {
8813 8816 cmd->cmd_pkt->pkt_reason = reason;
8814 8817 }
8815 8818 cmd->cmd_pkt->pkt_statistics |= stat;
8816 8819 }
8817 8820 }
8818 8821
8819 8822 static void
8820 8823 mptsas_start_watch_reset_delay()
8821 8824 {
8822 8825 NDBG22(("mptsas_start_watch_reset_delay"));
8823 8826
8824 8827 mutex_enter(&mptsas_global_mutex);
8825 8828 if (mptsas_reset_watch == NULL && mptsas_timeouts_enabled) {
8826 8829 mptsas_reset_watch = timeout(mptsas_watch_reset_delay, NULL,
8827 8830 drv_usectohz((clock_t)
8828 8831 MPTSAS_WATCH_RESET_DELAY_TICK * 1000));
8829 8832 ASSERT(mptsas_reset_watch != NULL);
8830 8833 }
8831 8834 mutex_exit(&mptsas_global_mutex);
8832 8835 }
8833 8836
8834 8837 static void
8835 8838 mptsas_setup_bus_reset_delay(mptsas_t *mpt)
8836 8839 {
8837 8840 mptsas_target_t *ptgt = NULL;
8838 8841
8839 8842 ASSERT(MUTEX_HELD(&mpt->m_mutex));
8840 8843
8841 8844 NDBG22(("mptsas_setup_bus_reset_delay"));
8842 8845 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8843 8846 ptgt = refhash_next(mpt->m_targets, ptgt)) {
8844 8847 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
8845 8848 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
8846 8849 }
8847 8850
8848 8851 mptsas_start_watch_reset_delay();
8849 8852 }
8850 8853
8851 8854 /*
8852 8855 * mptsas_watch_reset_delay(_subr) is invoked by timeout() and checks every
8853 8856 * mpt instance for active reset delays
8854 8857 */
8855 8858 static void
8856 8859 mptsas_watch_reset_delay(void *arg)
8857 8860 {
8858 8861 #ifndef __lock_lint
8859 8862 _NOTE(ARGUNUSED(arg))
8860 8863 #endif
8861 8864
8862 8865 mptsas_t *mpt;
8863 8866 int not_done = 0;
8864 8867
8865 8868 NDBG22(("mptsas_watch_reset_delay"));
8866 8869
8867 8870 mutex_enter(&mptsas_global_mutex);
8868 8871 mptsas_reset_watch = 0;
8869 8872 mutex_exit(&mptsas_global_mutex);
8870 8873 rw_enter(&mptsas_global_rwlock, RW_READER);
8871 8874 for (mpt = mptsas_head; mpt != NULL; mpt = mpt->m_next) {
8872 8875 if (mpt->m_tran == 0) {
8873 8876 continue;
8874 8877 }
8875 8878 mutex_enter(&mpt->m_mutex);
8876 8879 not_done += mptsas_watch_reset_delay_subr(mpt);
8877 8880 mutex_exit(&mpt->m_mutex);
8878 8881 }
8879 8882 rw_exit(&mptsas_global_rwlock);
8880 8883
8881 8884 if (not_done) {
8882 8885 mptsas_start_watch_reset_delay();
8883 8886 }
8884 8887 }
8885 8888
8886 8889 static int
8887 8890 mptsas_watch_reset_delay_subr(mptsas_t *mpt)
8888 8891 {
8889 8892 int done = 0;
8890 8893 int restart = 0;
8891 8894 mptsas_target_t *ptgt = NULL;
8892 8895
8893 8896 NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
8894 8897
8895 8898 ASSERT(mutex_owned(&mpt->m_mutex));
8896 8899
8897 8900 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8898 8901 ptgt = refhash_next(mpt->m_targets, ptgt)) {
8899 8902 if (ptgt->m_reset_delay != 0) {
8900 8903 ptgt->m_reset_delay -=
8901 8904 MPTSAS_WATCH_RESET_DELAY_TICK;
8902 8905 if (ptgt->m_reset_delay <= 0) {
8903 8906 ptgt->m_reset_delay = 0;
8904 8907 mptsas_set_throttle(mpt, ptgt,
8905 8908 MAX_THROTTLE);
8906 8909 restart++;
8907 8910 } else {
8908 8911 done = -1;
8909 8912 }
8910 8913 }
8911 8914 }
8912 8915
8913 8916 if (restart > 0) {
8914 8917 mptsas_restart_hba(mpt);
8915 8918 }
8916 8919 return (done);
8917 8920 }
8918 8921
8919 8922 #ifdef MPTSAS_TEST
8920 8923 static void
8921 8924 mptsas_test_reset(mptsas_t *mpt, int target)
8922 8925 {
8923 8926 mptsas_target_t *ptgt = NULL;
8924 8927
8925 8928 if (mptsas_rtest == target) {
8926 8929 if (mptsas_do_scsi_reset(mpt, target) == TRUE) {
8927 8930 mptsas_rtest = -1;
8928 8931 }
8929 8932 if (mptsas_rtest == -1) {
8930 8933 NDBG22(("mptsas_test_reset success"));
8931 8934 }
8932 8935 }
8933 8936 }
8934 8937 #endif
8935 8938
8936 8939 /*
8937 8940 * abort handling:
8938 8941 *
8939 8942 * Notes:
8940 8943 * - if pkt is not NULL, abort just that command
8941 8944 * - if pkt is NULL, abort all outstanding commands for target
8942 8945 */
8943 8946 static int
8944 8947 mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
8945 8948 {
8946 8949 mptsas_t *mpt = ADDR2MPT(ap);
8947 8950 int rval;
8948 8951 mptsas_tgt_private_t *tgt_private;
8949 8952 int target, lun;
8950 8953
8951 8954 tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
8952 8955 tran_tgt_private;
8953 8956 ASSERT(tgt_private != NULL);
8954 8957 target = tgt_private->t_private->m_devhdl;
8955 8958 lun = tgt_private->t_lun;
8956 8959
8957 8960 NDBG23(("mptsas_scsi_abort: target=%d.%d", target, lun));
8958 8961
8959 8962 mutex_enter(&mpt->m_mutex);
8960 8963 rval = mptsas_do_scsi_abort(mpt, target, lun, pkt);
8961 8964 mutex_exit(&mpt->m_mutex);
8962 8965 return (rval);
8963 8966 }
8964 8967
8965 8968 static int
8966 8969 mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun, struct scsi_pkt *pkt)
8967 8970 {
8968 8971 mptsas_cmd_t *sp = NULL;
8969 8972 mptsas_slots_t *slots = mpt->m_active;
8970 8973 int rval = FALSE;
8971 8974
8972 8975 ASSERT(mutex_owned(&mpt->m_mutex));
8973 8976
8974 8977 /*
8975 8978 * Abort the command pkt on the target/lun in ap. If pkt is
8976 8979 * NULL, abort all outstanding commands on that target/lun.
8977 8980 * If you can abort them, return 1, else return 0.
8978 8981 * Each packet that's aborted should be sent back to the target
8979 8982 * driver through the callback routine, with pkt_reason set to
8980 8983 * CMD_ABORTED.
8981 8984 *
8982 8985 * abort cmd pkt on HBA hardware; clean out of outstanding
8983 8986 * command lists, etc.
8984 8987 */
8985 8988 if (pkt != NULL) {
8986 8989 /* abort the specified packet */
8987 8990 sp = PKT2CMD(pkt);
8988 8991
8989 8992 if (sp->cmd_queued) {
8990 8993 NDBG23(("mptsas_do_scsi_abort: queued sp=0x%p aborted",
8991 8994 (void *)sp));
8992 8995 mptsas_waitq_delete(mpt, sp);
8993 8996 mptsas_set_pkt_reason(mpt, sp, CMD_ABORTED,
8994 8997 STAT_ABORTED);
8995 8998 mptsas_doneq_add(mpt, sp);
8996 8999 rval = TRUE;
8997 9000 goto done;
8998 9001 }
8999 9002
9000 9003 /*
9001 9004 * Have mpt firmware abort this command
9002 9005 */
9003 9006
9004 9007 if (slots->m_slot[sp->cmd_slot] != NULL) {
9005 9008 rval = mptsas_ioc_task_management(mpt,
9006 9009 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, target,
9007 9010 lun, NULL, 0, 0);
9008 9011
9009 9012 /*
9010 9013 * The transport layer expects only TRUE and FALSE.
9011 9014 * Therefore, if mptsas_ioc_task_management returns
9012 9015 * FAILED we will return FALSE.
9013 9016 */
9014 9017 if (rval == FAILED)
9015 9018 rval = FALSE;
9016 9019 goto done;
9017 9020 }
9018 9021 }
9019 9022
9020 9023 /*
9021 9024 * If pkt is NULL then abort task set
9022 9025 */
9023 9026 rval = mptsas_ioc_task_management(mpt,
9024 9027 MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, target, lun, NULL, 0, 0);
9025 9028
9026 9029 /*
9027 9030 * The transport layer expects only TRUE and FALSE.
9028 9031 * Therefore, if mptsas_ioc_task_management returns
9029 9032 * FAILED we will return FALSE.
9030 9033 */
9031 9034 if (rval == FAILED)
9032 9035 rval = FALSE;
9033 9036
9034 9037 #ifdef MPTSAS_TEST
9035 9038 if (rval && mptsas_test_stop) {
9036 9039 debug_enter("mptsas_do_scsi_abort");
9037 9040 }
9038 9041 #endif
9039 9042
9040 9043 done:
9041 9044 mptsas_doneq_empty(mpt);
9042 9045 return (rval);
9043 9046 }
9044 9047
9045 9048 /*
9046 9049 * capability handling:
9047 9050 * (*tran_getcap). Get the capability named, and return its value.
9048 9051 */
9049 9052 static int
9050 9053 mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly)
9051 9054 {
9052 9055 mptsas_t *mpt = ADDR2MPT(ap);
9053 9056 int ckey;
9054 9057 int rval = FALSE;
9055 9058
9056 9059 NDBG24(("mptsas_scsi_getcap: target=%d, cap=%s tgtonly=%x",
9057 9060 ap->a_target, cap, tgtonly));
9058 9061
9059 9062 mutex_enter(&mpt->m_mutex);
9060 9063
9061 9064 if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9062 9065 mutex_exit(&mpt->m_mutex);
9063 9066 return (UNDEFINED);
9064 9067 }
9065 9068
9066 9069 switch (ckey) {
9067 9070 case SCSI_CAP_DMA_MAX:
9068 9071 rval = (int)mpt->m_msg_dma_attr.dma_attr_maxxfer;
9069 9072 break;
9070 9073 case SCSI_CAP_ARQ:
9071 9074 rval = TRUE;
9072 9075 break;
9073 9076 case SCSI_CAP_MSG_OUT:
9074 9077 case SCSI_CAP_PARITY:
9075 9078 case SCSI_CAP_UNTAGGED_QING:
9076 9079 rval = TRUE;
9077 9080 break;
9078 9081 case SCSI_CAP_TAGGED_QING:
9079 9082 rval = TRUE;
9080 9083 break;
9081 9084 case SCSI_CAP_RESET_NOTIFICATION:
9082 9085 rval = TRUE;
9083 9086 break;
9084 9087 case SCSI_CAP_LINKED_CMDS:
9085 9088 rval = FALSE;
9086 9089 break;
9087 9090 case SCSI_CAP_QFULL_RETRIES:
9088 9091 rval = ((mptsas_tgt_private_t *)(ap->a_hba_tran->
9089 9092 tran_tgt_private))->t_private->m_qfull_retries;
9090 9093 break;
9091 9094 case SCSI_CAP_QFULL_RETRY_INTERVAL:
9092 9095 rval = drv_hztousec(((mptsas_tgt_private_t *)
9093 9096 (ap->a_hba_tran->tran_tgt_private))->
9094 9097 t_private->m_qfull_retry_interval) / 1000;
9095 9098 break;
9096 9099 case SCSI_CAP_CDB_LEN:
9097 9100 rval = CDB_GROUP4;
9098 9101 break;
9099 9102 case SCSI_CAP_INTERCONNECT_TYPE:
9100 9103 rval = INTERCONNECT_SAS;
9101 9104 break;
9102 9105 case SCSI_CAP_TRAN_LAYER_RETRIES:
9103 9106 if (mpt->m_ioc_capabilities &
9104 9107 MPI2_IOCFACTS_CAPABILITY_TLR)
9105 9108 rval = TRUE;
9106 9109 else
9107 9110 rval = FALSE;
9108 9111 break;
9109 9112 default:
9110 9113 rval = UNDEFINED;
9111 9114 break;
9112 9115 }
9113 9116
9114 9117 NDBG24(("mptsas_scsi_getcap: %s, rval=%x", cap, rval));
9115 9118
9116 9119 mutex_exit(&mpt->m_mutex);
9117 9120 return (rval);
9118 9121 }
9119 9122
9120 9123 /*
9121 9124 * (*tran_setcap). Set the capability named to the value given.
9122 9125 */
9123 9126 static int
9124 9127 mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value, int tgtonly)
9125 9128 {
9126 9129 mptsas_t *mpt = ADDR2MPT(ap);
9127 9130 int ckey;
9128 9131 int rval = FALSE;
9129 9132
9130 9133 NDBG24(("mptsas_scsi_setcap: target=%d, cap=%s value=%x tgtonly=%x",
9131 9134 ap->a_target, cap, value, tgtonly));
9132 9135
9133 9136 if (!tgtonly) {
9134 9137 return (rval);
9135 9138 }
9136 9139
9137 9140 mutex_enter(&mpt->m_mutex);
9138 9141
9139 9142 if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9140 9143 mutex_exit(&mpt->m_mutex);
9141 9144 return (UNDEFINED);
9142 9145 }
9143 9146
9144 9147 switch (ckey) {
9145 9148 case SCSI_CAP_DMA_MAX:
9146 9149 case SCSI_CAP_MSG_OUT:
9147 9150 case SCSI_CAP_PARITY:
9148 9151 case SCSI_CAP_INITIATOR_ID:
9149 9152 case SCSI_CAP_LINKED_CMDS:
9150 9153 case SCSI_CAP_UNTAGGED_QING:
9151 9154 case SCSI_CAP_RESET_NOTIFICATION:
9152 9155 /*
9153 9156 * None of these are settable via
9154 9157 * the capability interface.
9155 9158 */
9156 9159 break;
9157 9160 case SCSI_CAP_ARQ:
9158 9161 /*
9159 9162 * We cannot turn off arq so return false if asked to
9160 9163 */
9161 9164 if (value) {
9162 9165 rval = TRUE;
9163 9166 } else {
9164 9167 rval = FALSE;
9165 9168 }
9166 9169 break;
9167 9170 case SCSI_CAP_TAGGED_QING:
9168 9171 mptsas_set_throttle(mpt, ((mptsas_tgt_private_t *)
9169 9172 (ap->a_hba_tran->tran_tgt_private))->t_private,
9170 9173 MAX_THROTTLE);
9171 9174 rval = TRUE;
9172 9175 break;
9173 9176 case SCSI_CAP_QFULL_RETRIES:
9174 9177 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9175 9178 t_private->m_qfull_retries = (uchar_t)value;
9176 9179 rval = TRUE;
9177 9180 break;
9178 9181 case SCSI_CAP_QFULL_RETRY_INTERVAL:
9179 9182 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9180 9183 t_private->m_qfull_retry_interval =
9181 9184 drv_usectohz(value * 1000);
9182 9185 rval = TRUE;
9183 9186 break;
9184 9187 default:
9185 9188 rval = UNDEFINED;
9186 9189 break;
9187 9190 }
9188 9191 mutex_exit(&mpt->m_mutex);
9189 9192 return (rval);
9190 9193 }
9191 9194
9192 9195 /*
9193 9196 * Utility routine for mptsas_ifsetcap/ifgetcap
9194 9197 */
9195 9198 /*ARGSUSED*/
9196 9199 static int
9197 9200 mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp)
9198 9201 {
9199 9202 NDBG24(("mptsas_scsi_capchk: cap=%s", cap));
9200 9203
9201 9204 if (!cap)
9202 9205 return (FALSE);
9203 9206
9204 9207 *cidxp = scsi_hba_lookup_capstr(cap);
9205 9208 return (TRUE);
9206 9209 }
9207 9210
9208 9211 static int
9209 9212 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
9210 9213 {
9211 9214 mptsas_slots_t *old_active = mpt->m_active;
9212 9215 mptsas_slots_t *new_active;
9213 9216 size_t size;
9214 9217
9215 9218 /*
9216 9219 * if there are active commands, then we cannot
9217 9220 * change size of active slots array.
9218 9221 */
9219 9222 ASSERT(mpt->m_ncmds == 0);
9220 9223
9221 9224 size = MPTSAS_SLOTS_SIZE(mpt);
9222 9225 new_active = kmem_zalloc(size, flag);
9223 9226 if (new_active == NULL) {
9224 9227 NDBG1(("new active alloc failed"));
9225 9228 return (-1);
9226 9229 }
9227 9230 /*
9228 9231 * Since SMID 0 is reserved and the TM slot is reserved, the
9229 9232 * number of slots that can be used at any one time is
9230 9233 * m_max_requests - 2.
9231 9234 */
9232 9235 new_active->m_n_normal = (mpt->m_max_requests - 2);
9233 9236 new_active->m_size = size;
9234 9237 new_active->m_rotor = 1;
9235 9238 if (old_active)
9236 9239 mptsas_free_active_slots(mpt);
9237 9240 mpt->m_active = new_active;
9238 9241
9239 9242 return (0);
9240 9243 }
9241 9244
9242 9245 static void
9243 9246 mptsas_free_active_slots(mptsas_t *mpt)
9244 9247 {
9245 9248 mptsas_slots_t *active = mpt->m_active;
9246 9249 size_t size;
9247 9250
9248 9251 if (active == NULL)
9249 9252 return;
9250 9253 size = active->m_size;
9251 9254 kmem_free(active, size);
9252 9255 mpt->m_active = NULL;
9253 9256 }
9254 9257
9255 9258 /*
9256 9259 * Error logging, printing, and debug print routines.
9257 9260 */
9258 9261 static char *mptsas_label = "mpt_sas";
9259 9262
9260 9263 /*PRINTFLIKE3*/
9261 9264 void
9262 9265 mptsas_log(mptsas_t *mpt, int level, char *fmt, ...)
9263 9266 {
9264 9267 dev_info_t *dev;
9265 9268 va_list ap;
9266 9269
9267 9270 if (mpt) {
9268 9271 dev = mpt->m_dip;
9269 9272 } else {
9270 9273 dev = 0;
9271 9274 }
9272 9275
9273 9276 mutex_enter(&mptsas_log_mutex);
9274 9277
9275 9278 va_start(ap, fmt);
9276 9279 (void) vsprintf(mptsas_log_buf, fmt, ap);
9277 9280 va_end(ap);
9278 9281
9279 9282 if (level == CE_CONT) {
9280 9283 scsi_log(dev, mptsas_label, level, "%s\n", mptsas_log_buf);
9281 9284 } else {
9282 9285 scsi_log(dev, mptsas_label, level, "%s", mptsas_log_buf);
9283 9286 }
9284 9287
9285 9288 mutex_exit(&mptsas_log_mutex);
9286 9289 }
9287 9290
9288 9291 #ifdef MPTSAS_DEBUG
9289 9292 /*PRINTFLIKE1*/
9290 9293 void
9291 9294 mptsas_printf(char *fmt, ...)
9292 9295 {
9293 9296 dev_info_t *dev = 0;
9294 9297 va_list ap;
9295 9298
9296 9299 mutex_enter(&mptsas_log_mutex);
9297 9300
9298 9301 va_start(ap, fmt);
9299 9302 (void) vsprintf(mptsas_log_buf, fmt, ap);
9300 9303 va_end(ap);
9301 9304
9302 9305 #ifdef PROM_PRINTF
9303 9306 prom_printf("%s:\t%s\n", mptsas_label, mptsas_log_buf);
9304 9307 #else
9305 9308 scsi_log(dev, mptsas_label, SCSI_DEBUG, "%s\n", mptsas_log_buf);
9306 9309 #endif
9307 9310 mutex_exit(&mptsas_log_mutex);
9308 9311 }
9309 9312 #endif
9310 9313
9311 9314 /*
9312 9315 * timeout handling
9313 9316 */
9314 9317 static void
9315 9318 mptsas_watch(void *arg)
9316 9319 {
9317 9320 #ifndef __lock_lint
9318 9321 _NOTE(ARGUNUSED(arg))
9319 9322 #endif
9320 9323
9321 9324 mptsas_t *mpt;
9322 9325 uint32_t doorbell;
9323 9326
9324 9327 NDBG30(("mptsas_watch"));
9325 9328
9326 9329 rw_enter(&mptsas_global_rwlock, RW_READER);
9327 9330 for (mpt = mptsas_head; mpt != (mptsas_t *)NULL; mpt = mpt->m_next) {
9328 9331
9329 9332 mutex_enter(&mpt->m_mutex);
9330 9333
9331 9334 /* Skip device if not powered on */
9332 9335 if (mpt->m_options & MPTSAS_OPT_PM) {
9333 9336 if (mpt->m_power_level == PM_LEVEL_D0) {
9334 9337 (void) pm_busy_component(mpt->m_dip, 0);
9335 9338 mpt->m_busy = 1;
9336 9339 } else {
9337 9340 mutex_exit(&mpt->m_mutex);
9338 9341 continue;
9339 9342 }
9340 9343 }
9341 9344
9342 9345 /*
9343 9346 * Check if controller is in a FAULT state. If so, reset it.
9344 9347 */
9345 9348 doorbell = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
9346 9349 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
9347 9350 doorbell &= MPI2_DOORBELL_DATA_MASK;
9348 9351 mptsas_log(mpt, CE_WARN, "MPT Firmware Fault, "
9349 9352 "code: %04x", doorbell);
9350 9353 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
9351 9354 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
9352 9355 mptsas_log(mpt, CE_WARN, "Reset failed"
9353 9356 "after fault was detected");
9354 9357 }
9355 9358 }
9356 9359
9357 9360 /*
9358 9361 * For now, always call mptsas_watchsubr.
9359 9362 */
9360 9363 mptsas_watchsubr(mpt);
9361 9364
9362 9365 if (mpt->m_options & MPTSAS_OPT_PM) {
9363 9366 mpt->m_busy = 0;
9364 9367 (void) pm_idle_component(mpt->m_dip, 0);
9365 9368 }
9366 9369
9367 9370 mutex_exit(&mpt->m_mutex);
9368 9371 }
9369 9372 rw_exit(&mptsas_global_rwlock);
9370 9373
9371 9374 mutex_enter(&mptsas_global_mutex);
9372 9375 if (mptsas_timeouts_enabled)
9373 9376 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
9374 9377 mutex_exit(&mptsas_global_mutex);
9375 9378 }
9376 9379
9377 9380 static void
9378 9381 mptsas_watchsubr(mptsas_t *mpt)
9379 9382 {
9380 9383 int i;
9381 9384 mptsas_cmd_t *cmd;
9382 9385 mptsas_target_t *ptgt = NULL;
9383 9386
9384 9387 ASSERT(MUTEX_HELD(&mpt->m_mutex));
9385 9388
9386 9389 NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
9387 9390
9388 9391 #ifdef MPTSAS_TEST
9389 9392 if (mptsas_enable_untagged) {
9390 9393 mptsas_test_untagged++;
9391 9394 }
9392 9395 #endif
9393 9396
9394 9397 /*
9395 9398 * Check for commands stuck in active slot
9396 9399 * Account for TM requests, which use the last SMID.
9397 9400 */
9398 9401 for (i = 0; i <= mpt->m_active->m_n_normal; i++) {
9399 9402 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
9400 9403 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
9401 9404 cmd->cmd_active_timeout -=
9402 9405 mptsas_scsi_watchdog_tick;
9403 9406 if (cmd->cmd_active_timeout <= 0) {
9404 9407 /*
9405 9408 * There seems to be a command stuck
9406 9409 * in the active slot. Drain throttle.
9407 9410 */
9408 9411 mptsas_set_throttle(mpt,
9409 9412 cmd->cmd_tgt_addr,
9410 9413 DRAIN_THROTTLE);
9411 9414 }
9412 9415 }
9413 9416 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
9414 9417 (cmd->cmd_flags & CFLAG_CONFIG) ||
9415 9418 (cmd->cmd_flags & CFLAG_FW_DIAG)) {
9416 9419 cmd->cmd_active_timeout -=
9417 9420 mptsas_scsi_watchdog_tick;
9418 9421 if (cmd->cmd_active_timeout <= 0) {
9419 9422 /*
9420 9423 * passthrough command timeout
9421 9424 */
9422 9425 cmd->cmd_flags |= (CFLAG_FINISHED |
9423 9426 CFLAG_TIMEOUT);
9424 9427 cv_broadcast(&mpt->m_passthru_cv);
9425 9428 cv_broadcast(&mpt->m_config_cv);
9426 9429 cv_broadcast(&mpt->m_fw_diag_cv);
9427 9430 }
9428 9431 }
9429 9432 }
9430 9433 }
9431 9434
9432 9435 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9433 9436 ptgt = refhash_next(mpt->m_targets, ptgt)) {
9434 9437 /*
9435 9438 * If we were draining due to a qfull condition,
9436 9439 * go back to full throttle.
9437 9440 */
9438 9441 if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
9439 9442 (ptgt->m_t_throttle > HOLD_THROTTLE) &&
9440 9443 (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
9441 9444 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9442 9445 mptsas_restart_hba(mpt);
9443 9446 }
9444 9447
9445 9448 if ((ptgt->m_t_ncmds > 0) &&
9446 9449 (ptgt->m_timebase)) {
9447 9450
9448 9451 if (ptgt->m_timebase <=
9449 9452 mptsas_scsi_watchdog_tick) {
9450 9453 ptgt->m_timebase +=
9451 9454 mptsas_scsi_watchdog_tick;
9452 9455 continue;
9453 9456 }
9454 9457
9455 9458 ptgt->m_timeout -= mptsas_scsi_watchdog_tick;
9456 9459
9457 9460 if (ptgt->m_timeout < 0) {
9458 9461 mptsas_cmd_timeout(mpt, ptgt->m_devhdl);
9459 9462 continue;
9460 9463 }
9461 9464
9462 9465 if ((ptgt->m_timeout) <=
9463 9466 mptsas_scsi_watchdog_tick) {
9464 9467 NDBG23(("pending timeout"));
9465 9468 mptsas_set_throttle(mpt, ptgt,
9466 9469 DRAIN_THROTTLE);
9467 9470 }
9468 9471 }
9469 9472 }
9470 9473 }
9471 9474
9472 9475 /*
9473 9476 * timeout recovery
9474 9477 */
9475 9478 static void
9476 9479 mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl)
9477 9480 {
9478 9481
9479 9482 NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
9480 9483 mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
9481 9484 "Target %d", devhdl);
9482 9485
9483 9486 /*
9484 9487 * If the current target is not the target passed in,
9485 9488 * try to reset that target.
9486 9489 */
9487 9490 NDBG29(("mptsas_cmd_timeout: device reset"));
9488 9491 if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {
9489 9492 mptsas_log(mpt, CE_WARN, "Target %d reset for command timeout "
9490 9493 "recovery failed!", devhdl);
9491 9494 }
9492 9495 }
9493 9496
9494 9497 /*
9495 9498 * Device / Hotplug control
9496 9499 */
9497 9500 static int
9498 9501 mptsas_scsi_quiesce(dev_info_t *dip)
9499 9502 {
9500 9503 mptsas_t *mpt;
9501 9504 scsi_hba_tran_t *tran;
9502 9505
9503 9506 tran = ddi_get_driver_private(dip);
9504 9507 if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9505 9508 return (-1);
9506 9509
9507 9510 return (mptsas_quiesce_bus(mpt));
9508 9511 }
9509 9512
9510 9513 static int
9511 9514 mptsas_scsi_unquiesce(dev_info_t *dip)
9512 9515 {
9513 9516 mptsas_t *mpt;
9514 9517 scsi_hba_tran_t *tran;
9515 9518
9516 9519 tran = ddi_get_driver_private(dip);
9517 9520 if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9518 9521 return (-1);
9519 9522
9520 9523 return (mptsas_unquiesce_bus(mpt));
9521 9524 }
9522 9525
9523 9526 static int
9524 9527 mptsas_quiesce_bus(mptsas_t *mpt)
9525 9528 {
9526 9529 mptsas_target_t *ptgt = NULL;
9527 9530
9528 9531 NDBG28(("mptsas_quiesce_bus"));
9529 9532 mutex_enter(&mpt->m_mutex);
9530 9533
9531 9534 /* Set all the throttles to zero */
9532 9535 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9533 9536 ptgt = refhash_next(mpt->m_targets, ptgt)) {
9534 9537 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9535 9538 }
9536 9539
9537 9540 /* If there are any outstanding commands in the queue */
9538 9541 if (mpt->m_ncmds) {
9539 9542 mpt->m_softstate |= MPTSAS_SS_DRAINING;
9540 9543 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9541 9544 mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
9542 9545 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
9543 9546 /*
9544 9547 * Quiesce has been interrupted
9545 9548 */
9546 9549 mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9547 9550 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9548 9551 ptgt = refhash_next(mpt->m_targets, ptgt)) {
9549 9552 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9550 9553 }
9551 9554 mptsas_restart_hba(mpt);
9552 9555 if (mpt->m_quiesce_timeid != 0) {
9553 9556 timeout_id_t tid = mpt->m_quiesce_timeid;
9554 9557 mpt->m_quiesce_timeid = 0;
9555 9558 mutex_exit(&mpt->m_mutex);
9556 9559 (void) untimeout(tid);
9557 9560 return (-1);
9558 9561 }
9559 9562 mutex_exit(&mpt->m_mutex);
9560 9563 return (-1);
9561 9564 } else {
9562 9565 /* Bus has been quiesced */
9563 9566 ASSERT(mpt->m_quiesce_timeid == 0);
9564 9567 mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9565 9568 mpt->m_softstate |= MPTSAS_SS_QUIESCED;
9566 9569 mutex_exit(&mpt->m_mutex);
9567 9570 return (0);
9568 9571 }
9569 9572 }
9570 9573 /* Bus was not busy - QUIESCED */
9571 9574 mutex_exit(&mpt->m_mutex);
9572 9575
9573 9576 return (0);
9574 9577 }
9575 9578
9576 9579 static int
9577 9580 mptsas_unquiesce_bus(mptsas_t *mpt)
9578 9581 {
9579 9582 mptsas_target_t *ptgt = NULL;
9580 9583
9581 9584 NDBG28(("mptsas_unquiesce_bus"));
9582 9585 mutex_enter(&mpt->m_mutex);
9583 9586 mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
9584 9587 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9585 9588 ptgt = refhash_next(mpt->m_targets, ptgt)) {
9586 9589 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9587 9590 }
9588 9591 mptsas_restart_hba(mpt);
9589 9592 mutex_exit(&mpt->m_mutex);
9590 9593 return (0);
9591 9594 }
9592 9595
9593 9596 static void
9594 9597 mptsas_ncmds_checkdrain(void *arg)
9595 9598 {
9596 9599 mptsas_t *mpt = arg;
9597 9600 mptsas_target_t *ptgt = NULL;
9598 9601
9599 9602 mutex_enter(&mpt->m_mutex);
9600 9603 if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
9601 9604 mpt->m_quiesce_timeid = 0;
9602 9605 if (mpt->m_ncmds == 0) {
9603 9606 /* Command queue has been drained */
9604 9607 cv_signal(&mpt->m_cv);
9605 9608 } else {
9606 9609 /*
9607 9610 * The throttle may have been reset because
9608 9611 * of a SCSI bus reset
9609 9612 */
9610 9613 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9611 9614 ptgt = refhash_next(mpt->m_targets, ptgt)) {
9612 9615 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9613 9616 }
9614 9617
9615 9618 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9616 9619 mpt, (MPTSAS_QUIESCE_TIMEOUT *
9617 9620 drv_usectohz(1000000)));
9618 9621 }
9619 9622 }
9620 9623 mutex_exit(&mpt->m_mutex);
9621 9624 }
9622 9625
9623 9626 /*ARGSUSED*/
9624 9627 static void
9625 9628 mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
9626 9629 {
9627 9630 int i;
9628 9631 uint8_t *cp = (uchar_t *)cmd->cmd_pkt->pkt_cdbp;
9629 9632 char buf[128];
9630 9633
9631 9634 buf[0] = '\0';
9632 9635 NDBG25(("?Cmd (0x%p) dump for Target %d Lun %d:\n", (void *)cmd,
9633 9636 Tgt(cmd), Lun(cmd)));
9634 9637 (void) sprintf(&buf[0], "\tcdb=[");
9635 9638 for (i = 0; i < (int)cmd->cmd_cdblen; i++) {
9636 9639 (void) sprintf(&buf[strlen(buf)], " 0x%x", *cp++);
9637 9640 }
9638 9641 (void) sprintf(&buf[strlen(buf)], " ]");
9639 9642 NDBG25(("?%s\n", buf));
9640 9643 NDBG25(("?pkt_flags=0x%x pkt_statistics=0x%x pkt_state=0x%x\n",
9641 9644 cmd->cmd_pkt->pkt_flags, cmd->cmd_pkt->pkt_statistics,
9642 9645 cmd->cmd_pkt->pkt_state));
9643 9646 NDBG25(("?pkt_scbp=0x%x cmd_flags=0x%x\n", cmd->cmd_pkt->pkt_scbp ?
9644 9647 *(cmd->cmd_pkt->pkt_scbp) : 0, cmd->cmd_flags));
9645 9648 }
9646 9649
9647 9650 static void
9648 9651 mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd)
9649 9652 {
9650 9653 caddr_t memp;
9651 9654 pMPI2RequestHeader_t request_hdrp;
9652 9655 struct scsi_pkt *pkt = cmd->cmd_pkt;
9653 9656 mptsas_pt_request_t *pt = pkt->pkt_ha_private;
9654 9657 uint32_t request_size, data_size, dataout_size;
9655 9658 uint32_t direction;
9656 9659 ddi_dma_cookie_t data_cookie;
9657 9660 ddi_dma_cookie_t dataout_cookie;
9658 9661 uint32_t request_desc_low, request_desc_high = 0;
9659 9662 uint32_t i, sense_bufp;
9660 9663 uint8_t desc_type;
9661 9664 uint8_t *request, function;
9662 9665 ddi_dma_handle_t dma_hdl = mpt->m_dma_req_frame_hdl;
9663 9666 ddi_acc_handle_t acc_hdl = mpt->m_acc_req_frame_hdl;
9664 9667
9665 9668 desc_type = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
9666 9669
9667 9670 request = pt->request;
9668 9671 direction = pt->direction;
9669 9672 request_size = pt->request_size;
9670 9673 data_size = pt->data_size;
9671 9674 dataout_size = pt->dataout_size;
9672 9675 data_cookie = pt->data_cookie;
9673 9676 dataout_cookie = pt->dataout_cookie;
9674 9677
9675 9678 /*
9676 9679 * Store the passthrough message in memory location
9677 9680 * corresponding to our slot number
9678 9681 */
9679 9682 memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
9680 9683 request_hdrp = (pMPI2RequestHeader_t)memp;
9681 9684 bzero(memp, mpt->m_req_frame_size);
9682 9685
9683 9686 for (i = 0; i < request_size; i++) {
9684 9687 bcopy(request + i, memp + i, 1);
9685 9688 }
9686 9689
9687 9690 if (data_size || dataout_size) {
9688 9691 pMpi2SGESimple64_t sgep;
9689 9692 uint32_t sge_flags;
9690 9693
9691 9694 sgep = (pMpi2SGESimple64_t)((uint8_t *)request_hdrp +
9692 9695 request_size);
9693 9696 if (dataout_size) {
9694 9697
9695 9698 sge_flags = dataout_size |
9696 9699 ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
9697 9700 MPI2_SGE_FLAGS_END_OF_BUFFER |
9698 9701 MPI2_SGE_FLAGS_HOST_TO_IOC |
9699 9702 MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
9700 9703 MPI2_SGE_FLAGS_SHIFT);
9701 9704 ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
9702 9705 ddi_put32(acc_hdl, &sgep->Address.Low,
9703 9706 (uint32_t)(dataout_cookie.dmac_laddress &
9704 9707 0xffffffffull));
9705 9708 ddi_put32(acc_hdl, &sgep->Address.High,
9706 9709 (uint32_t)(dataout_cookie.dmac_laddress
9707 9710 >> 32));
9708 9711 sgep++;
9709 9712 }
9710 9713 sge_flags = data_size;
9711 9714 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
9712 9715 MPI2_SGE_FLAGS_LAST_ELEMENT |
9713 9716 MPI2_SGE_FLAGS_END_OF_BUFFER |
9714 9717 MPI2_SGE_FLAGS_END_OF_LIST |
9715 9718 MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
9716 9719 MPI2_SGE_FLAGS_SHIFT);
9717 9720 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
9718 9721 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
9719 9722 MPI2_SGE_FLAGS_SHIFT);
9720 9723 } else {
9721 9724 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
9722 9725 MPI2_SGE_FLAGS_SHIFT);
9723 9726 }
9724 9727 ddi_put32(acc_hdl, &sgep->FlagsLength,
9725 9728 sge_flags);
9726 9729 ddi_put32(acc_hdl, &sgep->Address.Low,
9727 9730 (uint32_t)(data_cookie.dmac_laddress &
9728 9731 0xffffffffull));
9729 9732 ddi_put32(acc_hdl, &sgep->Address.High,
9730 9733 (uint32_t)(data_cookie.dmac_laddress >> 32));
9731 9734 }
9732 9735
9733 9736 function = request_hdrp->Function;
9734 9737 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
9735 9738 (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
9736 9739 pMpi2SCSIIORequest_t scsi_io_req;
9737 9740
9738 9741 scsi_io_req = (pMpi2SCSIIORequest_t)request_hdrp;
9739 9742 /*
9740 9743 * Put SGE for data and data_out buffer at the end of
9741 9744 * scsi_io_request message header.(64 bytes in total)
9742 9745 * Following above SGEs, the residual space will be
9743 9746 * used by sense data.
9744 9747 */
9745 9748 ddi_put8(acc_hdl,
9746 9749 &scsi_io_req->SenseBufferLength,
9747 9750 (uint8_t)(request_size - 64));
9748 9751
9749 9752 sense_bufp = mpt->m_req_frame_dma_addr +
9750 9753 (mpt->m_req_frame_size * cmd->cmd_slot);
9751 9754 sense_bufp += 64;
9752 9755 ddi_put32(acc_hdl,
9753 9756 &scsi_io_req->SenseBufferLowAddress, sense_bufp);
9754 9757
9755 9758 /*
9756 9759 * Set SGLOffset0 value
9757 9760 */
9758 9761 ddi_put8(acc_hdl, &scsi_io_req->SGLOffset0,
9759 9762 offsetof(MPI2_SCSI_IO_REQUEST, SGL) / 4);
9760 9763
9761 9764 /*
9762 9765 * Setup descriptor info. RAID passthrough must use the
9763 9766 * default request descriptor which is already set, so if this
9764 9767 * is a SCSI IO request, change the descriptor to SCSI IO.
9765 9768 */
9766 9769 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
9767 9770 desc_type = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
9768 9771 request_desc_high = (ddi_get16(acc_hdl,
9769 9772 &scsi_io_req->DevHandle) << 16);
9770 9773 }
9771 9774 }
9772 9775
9773 9776 /*
9774 9777 * We must wait till the message has been completed before
9775 9778 * beginning the next message so we wait for this one to
9776 9779 * finish.
9777 9780 */
9778 9781 (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
9779 9782 request_desc_low = (cmd->cmd_slot << 16) + desc_type;
9780 9783 cmd->cmd_rfm = NULL;
9781 9784 MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
9782 9785 if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
9783 9786 (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
9784 9787 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
9785 9788 }
9786 9789 }
9787 9790
9788 9791
9789 9792
9790 9793 static int
9791 9794 mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
9792 9795 uint8_t *data, uint32_t request_size, uint32_t reply_size,
9793 9796 uint32_t data_size, uint32_t direction, uint8_t *dataout,
9794 9797 uint32_t dataout_size, short timeout, int mode)
9795 9798 {
9796 9799 mptsas_pt_request_t pt;
9797 9800 mptsas_dma_alloc_state_t data_dma_state;
9798 9801 mptsas_dma_alloc_state_t dataout_dma_state;
9799 9802 caddr_t memp;
9800 9803 mptsas_cmd_t *cmd = NULL;
9801 9804 struct scsi_pkt *pkt;
9802 9805 uint32_t reply_len = 0, sense_len = 0;
9803 9806 pMPI2RequestHeader_t request_hdrp;
9804 9807 pMPI2RequestHeader_t request_msg;
9805 9808 pMPI2DefaultReply_t reply_msg;
9806 9809 Mpi2SCSIIOReply_t rep_msg;
9807 9810 int i, status = 0, pt_flags = 0, rv = 0;
9808 9811 int rvalue;
9809 9812 uint8_t function;
9810 9813
9811 9814 ASSERT(mutex_owned(&mpt->m_mutex));
9812 9815
9813 9816 reply_msg = (pMPI2DefaultReply_t)(&rep_msg);
9814 9817 bzero(reply_msg, sizeof (MPI2_DEFAULT_REPLY));
9815 9818 request_msg = kmem_zalloc(request_size, KM_SLEEP);
9816 9819
9817 9820 mutex_exit(&mpt->m_mutex);
9818 9821 /*
9819 9822 * copy in the request buffer since it could be used by
9820 9823 * another thread when the pt request into waitq
9821 9824 */
9822 9825 if (ddi_copyin(request, request_msg, request_size, mode)) {
9823 9826 mutex_enter(&mpt->m_mutex);
9824 9827 status = EFAULT;
9825 9828 mptsas_log(mpt, CE_WARN, "failed to copy request data");
9826 9829 goto out;
9827 9830 }
9828 9831 mutex_enter(&mpt->m_mutex);
9829 9832
9830 9833 function = request_msg->Function;
9831 9834 if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
9832 9835 pMpi2SCSITaskManagementRequest_t task;
9833 9836 task = (pMpi2SCSITaskManagementRequest_t)request_msg;
9834 9837 mptsas_setup_bus_reset_delay(mpt);
9835 9838 rv = mptsas_ioc_task_management(mpt, task->TaskType,
9836 9839 task->DevHandle, (int)task->LUN[1], reply, reply_size,
9837 9840 mode);
9838 9841
9839 9842 if (rv != TRUE) {
9840 9843 status = EIO;
9841 9844 mptsas_log(mpt, CE_WARN, "task management failed");
9842 9845 }
9843 9846 goto out;
9844 9847 }
9845 9848
9846 9849 if (data_size != 0) {
9847 9850 data_dma_state.size = data_size;
9848 9851 if (mptsas_dma_alloc(mpt, &data_dma_state) != DDI_SUCCESS) {
9849 9852 status = ENOMEM;
9850 9853 mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
9851 9854 "resource");
9852 9855 goto out;
9853 9856 }
9854 9857 pt_flags |= MPTSAS_DATA_ALLOCATED;
9855 9858 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
9856 9859 mutex_exit(&mpt->m_mutex);
9857 9860 for (i = 0; i < data_size; i++) {
9858 9861 if (ddi_copyin(data + i, (uint8_t *)
9859 9862 data_dma_state.memp + i, 1, mode)) {
9860 9863 mutex_enter(&mpt->m_mutex);
9861 9864 status = EFAULT;
9862 9865 mptsas_log(mpt, CE_WARN, "failed to "
9863 9866 "copy read data");
9864 9867 goto out;
9865 9868 }
9866 9869 }
9867 9870 mutex_enter(&mpt->m_mutex);
9868 9871 }
9869 9872 }
9870 9873
9871 9874 if (dataout_size != 0) {
9872 9875 dataout_dma_state.size = dataout_size;
9873 9876 if (mptsas_dma_alloc(mpt, &dataout_dma_state) != DDI_SUCCESS) {
9874 9877 status = ENOMEM;
9875 9878 mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
9876 9879 "resource");
9877 9880 goto out;
9878 9881 }
9879 9882 pt_flags |= MPTSAS_DATAOUT_ALLOCATED;
9880 9883 mutex_exit(&mpt->m_mutex);
9881 9884 for (i = 0; i < dataout_size; i++) {
9882 9885 if (ddi_copyin(dataout + i, (uint8_t *)
9883 9886 dataout_dma_state.memp + i, 1, mode)) {
9884 9887 mutex_enter(&mpt->m_mutex);
9885 9888 mptsas_log(mpt, CE_WARN, "failed to copy out"
9886 9889 " data");
9887 9890 status = EFAULT;
9888 9891 goto out;
9889 9892 }
9890 9893 }
9891 9894 mutex_enter(&mpt->m_mutex);
9892 9895 }
9893 9896
9894 9897 if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
9895 9898 status = EAGAIN;
9896 9899 mptsas_log(mpt, CE_NOTE, "event ack command pool is full");
9897 9900 goto out;
9898 9901 }
9899 9902 pt_flags |= MPTSAS_REQUEST_POOL_CMD;
9900 9903
9901 9904 bzero((caddr_t)cmd, sizeof (*cmd));
9902 9905 bzero((caddr_t)pkt, scsi_pkt_size());
9903 9906 bzero((caddr_t)&pt, sizeof (pt));
9904 9907
9905 9908 cmd->ioc_cmd_slot = (uint32_t)(rvalue);
9906 9909
9907 9910 pt.request = (uint8_t *)request_msg;
9908 9911 pt.direction = direction;
9909 9912 pt.request_size = request_size;
9910 9913 pt.data_size = data_size;
9911 9914 pt.dataout_size = dataout_size;
9912 9915 pt.data_cookie = data_dma_state.cookie;
9913 9916 pt.dataout_cookie = dataout_dma_state.cookie;
9914 9917
9915 9918 /*
9916 9919 * Form a blank cmd/pkt to store the acknowledgement message
9917 9920 */
9918 9921 pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb[0];
9919 9922 pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
9920 9923 pkt->pkt_ha_private = (opaque_t)&pt;
9921 9924 pkt->pkt_flags = FLAG_HEAD;
9922 9925 pkt->pkt_time = timeout;
9923 9926 cmd->cmd_pkt = pkt;
9924 9927 cmd->cmd_flags = CFLAG_CMDIOC | CFLAG_PASSTHRU;
9925 9928
9926 9929 /*
9927 9930 * Save the command in a slot
9928 9931 */
9929 9932 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
9930 9933 /*
9931 9934 * Once passthru command get slot, set cmd_flags
9932 9935 * CFLAG_PREPARED.
9933 9936 */
9934 9937 cmd->cmd_flags |= CFLAG_PREPARED;
9935 9938 mptsas_start_passthru(mpt, cmd);
9936 9939 } else {
9937 9940 mptsas_waitq_add(mpt, cmd);
9938 9941 }
9939 9942
9940 9943 while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
9941 9944 cv_wait(&mpt->m_passthru_cv, &mpt->m_mutex);
9942 9945 }
9943 9946
9944 9947 if (cmd->cmd_flags & CFLAG_PREPARED) {
9945 9948 memp = mpt->m_req_frame + (mpt->m_req_frame_size *
9946 9949 cmd->cmd_slot);
9947 9950 request_hdrp = (pMPI2RequestHeader_t)memp;
9948 9951 }
9949 9952
9950 9953 if (cmd->cmd_flags & CFLAG_TIMEOUT) {
9951 9954 status = ETIMEDOUT;
9952 9955 mptsas_log(mpt, CE_WARN, "passthrough command timeout");
9953 9956 pt_flags |= MPTSAS_CMD_TIMEOUT;
9954 9957 goto out;
9955 9958 }
9956 9959
9957 9960 if (cmd->cmd_rfm) {
9958 9961 /*
9959 9962 * cmd_rfm is zero means the command reply is a CONTEXT
9960 9963 * reply and no PCI Write to post the free reply SMFA
9961 9964 * because no reply message frame is used.
9962 9965 * cmd_rfm is non-zero means the reply is a ADDRESS
9963 9966 * reply and reply message frame is used.
9964 9967 */
9965 9968 pt_flags |= MPTSAS_ADDRESS_REPLY;
9966 9969 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
9967 9970 DDI_DMA_SYNC_FORCPU);
9968 9971 reply_msg = (pMPI2DefaultReply_t)
9969 9972 (mpt->m_reply_frame + (cmd->cmd_rfm -
9970 9973 mpt->m_reply_frame_dma_addr));
9971 9974 }
9972 9975
9973 9976 mptsas_fma_check(mpt, cmd);
9974 9977 if (pkt->pkt_reason == CMD_TRAN_ERR) {
9975 9978 status = EAGAIN;
9976 9979 mptsas_log(mpt, CE_WARN, "passthru fma error");
9977 9980 goto out;
9978 9981 }
9979 9982 if (pkt->pkt_reason == CMD_RESET) {
9980 9983 status = EAGAIN;
9981 9984 mptsas_log(mpt, CE_WARN, "ioc reset abort passthru");
9982 9985 goto out;
9983 9986 }
9984 9987
9985 9988 if (pkt->pkt_reason == CMD_INCOMPLETE) {
9986 9989 status = EIO;
9987 9990 mptsas_log(mpt, CE_WARN, "passthrough command incomplete");
9988 9991 goto out;
9989 9992 }
9990 9993
9991 9994 mutex_exit(&mpt->m_mutex);
9992 9995 if (cmd->cmd_flags & CFLAG_PREPARED) {
9993 9996 function = request_hdrp->Function;
9994 9997 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
9995 9998 (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
9996 9999 reply_len = sizeof (MPI2_SCSI_IO_REPLY);
9997 10000 sense_len = reply_size - reply_len;
9998 10001 } else {
9999 10002 reply_len = reply_size;
10000 10003 sense_len = 0;
10001 10004 }
10002 10005
10003 10006 for (i = 0; i < reply_len; i++) {
10004 10007 if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
10005 10008 mode)) {
10006 10009 mutex_enter(&mpt->m_mutex);
10007 10010 status = EFAULT;
10008 10011 mptsas_log(mpt, CE_WARN, "failed to copy out "
10009 10012 "reply data");
10010 10013 goto out;
10011 10014 }
10012 10015 }
10013 10016 for (i = 0; i < sense_len; i++) {
10014 10017 if (ddi_copyout((uint8_t *)request_hdrp + 64 + i,
10015 10018 reply + reply_len + i, 1, mode)) {
10016 10019 mutex_enter(&mpt->m_mutex);
10017 10020 status = EFAULT;
10018 10021 mptsas_log(mpt, CE_WARN, "failed to copy out "
10019 10022 "sense data");
10020 10023 goto out;
10021 10024 }
10022 10025 }
10023 10026 }
10024 10027
10025 10028 if (data_size) {
10026 10029 if (direction != MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10027 10030 (void) ddi_dma_sync(data_dma_state.handle, 0, 0,
10028 10031 DDI_DMA_SYNC_FORCPU);
10029 10032 for (i = 0; i < data_size; i++) {
10030 10033 if (ddi_copyout((uint8_t *)(
10031 10034 data_dma_state.memp + i), data + i, 1,
10032 10035 mode)) {
10033 10036 mutex_enter(&mpt->m_mutex);
10034 10037 status = EFAULT;
10035 10038 mptsas_log(mpt, CE_WARN, "failed to "
10036 10039 "copy out the reply data");
10037 10040 goto out;
10038 10041 }
10039 10042 }
10040 10043 }
10041 10044 }
10042 10045 mutex_enter(&mpt->m_mutex);
10043 10046 out:
10044 10047 /*
10045 10048 * Put the reply frame back on the free queue, increment the free
10046 10049 * index, and write the new index to the free index register. But only
10047 10050 * if this reply is an ADDRESS reply.
10048 10051 */
10049 10052 if (pt_flags & MPTSAS_ADDRESS_REPLY) {
10050 10053 ddi_put32(mpt->m_acc_free_queue_hdl,
10051 10054 &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10052 10055 cmd->cmd_rfm);
10053 10056 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10054 10057 DDI_DMA_SYNC_FORDEV);
10055 10058 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10056 10059 mpt->m_free_index = 0;
10057 10060 }
10058 10061 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10059 10062 mpt->m_free_index);
10060 10063 }
10061 10064 if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10062 10065 mptsas_remove_cmd(mpt, cmd);
10063 10066 pt_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10064 10067 }
10065 10068 if (pt_flags & MPTSAS_REQUEST_POOL_CMD)
10066 10069 mptsas_return_to_pool(mpt, cmd);
10067 10070 if (pt_flags & MPTSAS_DATA_ALLOCATED) {
10068 10071 if (mptsas_check_dma_handle(data_dma_state.handle) !=
10069 10072 DDI_SUCCESS) {
10070 10073 ddi_fm_service_impact(mpt->m_dip,
10071 10074 DDI_SERVICE_UNAFFECTED);
10072 10075 status = EFAULT;
10073 10076 }
10074 10077 mptsas_dma_free(&data_dma_state);
10075 10078 }
10076 10079 if (pt_flags & MPTSAS_DATAOUT_ALLOCATED) {
10077 10080 if (mptsas_check_dma_handle(dataout_dma_state.handle) !=
10078 10081 DDI_SUCCESS) {
10079 10082 ddi_fm_service_impact(mpt->m_dip,
10080 10083 DDI_SERVICE_UNAFFECTED);
10081 10084 status = EFAULT;
10082 10085 }
10083 10086 mptsas_dma_free(&dataout_dma_state);
10084 10087 }
10085 10088 if (pt_flags & MPTSAS_CMD_TIMEOUT) {
10086 10089 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
10087 10090 mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
10088 10091 }
10089 10092 }
10090 10093 if (request_msg)
10091 10094 kmem_free(request_msg, request_size);
10092 10095
10093 10096 return (status);
10094 10097 }
10095 10098
10096 10099 static int
10097 10100 mptsas_pass_thru(mptsas_t *mpt, mptsas_pass_thru_t *data, int mode)
10098 10101 {
10099 10102 /*
10100 10103 * If timeout is 0, set timeout to default of 60 seconds.
10101 10104 */
10102 10105 if (data->Timeout == 0) {
10103 10106 data->Timeout = MPTSAS_PASS_THRU_TIME_DEFAULT;
10104 10107 }
10105 10108
10106 10109 if (((data->DataSize == 0) &&
10107 10110 (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_NONE)) ||
10108 10111 ((data->DataSize != 0) &&
10109 10112 ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_READ) ||
10110 10113 (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_WRITE) ||
10111 10114 ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) &&
10112 10115 (data->DataOutSize != 0))))) {
10113 10116 if (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) {
10114 10117 data->DataDirection = MPTSAS_PASS_THRU_DIRECTION_READ;
10115 10118 } else {
10116 10119 data->DataOutSize = 0;
10117 10120 }
10118 10121 /*
10119 10122 * Send passthru request messages
10120 10123 */
10121 10124 return (mptsas_do_passthru(mpt,
10122 10125 (uint8_t *)((uintptr_t)data->PtrRequest),
10123 10126 (uint8_t *)((uintptr_t)data->PtrReply),
10124 10127 (uint8_t *)((uintptr_t)data->PtrData),
10125 10128 data->RequestSize, data->ReplySize,
10126 10129 data->DataSize, data->DataDirection,
10127 10130 (uint8_t *)((uintptr_t)data->PtrDataOut),
10128 10131 data->DataOutSize, data->Timeout, mode));
10129 10132 } else {
10130 10133 return (EINVAL);
10131 10134 }
10132 10135 }
10133 10136
10134 10137 static uint8_t
10135 10138 mptsas_get_fw_diag_buffer_number(mptsas_t *mpt, uint32_t unique_id)
10136 10139 {
10137 10140 uint8_t index;
10138 10141
10139 10142 for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
10140 10143 if (mpt->m_fw_diag_buffer_list[index].unique_id == unique_id) {
10141 10144 return (index);
10142 10145 }
10143 10146 }
10144 10147
10145 10148 return (MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND);
10146 10149 }
10147 10150
10148 10151 static void
10149 10152 mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd)
10150 10153 {
10151 10154 pMpi2DiagBufferPostRequest_t pDiag_post_msg;
10152 10155 pMpi2DiagReleaseRequest_t pDiag_release_msg;
10153 10156 struct scsi_pkt *pkt = cmd->cmd_pkt;
10154 10157 mptsas_diag_request_t *diag = pkt->pkt_ha_private;
10155 10158 uint32_t request_desc_low, i;
10156 10159
10157 10160 ASSERT(mutex_owned(&mpt->m_mutex));
10158 10161
10159 10162 /*
10160 10163 * Form the diag message depending on the post or release function.
10161 10164 */
10162 10165 if (diag->function == MPI2_FUNCTION_DIAG_BUFFER_POST) {
10163 10166 pDiag_post_msg = (pMpi2DiagBufferPostRequest_t)
10164 10167 (mpt->m_req_frame + (mpt->m_req_frame_size *
10165 10168 cmd->cmd_slot));
10166 10169 bzero(pDiag_post_msg, mpt->m_req_frame_size);
10167 10170 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->Function,
10168 10171 diag->function);
10169 10172 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->BufferType,
10170 10173 diag->pBuffer->buffer_type);
10171 10174 ddi_put8(mpt->m_acc_req_frame_hdl,
10172 10175 &pDiag_post_msg->ExtendedType,
10173 10176 diag->pBuffer->extended_type);
10174 10177 ddi_put32(mpt->m_acc_req_frame_hdl,
10175 10178 &pDiag_post_msg->BufferLength,
10176 10179 diag->pBuffer->buffer_data.size);
10177 10180 for (i = 0; i < (sizeof (pDiag_post_msg->ProductSpecific) / 4);
10178 10181 i++) {
10179 10182 ddi_put32(mpt->m_acc_req_frame_hdl,
10180 10183 &pDiag_post_msg->ProductSpecific[i],
10181 10184 diag->pBuffer->product_specific[i]);
10182 10185 }
10183 10186 ddi_put32(mpt->m_acc_req_frame_hdl,
10184 10187 &pDiag_post_msg->BufferAddress.Low,
10185 10188 (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
10186 10189 & 0xffffffffull));
10187 10190 ddi_put32(mpt->m_acc_req_frame_hdl,
10188 10191 &pDiag_post_msg->BufferAddress.High,
10189 10192 (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
10190 10193 >> 32));
10191 10194 } else {
10192 10195 pDiag_release_msg = (pMpi2DiagReleaseRequest_t)
10193 10196 (mpt->m_req_frame + (mpt->m_req_frame_size *
10194 10197 cmd->cmd_slot));
10195 10198 bzero(pDiag_release_msg, mpt->m_req_frame_size);
10196 10199 ddi_put8(mpt->m_acc_req_frame_hdl,
10197 10200 &pDiag_release_msg->Function, diag->function);
10198 10201 ddi_put8(mpt->m_acc_req_frame_hdl,
10199 10202 &pDiag_release_msg->BufferType,
10200 10203 diag->pBuffer->buffer_type);
10201 10204 }
10202 10205
10203 10206 /*
10204 10207 * Send the message
10205 10208 */
10206 10209 (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
10207 10210 DDI_DMA_SYNC_FORDEV);
10208 10211 request_desc_low = (cmd->cmd_slot << 16) +
10209 10212 MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
10210 10213 cmd->cmd_rfm = NULL;
10211 10214 MPTSAS_START_CMD(mpt, request_desc_low, 0);
10212 10215 if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
10213 10216 DDI_SUCCESS) ||
10214 10217 (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
10215 10218 DDI_SUCCESS)) {
10216 10219 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10217 10220 }
10218 10221 }
10219 10222
10220 10223 static int
10221 10224 mptsas_post_fw_diag_buffer(mptsas_t *mpt,
10222 10225 mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
10223 10226 {
10224 10227 mptsas_diag_request_t diag;
10225 10228 int status, slot_num, post_flags = 0;
10226 10229 mptsas_cmd_t *cmd = NULL;
10227 10230 struct scsi_pkt *pkt;
10228 10231 pMpi2DiagBufferPostReply_t reply;
10229 10232 uint16_t iocstatus;
10230 10233 uint32_t iocloginfo, transfer_length;
10231 10234
10232 10235 /*
10233 10236 * If buffer is not enabled, just leave.
10234 10237 */
10235 10238 *return_code = MPTSAS_FW_DIAG_ERROR_POST_FAILED;
10236 10239 if (!pBuffer->enabled) {
10237 10240 status = DDI_FAILURE;
10238 10241 goto out;
10239 10242 }
10240 10243
10241 10244 /*
10242 10245 * Clear some flags initially.
10243 10246 */
10244 10247 pBuffer->force_release = FALSE;
10245 10248 pBuffer->valid_data = FALSE;
10246 10249 pBuffer->owned_by_firmware = FALSE;
10247 10250
10248 10251 /*
10249 10252 * Get a cmd buffer from the cmd buffer pool
10250 10253 */
10251 10254 if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10252 10255 status = DDI_FAILURE;
10253 10256 mptsas_log(mpt, CE_NOTE, "command pool is full: Post FW Diag");
10254 10257 goto out;
10255 10258 }
10256 10259 post_flags |= MPTSAS_REQUEST_POOL_CMD;
10257 10260
10258 10261 bzero((caddr_t)cmd, sizeof (*cmd));
10259 10262 bzero((caddr_t)pkt, scsi_pkt_size());
10260 10263
10261 10264 cmd->ioc_cmd_slot = (uint32_t)(slot_num);
10262 10265
10263 10266 diag.pBuffer = pBuffer;
10264 10267 diag.function = MPI2_FUNCTION_DIAG_BUFFER_POST;
10265 10268
10266 10269 /*
10267 10270 * Form a blank cmd/pkt to store the acknowledgement message
10268 10271 */
10269 10272 pkt->pkt_ha_private = (opaque_t)&diag;
10270 10273 pkt->pkt_flags = FLAG_HEAD;
10271 10274 pkt->pkt_time = 60;
10272 10275 cmd->cmd_pkt = pkt;
10273 10276 cmd->cmd_flags = CFLAG_CMDIOC | CFLAG_FW_DIAG;
10274 10277
10275 10278 /*
10276 10279 * Save the command in a slot
10277 10280 */
10278 10281 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10279 10282 /*
10280 10283 * Once passthru command get slot, set cmd_flags
10281 10284 * CFLAG_PREPARED.
10282 10285 */
10283 10286 cmd->cmd_flags |= CFLAG_PREPARED;
10284 10287 mptsas_start_diag(mpt, cmd);
10285 10288 } else {
10286 10289 mptsas_waitq_add(mpt, cmd);
10287 10290 }
10288 10291
10289 10292 while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10290 10293 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
10291 10294 }
10292 10295
10293 10296 if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10294 10297 status = DDI_FAILURE;
10295 10298 mptsas_log(mpt, CE_WARN, "Post FW Diag command timeout");
10296 10299 goto out;
10297 10300 }
10298 10301
10299 10302 /*
10300 10303 * cmd_rfm points to the reply message if a reply was given. Check the
10301 10304 * IOCStatus to make sure everything went OK with the FW diag request
10302 10305 * and set buffer flags.
10303 10306 */
10304 10307 if (cmd->cmd_rfm) {
10305 10308 post_flags |= MPTSAS_ADDRESS_REPLY;
10306 10309 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10307 10310 DDI_DMA_SYNC_FORCPU);
10308 10311 reply = (pMpi2DiagBufferPostReply_t)(mpt->m_reply_frame +
10309 10312 (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
10310 10313
10311 10314 /*
10312 10315 * Get the reply message data
10313 10316 */
10314 10317 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
10315 10318 &reply->IOCStatus);
10316 10319 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
10317 10320 &reply->IOCLogInfo);
10318 10321 transfer_length = ddi_get32(mpt->m_acc_reply_frame_hdl,
10319 10322 &reply->TransferLength);
10320 10323
10321 10324 /*
10322 10325 * If post failed quit.
10323 10326 */
10324 10327 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
10325 10328 status = DDI_FAILURE;
10326 10329 NDBG13(("post FW Diag Buffer failed: IOCStatus=0x%x, "
10327 10330 "IOCLogInfo=0x%x, TransferLength=0x%x", iocstatus,
10328 10331 iocloginfo, transfer_length));
10329 10332 goto out;
10330 10333 }
10331 10334
10332 10335 /*
10333 10336 * Post was successful.
10334 10337 */
10335 10338 pBuffer->valid_data = TRUE;
10336 10339 pBuffer->owned_by_firmware = TRUE;
10337 10340 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10338 10341 status = DDI_SUCCESS;
10339 10342 }
10340 10343
10341 10344 out:
10342 10345 /*
10343 10346 * Put the reply frame back on the free queue, increment the free
10344 10347 * index, and write the new index to the free index register. But only
10345 10348 * if this reply is an ADDRESS reply.
10346 10349 */
10347 10350 if (post_flags & MPTSAS_ADDRESS_REPLY) {
10348 10351 ddi_put32(mpt->m_acc_free_queue_hdl,
10349 10352 &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10350 10353 cmd->cmd_rfm);
10351 10354 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10352 10355 DDI_DMA_SYNC_FORDEV);
10353 10356 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10354 10357 mpt->m_free_index = 0;
10355 10358 }
10356 10359 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10357 10360 mpt->m_free_index);
10358 10361 }
10359 10362 if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10360 10363 mptsas_remove_cmd(mpt, cmd);
10361 10364 post_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10362 10365 }
10363 10366 if (post_flags & MPTSAS_REQUEST_POOL_CMD) {
10364 10367 mptsas_return_to_pool(mpt, cmd);
10365 10368 }
10366 10369
10367 10370 return (status);
10368 10371 }
10369 10372
10370 10373 static int
10371 10374 mptsas_release_fw_diag_buffer(mptsas_t *mpt,
10372 10375 mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
10373 10376 uint32_t diag_type)
10374 10377 {
10375 10378 mptsas_diag_request_t diag;
10376 10379 int status, slot_num, rel_flags = 0;
10377 10380 mptsas_cmd_t *cmd = NULL;
10378 10381 struct scsi_pkt *pkt;
10379 10382 pMpi2DiagReleaseReply_t reply;
10380 10383 uint16_t iocstatus;
10381 10384 uint32_t iocloginfo;
10382 10385
10383 10386 /*
10384 10387 * If buffer is not enabled, just leave.
10385 10388 */
10386 10389 *return_code = MPTSAS_FW_DIAG_ERROR_RELEASE_FAILED;
10387 10390 if (!pBuffer->enabled) {
10388 10391 mptsas_log(mpt, CE_NOTE, "This buffer type is not supported "
10389 10392 "by the IOC");
10390 10393 status = DDI_FAILURE;
10391 10394 goto out;
10392 10395 }
10393 10396
10394 10397 /*
10395 10398 * Clear some flags initially.
10396 10399 */
10397 10400 pBuffer->force_release = FALSE;
10398 10401 pBuffer->valid_data = FALSE;
10399 10402 pBuffer->owned_by_firmware = FALSE;
10400 10403
10401 10404 /*
10402 10405 * Get a cmd buffer from the cmd buffer pool
10403 10406 */
10404 10407 if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10405 10408 status = DDI_FAILURE;
10406 10409 mptsas_log(mpt, CE_NOTE, "command pool is full: Release FW "
10407 10410 "Diag");
10408 10411 goto out;
10409 10412 }
10410 10413 rel_flags |= MPTSAS_REQUEST_POOL_CMD;
10411 10414
10412 10415 bzero((caddr_t)cmd, sizeof (*cmd));
10413 10416 bzero((caddr_t)pkt, scsi_pkt_size());
10414 10417
10415 10418 cmd->ioc_cmd_slot = (uint32_t)(slot_num);
10416 10419
10417 10420 diag.pBuffer = pBuffer;
10418 10421 diag.function = MPI2_FUNCTION_DIAG_RELEASE;
10419 10422
10420 10423 /*
10421 10424 * Form a blank cmd/pkt to store the acknowledgement message
10422 10425 */
10423 10426 pkt->pkt_ha_private = (opaque_t)&diag;
10424 10427 pkt->pkt_flags = FLAG_HEAD;
10425 10428 pkt->pkt_time = 60;
10426 10429 cmd->cmd_pkt = pkt;
10427 10430 cmd->cmd_flags = CFLAG_CMDIOC | CFLAG_FW_DIAG;
10428 10431
10429 10432 /*
10430 10433 * Save the command in a slot
10431 10434 */
10432 10435 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10433 10436 /*
10434 10437 * Once passthru command get slot, set cmd_flags
10435 10438 * CFLAG_PREPARED.
10436 10439 */
10437 10440 cmd->cmd_flags |= CFLAG_PREPARED;
10438 10441 mptsas_start_diag(mpt, cmd);
10439 10442 } else {
10440 10443 mptsas_waitq_add(mpt, cmd);
10441 10444 }
10442 10445
10443 10446 while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10444 10447 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
10445 10448 }
10446 10449
10447 10450 if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10448 10451 status = DDI_FAILURE;
10449 10452 mptsas_log(mpt, CE_WARN, "Release FW Diag command timeout");
10450 10453 goto out;
10451 10454 }
10452 10455
10453 10456 /*
10454 10457 * cmd_rfm points to the reply message if a reply was given. Check the
10455 10458 * IOCStatus to make sure everything went OK with the FW diag request
10456 10459 * and set buffer flags.
10457 10460 */
10458 10461 if (cmd->cmd_rfm) {
10459 10462 rel_flags |= MPTSAS_ADDRESS_REPLY;
10460 10463 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10461 10464 DDI_DMA_SYNC_FORCPU);
10462 10465 reply = (pMpi2DiagReleaseReply_t)(mpt->m_reply_frame +
10463 10466 (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
10464 10467
10465 10468 /*
10466 10469 * Get the reply message data
10467 10470 */
10468 10471 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
10469 10472 &reply->IOCStatus);
10470 10473 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
10471 10474 &reply->IOCLogInfo);
10472 10475
10473 10476 /*
10474 10477 * If release failed quit.
10475 10478 */
10476 10479 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) ||
10477 10480 pBuffer->owned_by_firmware) {
10478 10481 status = DDI_FAILURE;
10479 10482 NDBG13(("release FW Diag Buffer failed: "
10480 10483 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
10481 10484 iocloginfo));
10482 10485 goto out;
10483 10486 }
10484 10487
10485 10488 /*
10486 10489 * Release was successful.
10487 10490 */
10488 10491 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10489 10492 status = DDI_SUCCESS;
10490 10493
10491 10494 /*
10492 10495 * If this was for an UNREGISTER diag type command, clear the
10493 10496 * unique ID.
10494 10497 */
10495 10498 if (diag_type == MPTSAS_FW_DIAG_TYPE_UNREGISTER) {
10496 10499 pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
10497 10500 }
10498 10501 }
10499 10502
10500 10503 out:
10501 10504 /*
10502 10505 * Put the reply frame back on the free queue, increment the free
10503 10506 * index, and write the new index to the free index register. But only
10504 10507 * if this reply is an ADDRESS reply.
10505 10508 */
10506 10509 if (rel_flags & MPTSAS_ADDRESS_REPLY) {
10507 10510 ddi_put32(mpt->m_acc_free_queue_hdl,
10508 10511 &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10509 10512 cmd->cmd_rfm);
10510 10513 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10511 10514 DDI_DMA_SYNC_FORDEV);
10512 10515 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10513 10516 mpt->m_free_index = 0;
10514 10517 }
10515 10518 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10516 10519 mpt->m_free_index);
10517 10520 }
10518 10521 if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10519 10522 mptsas_remove_cmd(mpt, cmd);
10520 10523 rel_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10521 10524 }
10522 10525 if (rel_flags & MPTSAS_REQUEST_POOL_CMD) {
10523 10526 mptsas_return_to_pool(mpt, cmd);
10524 10527 }
10525 10528
10526 10529 return (status);
10527 10530 }
10528 10531
10529 10532 static int
10530 10533 mptsas_diag_register(mptsas_t *mpt, mptsas_fw_diag_register_t *diag_register,
10531 10534 uint32_t *return_code)
10532 10535 {
10533 10536 mptsas_fw_diagnostic_buffer_t *pBuffer;
10534 10537 uint8_t extended_type, buffer_type, i;
10535 10538 uint32_t buffer_size;
10536 10539 uint32_t unique_id;
10537 10540 int status;
10538 10541
10539 10542 ASSERT(mutex_owned(&mpt->m_mutex));
10540 10543
10541 10544 extended_type = diag_register->ExtendedType;
10542 10545 buffer_type = diag_register->BufferType;
10543 10546 buffer_size = diag_register->RequestedBufferSize;
10544 10547 unique_id = diag_register->UniqueId;
10545 10548
10546 10549 /*
10547 10550 * Check for valid buffer type
10548 10551 */
10549 10552 if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
10550 10553 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10551 10554 return (DDI_FAILURE);
10552 10555 }
10553 10556
10554 10557 /*
10555 10558 * Get the current buffer and look up the unique ID. The unique ID
10556 10559 * should not be found. If it is, the ID is already in use.
10557 10560 */
10558 10561 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10559 10562 pBuffer = &mpt->m_fw_diag_buffer_list[buffer_type];
10560 10563 if (i != MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10561 10564 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10562 10565 return (DDI_FAILURE);
10563 10566 }
10564 10567
10565 10568 /*
10566 10569 * The buffer's unique ID should not be registered yet, and the given
10567 10570 * unique ID cannot be 0.
10568 10571 */
10569 10572 if ((pBuffer->unique_id != MPTSAS_FW_DIAG_INVALID_UID) ||
10570 10573 (unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
10571 10574 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10572 10575 return (DDI_FAILURE);
10573 10576 }
10574 10577
10575 10578 /*
10576 10579 * If this buffer is already posted as immediate, just change owner.
10577 10580 */
10578 10581 if (pBuffer->immediate && pBuffer->owned_by_firmware &&
10579 10582 (pBuffer->unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
10580 10583 pBuffer->immediate = FALSE;
10581 10584 pBuffer->unique_id = unique_id;
10582 10585 return (DDI_SUCCESS);
10583 10586 }
10584 10587
10585 10588 /*
10586 10589 * Post a new buffer after checking if it's enabled. The DMA buffer
10587 10590 * that is allocated will be contiguous (sgl_len = 1).
10588 10591 */
10589 10592 if (!pBuffer->enabled) {
10590 10593 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
10591 10594 return (DDI_FAILURE);
10592 10595 }
10593 10596 bzero(&pBuffer->buffer_data, sizeof (mptsas_dma_alloc_state_t));
10594 10597 pBuffer->buffer_data.size = buffer_size;
10595 10598 if (mptsas_dma_alloc(mpt, &pBuffer->buffer_data) != DDI_SUCCESS) {
10596 10599 mptsas_log(mpt, CE_WARN, "failed to alloc DMA resource for "
10597 10600 "diag buffer: size = %d bytes", buffer_size);
10598 10601 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
10599 10602 return (DDI_FAILURE);
10600 10603 }
10601 10604
10602 10605 /*
10603 10606 * Copy the given info to the diag buffer and post the buffer.
10604 10607 */
10605 10608 pBuffer->buffer_type = buffer_type;
10606 10609 pBuffer->immediate = FALSE;
10607 10610 if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
10608 10611 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
10609 10612 i++) {
10610 10613 pBuffer->product_specific[i] =
10611 10614 diag_register->ProductSpecific[i];
10612 10615 }
10613 10616 }
10614 10617 pBuffer->extended_type = extended_type;
10615 10618 pBuffer->unique_id = unique_id;
10616 10619 status = mptsas_post_fw_diag_buffer(mpt, pBuffer, return_code);
10617 10620
10618 10621 if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
10619 10622 DDI_SUCCESS) {
10620 10623 mptsas_log(mpt, CE_WARN, "Check of DMA handle failed in "
10621 10624 "mptsas_diag_register.");
10622 10625 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10623 10626 status = DDI_FAILURE;
10624 10627 }
10625 10628
10626 10629 /*
10627 10630 * In case there was a failure, free the DMA buffer.
10628 10631 */
10629 10632 if (status == DDI_FAILURE) {
10630 10633 mptsas_dma_free(&pBuffer->buffer_data);
10631 10634 }
10632 10635
10633 10636 return (status);
10634 10637 }
10635 10638
10636 10639 static int
10637 10640 mptsas_diag_unregister(mptsas_t *mpt,
10638 10641 mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
10639 10642 {
10640 10643 mptsas_fw_diagnostic_buffer_t *pBuffer;
10641 10644 uint8_t i;
10642 10645 uint32_t unique_id;
10643 10646 int status;
10644 10647
10645 10648 ASSERT(mutex_owned(&mpt->m_mutex));
10646 10649
10647 10650 unique_id = diag_unregister->UniqueId;
10648 10651
10649 10652 /*
10650 10653 * Get the current buffer and look up the unique ID. The unique ID
10651 10654 * should be there.
10652 10655 */
10653 10656 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10654 10657 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10655 10658 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10656 10659 return (DDI_FAILURE);
10657 10660 }
10658 10661
10659 10662 pBuffer = &mpt->m_fw_diag_buffer_list[i];
10660 10663
10661 10664 /*
10662 10665 * Try to release the buffer from FW before freeing it. If release
10663 10666 * fails, don't free the DMA buffer in case FW tries to access it
10664 10667 * later. If buffer is not owned by firmware, can't release it.
10665 10668 */
10666 10669 if (!pBuffer->owned_by_firmware) {
10667 10670 status = DDI_SUCCESS;
10668 10671 } else {
10669 10672 status = mptsas_release_fw_diag_buffer(mpt, pBuffer,
10670 10673 return_code, MPTSAS_FW_DIAG_TYPE_UNREGISTER);
10671 10674 }
10672 10675
10673 10676 /*
10674 10677 * At this point, return the current status no matter what happens with
10675 10678 * the DMA buffer.
10676 10679 */
10677 10680 pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
10678 10681 if (status == DDI_SUCCESS) {
10679 10682 if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
10680 10683 DDI_SUCCESS) {
10681 10684 mptsas_log(mpt, CE_WARN, "Check of DMA handle failed "
10682 10685 "in mptsas_diag_unregister.");
10683 10686 ddi_fm_service_impact(mpt->m_dip,
10684 10687 DDI_SERVICE_UNAFFECTED);
10685 10688 }
10686 10689 mptsas_dma_free(&pBuffer->buffer_data);
10687 10690 }
10688 10691
10689 10692 return (status);
10690 10693 }
10691 10694
10692 10695 static int
10693 10696 mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
10694 10697 uint32_t *return_code)
10695 10698 {
10696 10699 mptsas_fw_diagnostic_buffer_t *pBuffer;
10697 10700 uint8_t i;
10698 10701 uint32_t unique_id;
10699 10702
10700 10703 ASSERT(mutex_owned(&mpt->m_mutex));
10701 10704
10702 10705 unique_id = diag_query->UniqueId;
10703 10706
10704 10707 /*
10705 10708 * If ID is valid, query on ID.
10706 10709 * If ID is invalid, query on buffer type.
10707 10710 */
10708 10711 if (unique_id == MPTSAS_FW_DIAG_INVALID_UID) {
10709 10712 i = diag_query->BufferType;
10710 10713 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
10711 10714 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10712 10715 return (DDI_FAILURE);
10713 10716 }
10714 10717 } else {
10715 10718 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10716 10719 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10717 10720 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10718 10721 return (DDI_FAILURE);
10719 10722 }
10720 10723 }
10721 10724
10722 10725 /*
10723 10726 * Fill query structure with the diag buffer info.
10724 10727 */
10725 10728 pBuffer = &mpt->m_fw_diag_buffer_list[i];
10726 10729 diag_query->BufferType = pBuffer->buffer_type;
10727 10730 diag_query->ExtendedType = pBuffer->extended_type;
10728 10731 if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
10729 10732 for (i = 0; i < (sizeof (diag_query->ProductSpecific) / 4);
10730 10733 i++) {
10731 10734 diag_query->ProductSpecific[i] =
10732 10735 pBuffer->product_specific[i];
10733 10736 }
10734 10737 }
10735 10738 diag_query->TotalBufferSize = pBuffer->buffer_data.size;
10736 10739 diag_query->DriverAddedBufferSize = 0;
10737 10740 diag_query->UniqueId = pBuffer->unique_id;
10738 10741 diag_query->ApplicationFlags = 0;
10739 10742 diag_query->DiagnosticFlags = 0;
10740 10743
10741 10744 /*
10742 10745 * Set/Clear application flags
10743 10746 */
10744 10747 if (pBuffer->immediate) {
10745 10748 diag_query->ApplicationFlags &= ~MPTSAS_FW_DIAG_FLAG_APP_OWNED;
10746 10749 } else {
10747 10750 diag_query->ApplicationFlags |= MPTSAS_FW_DIAG_FLAG_APP_OWNED;
10748 10751 }
10749 10752 if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
10750 10753 diag_query->ApplicationFlags |=
10751 10754 MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
10752 10755 } else {
10753 10756 diag_query->ApplicationFlags &=
10754 10757 ~MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
10755 10758 }
10756 10759 if (pBuffer->owned_by_firmware) {
10757 10760 diag_query->ApplicationFlags |=
10758 10761 MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
10759 10762 } else {
10760 10763 diag_query->ApplicationFlags &=
10761 10764 ~MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
10762 10765 }
10763 10766
10764 10767 return (DDI_SUCCESS);
10765 10768 }
10766 10769
10767 10770 static int
10768 10771 mptsas_diag_read_buffer(mptsas_t *mpt,
10769 10772 mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
10770 10773 uint32_t *return_code, int ioctl_mode)
10771 10774 {
10772 10775 mptsas_fw_diagnostic_buffer_t *pBuffer;
10773 10776 uint8_t i, *pData;
10774 10777 uint32_t unique_id, byte;
10775 10778 int status;
10776 10779
10777 10780 ASSERT(mutex_owned(&mpt->m_mutex));
10778 10781
10779 10782 unique_id = diag_read_buffer->UniqueId;
10780 10783
10781 10784 /*
10782 10785 * Get the current buffer and look up the unique ID. The unique ID
10783 10786 * should be there.
10784 10787 */
10785 10788 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10786 10789 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10787 10790 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10788 10791 return (DDI_FAILURE);
10789 10792 }
10790 10793
10791 10794 pBuffer = &mpt->m_fw_diag_buffer_list[i];
10792 10795
10793 10796 /*
10794 10797 * Make sure requested read is within limits
10795 10798 */
10796 10799 if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
10797 10800 pBuffer->buffer_data.size) {
10798 10801 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10799 10802 return (DDI_FAILURE);
10800 10803 }
10801 10804
10802 10805 /*
10803 10806 * Copy the requested data from DMA to the diag_read_buffer. The DMA
10804 10807 * buffer that was allocated is one contiguous buffer.
10805 10808 */
10806 10809 pData = (uint8_t *)(pBuffer->buffer_data.memp +
10807 10810 diag_read_buffer->StartingOffset);
10808 10811 (void) ddi_dma_sync(pBuffer->buffer_data.handle, 0, 0,
10809 10812 DDI_DMA_SYNC_FORCPU);
10810 10813 for (byte = 0; byte < diag_read_buffer->BytesToRead; byte++) {
10811 10814 if (ddi_copyout(pData + byte, ioctl_buf + byte, 1, ioctl_mode)
10812 10815 != 0) {
10813 10816 return (DDI_FAILURE);
10814 10817 }
10815 10818 }
10816 10819 diag_read_buffer->Status = 0;
10817 10820
10818 10821 /*
10819 10822 * Set or clear the Force Release flag.
10820 10823 */
10821 10824 if (pBuffer->force_release) {
10822 10825 diag_read_buffer->Flags |= MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
10823 10826 } else {
10824 10827 diag_read_buffer->Flags &= ~MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
10825 10828 }
10826 10829
10827 10830 /*
10828 10831 * If buffer is to be reregistered, make sure it's not already owned by
10829 10832 * firmware first.
10830 10833 */
10831 10834 status = DDI_SUCCESS;
10832 10835 if (!pBuffer->owned_by_firmware) {
10833 10836 if (diag_read_buffer->Flags & MPTSAS_FW_DIAG_FLAG_REREGISTER) {
10834 10837 status = mptsas_post_fw_diag_buffer(mpt, pBuffer,
10835 10838 return_code);
10836 10839 }
10837 10840 }
10838 10841
10839 10842 return (status);
10840 10843 }
10841 10844
10842 10845 static int
10843 10846 mptsas_diag_release(mptsas_t *mpt, mptsas_fw_diag_release_t *diag_release,
10844 10847 uint32_t *return_code)
10845 10848 {
10846 10849 mptsas_fw_diagnostic_buffer_t *pBuffer;
10847 10850 uint8_t i;
10848 10851 uint32_t unique_id;
10849 10852 int status;
10850 10853
10851 10854 ASSERT(mutex_owned(&mpt->m_mutex));
10852 10855
10853 10856 unique_id = diag_release->UniqueId;
10854 10857
10855 10858 /*
10856 10859 * Get the current buffer and look up the unique ID. The unique ID
10857 10860 * should be there.
10858 10861 */
10859 10862 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10860 10863 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10861 10864 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10862 10865 return (DDI_FAILURE);
10863 10866 }
10864 10867
10865 10868 pBuffer = &mpt->m_fw_diag_buffer_list[i];
10866 10869
10867 10870 /*
10868 10871 * If buffer is not owned by firmware, it's already been released.
10869 10872 */
10870 10873 if (!pBuffer->owned_by_firmware) {
10871 10874 *return_code = MPTSAS_FW_DIAG_ERROR_ALREADY_RELEASED;
10872 10875 return (DDI_FAILURE);
10873 10876 }
10874 10877
10875 10878 /*
10876 10879 * Release the buffer.
10877 10880 */
10878 10881 status = mptsas_release_fw_diag_buffer(mpt, pBuffer, return_code,
10879 10882 MPTSAS_FW_DIAG_TYPE_RELEASE);
10880 10883 return (status);
10881 10884 }
10882 10885
10883 10886 static int
10884 10887 mptsas_do_diag_action(mptsas_t *mpt, uint32_t action, uint8_t *diag_action,
10885 10888 uint32_t length, uint32_t *return_code, int ioctl_mode)
10886 10889 {
10887 10890 mptsas_fw_diag_register_t diag_register;
10888 10891 mptsas_fw_diag_unregister_t diag_unregister;
10889 10892 mptsas_fw_diag_query_t diag_query;
10890 10893 mptsas_diag_read_buffer_t diag_read_buffer;
10891 10894 mptsas_fw_diag_release_t diag_release;
10892 10895 int status = DDI_SUCCESS;
10893 10896 uint32_t original_return_code, read_buf_len;
10894 10897
10895 10898 ASSERT(mutex_owned(&mpt->m_mutex));
10896 10899
10897 10900 original_return_code = *return_code;
10898 10901 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10899 10902
10900 10903 switch (action) {
10901 10904 case MPTSAS_FW_DIAG_TYPE_REGISTER:
10902 10905 if (!length) {
10903 10906 *return_code =
10904 10907 MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10905 10908 status = DDI_FAILURE;
10906 10909 break;
10907 10910 }
10908 10911 if (ddi_copyin(diag_action, &diag_register,
10909 10912 sizeof (diag_register), ioctl_mode) != 0) {
10910 10913 return (DDI_FAILURE);
10911 10914 }
10912 10915 status = mptsas_diag_register(mpt, &diag_register,
10913 10916 return_code);
10914 10917 break;
10915 10918
10916 10919 case MPTSAS_FW_DIAG_TYPE_UNREGISTER:
10917 10920 if (length < sizeof (diag_unregister)) {
10918 10921 *return_code =
10919 10922 MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10920 10923 status = DDI_FAILURE;
10921 10924 break;
10922 10925 }
10923 10926 if (ddi_copyin(diag_action, &diag_unregister,
10924 10927 sizeof (diag_unregister), ioctl_mode) != 0) {
10925 10928 return (DDI_FAILURE);
10926 10929 }
10927 10930 status = mptsas_diag_unregister(mpt, &diag_unregister,
10928 10931 return_code);
10929 10932 break;
10930 10933
10931 10934 case MPTSAS_FW_DIAG_TYPE_QUERY:
10932 10935 if (length < sizeof (diag_query)) {
10933 10936 *return_code =
10934 10937 MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10935 10938 status = DDI_FAILURE;
10936 10939 break;
10937 10940 }
10938 10941 if (ddi_copyin(diag_action, &diag_query,
10939 10942 sizeof (diag_query), ioctl_mode) != 0) {
10940 10943 return (DDI_FAILURE);
10941 10944 }
10942 10945 status = mptsas_diag_query(mpt, &diag_query,
10943 10946 return_code);
10944 10947 if (status == DDI_SUCCESS) {
10945 10948 if (ddi_copyout(&diag_query, diag_action,
10946 10949 sizeof (diag_query), ioctl_mode) != 0) {
10947 10950 return (DDI_FAILURE);
10948 10951 }
10949 10952 }
10950 10953 break;
10951 10954
10952 10955 case MPTSAS_FW_DIAG_TYPE_READ_BUFFER:
10953 10956 if (ddi_copyin(diag_action, &diag_read_buffer,
10954 10957 sizeof (diag_read_buffer) - 4, ioctl_mode) != 0) {
10955 10958 return (DDI_FAILURE);
10956 10959 }
10957 10960 read_buf_len = sizeof (diag_read_buffer) -
10958 10961 sizeof (diag_read_buffer.DataBuffer) +
10959 10962 diag_read_buffer.BytesToRead;
10960 10963 if (length < read_buf_len) {
10961 10964 *return_code =
10962 10965 MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10963 10966 status = DDI_FAILURE;
10964 10967 break;
10965 10968 }
10966 10969 status = mptsas_diag_read_buffer(mpt,
10967 10970 &diag_read_buffer, diag_action +
10968 10971 sizeof (diag_read_buffer) - 4, return_code,
10969 10972 ioctl_mode);
10970 10973 if (status == DDI_SUCCESS) {
10971 10974 if (ddi_copyout(&diag_read_buffer, diag_action,
10972 10975 sizeof (diag_read_buffer) - 4, ioctl_mode)
10973 10976 != 0) {
10974 10977 return (DDI_FAILURE);
10975 10978 }
10976 10979 }
10977 10980 break;
10978 10981
10979 10982 case MPTSAS_FW_DIAG_TYPE_RELEASE:
10980 10983 if (length < sizeof (diag_release)) {
10981 10984 *return_code =
10982 10985 MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10983 10986 status = DDI_FAILURE;
10984 10987 break;
10985 10988 }
10986 10989 if (ddi_copyin(diag_action, &diag_release,
10987 10990 sizeof (diag_release), ioctl_mode) != 0) {
10988 10991 return (DDI_FAILURE);
10989 10992 }
10990 10993 status = mptsas_diag_release(mpt, &diag_release,
10991 10994 return_code);
10992 10995 break;
10993 10996
10994 10997 default:
10995 10998 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10996 10999 status = DDI_FAILURE;
10997 11000 break;
10998 11001 }
10999 11002
11000 11003 if ((status == DDI_FAILURE) &&
11001 11004 (original_return_code == MPTSAS_FW_DIAG_NEW) &&
11002 11005 (*return_code != MPTSAS_FW_DIAG_ERROR_SUCCESS)) {
11003 11006 status = DDI_SUCCESS;
11004 11007 }
11005 11008
11006 11009 return (status);
11007 11010 }
11008 11011
11009 11012 static int
11010 11013 mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *user_data, int mode)
11011 11014 {
11012 11015 int status;
11013 11016 mptsas_diag_action_t driver_data;
11014 11017
11015 11018 ASSERT(mutex_owned(&mpt->m_mutex));
11016 11019
11017 11020 /*
11018 11021 * Copy the user data to a driver data buffer.
11019 11022 */
11020 11023 if (ddi_copyin(user_data, &driver_data, sizeof (mptsas_diag_action_t),
11021 11024 mode) == 0) {
11022 11025 /*
11023 11026 * Send diag action request if Action is valid
11024 11027 */
11025 11028 if (driver_data.Action == MPTSAS_FW_DIAG_TYPE_REGISTER ||
11026 11029 driver_data.Action == MPTSAS_FW_DIAG_TYPE_UNREGISTER ||
11027 11030 driver_data.Action == MPTSAS_FW_DIAG_TYPE_QUERY ||
11028 11031 driver_data.Action == MPTSAS_FW_DIAG_TYPE_READ_BUFFER ||
11029 11032 driver_data.Action == MPTSAS_FW_DIAG_TYPE_RELEASE) {
11030 11033 status = mptsas_do_diag_action(mpt, driver_data.Action,
11031 11034 (void *)(uintptr_t)driver_data.PtrDiagAction,
11032 11035 driver_data.Length, &driver_data.ReturnCode,
11033 11036 mode);
11034 11037 if (status == DDI_SUCCESS) {
11035 11038 if (ddi_copyout(&driver_data.ReturnCode,
11036 11039 &user_data->ReturnCode,
11037 11040 sizeof (user_data->ReturnCode), mode)
11038 11041 != 0) {
11039 11042 status = EFAULT;
11040 11043 } else {
11041 11044 status = 0;
11042 11045 }
11043 11046 } else {
11044 11047 status = EIO;
11045 11048 }
11046 11049 } else {
11047 11050 status = EINVAL;
11048 11051 }
11049 11052 } else {
11050 11053 status = EFAULT;
11051 11054 }
11052 11055
11053 11056 return (status);
11054 11057 }
11055 11058
11056 11059 /*
11057 11060 * This routine handles the "event query" ioctl.
11058 11061 */
11059 11062 static int
11060 11063 mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data, int mode,
11061 11064 int *rval)
11062 11065 {
11063 11066 int status;
11064 11067 mptsas_event_query_t driverdata;
11065 11068 uint8_t i;
11066 11069
11067 11070 driverdata.Entries = MPTSAS_EVENT_QUEUE_SIZE;
11068 11071
11069 11072 mutex_enter(&mpt->m_mutex);
11070 11073 for (i = 0; i < 4; i++) {
11071 11074 driverdata.Types[i] = mpt->m_event_mask[i];
11072 11075 }
11073 11076 mutex_exit(&mpt->m_mutex);
11074 11077
11075 11078 if (ddi_copyout(&driverdata, data, sizeof (driverdata), mode) != 0) {
11076 11079 status = EFAULT;
11077 11080 } else {
11078 11081 *rval = MPTIOCTL_STATUS_GOOD;
11079 11082 status = 0;
11080 11083 }
11081 11084
11082 11085 return (status);
11083 11086 }
11084 11087
11085 11088 /*
11086 11089 * This routine handles the "event enable" ioctl.
11087 11090 */
11088 11091 static int
11089 11092 mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data, int mode,
11090 11093 int *rval)
11091 11094 {
11092 11095 int status;
11093 11096 mptsas_event_enable_t driverdata;
11094 11097 uint8_t i;
11095 11098
11096 11099 if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
11097 11100 mutex_enter(&mpt->m_mutex);
11098 11101 for (i = 0; i < 4; i++) {
11099 11102 mpt->m_event_mask[i] = driverdata.Types[i];
11100 11103 }
11101 11104 mutex_exit(&mpt->m_mutex);
11102 11105
11103 11106 *rval = MPTIOCTL_STATUS_GOOD;
11104 11107 status = 0;
11105 11108 } else {
11106 11109 status = EFAULT;
11107 11110 }
11108 11111 return (status);
11109 11112 }
11110 11113
11111 11114 /*
11112 11115 * This routine handles the "event report" ioctl.
11113 11116 */
11114 11117 static int
11115 11118 mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data, int mode,
11116 11119 int *rval)
11117 11120 {
11118 11121 int status;
11119 11122 mptsas_event_report_t driverdata;
11120 11123
11121 11124 mutex_enter(&mpt->m_mutex);
11122 11125
11123 11126 if (ddi_copyin(&data->Size, &driverdata.Size, sizeof (driverdata.Size),
11124 11127 mode) == 0) {
11125 11128 if (driverdata.Size >= sizeof (mpt->m_events)) {
11126 11129 if (ddi_copyout(mpt->m_events, data->Events,
11127 11130 sizeof (mpt->m_events), mode) != 0) {
11128 11131 status = EFAULT;
11129 11132 } else {
11130 11133 if (driverdata.Size > sizeof (mpt->m_events)) {
11131 11134 driverdata.Size =
11132 11135 sizeof (mpt->m_events);
11133 11136 if (ddi_copyout(&driverdata.Size,
11134 11137 &data->Size,
11135 11138 sizeof (driverdata.Size),
11136 11139 mode) != 0) {
11137 11140 status = EFAULT;
11138 11141 } else {
11139 11142 *rval = MPTIOCTL_STATUS_GOOD;
11140 11143 status = 0;
11141 11144 }
11142 11145 } else {
11143 11146 *rval = MPTIOCTL_STATUS_GOOD;
11144 11147 status = 0;
11145 11148 }
11146 11149 }
11147 11150 } else {
11148 11151 *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
11149 11152 status = 0;
11150 11153 }
11151 11154 } else {
11152 11155 status = EFAULT;
11153 11156 }
11154 11157
11155 11158 mutex_exit(&mpt->m_mutex);
11156 11159 return (status);
11157 11160 }
11158 11161
11159 11162 static void
11160 11163 mptsas_lookup_pci_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
11161 11164 {
11162 11165 int *reg_data;
11163 11166 uint_t reglen;
11164 11167
11165 11168 /*
11166 11169 * Lookup the 'reg' property and extract the other data
11167 11170 */
11168 11171 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
11169 11172 DDI_PROP_DONTPASS, "reg", ®_data, ®len) ==
11170 11173 DDI_PROP_SUCCESS) {
11171 11174 /*
11172 11175 * Extract the PCI data from the 'reg' property first DWORD.
11173 11176 * The entry looks like the following:
11174 11177 * First DWORD:
11175 11178 * Bits 0 - 7 8-bit Register number
11176 11179 * Bits 8 - 10 3-bit Function number
11177 11180 * Bits 11 - 15 5-bit Device number
11178 11181 * Bits 16 - 23 8-bit Bus number
11179 11182 * Bits 24 - 25 2-bit Address Space type identifier
11180 11183 *
11181 11184 */
11182 11185 adapter_data->PciInformation.u.bits.BusNumber =
11183 11186 (reg_data[0] & 0x00FF0000) >> 16;
11184 11187 adapter_data->PciInformation.u.bits.DeviceNumber =
11185 11188 (reg_data[0] & 0x0000F800) >> 11;
11186 11189 adapter_data->PciInformation.u.bits.FunctionNumber =
11187 11190 (reg_data[0] & 0x00000700) >> 8;
11188 11191 ddi_prop_free((void *)reg_data);
11189 11192 } else {
11190 11193 /*
11191 11194 * If we can't determine the PCI data then we fill in FF's for
11192 11195 * the data to indicate this.
11193 11196 */
11194 11197 adapter_data->PCIDeviceHwId = 0xFFFFFFFF;
11195 11198 adapter_data->MpiPortNumber = 0xFFFFFFFF;
11196 11199 adapter_data->PciInformation.u.AsDWORD = 0xFFFFFFFF;
11197 11200 }
11198 11201
11199 11202 /*
11200 11203 * Saved in the mpt->m_fwversion
11201 11204 */
11202 11205 adapter_data->MpiFirmwareVersion = mpt->m_fwversion;
11203 11206 }
11204 11207
11205 11208 static void
11206 11209 mptsas_read_adapter_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
11207 11210 {
11208 11211 char *driver_verstr = MPTSAS_MOD_STRING;
11209 11212
11210 11213 mptsas_lookup_pci_data(mpt, adapter_data);
11211 11214 adapter_data->AdapterType = MPTIOCTL_ADAPTER_TYPE_SAS2;
11212 11215 adapter_data->PCIDeviceHwId = (uint32_t)mpt->m_devid;
11213 11216 adapter_data->PCIDeviceHwRev = (uint32_t)mpt->m_revid;
11214 11217 adapter_data->SubSystemId = (uint32_t)mpt->m_ssid;
11215 11218 adapter_data->SubsystemVendorId = (uint32_t)mpt->m_svid;
11216 11219 (void) strcpy((char *)&adapter_data->DriverVersion[0], driver_verstr);
11217 11220 adapter_data->BiosVersion = 0;
11218 11221 (void) mptsas_get_bios_page3(mpt, &adapter_data->BiosVersion);
11219 11222 }
11220 11223
11221 11224 static void
11222 11225 mptsas_read_pci_info(mptsas_t *mpt, mptsas_pci_info_t *pci_info)
11223 11226 {
11224 11227 int *reg_data, i;
11225 11228 uint_t reglen;
11226 11229
11227 11230 /*
11228 11231 * Lookup the 'reg' property and extract the other data
11229 11232 */
11230 11233 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
11231 11234 DDI_PROP_DONTPASS, "reg", ®_data, ®len) ==
11232 11235 DDI_PROP_SUCCESS) {
11233 11236 /*
11234 11237 * Extract the PCI data from the 'reg' property first DWORD.
11235 11238 * The entry looks like the following:
11236 11239 * First DWORD:
11237 11240 * Bits 8 - 10 3-bit Function number
11238 11241 * Bits 11 - 15 5-bit Device number
11239 11242 * Bits 16 - 23 8-bit Bus number
11240 11243 */
11241 11244 pci_info->BusNumber = (reg_data[0] & 0x00FF0000) >> 16;
11242 11245 pci_info->DeviceNumber = (reg_data[0] & 0x0000F800) >> 11;
11243 11246 pci_info->FunctionNumber = (reg_data[0] & 0x00000700) >> 8;
11244 11247 ddi_prop_free((void *)reg_data);
11245 11248 } else {
11246 11249 /*
11247 11250 * If we can't determine the PCI info then we fill in FF's for
11248 11251 * the data to indicate this.
11249 11252 */
11250 11253 pci_info->BusNumber = 0xFFFFFFFF;
11251 11254 pci_info->DeviceNumber = 0xFF;
11252 11255 pci_info->FunctionNumber = 0xFF;
11253 11256 }
11254 11257
11255 11258 /*
11256 11259 * Now get the interrupt vector and the pci header. The vector can
11257 11260 * only be 0 right now. The header is the first 256 bytes of config
11258 11261 * space.
11259 11262 */
11260 11263 pci_info->InterruptVector = 0;
11261 11264 for (i = 0; i < sizeof (pci_info->PciHeader); i++) {
11262 11265 pci_info->PciHeader[i] = pci_config_get8(mpt->m_config_handle,
11263 11266 i);
11264 11267 }
11265 11268 }
11266 11269
11267 11270 static int
11268 11271 mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data, int mode)
11269 11272 {
11270 11273 int status = 0;
11271 11274 mptsas_reg_access_t driverdata;
11272 11275
11273 11276 mutex_enter(&mpt->m_mutex);
11274 11277 if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
11275 11278 switch (driverdata.Command) {
11276 11279 /*
11277 11280 * IO access is not supported.
11278 11281 */
11279 11282 case REG_IO_READ:
11280 11283 case REG_IO_WRITE:
11281 11284 mptsas_log(mpt, CE_WARN, "IO access is not "
11282 11285 "supported. Use memory access.");
11283 11286 status = EINVAL;
11284 11287 break;
11285 11288
11286 11289 case REG_MEM_READ:
11287 11290 driverdata.RegData = ddi_get32(mpt->m_datap,
11288 11291 (uint32_t *)(void *)mpt->m_reg +
11289 11292 driverdata.RegOffset);
11290 11293 if (ddi_copyout(&driverdata.RegData,
11291 11294 &data->RegData,
11292 11295 sizeof (driverdata.RegData), mode) != 0) {
11293 11296 mptsas_log(mpt, CE_WARN, "Register "
11294 11297 "Read Failed");
11295 11298 status = EFAULT;
11296 11299 }
11297 11300 break;
11298 11301
11299 11302 case REG_MEM_WRITE:
11300 11303 ddi_put32(mpt->m_datap,
11301 11304 (uint32_t *)(void *)mpt->m_reg +
11302 11305 driverdata.RegOffset,
11303 11306 driverdata.RegData);
11304 11307 break;
11305 11308
11306 11309 default:
11307 11310 status = EINVAL;
11308 11311 break;
11309 11312 }
11310 11313 } else {
11311 11314 status = EFAULT;
11312 11315 }
11313 11316
11314 11317 mutex_exit(&mpt->m_mutex);
11315 11318 return (status);
11316 11319 }
11317 11320
11318 11321 static int
11319 11322 led_control(mptsas_t *mpt, intptr_t data, int mode)
11320 11323 {
11321 11324 int ret = 0;
11322 11325 mptsas_led_control_t lc;
11323 11326 mptsas_target_t *ptgt;
11324 11327
11325 11328 if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
11326 11329 return (EFAULT);
11327 11330 }
11328 11331
11329 11332 if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
11330 11333 lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
11331 11334 lc.Led < MPTSAS_LEDCTL_LED_MIN ||
11332 11335 lc.Led > MPTSAS_LEDCTL_LED_MAX ||
11333 11336 (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 &&
11334 11337 lc.LedStatus != 1)) {
11335 11338 return (EINVAL);
11336 11339 }
11337 11340
11338 11341 if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) ||
11339 11342 (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0))
11340 11343 return (EACCES);
11341 11344
11342 11345 /* Locate the target we're interrogating... */
11343 11346 mutex_enter(&mpt->m_mutex);
11344 11347 ptgt = refhash_linear_search(mpt->m_targets,
11345 11348 mptsas_target_eval_slot, &lc);
11346 11349 if (ptgt == NULL) {
11347 11350 /* We could not find a target for that enclosure/slot. */
11348 11351 mutex_exit(&mpt->m_mutex);
11349 11352 return (ENOENT);
11350 11353 }
11351 11354
11352 11355 if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
11353 11356 /* Update our internal LED state. */
11354 11357 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
11355 11358 ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1);
11356 11359
11357 11360 /* Flush it to the controller. */
11358 11361 ret = mptsas_flush_led_status(mpt, ptgt);
11359 11362 mutex_exit(&mpt->m_mutex);
11360 11363 return (ret);
11361 11364 }
11362 11365
11363 11366 /* Return our internal LED state. */
11364 11367 lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1;
11365 11368 mutex_exit(&mpt->m_mutex);
11366 11369
11367 11370 if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) {
11368 11371 return (EFAULT);
11369 11372 }
11370 11373
11371 11374 return (0);
11372 11375 }
11373 11376
11374 11377 static int
11375 11378 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
11376 11379 {
11377 11380 uint16_t i = 0;
11378 11381 uint16_t count = 0;
11379 11382 int ret = 0;
11380 11383 mptsas_target_t *ptgt;
11381 11384 mptsas_disk_info_t *di;
11382 11385 STRUCT_DECL(mptsas_get_disk_info, gdi);
11383 11386
11384 11387 if ((mode & FREAD) == 0)
11385 11388 return (EACCES);
11386 11389
11387 11390 STRUCT_INIT(gdi, get_udatamodel());
11388 11391
11389 11392 if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
11390 11393 mode) != 0) {
11391 11394 return (EFAULT);
11392 11395 }
11393 11396
11394 11397 /* Find out how many targets there are. */
11395 11398 mutex_enter(&mpt->m_mutex);
11396 11399 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11397 11400 ptgt = refhash_next(mpt->m_targets, ptgt)) {
11398 11401 count++;
11399 11402 }
11400 11403 mutex_exit(&mpt->m_mutex);
11401 11404
11402 11405 /*
11403 11406 * If we haven't been asked to copy out information on each target,
11404 11407 * then just return the count.
11405 11408 */
11406 11409 STRUCT_FSET(gdi, DiskCount, count);
11407 11410 if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
11408 11411 goto copy_out;
11409 11412
11410 11413 /*
11411 11414 * If we haven't been given a large enough buffer to copy out into,
11412 11415 * let the caller know.
11413 11416 */
11414 11417 if (STRUCT_FGET(gdi, DiskInfoArraySize) <
11415 11418 count * sizeof (mptsas_disk_info_t)) {
11416 11419 ret = ENOSPC;
11417 11420 goto copy_out;
11418 11421 }
11419 11422
11420 11423 di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
11421 11424
11422 11425 mutex_enter(&mpt->m_mutex);
11423 11426 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11424 11427 ptgt = refhash_next(mpt->m_targets, ptgt)) {
11425 11428 if (i >= count) {
11426 11429 /*
11427 11430 * The number of targets changed while we weren't
11428 11431 * looking, so give up.
11429 11432 */
11430 11433 refhash_rele(mpt->m_targets, ptgt);
11431 11434 mutex_exit(&mpt->m_mutex);
11432 11435 kmem_free(di, count * sizeof (mptsas_disk_info_t));
11433 11436 return (EAGAIN);
11434 11437 }
11435 11438 di[i].Instance = mpt->m_instance;
11436 11439 di[i].Enclosure = ptgt->m_enclosure;
11437 11440 di[i].Slot = ptgt->m_slot_num;
11438 11441 di[i].SasAddress = ptgt->m_addr.mta_wwn;
11439 11442 i++;
11440 11443 }
11441 11444 mutex_exit(&mpt->m_mutex);
11442 11445 STRUCT_FSET(gdi, DiskCount, i);
11443 11446
11444 11447 /* Copy out the disk information to the caller. */
11445 11448 if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
11446 11449 i * sizeof (mptsas_disk_info_t), mode) != 0) {
11447 11450 ret = EFAULT;
11448 11451 }
11449 11452
11450 11453 kmem_free(di, count * sizeof (mptsas_disk_info_t));
11451 11454
11452 11455 copy_out:
11453 11456 if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
11454 11457 mode) != 0) {
11455 11458 ret = EFAULT;
11456 11459 }
11457 11460
11458 11461 return (ret);
11459 11462 }
11460 11463
11461 11464 static int
11462 11465 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
11463 11466 int *rval)
11464 11467 {
11465 11468 int status = 0;
11466 11469 mptsas_t *mpt;
11467 11470 mptsas_update_flash_t flashdata;
11468 11471 mptsas_pass_thru_t passthru_data;
11469 11472 mptsas_adapter_data_t adapter_data;
11470 11473 mptsas_pci_info_t pci_info;
11471 11474 int copylen;
11472 11475
11473 11476 int iport_flag = 0;
11474 11477 dev_info_t *dip = NULL;
11475 11478 mptsas_phymask_t phymask = 0;
11476 11479 struct devctl_iocdata *dcp = NULL;
11477 11480 char *addr = NULL;
11478 11481 mptsas_target_t *ptgt = NULL;
11479 11482
11480 11483 *rval = MPTIOCTL_STATUS_GOOD;
11481 11484 if (secpolicy_sys_config(credp, B_FALSE) != 0) {
11482 11485 return (EPERM);
11483 11486 }
11484 11487
11485 11488 mpt = ddi_get_soft_state(mptsas_state, MINOR2INST(getminor(dev)));
11486 11489 if (mpt == NULL) {
11487 11490 /*
11488 11491 * Called from iport node, get the states
11489 11492 */
11490 11493 iport_flag = 1;
11491 11494 dip = mptsas_get_dip_from_dev(dev, &phymask);
11492 11495 if (dip == NULL) {
11493 11496 return (ENXIO);
11494 11497 }
11495 11498 mpt = DIP2MPT(dip);
11496 11499 }
11497 11500 /* Make sure power level is D0 before accessing registers */
11498 11501 mutex_enter(&mpt->m_mutex);
11499 11502 if (mpt->m_options & MPTSAS_OPT_PM) {
11500 11503 (void) pm_busy_component(mpt->m_dip, 0);
11501 11504 if (mpt->m_power_level != PM_LEVEL_D0) {
11502 11505 mutex_exit(&mpt->m_mutex);
11503 11506 if (pm_raise_power(mpt->m_dip, 0, PM_LEVEL_D0) !=
11504 11507 DDI_SUCCESS) {
11505 11508 mptsas_log(mpt, CE_WARN,
11506 11509 "mptsas%d: mptsas_ioctl: Raise power "
11507 11510 "request failed.", mpt->m_instance);
11508 11511 (void) pm_idle_component(mpt->m_dip, 0);
11509 11512 return (ENXIO);
11510 11513 }
11511 11514 } else {
11512 11515 mutex_exit(&mpt->m_mutex);
11513 11516 }
11514 11517 } else {
11515 11518 mutex_exit(&mpt->m_mutex);
11516 11519 }
11517 11520
11518 11521 if (iport_flag) {
11519 11522 status = scsi_hba_ioctl(dev, cmd, data, mode, credp, rval);
11520 11523 if (status != 0) {
11521 11524 goto out;
11522 11525 }
11523 11526 /*
11524 11527 * The following code control the OK2RM LED, it doesn't affect
11525 11528 * the ioctl return status.
11526 11529 */
11527 11530 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
11528 11531 (cmd == DEVCTL_DEVICE_OFFLINE)) {
11529 11532 if (ndi_dc_allochdl((void *)data, &dcp) !=
11530 11533 NDI_SUCCESS) {
11531 11534 goto out;
11532 11535 }
11533 11536 addr = ndi_dc_getaddr(dcp);
11534 11537 ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
11535 11538 if (ptgt == NULL) {
11536 11539 NDBG14(("mptsas_ioctl led control: tgt %s not "
11537 11540 "found", addr));
11538 11541 ndi_dc_freehdl(dcp);
11539 11542 goto out;
11540 11543 }
11541 11544 mutex_enter(&mpt->m_mutex);
11542 11545 if (cmd == DEVCTL_DEVICE_ONLINE) {
11543 11546 ptgt->m_tgt_unconfigured = 0;
11544 11547 } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
11545 11548 ptgt->m_tgt_unconfigured = 1;
11546 11549 }
11547 11550 if (cmd == DEVCTL_DEVICE_OFFLINE) {
11548 11551 ptgt->m_led_status |=
11549 11552 (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
11550 11553 } else {
11551 11554 ptgt->m_led_status &=
11552 11555 ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
11553 11556 }
11554 11557 (void) mptsas_flush_led_status(mpt, ptgt);
11555 11558 mutex_exit(&mpt->m_mutex);
11556 11559 ndi_dc_freehdl(dcp);
11557 11560 }
11558 11561 goto out;
11559 11562 }
11560 11563 switch (cmd) {
11561 11564 case MPTIOCTL_GET_DISK_INFO:
11562 11565 status = get_disk_info(mpt, data, mode);
11563 11566 break;
11564 11567 case MPTIOCTL_LED_CONTROL:
11565 11568 status = led_control(mpt, data, mode);
11566 11569 break;
11567 11570 case MPTIOCTL_UPDATE_FLASH:
11568 11571 if (ddi_copyin((void *)data, &flashdata,
11569 11572 sizeof (struct mptsas_update_flash), mode)) {
11570 11573 status = EFAULT;
11571 11574 break;
11572 11575 }
11573 11576
11574 11577 mutex_enter(&mpt->m_mutex);
11575 11578 if (mptsas_update_flash(mpt,
11576 11579 (caddr_t)(long)flashdata.PtrBuffer,
11577 11580 flashdata.ImageSize, flashdata.ImageType, mode)) {
11578 11581 status = EFAULT;
11579 11582 }
11580 11583
11581 11584 /*
11582 11585 * Reset the chip to start using the new
11583 11586 * firmware. Reset if failed also.
11584 11587 */
11585 11588 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
11586 11589 if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
11587 11590 status = EFAULT;
11588 11591 }
11589 11592 mutex_exit(&mpt->m_mutex);
11590 11593 break;
11591 11594 case MPTIOCTL_PASS_THRU:
11592 11595 /*
11593 11596 * The user has requested to pass through a command to
11594 11597 * be executed by the MPT firmware. Call our routine
11595 11598 * which does this. Only allow one passthru IOCTL at
11596 11599 * one time. Other threads will block on
11597 11600 * m_passthru_mutex, which is of adaptive variant.
11598 11601 */
11599 11602 if (ddi_copyin((void *)data, &passthru_data,
11600 11603 sizeof (mptsas_pass_thru_t), mode)) {
11601 11604 status = EFAULT;
11602 11605 break;
11603 11606 }
11604 11607 mutex_enter(&mpt->m_passthru_mutex);
11605 11608 mutex_enter(&mpt->m_mutex);
11606 11609 status = mptsas_pass_thru(mpt, &passthru_data, mode);
11607 11610 mutex_exit(&mpt->m_mutex);
11608 11611 mutex_exit(&mpt->m_passthru_mutex);
11609 11612
11610 11613 break;
11611 11614 case MPTIOCTL_GET_ADAPTER_DATA:
11612 11615 /*
11613 11616 * The user has requested to read adapter data. Call
11614 11617 * our routine which does this.
11615 11618 */
11616 11619 bzero(&adapter_data, sizeof (mptsas_adapter_data_t));
11617 11620 if (ddi_copyin((void *)data, (void *)&adapter_data,
11618 11621 sizeof (mptsas_adapter_data_t), mode)) {
11619 11622 status = EFAULT;
11620 11623 break;
11621 11624 }
11622 11625 if (adapter_data.StructureLength >=
11623 11626 sizeof (mptsas_adapter_data_t)) {
11624 11627 adapter_data.StructureLength = (uint32_t)
11625 11628 sizeof (mptsas_adapter_data_t);
11626 11629 copylen = sizeof (mptsas_adapter_data_t);
11627 11630 mutex_enter(&mpt->m_mutex);
11628 11631 mptsas_read_adapter_data(mpt, &adapter_data);
11629 11632 mutex_exit(&mpt->m_mutex);
11630 11633 } else {
11631 11634 adapter_data.StructureLength = (uint32_t)
11632 11635 sizeof (mptsas_adapter_data_t);
11633 11636 copylen = sizeof (adapter_data.StructureLength);
11634 11637 *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
11635 11638 }
11636 11639 if (ddi_copyout((void *)(&adapter_data), (void *)data,
11637 11640 copylen, mode) != 0) {
11638 11641 status = EFAULT;
11639 11642 }
11640 11643 break;
11641 11644 case MPTIOCTL_GET_PCI_INFO:
11642 11645 /*
11643 11646 * The user has requested to read pci info. Call
11644 11647 * our routine which does this.
11645 11648 */
11646 11649 bzero(&pci_info, sizeof (mptsas_pci_info_t));
11647 11650 mutex_enter(&mpt->m_mutex);
11648 11651 mptsas_read_pci_info(mpt, &pci_info);
11649 11652 mutex_exit(&mpt->m_mutex);
11650 11653 if (ddi_copyout((void *)(&pci_info), (void *)data,
11651 11654 sizeof (mptsas_pci_info_t), mode) != 0) {
11652 11655 status = EFAULT;
11653 11656 }
11654 11657 break;
11655 11658 case MPTIOCTL_RESET_ADAPTER:
11656 11659 mutex_enter(&mpt->m_mutex);
11657 11660 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
11658 11661 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
11659 11662 mptsas_log(mpt, CE_WARN, "reset adapter IOCTL "
11660 11663 "failed");
11661 11664 status = EFAULT;
11662 11665 }
11663 11666 mutex_exit(&mpt->m_mutex);
11664 11667 break;
11665 11668 case MPTIOCTL_DIAG_ACTION:
11666 11669 /*
11667 11670 * The user has done a diag buffer action. Call our
11668 11671 * routine which does this. Only allow one diag action
11669 11672 * at one time.
11670 11673 */
11671 11674 mutex_enter(&mpt->m_mutex);
11672 11675 if (mpt->m_diag_action_in_progress) {
11673 11676 mutex_exit(&mpt->m_mutex);
11674 11677 return (EBUSY);
11675 11678 }
11676 11679 mpt->m_diag_action_in_progress = 1;
11677 11680 status = mptsas_diag_action(mpt,
11678 11681 (mptsas_diag_action_t *)data, mode);
11679 11682 mpt->m_diag_action_in_progress = 0;
11680 11683 mutex_exit(&mpt->m_mutex);
11681 11684 break;
11682 11685 case MPTIOCTL_EVENT_QUERY:
11683 11686 /*
11684 11687 * The user has done an event query. Call our routine
11685 11688 * which does this.
11686 11689 */
11687 11690 status = mptsas_event_query(mpt,
11688 11691 (mptsas_event_query_t *)data, mode, rval);
11689 11692 break;
11690 11693 case MPTIOCTL_EVENT_ENABLE:
11691 11694 /*
11692 11695 * The user has done an event enable. Call our routine
11693 11696 * which does this.
11694 11697 */
11695 11698 status = mptsas_event_enable(mpt,
11696 11699 (mptsas_event_enable_t *)data, mode, rval);
11697 11700 break;
11698 11701 case MPTIOCTL_EVENT_REPORT:
11699 11702 /*
11700 11703 * The user has done an event report. Call our routine
11701 11704 * which does this.
11702 11705 */
11703 11706 status = mptsas_event_report(mpt,
11704 11707 (mptsas_event_report_t *)data, mode, rval);
11705 11708 break;
11706 11709 case MPTIOCTL_REG_ACCESS:
11707 11710 /*
11708 11711 * The user has requested register access. Call our
11709 11712 * routine which does this.
11710 11713 */
11711 11714 status = mptsas_reg_access(mpt,
11712 11715 (mptsas_reg_access_t *)data, mode);
11713 11716 break;
11714 11717 default:
11715 11718 status = scsi_hba_ioctl(dev, cmd, data, mode, credp,
11716 11719 rval);
11717 11720 break;
11718 11721 }
11719 11722
11720 11723 out:
11721 11724 return (status);
11722 11725 }
11723 11726
11724 11727 int
11725 11728 mptsas_restart_ioc(mptsas_t *mpt)
11726 11729 {
11727 11730 int rval = DDI_SUCCESS;
11728 11731 mptsas_target_t *ptgt = NULL;
11729 11732
11730 11733 ASSERT(mutex_owned(&mpt->m_mutex));
11731 11734
11732 11735 /*
11733 11736 * Set a flag telling I/O path that we're processing a reset. This is
11734 11737 * needed because after the reset is complete, the hash table still
11735 11738 * needs to be rebuilt. If I/Os are started before the hash table is
11736 11739 * rebuilt, I/O errors will occur. This flag allows I/Os to be marked
11737 11740 * so that they can be retried.
11738 11741 */
11739 11742 mpt->m_in_reset = TRUE;
11740 11743
11741 11744 /*
11742 11745 * Set all throttles to HOLD
11743 11746 */
11744 11747 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11745 11748 ptgt = refhash_next(mpt->m_targets, ptgt)) {
11746 11749 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
11747 11750 }
11748 11751
11749 11752 /*
11750 11753 * Disable interrupts
11751 11754 */
11752 11755 MPTSAS_DISABLE_INTR(mpt);
11753 11756
11754 11757 /*
11755 11758 * Abort all commands: outstanding commands, commands in waitq and
11756 11759 * tx_waitq.
11757 11760 */
11758 11761 mptsas_flush_hba(mpt);
11759 11762
11760 11763 /*
11761 11764 * Reinitialize the chip.
11762 11765 */
11763 11766 if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
11764 11767 rval = DDI_FAILURE;
11765 11768 }
11766 11769
11767 11770 /*
11768 11771 * Enable interrupts again
11769 11772 */
11770 11773 MPTSAS_ENABLE_INTR(mpt);
11771 11774
11772 11775 /*
11773 11776 * If mptsas_init_chip was successful, update the driver data.
11774 11777 */
11775 11778 if (rval == DDI_SUCCESS) {
11776 11779 mptsas_update_driver_data(mpt);
11777 11780 }
11778 11781
11779 11782 /*
11780 11783 * Reset the throttles
11781 11784 */
11782 11785 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11783 11786 ptgt = refhash_next(mpt->m_targets, ptgt)) {
11784 11787 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
11785 11788 }
11786 11789
11787 11790 mptsas_doneq_empty(mpt);
11788 11791 mptsas_restart_hba(mpt);
11789 11792
11790 11793 if (rval != DDI_SUCCESS) {
11791 11794 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
11792 11795 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
11793 11796 }
11794 11797
11795 11798 /*
11796 11799 * Clear the reset flag so that I/Os can continue.
11797 11800 */
11798 11801 mpt->m_in_reset = FALSE;
11799 11802
11800 11803 return (rval);
11801 11804 }
11802 11805
11803 11806 static int
11804 11807 mptsas_init_chip(mptsas_t *mpt, int first_time)
11805 11808 {
11806 11809 ddi_dma_cookie_t cookie;
11807 11810 uint32_t i;
11808 11811 int rval;
11809 11812
11810 11813 /*
11811 11814 * Check to see if the firmware image is valid
11812 11815 */
11813 11816 if (ddi_get32(mpt->m_datap, &mpt->m_reg->HostDiagnostic) &
11814 11817 MPI2_DIAG_FLASH_BAD_SIG) {
11815 11818 mptsas_log(mpt, CE_WARN, "mptsas bad flash signature!");
11816 11819 goto fail;
11817 11820 }
11818 11821
11819 11822 /*
11820 11823 * Reset the chip
11821 11824 */
11822 11825 rval = mptsas_ioc_reset(mpt, first_time);
11823 11826 if (rval == MPTSAS_RESET_FAIL) {
11824 11827 mptsas_log(mpt, CE_WARN, "hard reset failed!");
11825 11828 goto fail;
11826 11829 }
11827 11830
11828 11831 if ((rval == MPTSAS_SUCCESS_MUR) && (!first_time)) {
11829 11832 goto mur;
11830 11833 }
11831 11834 /*
11832 11835 * Setup configuration space
11833 11836 */
11834 11837 if (mptsas_config_space_init(mpt) == FALSE) {
11835 11838 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
11836 11839 "failed!");
11837 11840 goto fail;
11838 11841 }
11839 11842
11840 11843 /*
11841 11844 * IOC facts can change after a diag reset so all buffers that are
11842 11845 * based on these numbers must be de-allocated and re-allocated. Get
11843 11846 * new IOC facts each time chip is initialized.
11844 11847 */
11845 11848 if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
11846 11849 mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
11847 11850 goto fail;
11848 11851 }
11849 11852
11850 11853 mpt->m_targets = refhash_create(MPTSAS_TARGET_BUCKET_COUNT,
11851 11854 mptsas_target_addr_hash, mptsas_target_addr_cmp,
11852 11855 mptsas_target_free, sizeof (mptsas_target_t),
11853 11856 offsetof(mptsas_target_t, m_link),
11854 11857 offsetof(mptsas_target_t, m_addr), KM_SLEEP);
11855 11858
11856 11859 if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
11857 11860 goto fail;
11858 11861 }
11859 11862 /*
11860 11863 * Allocate request message frames, reply free queue, reply descriptor
11861 11864 * post queue, and reply message frames using latest IOC facts.
11862 11865 */
11863 11866 if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
11864 11867 mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
11865 11868 goto fail;
11866 11869 }
11867 11870 if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
11868 11871 mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
11869 11872 goto fail;
11870 11873 }
11871 11874 if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
11872 11875 mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
11873 11876 goto fail;
11874 11877 }
11875 11878 if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
11876 11879 mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames failed!");
11877 11880 goto fail;
11878 11881 }
11879 11882
11880 11883 mur:
11881 11884 /*
11882 11885 * Re-Initialize ioc to operational state
11883 11886 */
11884 11887 if (mptsas_ioc_init(mpt) == DDI_FAILURE) {
11885 11888 mptsas_log(mpt, CE_WARN, "mptsas_ioc_init failed");
11886 11889 goto fail;
11887 11890 }
11888 11891
11889 11892 mptsas_alloc_reply_args(mpt);
11890 11893
11891 11894 /*
11892 11895 * Initialize reply post index. Reply free index is initialized after
11893 11896 * the next loop.
11894 11897 */
11895 11898 mpt->m_post_index = 0;
11896 11899
11897 11900 /*
11898 11901 * Initialize the Reply Free Queue with the physical addresses of our
11899 11902 * reply frames.
11900 11903 */
11901 11904 cookie.dmac_address = mpt->m_reply_frame_dma_addr;
11902 11905 for (i = 0; i < mpt->m_max_replies; i++) {
11903 11906 ddi_put32(mpt->m_acc_free_queue_hdl,
11904 11907 &((uint32_t *)(void *)mpt->m_free_queue)[i],
11905 11908 cookie.dmac_address);
11906 11909 cookie.dmac_address += mpt->m_reply_frame_size;
11907 11910 }
11908 11911 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11909 11912 DDI_DMA_SYNC_FORDEV);
11910 11913
11911 11914 /*
11912 11915 * Initialize the reply free index to one past the last frame on the
11913 11916 * queue. This will signify that the queue is empty to start with.
11914 11917 */
11915 11918 mpt->m_free_index = i;
11916 11919 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex, i);
11917 11920
11918 11921 /*
11919 11922 * Initialize the reply post queue to 0xFFFFFFFF,0xFFFFFFFF's.
11920 11923 */
11921 11924 for (i = 0; i < mpt->m_post_queue_depth; i++) {
11922 11925 ddi_put64(mpt->m_acc_post_queue_hdl,
11923 11926 &((uint64_t *)(void *)mpt->m_post_queue)[i],
11924 11927 0xFFFFFFFFFFFFFFFF);
11925 11928 }
11926 11929 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
11927 11930 DDI_DMA_SYNC_FORDEV);
11928 11931
11929 11932 /*
11930 11933 * Enable ports
11931 11934 */
11932 11935 if (mptsas_ioc_enable_port(mpt) == DDI_FAILURE) {
11933 11936 mptsas_log(mpt, CE_WARN, "mptsas_ioc_enable_port failed");
11934 11937 goto fail;
11935 11938 }
11936 11939
11937 11940 /*
11938 11941 * enable events
11939 11942 */
11940 11943 if (mptsas_ioc_enable_event_notification(mpt)) {
11941 11944 goto fail;
11942 11945 }
11943 11946
11944 11947 /*
11945 11948 * We need checks in attach and these.
11946 11949 * chip_init is called in mult. places
11947 11950 */
11948 11951
11949 11952 if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
11950 11953 DDI_SUCCESS) ||
11951 11954 (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
11952 11955 DDI_SUCCESS) ||
11953 11956 (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
11954 11957 DDI_SUCCESS) ||
11955 11958 (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
11956 11959 DDI_SUCCESS) ||
11957 11960 (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
11958 11961 DDI_SUCCESS)) {
11959 11962 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11960 11963 goto fail;
11961 11964 }
11962 11965
11963 11966 /* Check all acc handles */
11964 11967 if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
11965 11968 (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
11966 11969 DDI_SUCCESS) ||
11967 11970 (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
11968 11971 DDI_SUCCESS) ||
11969 11972 (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
11970 11973 DDI_SUCCESS) ||
11971 11974 (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
11972 11975 DDI_SUCCESS) ||
11973 11976 (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
11974 11977 DDI_SUCCESS) ||
11975 11978 (mptsas_check_acc_handle(mpt->m_config_handle) !=
11976 11979 DDI_SUCCESS)) {
11977 11980 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11978 11981 goto fail;
11979 11982 }
11980 11983
11981 11984 return (DDI_SUCCESS);
11982 11985
11983 11986 fail:
11984 11987 return (DDI_FAILURE);
11985 11988 }
11986 11989
11987 11990 static int
11988 11991 mptsas_get_pci_cap(mptsas_t *mpt)
11989 11992 {
11990 11993 ushort_t caps_ptr, cap, cap_count;
11991 11994
11992 11995 if (mpt->m_config_handle == NULL)
11993 11996 return (FALSE);
11994 11997 /*
11995 11998 * Check if capabilities list is supported and if so,
11996 11999 * get initial capabilities pointer and clear bits 0,1.
11997 12000 */
11998 12001 if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT)
11999 12002 & PCI_STAT_CAP) {
12000 12003 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12001 12004 PCI_CONF_CAP_PTR), 4);
12002 12005 } else {
12003 12006 caps_ptr = PCI_CAP_NEXT_PTR_NULL;
12004 12007 }
12005 12008
12006 12009 /*
12007 12010 * Walk capabilities if supported.
12008 12011 */
12009 12012 for (cap_count = 0; caps_ptr != PCI_CAP_NEXT_PTR_NULL; ) {
12010 12013
12011 12014 /*
12012 12015 * Check that we haven't exceeded the maximum number of
12013 12016 * capabilities and that the pointer is in a valid range.
12014 12017 */
12015 12018 if (++cap_count > 48) {
12016 12019 mptsas_log(mpt, CE_WARN,
12017 12020 "too many device capabilities.\n");
12018 12021 break;
12019 12022 }
12020 12023 if (caps_ptr < 64) {
12021 12024 mptsas_log(mpt, CE_WARN,
12022 12025 "capabilities pointer 0x%x out of range.\n",
12023 12026 caps_ptr);
12024 12027 break;
12025 12028 }
12026 12029
12027 12030 /*
12028 12031 * Get next capability and check that it is valid.
12029 12032 * For now, we only support power management.
12030 12033 */
12031 12034 cap = pci_config_get8(mpt->m_config_handle, caps_ptr);
12032 12035 switch (cap) {
12033 12036 case PCI_CAP_ID_PM:
12034 12037 mptsas_log(mpt, CE_NOTE,
12035 12038 "?mptsas%d supports power management.\n",
12036 12039 mpt->m_instance);
12037 12040 mpt->m_options |= MPTSAS_OPT_PM;
12038 12041
12039 12042 /* Save PMCSR offset */
12040 12043 mpt->m_pmcsr_offset = caps_ptr + PCI_PMCSR;
12041 12044 break;
12042 12045 /*
12043 12046 * The following capabilities are valid. Any others
12044 12047 * will cause a message to be logged.
12045 12048 */
12046 12049 case PCI_CAP_ID_VPD:
12047 12050 case PCI_CAP_ID_MSI:
12048 12051 case PCI_CAP_ID_PCIX:
12049 12052 case PCI_CAP_ID_PCI_E:
12050 12053 case PCI_CAP_ID_MSI_X:
12051 12054 break;
12052 12055 default:
12053 12056 mptsas_log(mpt, CE_NOTE,
12054 12057 "?mptsas%d unrecognized capability "
12055 12058 "0x%x.\n", mpt->m_instance, cap);
12056 12059 break;
12057 12060 }
12058 12061
12059 12062 /*
12060 12063 * Get next capabilities pointer and clear bits 0,1.
12061 12064 */
12062 12065 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12063 12066 (caps_ptr + PCI_CAP_NEXT_PTR)), 4);
12064 12067 }
12065 12068 return (TRUE);
12066 12069 }
12067 12070
12068 12071 static int
12069 12072 mptsas_init_pm(mptsas_t *mpt)
12070 12073 {
12071 12074 char pmc_name[16];
12072 12075 char *pmc[] = {
12073 12076 NULL,
12074 12077 "0=Off (PCI D3 State)",
12075 12078 "3=On (PCI D0 State)",
12076 12079 NULL
12077 12080 };
12078 12081 uint16_t pmcsr_stat;
12079 12082
12080 12083 if (mptsas_get_pci_cap(mpt) == FALSE) {
12081 12084 return (DDI_FAILURE);
12082 12085 }
12083 12086 /*
12084 12087 * If PCI's capability does not support PM, then don't need
12085 12088 * to registe the pm-components
12086 12089 */
12087 12090 if (!(mpt->m_options & MPTSAS_OPT_PM))
12088 12091 return (DDI_SUCCESS);
12089 12092 /*
12090 12093 * If power management is supported by this chip, create
12091 12094 * pm-components property for the power management framework
12092 12095 */
12093 12096 (void) sprintf(pmc_name, "NAME=mptsas%d", mpt->m_instance);
12094 12097 pmc[0] = pmc_name;
12095 12098 if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip,
12096 12099 "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
12097 12100 mpt->m_options &= ~MPTSAS_OPT_PM;
12098 12101 mptsas_log(mpt, CE_WARN,
12099 12102 "mptsas%d: pm-component property creation failed.",
12100 12103 mpt->m_instance);
12101 12104 return (DDI_FAILURE);
12102 12105 }
12103 12106
12104 12107 /*
12105 12108 * Power on device.
12106 12109 */
12107 12110 (void) pm_busy_component(mpt->m_dip, 0);
12108 12111 pmcsr_stat = pci_config_get16(mpt->m_config_handle,
12109 12112 mpt->m_pmcsr_offset);
12110 12113 if ((pmcsr_stat & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_D0) {
12111 12114 mptsas_log(mpt, CE_WARN, "mptsas%d: Power up the device",
12112 12115 mpt->m_instance);
12113 12116 pci_config_put16(mpt->m_config_handle, mpt->m_pmcsr_offset,
12114 12117 PCI_PMCSR_D0);
12115 12118 }
12116 12119 if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
12117 12120 mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed");
12118 12121 return (DDI_FAILURE);
12119 12122 }
12120 12123 mpt->m_power_level = PM_LEVEL_D0;
12121 12124 /*
12122 12125 * Set pm idle delay.
12123 12126 */
12124 12127 mpt->m_pm_idle_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
12125 12128 mpt->m_dip, 0, "mptsas-pm-idle-delay", MPTSAS_PM_IDLE_TIMEOUT);
12126 12129
12127 12130 return (DDI_SUCCESS);
12128 12131 }
12129 12132
12130 12133 static int
12131 12134 mptsas_register_intrs(mptsas_t *mpt)
12132 12135 {
12133 12136 dev_info_t *dip;
12134 12137 int intr_types;
12135 12138
12136 12139 dip = mpt->m_dip;
12137 12140
12138 12141 /* Get supported interrupt types */
12139 12142 if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
12140 12143 mptsas_log(mpt, CE_WARN, "ddi_intr_get_supported_types "
12141 12144 "failed\n");
12142 12145 return (FALSE);
12143 12146 }
12144 12147
12145 12148 NDBG6(("ddi_intr_get_supported_types() returned: 0x%x", intr_types));
12146 12149
12147 12150 /*
12148 12151 * Try MSI, but fall back to FIXED
12149 12152 */
12150 12153 if (mptsas_enable_msi && (intr_types & DDI_INTR_TYPE_MSI)) {
12151 12154 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_MSI) == DDI_SUCCESS) {
12152 12155 NDBG0(("Using MSI interrupt type"));
12153 12156 mpt->m_intr_type = DDI_INTR_TYPE_MSI;
12154 12157 return (TRUE);
12155 12158 }
12156 12159 }
12157 12160 if (intr_types & DDI_INTR_TYPE_FIXED) {
12158 12161 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_FIXED) == DDI_SUCCESS) {
12159 12162 NDBG0(("Using FIXED interrupt type"));
12160 12163 mpt->m_intr_type = DDI_INTR_TYPE_FIXED;
12161 12164 return (TRUE);
12162 12165 } else {
12163 12166 NDBG0(("FIXED interrupt registration failed"));
12164 12167 return (FALSE);
12165 12168 }
12166 12169 }
12167 12170
12168 12171 return (FALSE);
12169 12172 }
12170 12173
12171 12174 static void
12172 12175 mptsas_unregister_intrs(mptsas_t *mpt)
12173 12176 {
12174 12177 mptsas_rem_intrs(mpt);
12175 12178 }
12176 12179
12177 12180 /*
12178 12181 * mptsas_add_intrs:
12179 12182 *
12180 12183 * Register FIXED or MSI interrupts.
12181 12184 */
12182 12185 static int
12183 12186 mptsas_add_intrs(mptsas_t *mpt, int intr_type)
12184 12187 {
12185 12188 dev_info_t *dip = mpt->m_dip;
12186 12189 int avail, actual, count = 0;
12187 12190 int i, flag, ret;
12188 12191
12189 12192 NDBG6(("mptsas_add_intrs:interrupt type 0x%x", intr_type));
12190 12193
12191 12194 /* Get number of interrupts */
12192 12195 ret = ddi_intr_get_nintrs(dip, intr_type, &count);
12193 12196 if ((ret != DDI_SUCCESS) || (count <= 0)) {
12194 12197 mptsas_log(mpt, CE_WARN, "ddi_intr_get_nintrs() failed, "
12195 12198 "ret %d count %d\n", ret, count);
12196 12199
12197 12200 return (DDI_FAILURE);
12198 12201 }
12199 12202
12200 12203 /* Get number of available interrupts */
12201 12204 ret = ddi_intr_get_navail(dip, intr_type, &avail);
12202 12205 if ((ret != DDI_SUCCESS) || (avail == 0)) {
12203 12206 mptsas_log(mpt, CE_WARN, "ddi_intr_get_navail() failed, "
12204 12207 "ret %d avail %d\n", ret, avail);
12205 12208
12206 12209 return (DDI_FAILURE);
12207 12210 }
12208 12211
12209 12212 if (avail < count) {
12210 12213 mptsas_log(mpt, CE_NOTE, "ddi_intr_get_nvail returned %d, "
12211 12214 "navail() returned %d", count, avail);
12212 12215 }
12213 12216
12214 12217 /* Mpt only have one interrupt routine */
12215 12218 if ((intr_type == DDI_INTR_TYPE_MSI) && (count > 1)) {
12216 12219 count = 1;
12217 12220 }
12218 12221
12219 12222 /* Allocate an array of interrupt handles */
12220 12223 mpt->m_intr_size = count * sizeof (ddi_intr_handle_t);
12221 12224 mpt->m_htable = kmem_alloc(mpt->m_intr_size, KM_SLEEP);
12222 12225
12223 12226 flag = DDI_INTR_ALLOC_NORMAL;
12224 12227
12225 12228 /* call ddi_intr_alloc() */
12226 12229 ret = ddi_intr_alloc(dip, mpt->m_htable, intr_type, 0,
12227 12230 count, &actual, flag);
12228 12231
12229 12232 if ((ret != DDI_SUCCESS) || (actual == 0)) {
12230 12233 mptsas_log(mpt, CE_WARN, "ddi_intr_alloc() failed, ret %d\n",
12231 12234 ret);
12232 12235 kmem_free(mpt->m_htable, mpt->m_intr_size);
12233 12236 return (DDI_FAILURE);
12234 12237 }
12235 12238
12236 12239 /* use interrupt count returned or abort? */
12237 12240 if (actual < count) {
12238 12241 mptsas_log(mpt, CE_NOTE, "Requested: %d, Received: %d\n",
12239 12242 count, actual);
12240 12243 }
12241 12244
12242 12245 mpt->m_intr_cnt = actual;
12243 12246
12244 12247 /*
12245 12248 * Get priority for first msi, assume remaining are all the same
12246 12249 */
12247 12250 if ((ret = ddi_intr_get_pri(mpt->m_htable[0],
12248 12251 &mpt->m_intr_pri)) != DDI_SUCCESS) {
12249 12252 mptsas_log(mpt, CE_WARN, "ddi_intr_get_pri() failed %d\n", ret);
12250 12253
12251 12254 /* Free already allocated intr */
12252 12255 for (i = 0; i < actual; i++) {
12253 12256 (void) ddi_intr_free(mpt->m_htable[i]);
12254 12257 }
12255 12258
12256 12259 kmem_free(mpt->m_htable, mpt->m_intr_size);
12257 12260 return (DDI_FAILURE);
12258 12261 }
12259 12262
12260 12263 /* Test for high level mutex */
12261 12264 if (mpt->m_intr_pri >= ddi_intr_get_hilevel_pri()) {
12262 12265 mptsas_log(mpt, CE_WARN, "mptsas_add_intrs: "
12263 12266 "Hi level interrupt not supported\n");
12264 12267
12265 12268 /* Free already allocated intr */
12266 12269 for (i = 0; i < actual; i++) {
12267 12270 (void) ddi_intr_free(mpt->m_htable[i]);
12268 12271 }
12269 12272
12270 12273 kmem_free(mpt->m_htable, mpt->m_intr_size);
12271 12274 return (DDI_FAILURE);
12272 12275 }
12273 12276
12274 12277 /* Call ddi_intr_add_handler() */
12275 12278 for (i = 0; i < actual; i++) {
12276 12279 if ((ret = ddi_intr_add_handler(mpt->m_htable[i], mptsas_intr,
12277 12280 (caddr_t)mpt, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
12278 12281 mptsas_log(mpt, CE_WARN, "ddi_intr_add_handler() "
12279 12282 "failed %d\n", ret);
12280 12283
12281 12284 /* Free already allocated intr */
12282 12285 for (i = 0; i < actual; i++) {
12283 12286 (void) ddi_intr_free(mpt->m_htable[i]);
12284 12287 }
12285 12288
12286 12289 kmem_free(mpt->m_htable, mpt->m_intr_size);
12287 12290 return (DDI_FAILURE);
12288 12291 }
12289 12292 }
12290 12293
12291 12294 if ((ret = ddi_intr_get_cap(mpt->m_htable[0], &mpt->m_intr_cap))
12292 12295 != DDI_SUCCESS) {
12293 12296 mptsas_log(mpt, CE_WARN, "ddi_intr_get_cap() failed %d\n", ret);
12294 12297
12295 12298 /* Free already allocated intr */
12296 12299 for (i = 0; i < actual; i++) {
12297 12300 (void) ddi_intr_free(mpt->m_htable[i]);
12298 12301 }
12299 12302
12300 12303 kmem_free(mpt->m_htable, mpt->m_intr_size);
12301 12304 return (DDI_FAILURE);
12302 12305 }
12303 12306
12304 12307 /*
12305 12308 * Enable interrupts
12306 12309 */
12307 12310 if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
12308 12311 /* Call ddi_intr_block_enable() for MSI interrupts */
12309 12312 (void) ddi_intr_block_enable(mpt->m_htable, mpt->m_intr_cnt);
12310 12313 } else {
12311 12314 /* Call ddi_intr_enable for MSI or FIXED interrupts */
12312 12315 for (i = 0; i < mpt->m_intr_cnt; i++) {
12313 12316 (void) ddi_intr_enable(mpt->m_htable[i]);
12314 12317 }
12315 12318 }
12316 12319 return (DDI_SUCCESS);
12317 12320 }
12318 12321
12319 12322 /*
12320 12323 * mptsas_rem_intrs:
12321 12324 *
12322 12325 * Unregister FIXED or MSI interrupts
12323 12326 */
12324 12327 static void
12325 12328 mptsas_rem_intrs(mptsas_t *mpt)
12326 12329 {
12327 12330 int i;
12328 12331
12329 12332 NDBG6(("mptsas_rem_intrs"));
12330 12333
12331 12334 /* Disable all interrupts */
12332 12335 if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
12333 12336 /* Call ddi_intr_block_disable() */
12334 12337 (void) ddi_intr_block_disable(mpt->m_htable, mpt->m_intr_cnt);
12335 12338 } else {
12336 12339 for (i = 0; i < mpt->m_intr_cnt; i++) {
12337 12340 (void) ddi_intr_disable(mpt->m_htable[i]);
12338 12341 }
12339 12342 }
12340 12343
12341 12344 /* Call ddi_intr_remove_handler() */
12342 12345 for (i = 0; i < mpt->m_intr_cnt; i++) {
12343 12346 (void) ddi_intr_remove_handler(mpt->m_htable[i]);
12344 12347 (void) ddi_intr_free(mpt->m_htable[i]);
12345 12348 }
12346 12349
12347 12350 kmem_free(mpt->m_htable, mpt->m_intr_size);
12348 12351 }
12349 12352
12350 12353 /*
12351 12354 * The IO fault service error handling callback function
12352 12355 */
12353 12356 /*ARGSUSED*/
12354 12357 static int
12355 12358 mptsas_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
12356 12359 {
12357 12360 /*
12358 12361 * as the driver can always deal with an error in any dma or
12359 12362 * access handle, we can just return the fme_status value.
12360 12363 */
12361 12364 pci_ereport_post(dip, err, NULL);
12362 12365 return (err->fme_status);
12363 12366 }
12364 12367
12365 12368 /*
12366 12369 * mptsas_fm_init - initialize fma capabilities and register with IO
12367 12370 * fault services.
12368 12371 */
12369 12372 static void
12370 12373 mptsas_fm_init(mptsas_t *mpt)
12371 12374 {
12372 12375 /*
12373 12376 * Need to change iblock to priority for new MSI intr
12374 12377 */
12375 12378 ddi_iblock_cookie_t fm_ibc;
12376 12379
12377 12380 /* Only register with IO Fault Services if we have some capability */
12378 12381 if (mpt->m_fm_capabilities) {
12379 12382 /* Adjust access and dma attributes for FMA */
12380 12383 mpt->m_reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
12381 12384 mpt->m_msg_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
12382 12385 mpt->m_io_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
12383 12386
12384 12387 /*
12385 12388 * Register capabilities with IO Fault Services.
12386 12389 * mpt->m_fm_capabilities will be updated to indicate
12387 12390 * capabilities actually supported (not requested.)
12388 12391 */
12389 12392 ddi_fm_init(mpt->m_dip, &mpt->m_fm_capabilities, &fm_ibc);
12390 12393
12391 12394 /*
12392 12395 * Initialize pci ereport capabilities if ereport
12393 12396 * capable (should always be.)
12394 12397 */
12395 12398 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
12396 12399 DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12397 12400 pci_ereport_setup(mpt->m_dip);
12398 12401 }
12399 12402
12400 12403 /*
12401 12404 * Register error callback if error callback capable.
12402 12405 */
12403 12406 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12404 12407 ddi_fm_handler_register(mpt->m_dip,
12405 12408 mptsas_fm_error_cb, (void *) mpt);
12406 12409 }
12407 12410 }
12408 12411 }
12409 12412
12410 12413 /*
12411 12414 * mptsas_fm_fini - Releases fma capabilities and un-registers with IO
12412 12415 * fault services.
12413 12416 *
12414 12417 */
12415 12418 static void
12416 12419 mptsas_fm_fini(mptsas_t *mpt)
12417 12420 {
12418 12421 /* Only unregister FMA capabilities if registered */
12419 12422 if (mpt->m_fm_capabilities) {
12420 12423
12421 12424 /*
12422 12425 * Un-register error callback if error callback capable.
12423 12426 */
12424 12427
12425 12428 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12426 12429 ddi_fm_handler_unregister(mpt->m_dip);
12427 12430 }
12428 12431
12429 12432 /*
12430 12433 * Release any resources allocated by pci_ereport_setup()
12431 12434 */
12432 12435
12433 12436 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
12434 12437 DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12435 12438 pci_ereport_teardown(mpt->m_dip);
12436 12439 }
12437 12440
12438 12441 /* Unregister from IO Fault Services */
12439 12442 ddi_fm_fini(mpt->m_dip);
12440 12443
12441 12444 /* Adjust access and dma attributes for FMA */
12442 12445 mpt->m_reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
12443 12446 mpt->m_msg_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12444 12447 mpt->m_io_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12445 12448
12446 12449 }
12447 12450 }
12448 12451
12449 12452 int
12450 12453 mptsas_check_acc_handle(ddi_acc_handle_t handle)
12451 12454 {
12452 12455 ddi_fm_error_t de;
12453 12456
12454 12457 if (handle == NULL)
12455 12458 return (DDI_FAILURE);
12456 12459 ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
12457 12460 return (de.fme_status);
12458 12461 }
12459 12462
12460 12463 int
12461 12464 mptsas_check_dma_handle(ddi_dma_handle_t handle)
12462 12465 {
12463 12466 ddi_fm_error_t de;
12464 12467
12465 12468 if (handle == NULL)
12466 12469 return (DDI_FAILURE);
12467 12470 ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
12468 12471 return (de.fme_status);
12469 12472 }
12470 12473
12471 12474 void
12472 12475 mptsas_fm_ereport(mptsas_t *mpt, char *detail)
12473 12476 {
12474 12477 uint64_t ena;
12475 12478 char buf[FM_MAX_CLASS];
12476 12479
12477 12480 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
12478 12481 ena = fm_ena_generate(0, FM_ENA_FMT1);
12479 12482 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities)) {
12480 12483 ddi_fm_ereport_post(mpt->m_dip, buf, ena, DDI_NOSLEEP,
12481 12484 FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
12482 12485 }
12483 12486 }
12484 12487
12485 12488 static int
12486 12489 mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
12487 12490 uint16_t *dev_handle, mptsas_target_t **pptgt)
12488 12491 {
12489 12492 int rval;
12490 12493 uint32_t dev_info;
12491 12494 uint64_t sas_wwn;
12492 12495 mptsas_phymask_t phymask;
12493 12496 uint8_t physport, phynum, config, disk;
12494 12497 uint64_t devicename;
12495 12498 uint16_t pdev_hdl;
12496 12499 mptsas_target_t *tmp_tgt = NULL;
12497 12500 uint16_t bay_num, enclosure;
12498 12501
12499 12502 ASSERT(*pptgt == NULL);
12500 12503
12501 12504 rval = mptsas_get_sas_device_page0(mpt, page_address, dev_handle,
12502 12505 &sas_wwn, &dev_info, &physport, &phynum, &pdev_hdl,
12503 12506 &bay_num, &enclosure);
12504 12507 if (rval != DDI_SUCCESS) {
12505 12508 rval = DEV_INFO_FAIL_PAGE0;
12506 12509 return (rval);
12507 12510 }
12508 12511
12509 12512 if ((dev_info & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
12510 12513 MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12511 12514 MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) == NULL) {
12512 12515 rval = DEV_INFO_WRONG_DEVICE_TYPE;
12513 12516 return (rval);
12514 12517 }
12515 12518
12516 12519 /*
12517 12520 * Check if the dev handle is for a Phys Disk. If so, set return value
12518 12521 * and exit. Don't add Phys Disks to hash.
12519 12522 */
12520 12523 for (config = 0; config < mpt->m_num_raid_configs; config++) {
12521 12524 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
12522 12525 if (*dev_handle == mpt->m_raidconfig[config].
12523 12526 m_physdisk_devhdl[disk]) {
12524 12527 rval = DEV_INFO_PHYS_DISK;
12525 12528 return (rval);
12526 12529 }
12527 12530 }
12528 12531 }
12529 12532
12530 12533 /*
12531 12534 * Get SATA Device Name from SAS device page0 for
12532 12535 * sata device, if device name doesn't exist, set mta_wwn to
12533 12536 * 0 for direct attached SATA. For the device behind the expander
12534 12537 * we still can use STP address assigned by expander.
12535 12538 */
12536 12539 if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12537 12540 MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
12538 12541 mutex_exit(&mpt->m_mutex);
12539 12542 /* alloc a tmp_tgt to send the cmd */
12540 12543 tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target),
12541 12544 KM_SLEEP);
12542 12545 tmp_tgt->m_devhdl = *dev_handle;
12543 12546 tmp_tgt->m_deviceinfo = dev_info;
12544 12547 tmp_tgt->m_qfull_retries = QFULL_RETRIES;
12545 12548 tmp_tgt->m_qfull_retry_interval =
12546 12549 drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
12547 12550 tmp_tgt->m_t_throttle = MAX_THROTTLE;
12548 12551 devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0);
12549 12552 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
12550 12553 mutex_enter(&mpt->m_mutex);
12551 12554 if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) {
12552 12555 sas_wwn = devicename;
12553 12556 } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
12554 12557 sas_wwn = 0;
12555 12558 }
12556 12559 }
12557 12560
12558 12561 phymask = mptsas_physport_to_phymask(mpt, physport);
12559 12562 *pptgt = mptsas_tgt_alloc(mpt, *dev_handle, sas_wwn,
12560 12563 dev_info, phymask, phynum);
12561 12564 if (*pptgt == NULL) {
12562 12565 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
12563 12566 "structure!");
12564 12567 rval = DEV_INFO_FAIL_ALLOC;
12565 12568 return (rval);
12566 12569 }
12567 12570 (*pptgt)->m_enclosure = enclosure;
12568 12571 (*pptgt)->m_slot_num = bay_num;
12569 12572 return (DEV_INFO_SUCCESS);
12570 12573 }
12571 12574
12572 12575 uint64_t
12573 12576 mptsas_get_sata_guid(mptsas_t *mpt, mptsas_target_t *ptgt, int lun)
12574 12577 {
12575 12578 uint64_t sata_guid = 0, *pwwn = NULL;
12576 12579 int target = ptgt->m_devhdl;
12577 12580 uchar_t *inq83 = NULL;
12578 12581 int inq83_len = 0xFF;
12579 12582 uchar_t *dblk = NULL;
12580 12583 int inq83_retry = 3;
12581 12584 int rval = DDI_FAILURE;
12582 12585
12583 12586 inq83 = kmem_zalloc(inq83_len, KM_SLEEP);
12584 12587
12585 12588 inq83_retry:
12586 12589 rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
12587 12590 inq83_len, NULL, 1);
12588 12591 if (rval != DDI_SUCCESS) {
12589 12592 mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
12590 12593 "0x83 for target:%x, lun:%x failed!", target, lun);
12591 12594 goto out;
12592 12595 }
12593 12596 /* According to SAT2, the first descriptor is logic unit name */
12594 12597 dblk = &inq83[4];
12595 12598 if ((dblk[1] & 0x30) != 0) {
12596 12599 mptsas_log(mpt, CE_WARN, "!Descriptor is not lun associated.");
12597 12600 goto out;
12598 12601 }
12599 12602 pwwn = (uint64_t *)(void *)(&dblk[4]);
12600 12603 if ((dblk[4] & 0xf0) == 0x50) {
12601 12604 sata_guid = BE_64(*pwwn);
12602 12605 goto out;
12603 12606 } else if (dblk[4] == 'A') {
12604 12607 NDBG20(("SATA drive has no NAA format GUID."));
12605 12608 goto out;
12606 12609 } else {
12607 12610 /* The data is not ready, wait and retry */
12608 12611 inq83_retry--;
12609 12612 if (inq83_retry <= 0) {
12610 12613 goto out;
12611 12614 }
12612 12615 NDBG20(("The GUID is not ready, retry..."));
12613 12616 delay(1 * drv_usectohz(1000000));
12614 12617 goto inq83_retry;
12615 12618 }
12616 12619 out:
12617 12620 kmem_free(inq83, inq83_len);
12618 12621 return (sata_guid);
12619 12622 }
12620 12623
12621 12624 static int
12622 12625 mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun, uchar_t page,
12623 12626 unsigned char *buf, int len, int *reallen, uchar_t evpd)
12624 12627 {
12625 12628 uchar_t cdb[CDB_GROUP0];
12626 12629 struct scsi_address ap;
12627 12630 struct buf *data_bp = NULL;
12628 12631 int resid = 0;
12629 12632 int ret = DDI_FAILURE;
12630 12633
12631 12634 ASSERT(len <= 0xffff);
12632 12635
12633 12636 ap.a_target = MPTSAS_INVALID_DEVHDL;
12634 12637 ap.a_lun = (uchar_t)(lun);
12635 12638 ap.a_hba_tran = mpt->m_tran;
12636 12639
12637 12640 data_bp = scsi_alloc_consistent_buf(&ap,
12638 12641 (struct buf *)NULL, len, B_READ, NULL_FUNC, NULL);
12639 12642 if (data_bp == NULL) {
12640 12643 return (ret);
12641 12644 }
12642 12645 bzero(cdb, CDB_GROUP0);
12643 12646 cdb[0] = SCMD_INQUIRY;
12644 12647 cdb[1] = evpd;
12645 12648 cdb[2] = page;
12646 12649 cdb[3] = (len & 0xff00) >> 8;
12647 12650 cdb[4] = (len & 0x00ff);
12648 12651 cdb[5] = 0;
12649 12652
12650 12653 ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP0, data_bp,
12651 12654 &resid);
12652 12655 if (ret == DDI_SUCCESS) {
12653 12656 if (reallen) {
12654 12657 *reallen = len - resid;
12655 12658 }
12656 12659 bcopy((caddr_t)data_bp->b_un.b_addr, buf, len);
12657 12660 }
12658 12661 if (data_bp) {
12659 12662 scsi_free_consistent_buf(data_bp);
12660 12663 }
12661 12664 return (ret);
12662 12665 }
12663 12666
12664 12667 static int
12665 12668 mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
12666 12669 mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
12667 12670 int *resid)
12668 12671 {
12669 12672 struct scsi_pkt *pktp = NULL;
12670 12673 scsi_hba_tran_t *tran_clone = NULL;
12671 12674 mptsas_tgt_private_t *tgt_private = NULL;
12672 12675 int ret = DDI_FAILURE;
12673 12676
12674 12677 /*
12675 12678 * scsi_hba_tran_t->tran_tgt_private is used to pass the address
12676 12679 * information to scsi_init_pkt, allocate a scsi_hba_tran structure
12677 12680 * to simulate the cmds from sd
12678 12681 */
12679 12682 tran_clone = kmem_alloc(
12680 12683 sizeof (scsi_hba_tran_t), KM_SLEEP);
12681 12684 if (tran_clone == NULL) {
12682 12685 goto out;
12683 12686 }
12684 12687 bcopy((caddr_t)mpt->m_tran,
12685 12688 (caddr_t)tran_clone, sizeof (scsi_hba_tran_t));
12686 12689 tgt_private = kmem_alloc(
12687 12690 sizeof (mptsas_tgt_private_t), KM_SLEEP);
12688 12691 if (tgt_private == NULL) {
12689 12692 goto out;
12690 12693 }
12691 12694 tgt_private->t_lun = ap->a_lun;
12692 12695 tgt_private->t_private = ptgt;
12693 12696 tran_clone->tran_tgt_private = tgt_private;
12694 12697 ap->a_hba_tran = tran_clone;
12695 12698
12696 12699 pktp = scsi_init_pkt(ap, (struct scsi_pkt *)NULL,
12697 12700 data_bp, cdblen, sizeof (struct scsi_arq_status),
12698 12701 0, PKT_CONSISTENT, NULL, NULL);
12699 12702 if (pktp == NULL) {
12700 12703 goto out;
12701 12704 }
12702 12705 bcopy(cdb, pktp->pkt_cdbp, cdblen);
12703 12706 pktp->pkt_flags = FLAG_NOPARITY;
12704 12707 if (scsi_poll(pktp) < 0) {
12705 12708 goto out;
12706 12709 }
12707 12710 if (((struct scsi_status *)pktp->pkt_scbp)->sts_chk) {
12708 12711 goto out;
12709 12712 }
12710 12713 if (resid != NULL) {
12711 12714 *resid = pktp->pkt_resid;
12712 12715 }
12713 12716
12714 12717 ret = DDI_SUCCESS;
12715 12718 out:
12716 12719 if (pktp) {
12717 12720 scsi_destroy_pkt(pktp);
12718 12721 }
12719 12722 if (tran_clone) {
12720 12723 kmem_free(tran_clone, sizeof (scsi_hba_tran_t));
12721 12724 }
12722 12725 if (tgt_private) {
12723 12726 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
12724 12727 }
12725 12728 return (ret);
12726 12729 }
12727 12730 static int
12728 12731 mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy, int *lun)
12729 12732 {
12730 12733 char *cp = NULL;
12731 12734 char *ptr = NULL;
12732 12735 size_t s = 0;
12733 12736 char *wwid_str = NULL;
12734 12737 char *lun_str = NULL;
12735 12738 long lunnum;
12736 12739 long phyid = -1;
12737 12740 int rc = DDI_FAILURE;
12738 12741
12739 12742 ptr = name;
12740 12743 ASSERT(ptr[0] == 'w' || ptr[0] == 'p');
12741 12744 ptr++;
12742 12745 if ((cp = strchr(ptr, ',')) == NULL) {
12743 12746 return (DDI_FAILURE);
12744 12747 }
12745 12748
12746 12749 wwid_str = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
12747 12750 s = (uintptr_t)cp - (uintptr_t)ptr;
12748 12751
12749 12752 bcopy(ptr, wwid_str, s);
12750 12753 wwid_str[s] = '\0';
12751 12754
12752 12755 ptr = ++cp;
12753 12756
12754 12757 if ((cp = strchr(ptr, '\0')) == NULL) {
12755 12758 goto out;
12756 12759 }
12757 12760 lun_str = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
12758 12761 s = (uintptr_t)cp - (uintptr_t)ptr;
12759 12762
12760 12763 bcopy(ptr, lun_str, s);
12761 12764 lun_str[s] = '\0';
12762 12765
12763 12766 if (name[0] == 'p') {
12764 12767 rc = ddi_strtol(wwid_str, NULL, 0x10, &phyid);
12765 12768 } else {
12766 12769 rc = scsi_wwnstr_to_wwn(wwid_str, wwid);
12767 12770 }
12768 12771 if (rc != DDI_SUCCESS)
12769 12772 goto out;
12770 12773
12771 12774 if (phyid != -1) {
12772 12775 ASSERT(phyid < MPTSAS_MAX_PHYS);
12773 12776 *phy = (uint8_t)phyid;
12774 12777 }
12775 12778 rc = ddi_strtol(lun_str, NULL, 0x10, &lunnum);
12776 12779 if (rc != 0)
12777 12780 goto out;
12778 12781
12779 12782 *lun = (int)lunnum;
12780 12783 rc = DDI_SUCCESS;
12781 12784 out:
12782 12785 if (wwid_str)
12783 12786 kmem_free(wwid_str, SCSI_MAXNAMELEN);
12784 12787 if (lun_str)
12785 12788 kmem_free(lun_str, SCSI_MAXNAMELEN);
12786 12789
12787 12790 return (rc);
12788 12791 }
12789 12792
12790 12793 /*
12791 12794 * mptsas_parse_smp_name() is to parse sas wwn string
12792 12795 * which format is "wWWN"
12793 12796 */
12794 12797 static int
12795 12798 mptsas_parse_smp_name(char *name, uint64_t *wwn)
12796 12799 {
12797 12800 char *ptr = name;
12798 12801
12799 12802 if (*ptr != 'w') {
12800 12803 return (DDI_FAILURE);
12801 12804 }
12802 12805
12803 12806 ptr++;
12804 12807 if (scsi_wwnstr_to_wwn(ptr, wwn)) {
12805 12808 return (DDI_FAILURE);
12806 12809 }
12807 12810 return (DDI_SUCCESS);
12808 12811 }
12809 12812
12810 12813 static int
12811 12814 mptsas_bus_config(dev_info_t *pdip, uint_t flag,
12812 12815 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
12813 12816 {
12814 12817 int ret = NDI_FAILURE;
12815 12818 int circ = 0;
12816 12819 int circ1 = 0;
12817 12820 mptsas_t *mpt;
12818 12821 char *ptr = NULL;
12819 12822 char *devnm = NULL;
12820 12823 uint64_t wwid = 0;
12821 12824 uint8_t phy = 0xFF;
12822 12825 int lun = 0;
12823 12826 uint_t mflags = flag;
12824 12827 int bconfig = TRUE;
12825 12828
12826 12829 if (scsi_hba_iport_unit_address(pdip) == 0) {
12827 12830 return (DDI_FAILURE);
12828 12831 }
12829 12832
12830 12833 mpt = DIP2MPT(pdip);
12831 12834 if (!mpt) {
12832 12835 return (DDI_FAILURE);
12833 12836 }
12834 12837 /*
12835 12838 * Hold the nexus across the bus_config
12836 12839 */
12837 12840 ndi_devi_enter(scsi_vhci_dip, &circ);
12838 12841 ndi_devi_enter(pdip, &circ1);
12839 12842 switch (op) {
12840 12843 case BUS_CONFIG_ONE:
12841 12844 /* parse wwid/target name out of name given */
12842 12845 if ((ptr = strchr((char *)arg, '@')) == NULL) {
12843 12846 ret = NDI_FAILURE;
12844 12847 break;
12845 12848 }
12846 12849 ptr++;
12847 12850 if (strncmp((char *)arg, "smp", 3) == 0) {
12848 12851 /*
12849 12852 * This is a SMP target device
12850 12853 */
12851 12854 ret = mptsas_parse_smp_name(ptr, &wwid);
12852 12855 if (ret != DDI_SUCCESS) {
12853 12856 ret = NDI_FAILURE;
12854 12857 break;
12855 12858 }
12856 12859 ret = mptsas_config_smp(pdip, wwid, childp);
12857 12860 } else if ((ptr[0] == 'w') || (ptr[0] == 'p')) {
12858 12861 /*
12859 12862 * OBP could pass down a non-canonical form
12860 12863 * bootpath without LUN part when LUN is 0.
12861 12864 * So driver need adjust the string.
12862 12865 */
12863 12866 if (strchr(ptr, ',') == NULL) {
12864 12867 devnm = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
12865 12868 (void) sprintf(devnm, "%s,0", (char *)arg);
12866 12869 ptr = strchr(devnm, '@');
12867 12870 ptr++;
12868 12871 }
12869 12872
12870 12873 /*
12871 12874 * The device path is wWWID format and the device
12872 12875 * is not SMP target device.
12873 12876 */
12874 12877 ret = mptsas_parse_address(ptr, &wwid, &phy, &lun);
12875 12878 if (ret != DDI_SUCCESS) {
12876 12879 ret = NDI_FAILURE;
12877 12880 break;
12878 12881 }
12879 12882 *childp = NULL;
12880 12883 if (ptr[0] == 'w') {
12881 12884 ret = mptsas_config_one_addr(pdip, wwid,
12882 12885 lun, childp);
12883 12886 } else if (ptr[0] == 'p') {
12884 12887 ret = mptsas_config_one_phy(pdip, phy, lun,
12885 12888 childp);
12886 12889 }
12887 12890
12888 12891 /*
12889 12892 * If this is CD/DVD device in OBP path, the
12890 12893 * ndi_busop_bus_config can be skipped as config one
12891 12894 * operation is done above.
12892 12895 */
12893 12896 if ((ret == NDI_SUCCESS) && (*childp != NULL) &&
12894 12897 (strcmp(ddi_node_name(*childp), "cdrom") == 0) &&
12895 12898 (strncmp((char *)arg, "disk", 4) == 0)) {
12896 12899 bconfig = FALSE;
12897 12900 ndi_hold_devi(*childp);
12898 12901 }
12899 12902 } else {
12900 12903 ret = NDI_FAILURE;
12901 12904 break;
12902 12905 }
12903 12906
12904 12907 /*
12905 12908 * DDI group instructed us to use this flag.
12906 12909 */
12907 12910 mflags |= NDI_MDI_FALLBACK;
12908 12911 break;
12909 12912 case BUS_CONFIG_DRIVER:
12910 12913 case BUS_CONFIG_ALL:
12911 12914 mptsas_config_all(pdip);
12912 12915 ret = NDI_SUCCESS;
12913 12916 break;
12914 12917 }
12915 12918
12916 12919 if ((ret == NDI_SUCCESS) && bconfig) {
12917 12920 ret = ndi_busop_bus_config(pdip, mflags, op,
12918 12921 (devnm == NULL) ? arg : devnm, childp, 0);
12919 12922 }
12920 12923
12921 12924 ndi_devi_exit(pdip, circ1);
12922 12925 ndi_devi_exit(scsi_vhci_dip, circ);
12923 12926 if (devnm != NULL)
12924 12927 kmem_free(devnm, SCSI_MAXNAMELEN);
12925 12928 return (ret);
12926 12929 }
12927 12930
12928 12931 static int
12929 12932 mptsas_probe_lun(dev_info_t *pdip, int lun, dev_info_t **dip,
12930 12933 mptsas_target_t *ptgt)
12931 12934 {
12932 12935 int rval = DDI_FAILURE;
12933 12936 struct scsi_inquiry *sd_inq = NULL;
12934 12937 mptsas_t *mpt = DIP2MPT(pdip);
12935 12938
12936 12939 sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
12937 12940
12938 12941 rval = mptsas_inquiry(mpt, ptgt, lun, 0, (uchar_t *)sd_inq,
12939 12942 SUN_INQSIZE, 0, (uchar_t)0);
12940 12943
12941 12944 if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
12942 12945 rval = mptsas_create_lun(pdip, sd_inq, dip, ptgt, lun);
12943 12946 } else {
12944 12947 rval = DDI_FAILURE;
12945 12948 }
12946 12949
12947 12950 kmem_free(sd_inq, SUN_INQSIZE);
12948 12951 return (rval);
12949 12952 }
12950 12953
12951 12954 static int
12952 12955 mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
12953 12956 dev_info_t **lundip)
12954 12957 {
12955 12958 int rval;
12956 12959 mptsas_t *mpt = DIP2MPT(pdip);
12957 12960 int phymask;
12958 12961 mptsas_target_t *ptgt = NULL;
12959 12962
12960 12963 /*
12961 12964 * Get the physical port associated to the iport
12962 12965 */
12963 12966 phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
12964 12967 "phymask", 0);
12965 12968
12966 12969 ptgt = mptsas_wwid_to_ptgt(mpt, phymask, sasaddr);
12967 12970 if (ptgt == NULL) {
12968 12971 /*
12969 12972 * didn't match any device by searching
12970 12973 */
12971 12974 return (DDI_FAILURE);
12972 12975 }
12973 12976 /*
12974 12977 * If the LUN already exists and the status is online,
12975 12978 * we just return the pointer to dev_info_t directly.
12976 12979 * For the mdi_pathinfo node, we'll handle it in
12977 12980 * mptsas_create_virt_lun()
12978 12981 * TODO should be also in mptsas_handle_dr
12979 12982 */
12980 12983
12981 12984 *lundip = mptsas_find_child_addr(pdip, sasaddr, lun);
12982 12985 if (*lundip != NULL) {
12983 12986 /*
12984 12987 * TODO Another senario is, we hotplug the same disk
12985 12988 * on the same slot, the devhdl changed, is this
12986 12989 * possible?
12987 12990 * tgt_private->t_private != ptgt
12988 12991 */
12989 12992 if (sasaddr != ptgt->m_addr.mta_wwn) {
12990 12993 /*
12991 12994 * The device has changed although the devhdl is the
12992 12995 * same (Enclosure mapping mode, change drive on the
12993 12996 * same slot)
12994 12997 */
12995 12998 return (DDI_FAILURE);
12996 12999 }
12997 13000 return (DDI_SUCCESS);
12998 13001 }
12999 13002
13000 13003 if (phymask == 0) {
13001 13004 /*
13002 13005 * Configure IR volume
13003 13006 */
13004 13007 rval = mptsas_config_raid(pdip, ptgt->m_devhdl, lundip);
13005 13008 return (rval);
13006 13009 }
13007 13010 rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13008 13011
13009 13012 return (rval);
13010 13013 }
13011 13014
13012 13015 static int
13013 13016 mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
13014 13017 dev_info_t **lundip)
13015 13018 {
13016 13019 int rval;
13017 13020 mptsas_t *mpt = DIP2MPT(pdip);
13018 13021 mptsas_phymask_t phymask;
13019 13022 mptsas_target_t *ptgt = NULL;
13020 13023
13021 13024 /*
13022 13025 * Get the physical port associated to the iport
13023 13026 */
13024 13027 phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13025 13028 "phymask", 0);
13026 13029
13027 13030 ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
13028 13031 if (ptgt == NULL) {
13029 13032 /*
13030 13033 * didn't match any device by searching
13031 13034 */
13032 13035 return (DDI_FAILURE);
13033 13036 }
13034 13037
13035 13038 /*
13036 13039 * If the LUN already exists and the status is online,
13037 13040 * we just return the pointer to dev_info_t directly.
13038 13041 * For the mdi_pathinfo node, we'll handle it in
13039 13042 * mptsas_create_virt_lun().
13040 13043 */
13041 13044
13042 13045 *lundip = mptsas_find_child_phy(pdip, phy);
13043 13046 if (*lundip != NULL) {
13044 13047 return (DDI_SUCCESS);
13045 13048 }
13046 13049
13047 13050 rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13048 13051
13049 13052 return (rval);
13050 13053 }
13051 13054
13052 13055 static int
13053 13056 mptsas_retrieve_lundata(int lun_cnt, uint8_t *buf, uint16_t *lun_num,
13054 13057 uint8_t *lun_addr_type)
13055 13058 {
13056 13059 uint32_t lun_idx = 0;
13057 13060
13058 13061 ASSERT(lun_num != NULL);
13059 13062 ASSERT(lun_addr_type != NULL);
13060 13063
13061 13064 lun_idx = (lun_cnt + 1) * MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
13062 13065 /* determine report luns addressing type */
13063 13066 switch (buf[lun_idx] & MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) {
13064 13067 /*
13065 13068 * Vendors in the field have been found to be concatenating
13066 13069 * bus/target/lun to equal the complete lun value instead
13067 13070 * of switching to flat space addressing
13068 13071 */
13069 13072 /* 00b - peripheral device addressing method */
13070 13073 case MPTSAS_SCSI_REPORTLUNS_ADDRESS_PERIPHERAL:
13071 13074 /* FALLTHRU */
13072 13075 /* 10b - logical unit addressing method */
13073 13076 case MPTSAS_SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT:
13074 13077 /* FALLTHRU */
13075 13078 /* 01b - flat space addressing method */
13076 13079 case MPTSAS_SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE:
13077 13080 /* byte0 bit0-5=msb lun byte1 bit0-7=lsb lun */
13078 13081 *lun_addr_type = (buf[lun_idx] &
13079 13082 MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) >> 6;
13080 13083 *lun_num = (buf[lun_idx] & 0x3F) << 8;
13081 13084 *lun_num |= buf[lun_idx + 1];
13082 13085 return (DDI_SUCCESS);
13083 13086 default:
13084 13087 return (DDI_FAILURE);
13085 13088 }
13086 13089 }
13087 13090
13088 13091 static int
13089 13092 mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt)
13090 13093 {
13091 13094 struct buf *repluns_bp = NULL;
13092 13095 struct scsi_address ap;
13093 13096 uchar_t cdb[CDB_GROUP5];
13094 13097 int ret = DDI_FAILURE;
13095 13098 int retry = 0;
13096 13099 int lun_list_len = 0;
13097 13100 uint16_t lun_num = 0;
13098 13101 uint8_t lun_addr_type = 0;
13099 13102 uint32_t lun_cnt = 0;
13100 13103 uint32_t lun_total = 0;
13101 13104 dev_info_t *cdip = NULL;
13102 13105 uint16_t *saved_repluns = NULL;
13103 13106 char *buffer = NULL;
13104 13107 int buf_len = 128;
13105 13108 mptsas_t *mpt = DIP2MPT(pdip);
13106 13109 uint64_t sas_wwn = 0;
13107 13110 uint8_t phy = 0xFF;
13108 13111 uint32_t dev_info = 0;
13109 13112
13110 13113 mutex_enter(&mpt->m_mutex);
13111 13114 sas_wwn = ptgt->m_addr.mta_wwn;
13112 13115 phy = ptgt->m_phynum;
13113 13116 dev_info = ptgt->m_deviceinfo;
13114 13117 mutex_exit(&mpt->m_mutex);
13115 13118
13116 13119 if (sas_wwn == 0) {
13117 13120 /*
13118 13121 * It's a SATA without Device Name
13119 13122 * So don't try multi-LUNs
13120 13123 */
13121 13124 if (mptsas_find_child_phy(pdip, phy)) {
13122 13125 return (DDI_SUCCESS);
13123 13126 } else {
13124 13127 /*
13125 13128 * need configure and create node
13126 13129 */
13127 13130 return (DDI_FAILURE);
13128 13131 }
13129 13132 }
13130 13133
13131 13134 /*
13132 13135 * WWN (SAS address or Device Name exist)
13133 13136 */
13134 13137 if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13135 13138 MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
13136 13139 /*
13137 13140 * SATA device with Device Name
13138 13141 * So don't try multi-LUNs
13139 13142 */
13140 13143 if (mptsas_find_child_addr(pdip, sas_wwn, 0)) {
13141 13144 return (DDI_SUCCESS);
13142 13145 } else {
13143 13146 return (DDI_FAILURE);
13144 13147 }
13145 13148 }
13146 13149
13147 13150 do {
13148 13151 ap.a_target = MPTSAS_INVALID_DEVHDL;
13149 13152 ap.a_lun = 0;
13150 13153 ap.a_hba_tran = mpt->m_tran;
13151 13154 repluns_bp = scsi_alloc_consistent_buf(&ap,
13152 13155 (struct buf *)NULL, buf_len, B_READ, NULL_FUNC, NULL);
13153 13156 if (repluns_bp == NULL) {
13154 13157 retry++;
13155 13158 continue;
13156 13159 }
13157 13160 bzero(cdb, CDB_GROUP5);
13158 13161 cdb[0] = SCMD_REPORT_LUNS;
13159 13162 cdb[6] = (buf_len & 0xff000000) >> 24;
13160 13163 cdb[7] = (buf_len & 0x00ff0000) >> 16;
13161 13164 cdb[8] = (buf_len & 0x0000ff00) >> 8;
13162 13165 cdb[9] = (buf_len & 0x000000ff);
13163 13166
13164 13167 ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP5,
13165 13168 repluns_bp, NULL);
13166 13169 if (ret != DDI_SUCCESS) {
13167 13170 scsi_free_consistent_buf(repluns_bp);
13168 13171 retry++;
13169 13172 continue;
13170 13173 }
13171 13174 lun_list_len = BE_32(*(int *)((void *)(
13172 13175 repluns_bp->b_un.b_addr)));
13173 13176 if (buf_len >= lun_list_len + 8) {
13174 13177 ret = DDI_SUCCESS;
13175 13178 break;
13176 13179 }
13177 13180 scsi_free_consistent_buf(repluns_bp);
13178 13181 buf_len = lun_list_len + 8;
13179 13182
13180 13183 } while (retry < 3);
13181 13184
13182 13185 if (ret != DDI_SUCCESS)
13183 13186 return (ret);
13184 13187 buffer = (char *)repluns_bp->b_un.b_addr;
13185 13188 /*
13186 13189 * find out the number of luns returned by the SCSI ReportLun call
13187 13190 * and allocate buffer space
13188 13191 */
13189 13192 lun_total = lun_list_len / MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
13190 13193 saved_repluns = kmem_zalloc(sizeof (uint16_t) * lun_total, KM_SLEEP);
13191 13194 if (saved_repluns == NULL) {
13192 13195 scsi_free_consistent_buf(repluns_bp);
13193 13196 return (DDI_FAILURE);
13194 13197 }
13195 13198 for (lun_cnt = 0; lun_cnt < lun_total; lun_cnt++) {
13196 13199 if (mptsas_retrieve_lundata(lun_cnt, (uint8_t *)(buffer),
13197 13200 &lun_num, &lun_addr_type) != DDI_SUCCESS) {
13198 13201 continue;
13199 13202 }
13200 13203 saved_repluns[lun_cnt] = lun_num;
13201 13204 if (cdip = mptsas_find_child_addr(pdip, sas_wwn, lun_num))
13202 13205 ret = DDI_SUCCESS;
13203 13206 else
13204 13207 ret = mptsas_probe_lun(pdip, lun_num, &cdip,
13205 13208 ptgt);
13206 13209 if ((ret == DDI_SUCCESS) && (cdip != NULL)) {
13207 13210 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip,
13208 13211 MPTSAS_DEV_GONE);
13209 13212 }
13210 13213 }
13211 13214 mptsas_offline_missed_luns(pdip, saved_repluns, lun_total, ptgt);
13212 13215 kmem_free(saved_repluns, sizeof (uint16_t) * lun_total);
13213 13216 scsi_free_consistent_buf(repluns_bp);
13214 13217 return (DDI_SUCCESS);
13215 13218 }
13216 13219
13217 13220 static int
13218 13221 mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
13219 13222 {
13220 13223 int rval = DDI_FAILURE;
13221 13224 struct scsi_inquiry *sd_inq = NULL;
13222 13225 mptsas_t *mpt = DIP2MPT(pdip);
13223 13226 mptsas_target_t *ptgt = NULL;
13224 13227
13225 13228 mutex_enter(&mpt->m_mutex);
13226 13229 ptgt = refhash_linear_search(mpt->m_targets,
13227 13230 mptsas_target_eval_devhdl, &target);
13228 13231 mutex_exit(&mpt->m_mutex);
13229 13232 if (ptgt == NULL) {
13230 13233 mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
13231 13234 "not found.", target);
13232 13235 return (rval);
13233 13236 }
13234 13237
13235 13238 sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13236 13239 rval = mptsas_inquiry(mpt, ptgt, 0, 0, (uchar_t *)sd_inq,
13237 13240 SUN_INQSIZE, 0, (uchar_t)0);
13238 13241
13239 13242 if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
13240 13243 rval = mptsas_create_phys_lun(pdip, sd_inq, NULL, dip, ptgt,
13241 13244 0);
13242 13245 } else {
13243 13246 rval = DDI_FAILURE;
13244 13247 }
13245 13248
13246 13249 kmem_free(sd_inq, SUN_INQSIZE);
13247 13250 return (rval);
13248 13251 }
13249 13252
13250 13253 /*
13251 13254 * configure all RAID volumes for virtual iport
13252 13255 */
13253 13256 static void
13254 13257 mptsas_config_all_viport(dev_info_t *pdip)
13255 13258 {
13256 13259 mptsas_t *mpt = DIP2MPT(pdip);
13257 13260 int config, vol;
13258 13261 int target;
13259 13262 dev_info_t *lundip = NULL;
13260 13263
13261 13264 /*
13262 13265 * Get latest RAID info and search for any Volume DevHandles. If any
13263 13266 * are found, configure the volume.
13264 13267 */
13265 13268 mutex_enter(&mpt->m_mutex);
13266 13269 for (config = 0; config < mpt->m_num_raid_configs; config++) {
13267 13270 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
13268 13271 if (mpt->m_raidconfig[config].m_raidvol[vol].m_israid
13269 13272 == 1) {
13270 13273 target = mpt->m_raidconfig[config].
13271 13274 m_raidvol[vol].m_raidhandle;
13272 13275 mutex_exit(&mpt->m_mutex);
13273 13276 (void) mptsas_config_raid(pdip, target,
13274 13277 &lundip);
13275 13278 mutex_enter(&mpt->m_mutex);
13276 13279 }
13277 13280 }
13278 13281 }
13279 13282 mutex_exit(&mpt->m_mutex);
13280 13283 }
13281 13284
13282 13285 static void
13283 13286 mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
13284 13287 int lun_cnt, mptsas_target_t *ptgt)
13285 13288 {
13286 13289 dev_info_t *child = NULL, *savechild = NULL;
13287 13290 mdi_pathinfo_t *pip = NULL, *savepip = NULL;
13288 13291 uint64_t sas_wwn, wwid;
13289 13292 uint8_t phy;
13290 13293 int lun;
13291 13294 int i;
13292 13295 int find;
13293 13296 char *addr;
13294 13297 char *nodename;
13295 13298 mptsas_t *mpt = DIP2MPT(pdip);
13296 13299
13297 13300 mutex_enter(&mpt->m_mutex);
13298 13301 wwid = ptgt->m_addr.mta_wwn;
13299 13302 mutex_exit(&mpt->m_mutex);
13300 13303
13301 13304 child = ddi_get_child(pdip);
13302 13305 while (child) {
13303 13306 find = 0;
13304 13307 savechild = child;
13305 13308 child = ddi_get_next_sibling(child);
13306 13309
13307 13310 nodename = ddi_node_name(savechild);
13308 13311 if (strcmp(nodename, "smp") == 0) {
13309 13312 continue;
13310 13313 }
13311 13314
13312 13315 addr = ddi_get_name_addr(savechild);
13313 13316 if (addr == NULL) {
13314 13317 continue;
13315 13318 }
13316 13319
13317 13320 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
13318 13321 DDI_SUCCESS) {
13319 13322 continue;
13320 13323 }
13321 13324
13322 13325 if (wwid == sas_wwn) {
13323 13326 for (i = 0; i < lun_cnt; i++) {
13324 13327 if (repluns[i] == lun) {
13325 13328 find = 1;
13326 13329 break;
13327 13330 }
13328 13331 }
13329 13332 } else {
13330 13333 continue;
13331 13334 }
13332 13335 if (find == 0) {
13333 13336 /*
13334 13337 * The lun has not been there already
13335 13338 */
13336 13339 (void) mptsas_offline_lun(pdip, savechild, NULL,
13337 13340 NDI_DEVI_REMOVE);
13338 13341 }
13339 13342 }
13340 13343
13341 13344 pip = mdi_get_next_client_path(pdip, NULL);
13342 13345 while (pip) {
13343 13346 find = 0;
13344 13347 savepip = pip;
13345 13348 addr = MDI_PI(pip)->pi_addr;
13346 13349
13347 13350 pip = mdi_get_next_client_path(pdip, pip);
13348 13351
13349 13352 if (addr == NULL) {
13350 13353 continue;
13351 13354 }
13352 13355
13353 13356 if (mptsas_parse_address(addr, &sas_wwn, &phy,
13354 13357 &lun) != DDI_SUCCESS) {
13355 13358 continue;
13356 13359 }
13357 13360
13358 13361 if (sas_wwn == wwid) {
13359 13362 for (i = 0; i < lun_cnt; i++) {
13360 13363 if (repluns[i] == lun) {
13361 13364 find = 1;
13362 13365 break;
13363 13366 }
13364 13367 }
13365 13368 } else {
13366 13369 continue;
13367 13370 }
13368 13371
13369 13372 if (find == 0) {
13370 13373 /*
13371 13374 * The lun has not been there already
13372 13375 */
13373 13376 (void) mptsas_offline_lun(pdip, NULL, savepip,
13374 13377 NDI_DEVI_REMOVE);
13375 13378 }
13376 13379 }
13377 13380 }
13378 13381
13379 13382 void
13380 13383 mptsas_update_hashtab(struct mptsas *mpt)
13381 13384 {
13382 13385 uint32_t page_address;
13383 13386 int rval = 0;
13384 13387 uint16_t dev_handle;
13385 13388 mptsas_target_t *ptgt = NULL;
13386 13389 mptsas_smp_t smp_node;
13387 13390
13388 13391 /*
13389 13392 * Get latest RAID info.
13390 13393 */
13391 13394 (void) mptsas_get_raid_info(mpt);
13392 13395
13393 13396 dev_handle = mpt->m_smp_devhdl;
13394 13397 for (; mpt->m_done_traverse_smp == 0; ) {
13395 13398 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
13396 13399 MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)dev_handle;
13397 13400 if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
13398 13401 != DDI_SUCCESS) {
13399 13402 break;
13400 13403 }
13401 13404 mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
13402 13405 (void) mptsas_smp_alloc(mpt, &smp_node);
13403 13406 }
13404 13407
13405 13408 /*
13406 13409 * Config target devices
13407 13410 */
13408 13411 dev_handle = mpt->m_dev_handle;
13409 13412
13410 13413 /*
13411 13414 * Do loop to get sas device page 0 by GetNextHandle till the
13412 13415 * the last handle. If the sas device is a SATA/SSP target,
13413 13416 * we try to config it.
13414 13417 */
13415 13418 for (; mpt->m_done_traverse_dev == 0; ) {
13416 13419 ptgt = NULL;
13417 13420 page_address =
13418 13421 (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
13419 13422 MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
13420 13423 (uint32_t)dev_handle;
13421 13424 rval = mptsas_get_target_device_info(mpt, page_address,
13422 13425 &dev_handle, &ptgt);
13423 13426 if ((rval == DEV_INFO_FAIL_PAGE0) ||
13424 13427 (rval == DEV_INFO_FAIL_ALLOC)) {
13425 13428 break;
13426 13429 }
13427 13430
13428 13431 mpt->m_dev_handle = dev_handle;
13429 13432 }
13430 13433
13431 13434 }
13432 13435
13433 13436 void
13434 13437 mptsas_update_driver_data(struct mptsas *mpt)
13435 13438 {
13436 13439 mptsas_target_t *tp;
13437 13440 mptsas_smp_t *sp;
13438 13441
13439 13442 ASSERT(MUTEX_HELD(&mpt->m_mutex));
13440 13443
13441 13444 /*
13442 13445 * TODO after hard reset, update the driver data structures
13443 13446 * 1. update port/phymask mapping table mpt->m_phy_info
13444 13447 * 2. invalid all the entries in hash table
13445 13448 * m_devhdl = 0xffff and m_deviceinfo = 0
13446 13449 * 3. call sas_device_page/expander_page to update hash table
13447 13450 */
13448 13451 mptsas_update_phymask(mpt);
13449 13452 /*
13450 13453 * Invalid the existing entries
13451 13454 *
13452 13455 * XXX - It seems like we should just delete everything here. We are
13453 13456 * holding the lock and are about to refresh all the targets in both
13454 13457 * hashes anyway. Given the path we're in, what outstanding async
13455 13458 * event could possibly be trying to reference one of these things
13456 13459 * without taking the lock, and how would that be useful anyway?
13457 13460 */
13458 13461 for (tp = refhash_first(mpt->m_targets); tp != NULL;
13459 13462 tp = refhash_next(mpt->m_targets, tp)) {
13460 13463 tp->m_devhdl = MPTSAS_INVALID_DEVHDL;
13461 13464 tp->m_deviceinfo = 0;
13462 13465 tp->m_dr_flag = MPTSAS_DR_INACTIVE;
13463 13466 }
13464 13467 for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
13465 13468 sp = refhash_next(mpt->m_smp_targets, sp)) {
13466 13469 sp->m_devhdl = MPTSAS_INVALID_DEVHDL;
13467 13470 sp->m_deviceinfo = 0;
13468 13471 }
13469 13472 mpt->m_done_traverse_dev = 0;
13470 13473 mpt->m_done_traverse_smp = 0;
13471 13474 mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
13472 13475 mptsas_update_hashtab(mpt);
13473 13476 }
13474 13477
13475 13478 static void
13476 13479 mptsas_config_all(dev_info_t *pdip)
13477 13480 {
13478 13481 dev_info_t *smpdip = NULL;
13479 13482 mptsas_t *mpt = DIP2MPT(pdip);
13480 13483 int phymask = 0;
13481 13484 mptsas_phymask_t phy_mask;
13482 13485 mptsas_target_t *ptgt = NULL;
13483 13486 mptsas_smp_t *psmp;
13484 13487
13485 13488 /*
13486 13489 * Get the phymask associated to the iport
13487 13490 */
13488 13491 phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13489 13492 "phymask", 0);
13490 13493
13491 13494 /*
13492 13495 * Enumerate RAID volumes here (phymask == 0).
13493 13496 */
13494 13497 if (phymask == 0) {
13495 13498 mptsas_config_all_viport(pdip);
13496 13499 return;
13497 13500 }
13498 13501
13499 13502 mutex_enter(&mpt->m_mutex);
13500 13503
13501 13504 if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
13502 13505 mptsas_update_hashtab(mpt);
13503 13506 }
13504 13507
13505 13508 for (psmp = refhash_first(mpt->m_smp_targets); psmp != NULL;
13506 13509 psmp = refhash_next(mpt->m_smp_targets, psmp)) {
13507 13510 phy_mask = psmp->m_addr.mta_phymask;
13508 13511 if (phy_mask == phymask) {
13509 13512 smpdip = NULL;
13510 13513 mutex_exit(&mpt->m_mutex);
13511 13514 (void) mptsas_online_smp(pdip, psmp, &smpdip);
13512 13515 mutex_enter(&mpt->m_mutex);
13513 13516 }
13514 13517 }
13515 13518
13516 13519 for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
13517 13520 ptgt = refhash_next(mpt->m_targets, ptgt)) {
13518 13521 phy_mask = ptgt->m_addr.mta_phymask;
13519 13522 if (phy_mask == phymask) {
13520 13523 mutex_exit(&mpt->m_mutex);
13521 13524 (void) mptsas_config_target(pdip, ptgt);
13522 13525 mutex_enter(&mpt->m_mutex);
13523 13526 }
13524 13527 }
13525 13528 mutex_exit(&mpt->m_mutex);
13526 13529 }
13527 13530
13528 13531 static int
13529 13532 mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt)
13530 13533 {
13531 13534 int rval = DDI_FAILURE;
13532 13535 dev_info_t *tdip;
13533 13536
13534 13537 rval = mptsas_config_luns(pdip, ptgt);
13535 13538 if (rval != DDI_SUCCESS) {
13536 13539 /*
13537 13540 * The return value means the SCMD_REPORT_LUNS
13538 13541 * did not execute successfully. The target maybe
13539 13542 * doesn't support such command.
13540 13543 */
13541 13544 rval = mptsas_probe_lun(pdip, 0, &tdip, ptgt);
13542 13545 }
13543 13546 return (rval);
13544 13547 }
13545 13548
13546 13549 /*
13547 13550 * Return fail if not all the childs/paths are freed.
13548 13551 * if there is any path under the HBA, the return value will be always fail
13549 13552 * because we didn't call mdi_pi_free for path
13550 13553 */
13551 13554 static int
13552 13555 mptsas_offline_target(dev_info_t *pdip, char *name)
13553 13556 {
13554 13557 dev_info_t *child = NULL, *prechild = NULL;
13555 13558 mdi_pathinfo_t *pip = NULL, *savepip = NULL;
13556 13559 int tmp_rval, rval = DDI_SUCCESS;
13557 13560 char *addr, *cp;
13558 13561 size_t s;
13559 13562 mptsas_t *mpt = DIP2MPT(pdip);
13560 13563
13561 13564 child = ddi_get_child(pdip);
13562 13565 while (child) {
13563 13566 addr = ddi_get_name_addr(child);
13564 13567 prechild = child;
13565 13568 child = ddi_get_next_sibling(child);
13566 13569
13567 13570 if (addr == NULL) {
13568 13571 continue;
13569 13572 }
13570 13573 if ((cp = strchr(addr, ',')) == NULL) {
13571 13574 continue;
13572 13575 }
13573 13576
13574 13577 s = (uintptr_t)cp - (uintptr_t)addr;
13575 13578
13576 13579 if (strncmp(addr, name, s) != 0) {
13577 13580 continue;
13578 13581 }
13579 13582
13580 13583 tmp_rval = mptsas_offline_lun(pdip, prechild, NULL,
13581 13584 NDI_DEVI_REMOVE);
13582 13585 if (tmp_rval != DDI_SUCCESS) {
13583 13586 rval = DDI_FAILURE;
13584 13587 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
13585 13588 prechild, MPTSAS_DEV_GONE) !=
13586 13589 DDI_PROP_SUCCESS) {
13587 13590 mptsas_log(mpt, CE_WARN, "mptsas driver "
13588 13591 "unable to create property for "
13589 13592 "SAS %s (MPTSAS_DEV_GONE)", addr);
13590 13593 }
13591 13594 }
13592 13595 }
13593 13596
13594 13597 pip = mdi_get_next_client_path(pdip, NULL);
13595 13598 while (pip) {
13596 13599 addr = MDI_PI(pip)->pi_addr;
13597 13600 savepip = pip;
13598 13601 pip = mdi_get_next_client_path(pdip, pip);
13599 13602 if (addr == NULL) {
13600 13603 continue;
13601 13604 }
13602 13605
13603 13606 if ((cp = strchr(addr, ',')) == NULL) {
13604 13607 continue;
13605 13608 }
13606 13609
13607 13610 s = (uintptr_t)cp - (uintptr_t)addr;
13608 13611
13609 13612 if (strncmp(addr, name, s) != 0) {
13610 13613 continue;
13611 13614 }
13612 13615
13613 13616 (void) mptsas_offline_lun(pdip, NULL, savepip,
13614 13617 NDI_DEVI_REMOVE);
13615 13618 /*
13616 13619 * driver will not invoke mdi_pi_free, so path will not
13617 13620 * be freed forever, return DDI_FAILURE.
13618 13621 */
13619 13622 rval = DDI_FAILURE;
13620 13623 }
13621 13624 return (rval);
13622 13625 }
13623 13626
13624 13627 static int
13625 13628 mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
13626 13629 mdi_pathinfo_t *rpip, uint_t flags)
13627 13630 {
13628 13631 int rval = DDI_FAILURE;
13629 13632 char *devname;
13630 13633 dev_info_t *cdip, *parent;
13631 13634
13632 13635 if (rpip != NULL) {
13633 13636 parent = scsi_vhci_dip;
13634 13637 cdip = mdi_pi_get_client(rpip);
13635 13638 } else if (rdip != NULL) {
13636 13639 parent = pdip;
13637 13640 cdip = rdip;
13638 13641 } else {
13639 13642 return (DDI_FAILURE);
13640 13643 }
13641 13644
13642 13645 /*
13643 13646 * Make sure node is attached otherwise
13644 13647 * it won't have related cache nodes to
13645 13648 * clean up. i_ddi_devi_attached is
13646 13649 * similiar to i_ddi_node_state(cdip) >=
13647 13650 * DS_ATTACHED.
13648 13651 */
13649 13652 if (i_ddi_devi_attached(cdip)) {
13650 13653
13651 13654 /* Get full devname */
13652 13655 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
13653 13656 (void) ddi_deviname(cdip, devname);
13654 13657 /* Clean cache */
13655 13658 (void) devfs_clean(parent, devname + 1,
13656 13659 DV_CLEAN_FORCE);
13657 13660 kmem_free(devname, MAXNAMELEN + 1);
13658 13661 }
13659 13662 if (rpip != NULL) {
13660 13663 if (MDI_PI_IS_OFFLINE(rpip)) {
13661 13664 rval = DDI_SUCCESS;
13662 13665 } else {
13663 13666 rval = mdi_pi_offline(rpip, 0);
13664 13667 }
13665 13668 } else {
13666 13669 rval = ndi_devi_offline(cdip, flags);
13667 13670 }
13668 13671
13669 13672 return (rval);
13670 13673 }
13671 13674
13672 13675 static dev_info_t *
13673 13676 mptsas_find_smp_child(dev_info_t *parent, char *str_wwn)
13674 13677 {
13675 13678 dev_info_t *child = NULL;
13676 13679 char *smp_wwn = NULL;
13677 13680
13678 13681 child = ddi_get_child(parent);
13679 13682 while (child) {
13680 13683 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
13681 13684 DDI_PROP_DONTPASS, SMP_WWN, &smp_wwn)
13682 13685 != DDI_SUCCESS) {
13683 13686 child = ddi_get_next_sibling(child);
13684 13687 continue;
13685 13688 }
13686 13689
13687 13690 if (strcmp(smp_wwn, str_wwn) == 0) {
13688 13691 ddi_prop_free(smp_wwn);
13689 13692 break;
13690 13693 }
13691 13694 child = ddi_get_next_sibling(child);
13692 13695 ddi_prop_free(smp_wwn);
13693 13696 }
13694 13697 return (child);
13695 13698 }
13696 13699
13697 13700 static int
13698 13701 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
13699 13702 {
13700 13703 int rval = DDI_FAILURE;
13701 13704 char *devname;
13702 13705 char wwn_str[MPTSAS_WWN_STRLEN];
13703 13706 dev_info_t *cdip;
13704 13707
13705 13708 (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
13706 13709
13707 13710 cdip = mptsas_find_smp_child(pdip, wwn_str);
13708 13711
13709 13712 if (cdip == NULL)
13710 13713 return (DDI_SUCCESS);
13711 13714
13712 13715 /*
13713 13716 * Make sure node is attached otherwise
13714 13717 * it won't have related cache nodes to
13715 13718 * clean up. i_ddi_devi_attached is
13716 13719 * similiar to i_ddi_node_state(cdip) >=
13717 13720 * DS_ATTACHED.
13718 13721 */
13719 13722 if (i_ddi_devi_attached(cdip)) {
13720 13723
13721 13724 /* Get full devname */
13722 13725 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
13723 13726 (void) ddi_deviname(cdip, devname);
13724 13727 /* Clean cache */
13725 13728 (void) devfs_clean(pdip, devname + 1,
13726 13729 DV_CLEAN_FORCE);
13727 13730 kmem_free(devname, MAXNAMELEN + 1);
13728 13731 }
13729 13732
13730 13733 rval = ndi_devi_offline(cdip, flags);
13731 13734
13732 13735 return (rval);
13733 13736 }
13734 13737
13735 13738 static dev_info_t *
13736 13739 mptsas_find_child(dev_info_t *pdip, char *name)
13737 13740 {
13738 13741 dev_info_t *child = NULL;
13739 13742 char *rname = NULL;
13740 13743 int rval = DDI_FAILURE;
13741 13744
13742 13745 rname = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13743 13746
13744 13747 child = ddi_get_child(pdip);
13745 13748 while (child) {
13746 13749 rval = mptsas_name_child(child, rname, SCSI_MAXNAMELEN);
13747 13750 if (rval != DDI_SUCCESS) {
13748 13751 child = ddi_get_next_sibling(child);
13749 13752 bzero(rname, SCSI_MAXNAMELEN);
13750 13753 continue;
13751 13754 }
13752 13755
13753 13756 if (strcmp(rname, name) == 0) {
13754 13757 break;
13755 13758 }
13756 13759 child = ddi_get_next_sibling(child);
13757 13760 bzero(rname, SCSI_MAXNAMELEN);
13758 13761 }
13759 13762
13760 13763 kmem_free(rname, SCSI_MAXNAMELEN);
13761 13764
13762 13765 return (child);
13763 13766 }
13764 13767
13765 13768
13766 13769 static dev_info_t *
13767 13770 mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr, int lun)
13768 13771 {
13769 13772 dev_info_t *child = NULL;
13770 13773 char *name = NULL;
13771 13774 char *addr = NULL;
13772 13775
13773 13776 name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13774 13777 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13775 13778 (void) sprintf(name, "%016"PRIx64, sasaddr);
13776 13779 (void) sprintf(addr, "w%s,%x", name, lun);
13777 13780 child = mptsas_find_child(pdip, addr);
13778 13781 kmem_free(name, SCSI_MAXNAMELEN);
13779 13782 kmem_free(addr, SCSI_MAXNAMELEN);
13780 13783 return (child);
13781 13784 }
13782 13785
13783 13786 static dev_info_t *
13784 13787 mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy)
13785 13788 {
13786 13789 dev_info_t *child;
13787 13790 char *addr;
13788 13791
13789 13792 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13790 13793 (void) sprintf(addr, "p%x,0", phy);
13791 13794 child = mptsas_find_child(pdip, addr);
13792 13795 kmem_free(addr, SCSI_MAXNAMELEN);
13793 13796 return (child);
13794 13797 }
13795 13798
13796 13799 static mdi_pathinfo_t *
13797 13800 mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy)
13798 13801 {
13799 13802 mdi_pathinfo_t *path;
13800 13803 char *addr = NULL;
13801 13804
13802 13805 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13803 13806 (void) sprintf(addr, "p%x,0", phy);
13804 13807 path = mdi_pi_find(pdip, NULL, addr);
13805 13808 kmem_free(addr, SCSI_MAXNAMELEN);
13806 13809 return (path);
13807 13810 }
13808 13811
13809 13812 static mdi_pathinfo_t *
13810 13813 mptsas_find_path_addr(dev_info_t *parent, uint64_t sasaddr, int lun)
13811 13814 {
13812 13815 mdi_pathinfo_t *path;
13813 13816 char *name = NULL;
13814 13817 char *addr = NULL;
13815 13818
13816 13819 name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13817 13820 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13818 13821 (void) sprintf(name, "%016"PRIx64, sasaddr);
13819 13822 (void) sprintf(addr, "w%s,%x", name, lun);
13820 13823 path = mdi_pi_find(parent, NULL, addr);
13821 13824 kmem_free(name, SCSI_MAXNAMELEN);
13822 13825 kmem_free(addr, SCSI_MAXNAMELEN);
13823 13826
13824 13827 return (path);
13825 13828 }
13826 13829
13827 13830 static int
13828 13831 mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
13829 13832 dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
13830 13833 {
13831 13834 int i = 0;
13832 13835 uchar_t *inq83 = NULL;
13833 13836 int inq83_len1 = 0xFF;
13834 13837 int inq83_len = 0;
13835 13838 int rval = DDI_FAILURE;
13836 13839 ddi_devid_t devid;
13837 13840 char *guid = NULL;
13838 13841 int target = ptgt->m_devhdl;
13839 13842 mdi_pathinfo_t *pip = NULL;
13840 13843 mptsas_t *mpt = DIP2MPT(pdip);
13841 13844
13842 13845 /*
13843 13846 * For DVD/CD ROM and tape devices and optical
13844 13847 * devices, we won't try to enumerate them under
13845 13848 * scsi_vhci, so no need to try page83
13846 13849 */
13847 13850 if (sd_inq && (sd_inq->inq_dtype == DTYPE_RODIRECT ||
13848 13851 sd_inq->inq_dtype == DTYPE_OPTICAL ||
13849 13852 sd_inq->inq_dtype == DTYPE_ESI))
13850 13853 goto create_lun;
13851 13854
13852 13855 /*
13853 13856 * The LCA returns good SCSI status, but corrupt page 83 data the first
13854 13857 * time it is queried. The solution is to keep trying to request page83
13855 13858 * and verify the GUID is not (DDI_NOT_WELL_FORMED) in
13856 13859 * mptsas_inq83_retry_timeout seconds. If the timeout expires, driver
13857 13860 * give up to get VPD page at this stage and fail the enumeration.
13858 13861 */
13859 13862
13860 13863 inq83 = kmem_zalloc(inq83_len1, KM_SLEEP);
13861 13864
13862 13865 for (i = 0; i < mptsas_inq83_retry_timeout; i++) {
13863 13866 rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
13864 13867 inq83_len1, &inq83_len, 1);
13865 13868 if (rval != 0) {
13866 13869 mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
13867 13870 "0x83 for target:%x, lun:%x failed!", target, lun);
13868 13871 if (mptsas_physical_bind_failed_page_83 != B_FALSE)
13869 13872 goto create_lun;
13870 13873 goto out;
13871 13874 }
13872 13875 /*
13873 13876 * create DEVID from inquiry data
13874 13877 */
13875 13878 if ((rval = ddi_devid_scsi_encode(
13876 13879 DEVID_SCSI_ENCODE_VERSION_LATEST, NULL, (uchar_t *)sd_inq,
13877 13880 sizeof (struct scsi_inquiry), NULL, 0, inq83,
13878 13881 (size_t)inq83_len, &devid)) == DDI_SUCCESS) {
13879 13882 /*
13880 13883 * extract GUID from DEVID
13881 13884 */
13882 13885 guid = ddi_devid_to_guid(devid);
13883 13886
13884 13887 /*
13885 13888 * Do not enable MPXIO if the strlen(guid) is greater
13886 13889 * than MPTSAS_MAX_GUID_LEN, this constrain would be
13887 13890 * handled by framework later.
13888 13891 */
13889 13892 if (guid && (strlen(guid) > MPTSAS_MAX_GUID_LEN)) {
13890 13893 ddi_devid_free_guid(guid);
13891 13894 guid = NULL;
13892 13895 if (mpt->m_mpxio_enable == TRUE) {
13893 13896 mptsas_log(mpt, CE_NOTE, "!Target:%x, "
13894 13897 "lun:%x doesn't have a valid GUID, "
13895 13898 "multipathing for this drive is "
13896 13899 "not enabled", target, lun);
13897 13900 }
13898 13901 }
13899 13902
13900 13903 /*
13901 13904 * devid no longer needed
13902 13905 */
13903 13906 ddi_devid_free(devid);
13904 13907 break;
13905 13908 } else if (rval == DDI_NOT_WELL_FORMED) {
13906 13909 /*
13907 13910 * return value of ddi_devid_scsi_encode equal to
13908 13911 * DDI_NOT_WELL_FORMED means DEVID_RETRY, it worth
13909 13912 * to retry inquiry page 0x83 and get GUID.
13910 13913 */
13911 13914 NDBG20(("Not well formed devid, retry..."));
13912 13915 delay(1 * drv_usectohz(1000000));
13913 13916 continue;
13914 13917 } else {
13915 13918 mptsas_log(mpt, CE_WARN, "!Encode devid failed for "
13916 13919 "path target:%x, lun:%x", target, lun);
13917 13920 rval = DDI_FAILURE;
13918 13921 goto create_lun;
13919 13922 }
13920 13923 }
13921 13924
13922 13925 if (i == mptsas_inq83_retry_timeout) {
13923 13926 mptsas_log(mpt, CE_WARN, "!Repeated page83 requests timeout "
13924 13927 "for path target:%x, lun:%x", target, lun);
13925 13928 }
13926 13929
13927 13930 rval = DDI_FAILURE;
13928 13931
13929 13932 create_lun:
13930 13933 if ((guid != NULL) && (mpt->m_mpxio_enable == TRUE)) {
13931 13934 rval = mptsas_create_virt_lun(pdip, sd_inq, guid, lun_dip, &pip,
13932 13935 ptgt, lun);
13933 13936 }
13934 13937 if (rval != DDI_SUCCESS) {
13935 13938 rval = mptsas_create_phys_lun(pdip, sd_inq, guid, lun_dip,
13936 13939 ptgt, lun);
13937 13940
13938 13941 }
13939 13942 out:
13940 13943 if (guid != NULL) {
13941 13944 /*
13942 13945 * guid no longer needed
13943 13946 */
13944 13947 ddi_devid_free_guid(guid);
13945 13948 }
13946 13949 if (inq83 != NULL)
13947 13950 kmem_free(inq83, inq83_len1);
13948 13951 return (rval);
13949 13952 }
13950 13953
13951 13954 static int
13952 13955 mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *inq, char *guid,
13953 13956 dev_info_t **lun_dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt, int lun)
13954 13957 {
13955 13958 int target;
13956 13959 char *nodename = NULL;
13957 13960 char **compatible = NULL;
13958 13961 int ncompatible = 0;
13959 13962 int mdi_rtn = MDI_FAILURE;
13960 13963 int rval = DDI_FAILURE;
13961 13964 char *old_guid = NULL;
13962 13965 mptsas_t *mpt = DIP2MPT(pdip);
13963 13966 char *lun_addr = NULL;
13964 13967 char *wwn_str = NULL;
13965 13968 char *attached_wwn_str = NULL;
13966 13969 char *component = NULL;
13967 13970 uint8_t phy = 0xFF;
13968 13971 uint64_t sas_wwn;
13969 13972 int64_t lun64 = 0;
13970 13973 uint32_t devinfo;
13971 13974 uint16_t dev_hdl;
13972 13975 uint16_t pdev_hdl;
13973 13976 uint64_t dev_sas_wwn;
13974 13977 uint64_t pdev_sas_wwn;
13975 13978 uint32_t pdev_info;
13976 13979 uint8_t physport;
13977 13980 uint8_t phy_id;
13978 13981 uint32_t page_address;
13979 13982 uint16_t bay_num, enclosure;
13980 13983 char pdev_wwn_str[MPTSAS_WWN_STRLEN];
13981 13984 uint32_t dev_info;
13982 13985
13983 13986 mutex_enter(&mpt->m_mutex);
13984 13987 target = ptgt->m_devhdl;
13985 13988 sas_wwn = ptgt->m_addr.mta_wwn;
13986 13989 devinfo = ptgt->m_deviceinfo;
13987 13990 phy = ptgt->m_phynum;
13988 13991 mutex_exit(&mpt->m_mutex);
13989 13992
13990 13993 if (sas_wwn) {
13991 13994 *pip = mptsas_find_path_addr(pdip, sas_wwn, lun);
13992 13995 } else {
13993 13996 *pip = mptsas_find_path_phy(pdip, phy);
13994 13997 }
13995 13998
13996 13999 if (*pip != NULL) {
13997 14000 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
13998 14001 ASSERT(*lun_dip != NULL);
13999 14002 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14000 14003 (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14001 14004 MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14002 14005 if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14003 14006 /*
14004 14007 * Same path back online again.
14005 14008 */
14006 14009 (void) ddi_prop_free(old_guid);
14007 14010 if ((!MDI_PI_IS_ONLINE(*pip)) &&
14008 14011 (!MDI_PI_IS_STANDBY(*pip)) &&
14009 14012 (ptgt->m_tgt_unconfigured == 0)) {
14010 14013 rval = mdi_pi_online(*pip, 0);
14011 14014 mutex_enter(&mpt->m_mutex);
14012 14015 ptgt->m_led_status = 0;
14013 14016 (void) mptsas_flush_led_status(mpt,
14014 14017 ptgt);
14015 14018 mutex_exit(&mpt->m_mutex);
14016 14019 } else {
14017 14020 rval = DDI_SUCCESS;
14018 14021 }
14019 14022 if (rval != DDI_SUCCESS) {
14020 14023 mptsas_log(mpt, CE_WARN, "path:target: "
14021 14024 "%x, lun:%x online failed!", target,
14022 14025 lun);
14023 14026 *pip = NULL;
14024 14027 *lun_dip = NULL;
14025 14028 }
14026 14029 return (rval);
14027 14030 } else {
14028 14031 /*
14029 14032 * The GUID of the LUN has changed which maybe
14030 14033 * because customer mapped another volume to the
14031 14034 * same LUN.
14032 14035 */
14033 14036 mptsas_log(mpt, CE_WARN, "The GUID of the "
14034 14037 "target:%x, lun:%x was changed, maybe "
14035 14038 "because someone mapped another volume "
14036 14039 "to the same LUN", target, lun);
14037 14040 (void) ddi_prop_free(old_guid);
14038 14041 if (!MDI_PI_IS_OFFLINE(*pip)) {
14039 14042 rval = mdi_pi_offline(*pip, 0);
14040 14043 if (rval != MDI_SUCCESS) {
14041 14044 mptsas_log(mpt, CE_WARN, "path:"
14042 14045 "target:%x, lun:%x offline "
14043 14046 "failed!", target, lun);
14044 14047 *pip = NULL;
14045 14048 *lun_dip = NULL;
14046 14049 return (DDI_FAILURE);
14047 14050 }
14048 14051 }
14049 14052 if (mdi_pi_free(*pip, 0) != MDI_SUCCESS) {
14050 14053 mptsas_log(mpt, CE_WARN, "path:target:"
14051 14054 "%x, lun:%x free failed!", target,
14052 14055 lun);
14053 14056 *pip = NULL;
14054 14057 *lun_dip = NULL;
14055 14058 return (DDI_FAILURE);
14056 14059 }
14057 14060 }
14058 14061 } else {
14059 14062 mptsas_log(mpt, CE_WARN, "Can't get client-guid "
14060 14063 "property for path:target:%x, lun:%x", target, lun);
14061 14064 *pip = NULL;
14062 14065 *lun_dip = NULL;
14063 14066 return (DDI_FAILURE);
14064 14067 }
14065 14068 }
14066 14069 scsi_hba_nodename_compatible_get(inq, NULL,
14067 14070 inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
14068 14071
14069 14072 /*
14070 14073 * if nodename can't be determined then print a message and skip it
14071 14074 */
14072 14075 if (nodename == NULL) {
14073 14076 mptsas_log(mpt, CE_WARN, "mptsas driver found no compatible "
14074 14077 "driver for target%d lun %d dtype:0x%02x", target, lun,
14075 14078 inq->inq_dtype);
14076 14079 return (DDI_FAILURE);
14077 14080 }
14078 14081
14079 14082 wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
14080 14083 /* The property is needed by MPAPI */
14081 14084 (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
14082 14085
14083 14086 lun_addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14084 14087 if (guid) {
14085 14088 (void) sprintf(lun_addr, "w%s,%x", wwn_str, lun);
14086 14089 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14087 14090 } else {
14088 14091 (void) sprintf(lun_addr, "p%x,%x", phy, lun);
14089 14092 (void) sprintf(wwn_str, "p%x", phy);
14090 14093 }
14091 14094
14092 14095 mdi_rtn = mdi_pi_alloc_compatible(pdip, nodename,
14093 14096 guid, lun_addr, compatible, ncompatible,
14094 14097 0, pip);
14095 14098 if (mdi_rtn == MDI_SUCCESS) {
14096 14099
14097 14100 if (mdi_prop_update_string(*pip, MDI_GUID,
14098 14101 guid) != DDI_SUCCESS) {
14099 14102 mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14100 14103 "create prop for target %d lun %d (MDI_GUID)",
14101 14104 target, lun);
14102 14105 mdi_rtn = MDI_FAILURE;
14103 14106 goto virt_create_done;
14104 14107 }
14105 14108
14106 14109 if (mdi_prop_update_int(*pip, LUN_PROP,
14107 14110 lun) != DDI_SUCCESS) {
14108 14111 mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14109 14112 "create prop for target %d lun %d (LUN_PROP)",
14110 14113 target, lun);
14111 14114 mdi_rtn = MDI_FAILURE;
14112 14115 goto virt_create_done;
14113 14116 }
14114 14117 lun64 = (int64_t)lun;
14115 14118 if (mdi_prop_update_int64(*pip, LUN64_PROP,
14116 14119 lun64) != DDI_SUCCESS) {
14117 14120 mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14118 14121 "create prop for target %d (LUN64_PROP)",
14119 14122 target);
14120 14123 mdi_rtn = MDI_FAILURE;
14121 14124 goto virt_create_done;
14122 14125 }
14123 14126 if (mdi_prop_update_string_array(*pip, "compatible",
14124 14127 compatible, ncompatible) !=
14125 14128 DDI_PROP_SUCCESS) {
14126 14129 mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14127 14130 "create prop for target %d lun %d (COMPATIBLE)",
14128 14131 target, lun);
14129 14132 mdi_rtn = MDI_FAILURE;
14130 14133 goto virt_create_done;
14131 14134 }
14132 14135 if (sas_wwn && (mdi_prop_update_string(*pip,
14133 14136 SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS)) {
14134 14137 mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14135 14138 "create prop for target %d lun %d "
14136 14139 "(target-port)", target, lun);
14137 14140 mdi_rtn = MDI_FAILURE;
14138 14141 goto virt_create_done;
14139 14142 } else if ((sas_wwn == 0) && (mdi_prop_update_int(*pip,
14140 14143 "sata-phy", phy) != DDI_PROP_SUCCESS)) {
14141 14144 /*
14142 14145 * Direct attached SATA device without DeviceName
14143 14146 */
14144 14147 mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14145 14148 "create prop for SAS target %d lun %d "
14146 14149 "(sata-phy)", target, lun);
14147 14150 mdi_rtn = MDI_FAILURE;
14148 14151 goto virt_create_done;
14149 14152 }
14150 14153 mutex_enter(&mpt->m_mutex);
14151 14154
14152 14155 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14153 14156 MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14154 14157 (uint32_t)ptgt->m_devhdl;
14155 14158 rval = mptsas_get_sas_device_page0(mpt, page_address,
14156 14159 &dev_hdl, &dev_sas_wwn, &dev_info, &physport,
14157 14160 &phy_id, &pdev_hdl, &bay_num, &enclosure);
14158 14161 if (rval != DDI_SUCCESS) {
14159 14162 mutex_exit(&mpt->m_mutex);
14160 14163 mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14161 14164 "parent device for handle %d", page_address);
14162 14165 mdi_rtn = MDI_FAILURE;
14163 14166 goto virt_create_done;
14164 14167 }
14165 14168
14166 14169 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14167 14170 MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
14168 14171 rval = mptsas_get_sas_device_page0(mpt, page_address,
14169 14172 &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
14170 14173 &phy_id, &pdev_hdl, &bay_num, &enclosure);
14171 14174 if (rval != DDI_SUCCESS) {
14172 14175 mutex_exit(&mpt->m_mutex);
14173 14176 mptsas_log(mpt, CE_WARN, "mptsas unable to get"
14174 14177 "device info for handle %d", page_address);
14175 14178 mdi_rtn = MDI_FAILURE;
14176 14179 goto virt_create_done;
14177 14180 }
14178 14181
14179 14182 mutex_exit(&mpt->m_mutex);
14180 14183
14181 14184 /*
14182 14185 * If this device direct attached to the controller
14183 14186 * set the attached-port to the base wwid
14184 14187 */
14185 14188 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14186 14189 != DEVINFO_DIRECT_ATTACHED) {
14187 14190 (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14188 14191 pdev_sas_wwn);
14189 14192 } else {
14190 14193 /*
14191 14194 * Update the iport's attached-port to guid
14192 14195 */
14193 14196 if (sas_wwn == 0) {
14194 14197 (void) sprintf(wwn_str, "p%x", phy);
14195 14198 } else {
14196 14199 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14197 14200 }
14198 14201 if (ddi_prop_update_string(DDI_DEV_T_NONE,
14199 14202 pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14200 14203 DDI_PROP_SUCCESS) {
14201 14204 mptsas_log(mpt, CE_WARN,
14202 14205 "mptsas unable to create "
14203 14206 "property for iport target-port"
14204 14207 " %s (sas_wwn)",
14205 14208 wwn_str);
14206 14209 mdi_rtn = MDI_FAILURE;
14207 14210 goto virt_create_done;
14208 14211 }
14209 14212
14210 14213 (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14211 14214 mpt->un.m_base_wwid);
14212 14215 }
14213 14216
14214 14217 if (mdi_prop_update_string(*pip,
14215 14218 SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
14216 14219 DDI_PROP_SUCCESS) {
14217 14220 mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14218 14221 "property for iport attached-port %s (sas_wwn)",
14219 14222 attached_wwn_str);
14220 14223 mdi_rtn = MDI_FAILURE;
14221 14224 goto virt_create_done;
14222 14225 }
14223 14226
14224 14227
14225 14228 if (inq->inq_dtype == 0) {
14226 14229 component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
14227 14230 /*
14228 14231 * set obp path for pathinfo
14229 14232 */
14230 14233 (void) snprintf(component, MAXPATHLEN,
14231 14234 "disk@%s", lun_addr);
14232 14235
14233 14236 if (mdi_pi_pathname_obp_set(*pip, component) !=
14234 14237 DDI_SUCCESS) {
14235 14238 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
14236 14239 "unable to set obp-path for object %s",
14237 14240 component);
14238 14241 mdi_rtn = MDI_FAILURE;
14239 14242 goto virt_create_done;
14240 14243 }
14241 14244 }
14242 14245
14243 14246 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14244 14247 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14245 14248 MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14246 14249 if ((ndi_prop_update_int(DDI_DEV_T_NONE, *lun_dip,
14247 14250 "pm-capable", 1)) !=
14248 14251 DDI_PROP_SUCCESS) {
14249 14252 mptsas_log(mpt, CE_WARN, "mptsas driver"
14250 14253 "failed to create pm-capable "
14251 14254 "property, target %d", target);
14252 14255 mdi_rtn = MDI_FAILURE;
14253 14256 goto virt_create_done;
14254 14257 }
14255 14258 }
14256 14259 /*
14257 14260 * Create the phy-num property
14258 14261 */
14259 14262 if (mdi_prop_update_int(*pip, "phy-num",
14260 14263 ptgt->m_phynum) != DDI_SUCCESS) {
14261 14264 mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14262 14265 "create phy-num property for target %d lun %d",
14263 14266 target, lun);
14264 14267 mdi_rtn = MDI_FAILURE;
14265 14268 goto virt_create_done;
14266 14269 }
14267 14270 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
14268 14271 mdi_rtn = mdi_pi_online(*pip, 0);
14269 14272 if (mdi_rtn == MDI_SUCCESS) {
14270 14273 mutex_enter(&mpt->m_mutex);
14271 14274 ptgt->m_led_status = 0;
14272 14275 (void) mptsas_flush_led_status(mpt, ptgt);
14273 14276 mutex_exit(&mpt->m_mutex);
14274 14277 }
14275 14278 if (mdi_rtn == MDI_NOT_SUPPORTED) {
14276 14279 mdi_rtn = MDI_FAILURE;
14277 14280 }
14278 14281 virt_create_done:
14279 14282 if (*pip && mdi_rtn != MDI_SUCCESS) {
14280 14283 (void) mdi_pi_free(*pip, 0);
14281 14284 *pip = NULL;
14282 14285 *lun_dip = NULL;
14283 14286 }
14284 14287 }
14285 14288
14286 14289 scsi_hba_nodename_compatible_free(nodename, compatible);
14287 14290 if (lun_addr != NULL) {
14288 14291 kmem_free(lun_addr, SCSI_MAXNAMELEN);
14289 14292 }
14290 14293 if (wwn_str != NULL) {
14291 14294 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
14292 14295 }
14293 14296 if (component != NULL) {
14294 14297 kmem_free(component, MAXPATHLEN);
14295 14298 }
14296 14299
14297 14300 return ((mdi_rtn == MDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14298 14301 }
14299 14302
14300 14303 static int
14301 14304 mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *inq,
14302 14305 char *guid, dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
14303 14306 {
14304 14307 int target;
14305 14308 int rval;
14306 14309 int ndi_rtn = NDI_FAILURE;
14307 14310 uint64_t be_sas_wwn;
14308 14311 char *nodename = NULL;
14309 14312 char **compatible = NULL;
14310 14313 int ncompatible = 0;
14311 14314 int instance = 0;
14312 14315 mptsas_t *mpt = DIP2MPT(pdip);
14313 14316 char *wwn_str = NULL;
14314 14317 char *component = NULL;
14315 14318 char *attached_wwn_str = NULL;
14316 14319 uint8_t phy = 0xFF;
14317 14320 uint64_t sas_wwn;
14318 14321 uint32_t devinfo;
14319 14322 uint16_t dev_hdl;
14320 14323 uint16_t pdev_hdl;
14321 14324 uint64_t pdev_sas_wwn;
14322 14325 uint64_t dev_sas_wwn;
14323 14326 uint32_t pdev_info;
14324 14327 uint8_t physport;
14325 14328 uint8_t phy_id;
14326 14329 uint32_t page_address;
14327 14330 uint16_t bay_num, enclosure;
14328 14331 char pdev_wwn_str[MPTSAS_WWN_STRLEN];
14329 14332 uint32_t dev_info;
14330 14333 int64_t lun64 = 0;
14331 14334
14332 14335 mutex_enter(&mpt->m_mutex);
14333 14336 target = ptgt->m_devhdl;
14334 14337 sas_wwn = ptgt->m_addr.mta_wwn;
14335 14338 devinfo = ptgt->m_deviceinfo;
14336 14339 phy = ptgt->m_phynum;
14337 14340 mutex_exit(&mpt->m_mutex);
14338 14341
14339 14342 /*
14340 14343 * generate compatible property with binding-set "mpt"
14341 14344 */
14342 14345 scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
14343 14346 &nodename, &compatible, &ncompatible);
14344 14347
14345 14348 /*
14346 14349 * if nodename can't be determined then print a message and skip it
14347 14350 */
14348 14351 if (nodename == NULL) {
14349 14352 mptsas_log(mpt, CE_WARN, "mptsas found no compatible driver "
14350 14353 "for target %d lun %d", target, lun);
14351 14354 return (DDI_FAILURE);
14352 14355 }
14353 14356
14354 14357 ndi_rtn = ndi_devi_alloc(pdip, nodename,
14355 14358 DEVI_SID_NODEID, lun_dip);
14356 14359
14357 14360 /*
14358 14361 * if lun alloc success, set props
14359 14362 */
14360 14363 if (ndi_rtn == NDI_SUCCESS) {
14361 14364
14362 14365 if (ndi_prop_update_int(DDI_DEV_T_NONE,
14363 14366 *lun_dip, LUN_PROP, lun) !=
14364 14367 DDI_PROP_SUCCESS) {
14365 14368 mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14366 14369 "property for target %d lun %d (LUN_PROP)",
14367 14370 target, lun);
14368 14371 ndi_rtn = NDI_FAILURE;
14369 14372 goto phys_create_done;
14370 14373 }
14371 14374
14372 14375 lun64 = (int64_t)lun;
14373 14376 if (ndi_prop_update_int64(DDI_DEV_T_NONE,
14374 14377 *lun_dip, LUN64_PROP, lun64) !=
14375 14378 DDI_PROP_SUCCESS) {
14376 14379 mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14377 14380 "property for target %d lun64 %d (LUN64_PROP)",
14378 14381 target, lun);
14379 14382 ndi_rtn = NDI_FAILURE;
14380 14383 goto phys_create_done;
14381 14384 }
14382 14385 if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
14383 14386 *lun_dip, "compatible", compatible, ncompatible)
14384 14387 != DDI_PROP_SUCCESS) {
14385 14388 mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14386 14389 "property for target %d lun %d (COMPATIBLE)",
14387 14390 target, lun);
14388 14391 ndi_rtn = NDI_FAILURE;
14389 14392 goto phys_create_done;
14390 14393 }
14391 14394
14392 14395 /*
14393 14396 * We need the SAS WWN for non-multipath devices, so
14394 14397 * we'll use the same property as that multipathing
14395 14398 * devices need to present for MPAPI. If we don't have
14396 14399 * a WWN (e.g. parallel SCSI), don't create the prop.
14397 14400 */
14398 14401 wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
14399 14402 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14400 14403 if (sas_wwn && ndi_prop_update_string(DDI_DEV_T_NONE,
14401 14404 *lun_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str)
14402 14405 != DDI_PROP_SUCCESS) {
14403 14406 mptsas_log(mpt, CE_WARN, "mptsas unable to "
14404 14407 "create property for SAS target %d lun %d "
14405 14408 "(target-port)", target, lun);
14406 14409 ndi_rtn = NDI_FAILURE;
14407 14410 goto phys_create_done;
14408 14411 }
14409 14412
14410 14413 be_sas_wwn = BE_64(sas_wwn);
14411 14414 if (sas_wwn && ndi_prop_update_byte_array(
14412 14415 DDI_DEV_T_NONE, *lun_dip, "port-wwn",
14413 14416 (uchar_t *)&be_sas_wwn, 8) != DDI_PROP_SUCCESS) {
14414 14417 mptsas_log(mpt, CE_WARN, "mptsas unable to "
14415 14418 "create property for SAS target %d lun %d "
14416 14419 "(port-wwn)", target, lun);
14417 14420 ndi_rtn = NDI_FAILURE;
14418 14421 goto phys_create_done;
14419 14422 } else if ((sas_wwn == 0) && (ndi_prop_update_int(
14420 14423 DDI_DEV_T_NONE, *lun_dip, "sata-phy", phy) !=
14421 14424 DDI_PROP_SUCCESS)) {
14422 14425 /*
14423 14426 * Direct attached SATA device without DeviceName
14424 14427 */
14425 14428 mptsas_log(mpt, CE_WARN, "mptsas unable to "
14426 14429 "create property for SAS target %d lun %d "
14427 14430 "(sata-phy)", target, lun);
14428 14431 ndi_rtn = NDI_FAILURE;
14429 14432 goto phys_create_done;
14430 14433 }
14431 14434
14432 14435 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14433 14436 *lun_dip, SAS_PROP) != DDI_PROP_SUCCESS) {
14434 14437 mptsas_log(mpt, CE_WARN, "mptsas unable to"
14435 14438 "create property for SAS target %d lun %d"
14436 14439 " (SAS_PROP)", target, lun);
14437 14440 ndi_rtn = NDI_FAILURE;
14438 14441 goto phys_create_done;
14439 14442 }
14440 14443 if (guid && (ndi_prop_update_string(DDI_DEV_T_NONE,
14441 14444 *lun_dip, NDI_GUID, guid) != DDI_SUCCESS)) {
14442 14445 mptsas_log(mpt, CE_WARN, "mptsas unable "
14443 14446 "to create guid property for target %d "
14444 14447 "lun %d", target, lun);
14445 14448 ndi_rtn = NDI_FAILURE;
14446 14449 goto phys_create_done;
14447 14450 }
14448 14451
14449 14452 /*
14450 14453 * The following code is to set properties for SM-HBA support,
14451 14454 * it doesn't apply to RAID volumes
14452 14455 */
14453 14456 if (ptgt->m_addr.mta_phymask == 0)
14454 14457 goto phys_raid_lun;
14455 14458
14456 14459 mutex_enter(&mpt->m_mutex);
14457 14460
14458 14461 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14459 14462 MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14460 14463 (uint32_t)ptgt->m_devhdl;
14461 14464 rval = mptsas_get_sas_device_page0(mpt, page_address,
14462 14465 &dev_hdl, &dev_sas_wwn, &dev_info,
14463 14466 &physport, &phy_id, &pdev_hdl,
14464 14467 &bay_num, &enclosure);
14465 14468 if (rval != DDI_SUCCESS) {
14466 14469 mutex_exit(&mpt->m_mutex);
14467 14470 mptsas_log(mpt, CE_WARN, "mptsas unable to get"
14468 14471 "parent device for handle %d.", page_address);
14469 14472 ndi_rtn = NDI_FAILURE;
14470 14473 goto phys_create_done;
14471 14474 }
14472 14475
14473 14476 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14474 14477 MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
14475 14478 rval = mptsas_get_sas_device_page0(mpt, page_address,
14476 14479 &dev_hdl, &pdev_sas_wwn, &pdev_info,
14477 14480 &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
14478 14481 if (rval != DDI_SUCCESS) {
14479 14482 mutex_exit(&mpt->m_mutex);
14480 14483 mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14481 14484 "device for handle %d.", page_address);
14482 14485 ndi_rtn = NDI_FAILURE;
14483 14486 goto phys_create_done;
14484 14487 }
14485 14488
14486 14489 mutex_exit(&mpt->m_mutex);
14487 14490
14488 14491 /*
14489 14492 * If this device direct attached to the controller
14490 14493 * set the attached-port to the base wwid
14491 14494 */
14492 14495 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14493 14496 != DEVINFO_DIRECT_ATTACHED) {
14494 14497 (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14495 14498 pdev_sas_wwn);
14496 14499 } else {
14497 14500 /*
14498 14501 * Update the iport's attached-port to guid
14499 14502 */
14500 14503 if (sas_wwn == 0) {
14501 14504 (void) sprintf(wwn_str, "p%x", phy);
14502 14505 } else {
14503 14506 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14504 14507 }
14505 14508 if (ddi_prop_update_string(DDI_DEV_T_NONE,
14506 14509 pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14507 14510 DDI_PROP_SUCCESS) {
14508 14511 mptsas_log(mpt, CE_WARN,
14509 14512 "mptsas unable to create "
14510 14513 "property for iport target-port"
14511 14514 " %s (sas_wwn)",
14512 14515 wwn_str);
14513 14516 ndi_rtn = NDI_FAILURE;
14514 14517 goto phys_create_done;
14515 14518 }
14516 14519
14517 14520 (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14518 14521 mpt->un.m_base_wwid);
14519 14522 }
14520 14523
14521 14524 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14522 14525 *lun_dip, SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
14523 14526 DDI_PROP_SUCCESS) {
14524 14527 mptsas_log(mpt, CE_WARN,
14525 14528 "mptsas unable to create "
14526 14529 "property for iport attached-port %s (sas_wwn)",
14527 14530 attached_wwn_str);
14528 14531 ndi_rtn = NDI_FAILURE;
14529 14532 goto phys_create_done;
14530 14533 }
14531 14534
14532 14535 if (IS_SATA_DEVICE(dev_info)) {
14533 14536 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14534 14537 *lun_dip, MPTSAS_VARIANT, "sata") !=
14535 14538 DDI_PROP_SUCCESS) {
14536 14539 mptsas_log(mpt, CE_WARN,
14537 14540 "mptsas unable to create "
14538 14541 "property for device variant ");
14539 14542 ndi_rtn = NDI_FAILURE;
14540 14543 goto phys_create_done;
14541 14544 }
14542 14545 }
14543 14546
14544 14547 if (IS_ATAPI_DEVICE(dev_info)) {
14545 14548 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14546 14549 *lun_dip, MPTSAS_VARIANT, "atapi") !=
14547 14550 DDI_PROP_SUCCESS) {
14548 14551 mptsas_log(mpt, CE_WARN,
14549 14552 "mptsas unable to create "
14550 14553 "property for device variant ");
14551 14554 ndi_rtn = NDI_FAILURE;
14552 14555 goto phys_create_done;
14553 14556 }
14554 14557 }
14555 14558
14556 14559 phys_raid_lun:
14557 14560 /*
14558 14561 * if this is a SAS controller, and the target is a SATA
14559 14562 * drive, set the 'pm-capable' property for sd and if on
14560 14563 * an OPL platform, also check if this is an ATAPI
14561 14564 * device.
14562 14565 */
14563 14566 instance = ddi_get_instance(mpt->m_dip);
14564 14567 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14565 14568 MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14566 14569 NDBG2(("mptsas%d: creating pm-capable property, "
14567 14570 "target %d", instance, target));
14568 14571
14569 14572 if ((ndi_prop_update_int(DDI_DEV_T_NONE,
14570 14573 *lun_dip, "pm-capable", 1)) !=
14571 14574 DDI_PROP_SUCCESS) {
14572 14575 mptsas_log(mpt, CE_WARN, "mptsas "
14573 14576 "failed to create pm-capable "
14574 14577 "property, target %d", target);
14575 14578 ndi_rtn = NDI_FAILURE;
14576 14579 goto phys_create_done;
14577 14580 }
14578 14581
14579 14582 }
14580 14583
14581 14584 if ((inq->inq_dtype == 0) || (inq->inq_dtype == 5)) {
14582 14585 /*
14583 14586 * add 'obp-path' properties for devinfo
14584 14587 */
14585 14588 bzero(wwn_str, sizeof (wwn_str));
14586 14589 (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
14587 14590 component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
14588 14591 if (guid) {
14589 14592 (void) snprintf(component, MAXPATHLEN,
14590 14593 "disk@w%s,%x", wwn_str, lun);
14591 14594 } else {
14592 14595 (void) snprintf(component, MAXPATHLEN,
14593 14596 "disk@p%x,%x", phy, lun);
14594 14597 }
14595 14598 if (ddi_pathname_obp_set(*lun_dip, component)
14596 14599 != DDI_SUCCESS) {
14597 14600 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
14598 14601 "unable to set obp-path for SAS "
14599 14602 "object %s", component);
14600 14603 ndi_rtn = NDI_FAILURE;
14601 14604 goto phys_create_done;
14602 14605 }
14603 14606 }
14604 14607 /*
14605 14608 * Create the phy-num property for non-raid disk
14606 14609 */
14607 14610 if (ptgt->m_addr.mta_phymask != 0) {
14608 14611 if (ndi_prop_update_int(DDI_DEV_T_NONE,
14609 14612 *lun_dip, "phy-num", ptgt->m_phynum) !=
14610 14613 DDI_PROP_SUCCESS) {
14611 14614 mptsas_log(mpt, CE_WARN, "mptsas driver "
14612 14615 "failed to create phy-num property for "
14613 14616 "target %d", target);
14614 14617 ndi_rtn = NDI_FAILURE;
14615 14618 goto phys_create_done;
14616 14619 }
14617 14620 }
14618 14621 phys_create_done:
14619 14622 /*
14620 14623 * If props were setup ok, online the lun
14621 14624 */
14622 14625 if (ndi_rtn == NDI_SUCCESS) {
14623 14626 /*
14624 14627 * Try to online the new node
14625 14628 */
14626 14629 ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
14627 14630 }
14628 14631 if (ndi_rtn == NDI_SUCCESS) {
14629 14632 mutex_enter(&mpt->m_mutex);
14630 14633 ptgt->m_led_status = 0;
14631 14634 (void) mptsas_flush_led_status(mpt, ptgt);
14632 14635 mutex_exit(&mpt->m_mutex);
14633 14636 }
14634 14637
14635 14638 /*
14636 14639 * If success set rtn flag, else unwire alloc'd lun
14637 14640 */
14638 14641 if (ndi_rtn != NDI_SUCCESS) {
14639 14642 NDBG12(("mptsas driver unable to online "
14640 14643 "target %d lun %d", target, lun));
14641 14644 ndi_prop_remove_all(*lun_dip);
14642 14645 (void) ndi_devi_free(*lun_dip);
14643 14646 *lun_dip = NULL;
14644 14647 }
14645 14648 }
14646 14649
14647 14650 scsi_hba_nodename_compatible_free(nodename, compatible);
14648 14651
14649 14652 if (wwn_str != NULL) {
14650 14653 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
14651 14654 }
14652 14655 if (component != NULL) {
14653 14656 kmem_free(component, MAXPATHLEN);
14654 14657 }
14655 14658
14656 14659
14657 14660 return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14658 14661 }
14659 14662
14660 14663 static int
14661 14664 mptsas_probe_smp(dev_info_t *pdip, uint64_t wwn)
14662 14665 {
14663 14666 mptsas_t *mpt = DIP2MPT(pdip);
14664 14667 struct smp_device smp_sd;
14665 14668
14666 14669 /* XXX An HBA driver should not be allocating an smp_device. */
14667 14670 bzero(&smp_sd, sizeof (struct smp_device));
14668 14671 smp_sd.smp_sd_address.smp_a_hba_tran = mpt->m_smptran;
14669 14672 bcopy(&wwn, smp_sd.smp_sd_address.smp_a_wwn, SAS_WWN_BYTE_SIZE);
14670 14673
14671 14674 if (smp_probe(&smp_sd) != DDI_PROBE_SUCCESS)
14672 14675 return (NDI_FAILURE);
14673 14676 return (NDI_SUCCESS);
14674 14677 }
14675 14678
14676 14679 static int
14677 14680 mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn, dev_info_t **smp_dip)
14678 14681 {
14679 14682 mptsas_t *mpt = DIP2MPT(pdip);
14680 14683 mptsas_smp_t *psmp = NULL;
14681 14684 int rval;
14682 14685 int phymask;
14683 14686
14684 14687 /*
14685 14688 * Get the physical port associated to the iport
14686 14689 * PHYMASK TODO
14687 14690 */
14688 14691 phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14689 14692 "phymask", 0);
14690 14693 /*
14691 14694 * Find the smp node in hash table with specified sas address and
14692 14695 * physical port
14693 14696 */
14694 14697 psmp = mptsas_wwid_to_psmp(mpt, phymask, sas_wwn);
14695 14698 if (psmp == NULL) {
14696 14699 return (DDI_FAILURE);
14697 14700 }
14698 14701
14699 14702 rval = mptsas_online_smp(pdip, psmp, smp_dip);
14700 14703
14701 14704 return (rval);
14702 14705 }
14703 14706
14704 14707 static int
14705 14708 mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
14706 14709 dev_info_t **smp_dip)
14707 14710 {
14708 14711 char wwn_str[MPTSAS_WWN_STRLEN];
14709 14712 char attached_wwn_str[MPTSAS_WWN_STRLEN];
14710 14713 int ndi_rtn = NDI_FAILURE;
14711 14714 int rval = 0;
14712 14715 mptsas_smp_t dev_info;
14713 14716 uint32_t page_address;
14714 14717 mptsas_t *mpt = DIP2MPT(pdip);
14715 14718 uint16_t dev_hdl;
14716 14719 uint64_t sas_wwn;
14717 14720 uint64_t smp_sas_wwn;
14718 14721 uint8_t physport;
14719 14722 uint8_t phy_id;
14720 14723 uint16_t pdev_hdl;
14721 14724 uint8_t numphys = 0;
14722 14725 uint16_t i = 0;
14723 14726 char phymask[MPTSAS_MAX_PHYS];
14724 14727 char *iport = NULL;
14725 14728 mptsas_phymask_t phy_mask = 0;
14726 14729 uint16_t attached_devhdl;
14727 14730 uint16_t bay_num, enclosure;
14728 14731
14729 14732 (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
14730 14733
14731 14734 /*
14732 14735 * Probe smp device, prevent the node of removed device from being
14733 14736 * configured succesfully
14734 14737 */
14735 14738 if (mptsas_probe_smp(pdip, smp_node->m_addr.mta_wwn) != NDI_SUCCESS) {
14736 14739 return (DDI_FAILURE);
14737 14740 }
14738 14741
14739 14742 if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
14740 14743 return (DDI_SUCCESS);
14741 14744 }
14742 14745
14743 14746 ndi_rtn = ndi_devi_alloc(pdip, "smp", DEVI_SID_NODEID, smp_dip);
14744 14747
14745 14748 /*
14746 14749 * if lun alloc success, set props
14747 14750 */
14748 14751 if (ndi_rtn == NDI_SUCCESS) {
14749 14752 /*
14750 14753 * Set the flavor of the child to be SMP flavored
14751 14754 */
14752 14755 ndi_flavor_set(*smp_dip, SCSA_FLAVOR_SMP);
14753 14756
14754 14757 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14755 14758 *smp_dip, SMP_WWN, wwn_str) !=
14756 14759 DDI_PROP_SUCCESS) {
14757 14760 mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14758 14761 "property for smp device %s (sas_wwn)",
14759 14762 wwn_str);
14760 14763 ndi_rtn = NDI_FAILURE;
14761 14764 goto smp_create_done;
14762 14765 }
14763 14766 (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_addr.mta_wwn);
14764 14767 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14765 14768 *smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
14766 14769 DDI_PROP_SUCCESS) {
14767 14770 mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14768 14771 "property for iport target-port %s (sas_wwn)",
14769 14772 wwn_str);
14770 14773 ndi_rtn = NDI_FAILURE;
14771 14774 goto smp_create_done;
14772 14775 }
14773 14776
14774 14777 mutex_enter(&mpt->m_mutex);
14775 14778
14776 14779 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
14777 14780 MPI2_SAS_EXPAND_PGAD_FORM_MASK) | smp_node->m_devhdl;
14778 14781 rval = mptsas_get_sas_expander_page0(mpt, page_address,
14779 14782 &dev_info);
14780 14783 if (rval != DDI_SUCCESS) {
14781 14784 mutex_exit(&mpt->m_mutex);
14782 14785 mptsas_log(mpt, CE_WARN,
14783 14786 "mptsas unable to get expander "
14784 14787 "parent device info for %x", page_address);
14785 14788 ndi_rtn = NDI_FAILURE;
14786 14789 goto smp_create_done;
14787 14790 }
14788 14791
14789 14792 smp_node->m_pdevhdl = dev_info.m_pdevhdl;
14790 14793 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14791 14794 MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14792 14795 (uint32_t)dev_info.m_pdevhdl;
14793 14796 rval = mptsas_get_sas_device_page0(mpt, page_address,
14794 14797 &dev_hdl, &sas_wwn, &smp_node->m_pdevinfo,
14795 14798 &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
14796 14799 if (rval != DDI_SUCCESS) {
14797 14800 mutex_exit(&mpt->m_mutex);
14798 14801 mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14799 14802 "device info for %x", page_address);
14800 14803 ndi_rtn = NDI_FAILURE;
14801 14804 goto smp_create_done;
14802 14805 }
14803 14806
14804 14807 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14805 14808 MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14806 14809 (uint32_t)dev_info.m_devhdl;
14807 14810 rval = mptsas_get_sas_device_page0(mpt, page_address,
14808 14811 &dev_hdl, &smp_sas_wwn, &smp_node->m_deviceinfo,
14809 14812 &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
14810 14813 if (rval != DDI_SUCCESS) {
14811 14814 mutex_exit(&mpt->m_mutex);
14812 14815 mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14813 14816 "device info for %x", page_address);
14814 14817 ndi_rtn = NDI_FAILURE;
14815 14818 goto smp_create_done;
14816 14819 }
14817 14820 mutex_exit(&mpt->m_mutex);
14818 14821
14819 14822 /*
14820 14823 * If this smp direct attached to the controller
14821 14824 * set the attached-port to the base wwid
14822 14825 */
14823 14826 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14824 14827 != DEVINFO_DIRECT_ATTACHED) {
14825 14828 (void) sprintf(attached_wwn_str, "w%016"PRIx64,
14826 14829 sas_wwn);
14827 14830 } else {
14828 14831 (void) sprintf(attached_wwn_str, "w%016"PRIx64,
14829 14832 mpt->un.m_base_wwid);
14830 14833 }
14831 14834
14832 14835 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14833 14836 *smp_dip, SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwn_str) !=
14834 14837 DDI_PROP_SUCCESS) {
14835 14838 mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14836 14839 "property for smp attached-port %s (sas_wwn)",
14837 14840 attached_wwn_str);
14838 14841 ndi_rtn = NDI_FAILURE;
14839 14842 goto smp_create_done;
14840 14843 }
14841 14844
14842 14845 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14843 14846 *smp_dip, SMP_PROP) != DDI_PROP_SUCCESS) {
14844 14847 mptsas_log(mpt, CE_WARN, "mptsas unable to "
14845 14848 "create property for SMP %s (SMP_PROP) ",
14846 14849 wwn_str);
14847 14850 ndi_rtn = NDI_FAILURE;
14848 14851 goto smp_create_done;
14849 14852 }
14850 14853
14851 14854 /*
14852 14855 * check the smp to see whether it direct
14853 14856 * attached to the controller
14854 14857 */
14855 14858 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14856 14859 != DEVINFO_DIRECT_ATTACHED) {
14857 14860 goto smp_create_done;
14858 14861 }
14859 14862 numphys = ddi_prop_get_int(DDI_DEV_T_ANY, pdip,
14860 14863 DDI_PROP_DONTPASS, MPTSAS_NUM_PHYS, -1);
14861 14864 if (numphys > 0) {
14862 14865 goto smp_create_done;
14863 14866 }
14864 14867 /*
14865 14868 * this iport is an old iport, we need to
14866 14869 * reconfig the props for it.
14867 14870 */
14868 14871 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
14869 14872 MPTSAS_VIRTUAL_PORT, 0) !=
14870 14873 DDI_PROP_SUCCESS) {
14871 14874 (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
14872 14875 MPTSAS_VIRTUAL_PORT);
14873 14876 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
14874 14877 "prop update failed");
14875 14878 goto smp_create_done;
14876 14879 }
14877 14880
14878 14881 mutex_enter(&mpt->m_mutex);
14879 14882 numphys = 0;
14880 14883 iport = ddi_get_name_addr(pdip);
14881 14884 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
14882 14885 bzero(phymask, sizeof (phymask));
14883 14886 (void) sprintf(phymask,
14884 14887 "%x", mpt->m_phy_info[i].phy_mask);
14885 14888 if (strcmp(phymask, iport) == 0) {
14886 14889 phy_mask = mpt->m_phy_info[i].phy_mask;
14887 14890 break;
14888 14891 }
14889 14892 }
14890 14893
14891 14894 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
14892 14895 if ((phy_mask >> i) & 0x01) {
14893 14896 numphys++;
14894 14897 }
14895 14898 }
14896 14899 /*
14897 14900 * Update PHY info for smhba
14898 14901 */
14899 14902 if (mptsas_smhba_phy_init(mpt)) {
14900 14903 mutex_exit(&mpt->m_mutex);
14901 14904 mptsas_log(mpt, CE_WARN, "mptsas phy update "
14902 14905 "failed");
14903 14906 goto smp_create_done;
14904 14907 }
14905 14908 mutex_exit(&mpt->m_mutex);
14906 14909
14907 14910 mptsas_smhba_set_all_phy_props(mpt, pdip, numphys, phy_mask,
14908 14911 &attached_devhdl);
14909 14912
14910 14913 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
14911 14914 MPTSAS_NUM_PHYS, numphys) !=
14912 14915 DDI_PROP_SUCCESS) {
14913 14916 (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
14914 14917 MPTSAS_NUM_PHYS);
14915 14918 mptsas_log(mpt, CE_WARN, "mptsas update "
14916 14919 "num phys props failed");
14917 14920 goto smp_create_done;
14918 14921 }
14919 14922 /*
14920 14923 * Add parent's props for SMHBA support
14921 14924 */
14922 14925 if (ddi_prop_update_string(DDI_DEV_T_NONE, pdip,
14923 14926 SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14924 14927 DDI_PROP_SUCCESS) {
14925 14928 (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
14926 14929 SCSI_ADDR_PROP_ATTACHED_PORT);
14927 14930 mptsas_log(mpt, CE_WARN, "mptsas update iport"
14928 14931 "attached-port failed");
14929 14932 goto smp_create_done;
14930 14933 }
14931 14934
14932 14935 smp_create_done:
14933 14936 /*
14934 14937 * If props were setup ok, online the lun
14935 14938 */
14936 14939 if (ndi_rtn == NDI_SUCCESS) {
14937 14940 /*
14938 14941 * Try to online the new node
14939 14942 */
14940 14943 ndi_rtn = ndi_devi_online(*smp_dip, NDI_ONLINE_ATTACH);
14941 14944 }
14942 14945
14943 14946 /*
14944 14947 * If success set rtn flag, else unwire alloc'd lun
14945 14948 */
14946 14949 if (ndi_rtn != NDI_SUCCESS) {
14947 14950 NDBG12(("mptsas unable to online "
14948 14951 "SMP target %s", wwn_str));
14949 14952 ndi_prop_remove_all(*smp_dip);
14950 14953 (void) ndi_devi_free(*smp_dip);
14951 14954 }
14952 14955 }
14953 14956
14954 14957 return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14955 14958 }
14956 14959
14957 14960 /* smp transport routine */
14958 14961 static int mptsas_smp_start(struct smp_pkt *smp_pkt)
14959 14962 {
14960 14963 uint64_t wwn;
14961 14964 Mpi2SmpPassthroughRequest_t req;
14962 14965 Mpi2SmpPassthroughReply_t rep;
14963 14966 uint32_t direction = 0;
14964 14967 mptsas_t *mpt;
14965 14968 int ret;
14966 14969 uint64_t tmp64;
14967 14970
14968 14971 mpt = (mptsas_t *)smp_pkt->smp_pkt_address->
14969 14972 smp_a_hba_tran->smp_tran_hba_private;
14970 14973
14971 14974 bcopy(smp_pkt->smp_pkt_address->smp_a_wwn, &wwn, SAS_WWN_BYTE_SIZE);
14972 14975 /*
14973 14976 * Need to compose a SMP request message
14974 14977 * and call mptsas_do_passthru() function
14975 14978 */
14976 14979 bzero(&req, sizeof (req));
14977 14980 bzero(&rep, sizeof (rep));
14978 14981 req.PassthroughFlags = 0;
14979 14982 req.PhysicalPort = 0xff;
14980 14983 req.ChainOffset = 0;
14981 14984 req.Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
14982 14985
14983 14986 if ((smp_pkt->smp_pkt_reqsize & 0xffff0000ul) != 0) {
14984 14987 smp_pkt->smp_pkt_reason = ERANGE;
14985 14988 return (DDI_FAILURE);
14986 14989 }
14987 14990 req.RequestDataLength = LE_16((uint16_t)(smp_pkt->smp_pkt_reqsize - 4));
14988 14991
14989 14992 req.MsgFlags = 0;
14990 14993 tmp64 = LE_64(wwn);
14991 14994 bcopy(&tmp64, &req.SASAddress, SAS_WWN_BYTE_SIZE);
14992 14995 if (smp_pkt->smp_pkt_rspsize > 0) {
14993 14996 direction |= MPTSAS_PASS_THRU_DIRECTION_READ;
14994 14997 }
14995 14998 if (smp_pkt->smp_pkt_reqsize > 0) {
14996 14999 direction |= MPTSAS_PASS_THRU_DIRECTION_WRITE;
14997 15000 }
14998 15001
14999 15002 mutex_enter(&mpt->m_mutex);
15000 15003 ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep,
15001 15004 (uint8_t *)smp_pkt->smp_pkt_rsp,
15002 15005 offsetof(Mpi2SmpPassthroughRequest_t, SGL), sizeof (rep),
15003 15006 smp_pkt->smp_pkt_rspsize - 4, direction,
15004 15007 (uint8_t *)smp_pkt->smp_pkt_req, smp_pkt->smp_pkt_reqsize - 4,
15005 15008 smp_pkt->smp_pkt_timeout, FKIOCTL);
15006 15009 mutex_exit(&mpt->m_mutex);
15007 15010 if (ret != 0) {
15008 15011 cmn_err(CE_WARN, "smp_start do passthru error %d", ret);
15009 15012 smp_pkt->smp_pkt_reason = (uchar_t)(ret);
15010 15013 return (DDI_FAILURE);
15011 15014 }
15012 15015 /* do passthrough success, check the smp status */
15013 15016 if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
15014 15017 switch (LE_16(rep.IOCStatus)) {
15015 15018 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
15016 15019 smp_pkt->smp_pkt_reason = ENODEV;
15017 15020 break;
15018 15021 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
15019 15022 smp_pkt->smp_pkt_reason = EOVERFLOW;
15020 15023 break;
15021 15024 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
15022 15025 smp_pkt->smp_pkt_reason = EIO;
15023 15026 break;
15024 15027 default:
15025 15028 mptsas_log(mpt, CE_NOTE, "smp_start: get unknown ioc"
15026 15029 "status:%x", LE_16(rep.IOCStatus));
15027 15030 smp_pkt->smp_pkt_reason = EIO;
15028 15031 break;
15029 15032 }
15030 15033 return (DDI_FAILURE);
15031 15034 }
15032 15035 if (rep.SASStatus != MPI2_SASSTATUS_SUCCESS) {
15033 15036 mptsas_log(mpt, CE_NOTE, "smp_start: get error SAS status:%x",
15034 15037 rep.SASStatus);
15035 15038 smp_pkt->smp_pkt_reason = EIO;
15036 15039 return (DDI_FAILURE);
15037 15040 }
15038 15041
15039 15042 return (DDI_SUCCESS);
15040 15043 }
15041 15044
15042 15045 /*
15043 15046 * If we didn't get a match, we need to get sas page0 for each device, and
15044 15047 * untill we get a match. If failed, return NULL
15045 15048 */
15046 15049 static mptsas_target_t *
15047 15050 mptsas_phy_to_tgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint8_t phy)
15048 15051 {
15049 15052 int i, j = 0;
15050 15053 int rval = 0;
15051 15054 uint16_t cur_handle;
15052 15055 uint32_t page_address;
15053 15056 mptsas_target_t *ptgt = NULL;
15054 15057
15055 15058 /*
15056 15059 * PHY named device must be direct attached and attaches to
15057 15060 * narrow port, if the iport is not parent of the device which
15058 15061 * we are looking for.
15059 15062 */
15060 15063 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15061 15064 if ((1 << i) & phymask)
15062 15065 j++;
15063 15066 }
15064 15067
15065 15068 if (j > 1)
15066 15069 return (NULL);
15067 15070
15068 15071 /*
15069 15072 * Must be a narrow port and single device attached to the narrow port
15070 15073 * So the physical port num of device which is equal to the iport's
15071 15074 * port num is the device what we are looking for.
15072 15075 */
15073 15076
15074 15077 if (mpt->m_phy_info[phy].phy_mask != phymask)
15075 15078 return (NULL);
15076 15079
15077 15080 mutex_enter(&mpt->m_mutex);
15078 15081
15079 15082 ptgt = refhash_linear_search(mpt->m_targets, mptsas_target_eval_nowwn,
15080 15083 &phy);
15081 15084 if (ptgt != NULL) {
15082 15085 mutex_exit(&mpt->m_mutex);
15083 15086 return (ptgt);
15084 15087 }
15085 15088
15086 15089 if (mpt->m_done_traverse_dev) {
15087 15090 mutex_exit(&mpt->m_mutex);
15088 15091 return (NULL);
15089 15092 }
15090 15093
15091 15094 /* If didn't get a match, come here */
15092 15095 cur_handle = mpt->m_dev_handle;
15093 15096 for (; ; ) {
15094 15097 ptgt = NULL;
15095 15098 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15096 15099 MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15097 15100 rval = mptsas_get_target_device_info(mpt, page_address,
15098 15101 &cur_handle, &ptgt);
15099 15102 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15100 15103 (rval == DEV_INFO_FAIL_ALLOC)) {
15101 15104 break;
15102 15105 }
15103 15106 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15104 15107 (rval == DEV_INFO_PHYS_DISK)) {
15105 15108 continue;
15106 15109 }
15107 15110 mpt->m_dev_handle = cur_handle;
15108 15111
15109 15112 if ((ptgt->m_addr.mta_wwn == 0) && (ptgt->m_phynum == phy)) {
15110 15113 break;
15111 15114 }
15112 15115 }
15113 15116
15114 15117 mutex_exit(&mpt->m_mutex);
15115 15118 return (ptgt);
15116 15119 }
15117 15120
15118 15121 /*
15119 15122 * The ptgt->m_addr.mta_wwn contains the wwid for each disk.
15120 15123 * For Raid volumes, we need to check m_raidvol[x].m_raidwwid
15121 15124 * If we didn't get a match, we need to get sas page0 for each device, and
15122 15125 * untill we get a match
15123 15126 * If failed, return NULL
15124 15127 */
15125 15128 static mptsas_target_t *
15126 15129 mptsas_wwid_to_ptgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
15127 15130 {
15128 15131 int rval = 0;
15129 15132 uint16_t cur_handle;
15130 15133 uint32_t page_address;
15131 15134 mptsas_target_t *tmp_tgt = NULL;
15132 15135 mptsas_target_addr_t addr;
15133 15136
15134 15137 addr.mta_wwn = wwid;
15135 15138 addr.mta_phymask = phymask;
15136 15139 mutex_enter(&mpt->m_mutex);
15137 15140 tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15138 15141 if (tmp_tgt != NULL) {
15139 15142 mutex_exit(&mpt->m_mutex);
15140 15143 return (tmp_tgt);
15141 15144 }
15142 15145
15143 15146 if (phymask == 0) {
15144 15147 /*
15145 15148 * It's IR volume
15146 15149 */
15147 15150 rval = mptsas_get_raid_info(mpt);
15148 15151 if (rval) {
15149 15152 tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15150 15153 }
15151 15154 mutex_exit(&mpt->m_mutex);
15152 15155 return (tmp_tgt);
15153 15156 }
15154 15157
15155 15158 if (mpt->m_done_traverse_dev) {
15156 15159 mutex_exit(&mpt->m_mutex);
15157 15160 return (NULL);
15158 15161 }
15159 15162
15160 15163 /* If didn't get a match, come here */
15161 15164 cur_handle = mpt->m_dev_handle;
15162 15165 for (;;) {
15163 15166 tmp_tgt = NULL;
15164 15167 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15165 15168 MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
15166 15169 rval = mptsas_get_target_device_info(mpt, page_address,
15167 15170 &cur_handle, &tmp_tgt);
15168 15171 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15169 15172 (rval == DEV_INFO_FAIL_ALLOC)) {
15170 15173 tmp_tgt = NULL;
15171 15174 break;
15172 15175 }
15173 15176 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15174 15177 (rval == DEV_INFO_PHYS_DISK)) {
15175 15178 continue;
15176 15179 }
15177 15180 mpt->m_dev_handle = cur_handle;
15178 15181 if ((tmp_tgt->m_addr.mta_wwn) &&
15179 15182 (tmp_tgt->m_addr.mta_wwn == wwid) &&
15180 15183 (tmp_tgt->m_addr.mta_phymask == phymask)) {
15181 15184 break;
15182 15185 }
15183 15186 }
15184 15187
15185 15188 mutex_exit(&mpt->m_mutex);
15186 15189 return (tmp_tgt);
15187 15190 }
15188 15191
15189 15192 static mptsas_smp_t *
15190 15193 mptsas_wwid_to_psmp(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
15191 15194 {
15192 15195 int rval = 0;
15193 15196 uint16_t cur_handle;
15194 15197 uint32_t page_address;
15195 15198 mptsas_smp_t smp_node, *psmp = NULL;
15196 15199 mptsas_target_addr_t addr;
15197 15200
15198 15201 addr.mta_wwn = wwid;
15199 15202 addr.mta_phymask = phymask;
15200 15203 mutex_enter(&mpt->m_mutex);
15201 15204 psmp = refhash_lookup(mpt->m_smp_targets, &addr);
15202 15205 if (psmp != NULL) {
15203 15206 mutex_exit(&mpt->m_mutex);
15204 15207 return (psmp);
15205 15208 }
15206 15209
15207 15210 if (mpt->m_done_traverse_smp) {
15208 15211 mutex_exit(&mpt->m_mutex);
15209 15212 return (NULL);
15210 15213 }
15211 15214
15212 15215 /* If didn't get a match, come here */
15213 15216 cur_handle = mpt->m_smp_devhdl;
15214 15217 for (;;) {
15215 15218 psmp = NULL;
15216 15219 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
15217 15220 MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15218 15221 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15219 15222 &smp_node);
15220 15223 if (rval != DDI_SUCCESS) {
15221 15224 break;
15222 15225 }
15223 15226 mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
15224 15227 psmp = mptsas_smp_alloc(mpt, &smp_node);
15225 15228 ASSERT(psmp);
15226 15229 if ((psmp->m_addr.mta_wwn) && (psmp->m_addr.mta_wwn == wwid) &&
15227 15230 (psmp->m_addr.mta_phymask == phymask)) {
15228 15231 break;
15229 15232 }
15230 15233 }
15231 15234
15232 15235 mutex_exit(&mpt->m_mutex);
15233 15236 return (psmp);
15234 15237 }
15235 15238
15236 15239 mptsas_target_t *
15237 15240 mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid,
15238 15241 uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
15239 15242 {
15240 15243 mptsas_target_t *tmp_tgt = NULL;
15241 15244 mptsas_target_addr_t addr;
15242 15245
15243 15246 addr.mta_wwn = wwid;
15244 15247 addr.mta_phymask = phymask;
15245 15248 tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15246 15249 if (tmp_tgt != NULL) {
15247 15250 NDBG20(("Hash item already exist"));
15248 15251 tmp_tgt->m_deviceinfo = devinfo;
15249 15252 tmp_tgt->m_devhdl = devhdl; /* XXX - duplicate? */
15250 15253 return (tmp_tgt);
15251 15254 }
15252 15255 tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
15253 15256 if (tmp_tgt == NULL) {
15254 15257 cmn_err(CE_WARN, "Fatal, allocated tgt failed");
15255 15258 return (NULL);
15256 15259 }
15257 15260 tmp_tgt->m_devhdl = devhdl;
15258 15261 tmp_tgt->m_addr.mta_wwn = wwid;
15259 15262 tmp_tgt->m_deviceinfo = devinfo;
15260 15263 tmp_tgt->m_addr.mta_phymask = phymask;
15261 15264 tmp_tgt->m_phynum = phynum;
15262 15265 /* Initialized the tgt structure */
15263 15266 tmp_tgt->m_qfull_retries = QFULL_RETRIES;
15264 15267 tmp_tgt->m_qfull_retry_interval =
15265 15268 drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
15266 15269 tmp_tgt->m_t_throttle = MAX_THROTTLE;
15267 15270
15268 15271 refhash_insert(mpt->m_targets, tmp_tgt);
15269 15272
15270 15273 return (tmp_tgt);
15271 15274 }
15272 15275
15273 15276 static mptsas_smp_t *
15274 15277 mptsas_smp_alloc(mptsas_t *mpt, mptsas_smp_t *data)
15275 15278 {
15276 15279 mptsas_target_addr_t addr;
15277 15280 mptsas_smp_t *ret_data;
15278 15281
15279 15282 addr.mta_wwn = data->m_addr.mta_wwn;
15280 15283 addr.mta_phymask = data->m_addr.mta_phymask;
15281 15284 ret_data = refhash_lookup(mpt->m_smp_targets, &addr);
15282 15285 if (ret_data != NULL) {
15283 15286 bcopy(data, ret_data, sizeof (mptsas_smp_t)); /* XXX - dupl */
15284 15287 return (ret_data);
15285 15288 }
15286 15289
15287 15290 ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
15288 15291 bcopy(data, ret_data, sizeof (mptsas_smp_t));
15289 15292 refhash_insert(mpt->m_smp_targets, ret_data);
15290 15293 return (ret_data);
15291 15294 }
15292 15295
15293 15296 /*
15294 15297 * Functions for SGPIO LED support
15295 15298 */
15296 15299 static dev_info_t *
15297 15300 mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
15298 15301 {
15299 15302 dev_info_t *dip;
15300 15303 int prop;
15301 15304 dip = e_ddi_hold_devi_by_dev(dev, 0);
15302 15305 if (dip == NULL)
15303 15306 return (dip);
15304 15307 prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
15305 15308 "phymask", 0);
15306 15309 *phymask = (mptsas_phymask_t)prop;
15307 15310 ddi_release_devi(dip);
15308 15311 return (dip);
15309 15312 }
15310 15313 static mptsas_target_t *
15311 15314 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
15312 15315 {
15313 15316 uint8_t phynum;
15314 15317 uint64_t wwn;
15315 15318 int lun;
15316 15319 mptsas_target_t *ptgt = NULL;
15317 15320
15318 15321 if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
15319 15322 return (NULL);
15320 15323 }
15321 15324 if (addr[0] == 'w') {
15322 15325 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
15323 15326 } else {
15324 15327 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
15325 15328 }
15326 15329 return (ptgt);
15327 15330 }
15328 15331
15329 15332 static int
15330 15333 mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt)
15331 15334 {
15332 15335 uint32_t slotstatus = 0;
15333 15336
15334 15337 /* Build an MPI2 Slot Status based on our view of the world */
15335 15338 if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1)))
15336 15339 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST;
15337 15340 if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1)))
15338 15341 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
15339 15342 if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)))
15340 15343 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
15341 15344
15342 15345 /* Write it to the controller */
15343 15346 NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
15344 15347 slotstatus, ptgt->m_slot_num));
15345 15348 return (mptsas_send_sep(mpt, ptgt, &slotstatus,
15346 15349 MPI2_SEP_REQ_ACTION_WRITE_STATUS));
15347 15350 }
15348 15351
15349 15352 /*
15350 15353 * send sep request, use enclosure/slot addressing
15351 15354 */
15352 15355 static int
15353 15356 mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
15354 15357 uint32_t *status, uint8_t act)
15355 15358 {
15356 15359 Mpi2SepRequest_t req;
15357 15360 Mpi2SepReply_t rep;
15358 15361 int ret;
15359 15362
15360 15363 ASSERT(mutex_owned(&mpt->m_mutex));
15361 15364
15362 15365 /*
15363 15366 * We only support SEP control of directly-attached targets, in which
15364 15367 * case the "SEP" we're talking to is a virtual one contained within
15365 15368 * the HBA itself. This is necessary because DA targets typically have
15366 15369 * no other mechanism for LED control. Targets for which a separate
15367 15370 * enclosure service processor exists should be controlled via ses(7d)
15368 15371 * or sgen(7d). Furthermore, since such requests can time out, they
15369 15372 * should be made in user context rather than in response to
15370 15373 * asynchronous fabric changes.
15371 15374 *
15372 15375 * In addition, we do not support this operation for RAID volumes,
15373 15376 * since there is no slot associated with them.
15374 15377 */
15375 15378 if (!(ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED) ||
15376 15379 ptgt->m_addr.mta_phymask == 0) {
15377 15380 return (ENOTTY);
15378 15381 }
15379 15382
15380 15383 bzero(&req, sizeof (req));
15381 15384 bzero(&rep, sizeof (rep));
15382 15385
15383 15386 req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
15384 15387 req.Action = act;
15385 15388 req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
15386 15389 req.EnclosureHandle = LE_16(ptgt->m_enclosure);
15387 15390 req.Slot = LE_16(ptgt->m_slot_num);
15388 15391 if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
15389 15392 req.SlotStatus = LE_32(*status);
15390 15393 }
15391 15394 ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
15392 15395 sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
15393 15396 if (ret != 0) {
15394 15397 mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
15395 15398 "Processor Request message error %d", ret);
15396 15399 return (ret);
15397 15400 }
15398 15401 /* do passthrough success, check the ioc status */
15399 15402 if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
15400 15403 mptsas_log(mpt, CE_NOTE, "send_sep act %x: ioc "
15401 15404 "status:%x loginfo %x", act, LE_16(rep.IOCStatus),
15402 15405 LE_32(rep.IOCLogInfo));
15403 15406 switch (LE_16(rep.IOCStatus) & MPI2_IOCSTATUS_MASK) {
15404 15407 case MPI2_IOCSTATUS_INVALID_FUNCTION:
15405 15408 case MPI2_IOCSTATUS_INVALID_VPID:
15406 15409 case MPI2_IOCSTATUS_INVALID_FIELD:
15407 15410 case MPI2_IOCSTATUS_INVALID_STATE:
15408 15411 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
15409 15412 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
15410 15413 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
15411 15414 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
15412 15415 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
15413 15416 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
15414 15417 return (EINVAL);
15415 15418 case MPI2_IOCSTATUS_BUSY:
15416 15419 return (EBUSY);
15417 15420 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
15418 15421 return (EAGAIN);
15419 15422 case MPI2_IOCSTATUS_INVALID_SGL:
15420 15423 case MPI2_IOCSTATUS_INTERNAL_ERROR:
15421 15424 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
15422 15425 default:
15423 15426 return (EIO);
15424 15427 }
15425 15428 }
15426 15429 if (act != MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
15427 15430 *status = LE_32(rep.SlotStatus);
15428 15431 }
15429 15432
15430 15433 return (0);
15431 15434 }
15432 15435
15433 15436 int
15434 15437 mptsas_dma_addr_create(mptsas_t *mpt, ddi_dma_attr_t dma_attr,
15435 15438 ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp, caddr_t *dma_memp,
15436 15439 uint32_t alloc_size, ddi_dma_cookie_t *cookiep)
|
↓ open down ↓ |
13385 lines elided |
↑ open up ↑ |
15437 15440 {
15438 15441 ddi_dma_cookie_t new_cookie;
15439 15442 size_t alloc_len;
15440 15443 uint_t ncookie;
15441 15444
15442 15445 if (cookiep == NULL)
15443 15446 cookiep = &new_cookie;
15444 15447
15445 15448 if (ddi_dma_alloc_handle(mpt->m_dip, &dma_attr, DDI_DMA_SLEEP,
15446 15449 NULL, dma_hdp) != DDI_SUCCESS) {
15447 - dma_hdp = NULL;
15448 15450 return (FALSE);
15449 15451 }
15450 15452
15451 15453 if (ddi_dma_mem_alloc(*dma_hdp, alloc_size, &mpt->m_dev_acc_attr,
15452 15454 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, dma_memp, &alloc_len,
15453 15455 acc_hdp) != DDI_SUCCESS) {
15454 15456 ddi_dma_free_handle(dma_hdp);
15455 - dma_hdp = NULL;
15456 15457 return (FALSE);
15457 15458 }
15458 15459
15459 15460 if (ddi_dma_addr_bind_handle(*dma_hdp, NULL, *dma_memp, alloc_len,
15460 15461 (DDI_DMA_RDWR | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL,
15461 15462 cookiep, &ncookie) != DDI_DMA_MAPPED) {
15462 15463 (void) ddi_dma_mem_free(acc_hdp);
15463 15464 ddi_dma_free_handle(dma_hdp);
15464 - dma_hdp = NULL;
15465 15465 return (FALSE);
15466 15466 }
15467 15467
15468 15468 return (TRUE);
15469 15469 }
15470 15470
15471 15471 void
15472 15472 mptsas_dma_addr_destroy(ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp)
15473 15473 {
15474 15474 if (*dma_hdp == NULL)
15475 15475 return;
15476 15476
15477 15477 (void) ddi_dma_unbind_handle(*dma_hdp);
15478 15478 (void) ddi_dma_mem_free(acc_hdp);
15479 15479 ddi_dma_free_handle(dma_hdp);
15480 - dma_hdp = NULL;
15481 15480 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX