Print this page
Update tx waitq's code.
Create 2 threads, divide the workflow and deliver
to the hardware from the threads.
Enable Fast Path for capable devices.
Lint and cstyle fixes.
Fix problem with running against 64bit msgaddr attributes for DMA.
Default is now to run like this.
Major rework of mutexes.
During normal operation do not grab m_mutex during interrupt.
Use reply post queues instead.
Fixes to some address arithmetic using 32bit values.
Merge fixes for "4403 mpt_sas panic when pulling a drive", commit f7d0d869a9ae78d
Initial modifications using the code changes present between
the LSI source code for FreeBSD drivers. Specifically the changes
between from mpslsi-source-17.00.00.00 -> mpslsi-source-03.00.00.00.
This mainly involves using a different scatter/gather element in
frame setup.
Changes to enable driver to compile.
Header paths, object lists, etc.
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/scsi/adapters/mpt_sas3/mptsas3_impl.c
+++ new/usr/src/uts/common/io/scsi/adapters/mpt_sas3/mptsas3_impl.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.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
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 + * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
26 + * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
25 27 */
26 28
27 29 /*
28 30 * Copyright (c) 2000 to 2010, LSI Corporation.
29 31 * All rights reserved.
30 32 *
31 33 * Redistribution and use in source and binary forms of all code within
32 34 * this file that is exclusively owned by LSI, with or without
33 35 * modification, is permitted provided that, in addition to the CDDL 1.0
34 36 * License requirements, the following conditions are met:
35 37 *
36 38 * Neither the name of the author nor the names of its contributors may be
37 39 * used to endorse or promote products derived from this software without
38 40 * specific prior written permission.
39 41 *
40 42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
43 45 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
44 46 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
45 47 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
46 48 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
47 49 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
48 50 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49 51 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50 52 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
51 53 * DAMAGE.
52 54 */
53 55
54 56 /*
55 57 * mptsas_impl - This file contains all the basic functions for communicating
56 58 * to MPT based hardware.
57 59 */
58 60
59 61 #if defined(lint) || defined(DEBUG)
60 62 #define MPTSAS_DEBUG
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
61 63 #endif
62 64
63 65 /*
64 66 * standard header files
65 67 */
66 68 #include <sys/note.h>
67 69 #include <sys/scsi/scsi.h>
68 70 #include <sys/pci.h>
69 71
70 72 #pragma pack(1)
71 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
72 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
73 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
74 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
75 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
76 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
77 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
73 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_type.h>
74 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2.h>
75 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_cnfg.h>
76 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_init.h>
77 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_ioc.h>
78 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_sas.h>
79 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_tool.h>
78 80 #pragma pack()
79 81
80 82 /*
81 83 * private header files.
82 84 */
83 -#include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
84 -#include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
85 +#include <sys/scsi/adapters/mpt_sas3/mptsas3_var.h>
86 +#include <sys/scsi/adapters/mpt_sas3/mptsas3_smhba.h>
85 87
86 88 /*
87 89 * FMA header files.
88 90 */
89 91 #include <sys/fm/io/ddi.h>
90 92
91 93 #if defined(MPTSAS_DEBUG)
92 94 extern uint32_t mptsas_debug_flags;
95 +extern uint32_t mptsas_dbglog_imask;
93 96 #endif
94 97
95 98 /*
96 99 * prototypes
97 100 */
98 101 static void mptsas_ioc_event_cmdq_add(mptsas_t *mpt, m_event_struct_t *cmd);
99 102 static void mptsas_ioc_event_cmdq_delete(mptsas_t *mpt, m_event_struct_t *cmd);
100 103 static m_event_struct_t *mptsas_ioc_event_find_by_cmd(mptsas_t *mpt,
101 104 struct mptsas_cmd *cmd);
102 105
103 106 /*
104 107 * add ioc evnet cmd into the queue
105 108 */
106 109 static void
107 110 mptsas_ioc_event_cmdq_add(mptsas_t *mpt, m_event_struct_t *cmd)
108 111 {
109 112 if ((cmd->m_event_linkp = mpt->m_ioc_event_cmdq) == NULL) {
110 113 mpt->m_ioc_event_cmdtail = &cmd->m_event_linkp;
111 114 mpt->m_ioc_event_cmdq = cmd;
112 115 } else {
113 116 cmd->m_event_linkp = NULL;
114 117 *(mpt->m_ioc_event_cmdtail) = cmd;
115 118 mpt->m_ioc_event_cmdtail = &cmd->m_event_linkp;
116 119 }
117 120 }
118 121
119 122 /*
120 123 * remove specified cmd from the ioc event queue
121 124 */
122 125 static void
123 126 mptsas_ioc_event_cmdq_delete(mptsas_t *mpt, m_event_struct_t *cmd)
124 127 {
125 128 m_event_struct_t *prev = mpt->m_ioc_event_cmdq;
126 129 if (prev == cmd) {
127 130 if ((mpt->m_ioc_event_cmdq = cmd->m_event_linkp) == NULL) {
128 131 mpt->m_ioc_event_cmdtail = &mpt->m_ioc_event_cmdq;
129 132 }
130 133 cmd->m_event_linkp = NULL;
131 134 return;
132 135 }
133 136 while (prev != NULL) {
134 137 if (prev->m_event_linkp == cmd) {
135 138 prev->m_event_linkp = cmd->m_event_linkp;
136 139 if (cmd->m_event_linkp == NULL) {
137 140 mpt->m_ioc_event_cmdtail = &prev->m_event_linkp;
138 141 }
139 142
140 143 cmd->m_event_linkp = NULL;
141 144 return;
142 145 }
143 146 prev = prev->m_event_linkp;
144 147 }
145 148 }
146 149
147 150 static m_event_struct_t *
148 151 mptsas_ioc_event_find_by_cmd(mptsas_t *mpt, struct mptsas_cmd *cmd)
149 152 {
150 153 m_event_struct_t *ioc_cmd = NULL;
151 154
152 155 ioc_cmd = mpt->m_ioc_event_cmdq;
153 156 while (ioc_cmd != NULL) {
154 157 if (&(ioc_cmd->m_event_cmd) == cmd) {
155 158 return (ioc_cmd);
156 159 }
157 160 ioc_cmd = ioc_cmd->m_event_linkp;
158 161 }
159 162 ioc_cmd = NULL;
160 163 return (ioc_cmd);
161 164 }
162 165
163 166 void
164 167 mptsas_destroy_ioc_event_cmd(mptsas_t *mpt)
165 168 {
166 169 m_event_struct_t *ioc_cmd = NULL;
167 170 m_event_struct_t *ioc_cmd_tmp = NULL;
168 171 ioc_cmd = mpt->m_ioc_event_cmdq;
169 172
170 173 /*
171 174 * because the IOC event queue is resource of per instance for driver,
172 175 * it's not only ACK event commands used it, but also some others used
173 176 * it. We need destroy all ACK event commands when IOC reset, but can't
174 177 * disturb others.So we use filter to clear the ACK event cmd in ioc
175 178 * event queue, and other requests should be reserved, and they would
176 179 * be free by its owner.
177 180 */
178 181 while (ioc_cmd != NULL) {
179 182 if (ioc_cmd->m_event_cmd.cmd_flags & CFLAG_CMDACK) {
180 183 NDBG20(("destroy!! remove Ack Flag ioc_cmd\n"));
181 184 if ((mpt->m_ioc_event_cmdq =
182 185 ioc_cmd->m_event_linkp) == NULL)
183 186 mpt->m_ioc_event_cmdtail =
184 187 &mpt->m_ioc_event_cmdq;
185 188 ioc_cmd_tmp = ioc_cmd;
186 189 ioc_cmd = ioc_cmd->m_event_linkp;
187 190 kmem_free(ioc_cmd_tmp, M_EVENT_STRUCT_SIZE);
188 191 } else {
189 192 /*
190 193 * it's not ack cmd, so continue to check next one
191 194 */
192 195
193 196 NDBG20(("destroy!! it's not Ack Flag, continue\n"));
194 197 ioc_cmd = ioc_cmd->m_event_linkp;
195 198 }
196 199
197 200 }
↓ open down ↓ |
95 lines elided |
↑ open up ↑ |
198 201 }
199 202
200 203 void
201 204 mptsas_start_config_page_access(mptsas_t *mpt, mptsas_cmd_t *cmd)
202 205 {
203 206 pMpi2ConfigRequest_t request;
204 207 pMpi2SGESimple64_t sge;
205 208 struct scsi_pkt *pkt = cmd->cmd_pkt;
206 209 mptsas_config_request_t *config = pkt->pkt_ha_private;
207 210 uint8_t direction;
208 - uint32_t length, flagslength, request_desc_low;
211 + uint32_t length, flagslength;
212 + uint64_t request_desc;
209 213
210 214 ASSERT(mutex_owned(&mpt->m_mutex));
211 215
212 216 /*
213 217 * Point to the correct message and clear it as well as the global
214 218 * config page memory.
215 219 */
216 220 request = (pMpi2ConfigRequest_t)(mpt->m_req_frame +
217 221 (mpt->m_req_frame_size * cmd->cmd_slot));
218 222 bzero(request, mpt->m_req_frame_size);
219 223
220 224 /*
221 225 * Form the request message.
222 226 */
223 227 ddi_put8(mpt->m_acc_req_frame_hdl, &request->Function,
224 228 MPI2_FUNCTION_CONFIG);
225 229 ddi_put8(mpt->m_acc_req_frame_hdl, &request->Action, config->action);
226 230 direction = MPI2_SGE_FLAGS_IOC_TO_HOST;
227 231 length = 0;
228 232 sge = (pMpi2SGESimple64_t)&request->PageBufferSGE;
229 233 if (config->action == MPI2_CONFIG_ACTION_PAGE_HEADER) {
230 234 if (config->page_type > MPI2_CONFIG_PAGETYPE_MASK) {
231 235 ddi_put8(mpt->m_acc_req_frame_hdl,
232 236 &request->Header.PageType,
233 237 MPI2_CONFIG_PAGETYPE_EXTENDED);
234 238 ddi_put8(mpt->m_acc_req_frame_hdl,
235 239 &request->ExtPageType, config->page_type);
236 240 } else {
237 241 ddi_put8(mpt->m_acc_req_frame_hdl,
238 242 &request->Header.PageType, config->page_type);
239 243 }
240 244 } else {
241 245 ddi_put8(mpt->m_acc_req_frame_hdl, &request->ExtPageType,
242 246 config->ext_page_type);
243 247 ddi_put16(mpt->m_acc_req_frame_hdl, &request->ExtPageLength,
244 248 config->ext_page_length);
245 249 ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageType,
246 250 config->page_type);
247 251 ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageLength,
248 252 config->page_length);
249 253 ddi_put8(mpt->m_acc_req_frame_hdl,
250 254 &request->Header.PageVersion, config->page_version);
251 255 if ((config->page_type & MPI2_CONFIG_PAGETYPE_MASK) ==
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
252 256 MPI2_CONFIG_PAGETYPE_EXTENDED) {
253 257 length = config->ext_page_length * 4;
254 258 } else {
255 259 length = config->page_length * 4;
256 260 }
257 261
258 262 if (config->action == MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
259 263 direction = MPI2_SGE_FLAGS_HOST_TO_IOC;
260 264 }
261 265 ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.Low,
262 - (uint32_t)cmd->cmd_dma_addr);
266 + (uint32_t)(cmd->cmd_dma_addr&0xfffffffful));
263 267 ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.High,
264 268 (uint32_t)(cmd->cmd_dma_addr >> 32));
265 269 }
266 270 ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageNumber,
267 271 config->page_number);
268 272 ddi_put32(mpt->m_acc_req_frame_hdl, &request->PageAddress,
269 273 config->page_address);
270 274 flagslength = ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
271 275 MPI2_SGE_FLAGS_END_OF_BUFFER |
272 276 MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
273 277 MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
274 278 MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
275 279 direction |
276 280 MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
277 281 flagslength |= length;
278 282 ddi_put32(mpt->m_acc_req_frame_hdl, &sge->FlagsLength, flagslength);
279 283
280 284 (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
281 285 DDI_DMA_SYNC_FORDEV);
282 - request_desc_low = (cmd->cmd_slot << 16) +
286 + request_desc = (cmd->cmd_slot << 16) +
283 287 MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
284 288 cmd->cmd_rfm = NULL;
285 - MPTSAS_START_CMD(mpt, request_desc_low, 0);
289 + MPTSAS_START_CMD(mpt, request_desc);
286 290 if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
287 291 DDI_SUCCESS) ||
288 292 (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
289 293 DDI_SUCCESS)) {
290 294 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
291 295 }
292 296 }
293 297
294 298 int
295 299 mptsas_access_config_page(mptsas_t *mpt, uint8_t action, uint8_t page_type,
296 300 uint8_t page_number, uint32_t page_address, int (*callback) (mptsas_t *,
297 301 caddr_t, ddi_acc_handle_t, uint16_t, uint32_t, va_list), ...)
298 302 {
299 303 va_list ap;
300 304 ddi_dma_attr_t attrs;
301 305 ddi_dma_cookie_t cookie;
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
302 306 ddi_acc_handle_t accessp;
303 307 size_t len = 0;
304 308 mptsas_config_request_t config;
305 309 int rval = DDI_SUCCESS, config_flags = 0;
306 310 mptsas_cmd_t *cmd;
307 311 struct scsi_pkt *pkt;
308 312 pMpi2ConfigReply_t reply;
309 313 uint16_t iocstatus = 0;
310 314 uint32_t iocloginfo;
311 315 caddr_t page_memp;
316 + boolean_t free_dma = B_FALSE;
312 317
313 318 va_start(ap, callback);
314 319 ASSERT(mutex_owned(&mpt->m_mutex));
315 320
316 321 /*
317 322 * Get a command from the pool.
318 323 */
319 324 if ((rval = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
320 325 mptsas_log(mpt, CE_NOTE, "command pool is full for config "
321 326 "page request");
322 327 rval = DDI_FAILURE;
323 328 goto page_done;
324 329 }
325 330 config_flags |= MPTSAS_REQUEST_POOL_CMD;
326 331
327 332 bzero((caddr_t)cmd, sizeof (*cmd));
328 333 bzero((caddr_t)pkt, scsi_pkt_size());
329 334 bzero((caddr_t)&config, sizeof (config));
330 335
331 336 /*
332 337 * Save the data for this request to be used in the call to start the
333 338 * config header request.
334 339 */
335 340 config.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
336 341 config.page_type = page_type;
337 342 config.page_number = page_number;
338 343 config.page_address = page_address;
339 344
340 345 /*
341 346 * Form a blank cmd/pkt to store the acknowledgement message
342 347 */
343 348 pkt->pkt_ha_private = (opaque_t)&config;
344 349 pkt->pkt_flags = FLAG_HEAD;
345 350 pkt->pkt_time = 60;
346 351 cmd->cmd_pkt = pkt;
347 352 cmd->cmd_flags = CFLAG_CMDIOC | CFLAG_CONFIG;
348 353
349 354 /*
350 355 * Save the config header request message in a slot.
351 356 */
352 357 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
353 358 cmd->cmd_flags |= CFLAG_PREPARED;
354 359 mptsas_start_config_page_access(mpt, cmd);
355 360 } else {
356 361 mptsas_waitq_add(mpt, cmd);
357 362 }
358 363
359 364 /*
360 365 * If this is a request for a RAID info page, or any page called during
361 366 * the RAID info page request, poll because these config page requests
362 367 * are nested. Poll to avoid data corruption due to one page's data
363 368 * overwriting the outer page request's data. This can happen when
364 369 * the mutex is released in cv_wait.
365 370 */
366 371 if ((page_type == MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG) ||
367 372 (page_type == MPI2_CONFIG_PAGETYPE_RAID_VOLUME) ||
368 373 (page_type == MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK)) {
369 374 (void) mptsas_poll(mpt, cmd, pkt->pkt_time * 1000);
370 375 } else {
371 376 while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
372 377 cv_wait(&mpt->m_config_cv, &mpt->m_mutex);
373 378 }
374 379 }
375 380
376 381 /*
377 382 * Check if the header request completed without timing out
378 383 */
379 384 if (cmd->cmd_flags & CFLAG_TIMEOUT) {
380 385 mptsas_log(mpt, CE_WARN, "config header request timeout");
381 386 rval = DDI_FAILURE;
382 387 goto page_done;
383 388 }
↓ open down ↓ |
62 lines elided |
↑ open up ↑ |
384 389
385 390 /*
386 391 * cmd_rfm points to the reply message if a reply was given. Check the
387 392 * IOCStatus to make sure everything went OK with the header request.
388 393 */
389 394 if (cmd->cmd_rfm) {
390 395 config_flags |= MPTSAS_ADDRESS_REPLY;
391 396 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
392 397 DDI_DMA_SYNC_FORCPU);
393 398 reply = (pMpi2ConfigReply_t)(mpt->m_reply_frame + (cmd->cmd_rfm
394 - - mpt->m_reply_frame_dma_addr));
399 + - (mpt->m_reply_frame_dma_addr&0xfffffffful)));
395 400 config.page_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
396 401 &reply->Header.PageType);
397 402 config.page_number = ddi_get8(mpt->m_acc_reply_frame_hdl,
398 403 &reply->Header.PageNumber);
399 404 config.page_length = ddi_get8(mpt->m_acc_reply_frame_hdl,
400 405 &reply->Header.PageLength);
401 406 config.page_version = ddi_get8(mpt->m_acc_reply_frame_hdl,
402 407 &reply->Header.PageVersion);
403 408 config.ext_page_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
404 409 &reply->ExtPageType);
405 410 config.ext_page_length = ddi_get16(mpt->m_acc_reply_frame_hdl,
406 411 &reply->ExtPageLength);
407 412
408 413 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
409 414 &reply->IOCStatus);
410 415 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
411 416 &reply->IOCLogInfo);
412 417
413 418 if (iocstatus) {
414 419 NDBG13(("mptsas_access_config_page header: "
415 420 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
416 421 iocloginfo));
417 422 rval = DDI_FAILURE;
418 423 goto page_done;
419 424 }
420 425
421 426 if ((config.page_type & MPI2_CONFIG_PAGETYPE_MASK) ==
422 427 MPI2_CONFIG_PAGETYPE_EXTENDED)
423 428 len = (config.ext_page_length * 4);
424 429 else
425 430 len = (config.page_length * 4);
426 431
427 432 }
428 433
429 434 if (pkt->pkt_reason == CMD_RESET) {
430 435 mptsas_log(mpt, CE_WARN, "ioc reset abort config header "
431 436 "request");
432 437 rval = DDI_FAILURE;
433 438 goto page_done;
434 439 }
435 440
436 441 /*
437 442 * Put the reply frame back on the free queue, increment the free
438 443 * index, and write the new index to the free index register. But only
439 444 * if this reply is an ADDRESS reply.
440 445 */
441 446 if (config_flags & MPTSAS_ADDRESS_REPLY) {
442 447 ddi_put32(mpt->m_acc_free_queue_hdl,
443 448 &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
444 449 cmd->cmd_rfm);
445 450 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
446 451 DDI_DMA_SYNC_FORDEV);
447 452 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
448 453 mpt->m_free_index = 0;
449 454 }
450 455 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
451 456 mpt->m_free_index);
452 457 config_flags &= (~MPTSAS_ADDRESS_REPLY);
453 458 }
454 459
455 460 /*
456 461 * Allocate DMA buffer here. Store the info regarding this buffer in
457 462 * the cmd struct so that it can be used for this specific command and
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
458 463 * de-allocated after the command completes. The size of the reply
459 464 * will not be larger than the reply frame size.
460 465 */
461 466 attrs = mpt->m_msg_dma_attr;
462 467 attrs.dma_attr_sgllen = 1;
463 468 attrs.dma_attr_granular = (uint32_t)len;
464 469
465 470 if (mptsas_dma_addr_create(mpt, attrs,
466 471 &cmd->cmd_dmahandle, &accessp, &page_memp,
467 472 len, &cookie) == FALSE) {
473 + mptsas_log(mpt, CE_WARN,
474 + "mptsas_dma_addr_create(len=0x%x) failed", (int)len);
475 + rval = DDI_FAILURE;
468 476 goto page_done;
469 477 }
478 + /* NOW we can safely call mptsas_dma_addr_destroy(). */
479 + free_dma = B_TRUE;
480 +
470 481 cmd->cmd_dma_addr = cookie.dmac_laddress;
471 482 bzero(page_memp, len);
472 483
473 484 /*
474 485 * Save the data for this request to be used in the call to start the
475 486 * config page read
476 487 */
477 488 config.action = action;
478 489 config.page_address = page_address;
479 490
480 491 /*
481 492 * Re-use the cmd that was used to get the header. Reset some of the
482 493 * values.
483 494 */
484 495 bzero((caddr_t)pkt, scsi_pkt_size());
485 496 pkt->pkt_ha_private = (opaque_t)&config;
486 497 pkt->pkt_flags = FLAG_HEAD;
487 498 pkt->pkt_time = 60;
488 499 cmd->cmd_flags = CFLAG_PREPARED | CFLAG_CMDIOC | CFLAG_CONFIG;
489 500
490 501 /*
491 502 * Send the config page request. cmd is re-used from header request.
492 503 */
493 504 mptsas_start_config_page_access(mpt, cmd);
494 505
495 506 /*
496 507 * If this is a request for a RAID info page, or any page called during
497 508 * the RAID info page request, poll because these config page requests
498 509 * are nested. Poll to avoid data corruption due to one page's data
499 510 * overwriting the outer page request's data. This can happen when
500 511 * the mutex is released in cv_wait.
501 512 */
502 513 if ((page_type == MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG) ||
503 514 (page_type == MPI2_CONFIG_PAGETYPE_RAID_VOLUME) ||
504 515 (page_type == MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK)) {
505 516 (void) mptsas_poll(mpt, cmd, pkt->pkt_time * 1000);
506 517 } else {
507 518 while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
508 519 cv_wait(&mpt->m_config_cv, &mpt->m_mutex);
509 520 }
510 521 }
511 522
512 523 /*
513 524 * Check if the request completed without timing out
514 525 */
515 526 if (cmd->cmd_flags & CFLAG_TIMEOUT) {
516 527 mptsas_log(mpt, CE_WARN, "config page request timeout");
517 528 rval = DDI_FAILURE;
518 529 goto page_done;
519 530 }
520 531
521 532 /*
522 533 * cmd_rfm points to the reply message if a reply was given. The reply
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
523 534 * frame and the config page are returned from this function in the
524 535 * param list.
525 536 */
526 537 if (cmd->cmd_rfm) {
527 538 config_flags |= MPTSAS_ADDRESS_REPLY;
528 539 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
529 540 DDI_DMA_SYNC_FORCPU);
530 541 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
531 542 DDI_DMA_SYNC_FORCPU);
532 543 reply = (pMpi2ConfigReply_t)(mpt->m_reply_frame + (cmd->cmd_rfm
533 - - mpt->m_reply_frame_dma_addr));
544 + - (mpt->m_reply_frame_dma_addr&0xfffffffful)));
534 545 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
535 546 &reply->IOCStatus);
536 547 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
537 548 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
538 549 &reply->IOCLogInfo);
539 550 }
540 551
541 552 if (callback(mpt, page_memp, accessp, iocstatus, iocloginfo, ap)) {
542 553 rval = DDI_FAILURE;
543 554 goto page_done;
544 555 }
545 556
546 557 mptsas_fma_check(mpt, cmd);
547 558 /*
548 559 * Check the DMA/ACC handles and then free the DMA buffer.
549 560 */
550 561 if ((mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS) ||
551 562 (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
552 563 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
553 564 rval = DDI_FAILURE;
554 565 }
555 566
556 567 if (pkt->pkt_reason == CMD_TRAN_ERR) {
557 568 mptsas_log(mpt, CE_WARN, "config fma error");
558 569 rval = DDI_FAILURE;
559 570 goto page_done;
560 571 }
561 572 if (pkt->pkt_reason == CMD_RESET) {
562 573 mptsas_log(mpt, CE_WARN, "ioc reset abort config request");
563 574 rval = DDI_FAILURE;
564 575 goto page_done;
565 576 }
566 577
567 578 page_done:
568 579 va_end(ap);
569 580 /*
570 581 * Put the reply frame back on the free queue, increment the free
571 582 * index, and write the new index to the free index register. But only
572 583 * if this reply is an ADDRESS reply.
573 584 */
574 585 if (config_flags & MPTSAS_ADDRESS_REPLY) {
575 586 ddi_put32(mpt->m_acc_free_queue_hdl,
576 587 &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
577 588 cmd->cmd_rfm);
578 589 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
579 590 DDI_DMA_SYNC_FORDEV);
580 591 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
581 592 mpt->m_free_index = 0;
582 593 }
583 594 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
584 595 mpt->m_free_index);
585 596 }
586 597
587 - mptsas_dma_addr_destroy(&cmd->cmd_dmahandle, &accessp);
598 + if (free_dma)
599 + mptsas_dma_addr_destroy(&cmd->cmd_dmahandle, &accessp);
588 600
589 601 if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
590 602 mptsas_remove_cmd(mpt, cmd);
591 603 config_flags &= (~MPTSAS_REQUEST_POOL_CMD);
592 604 }
593 605 if (config_flags & MPTSAS_REQUEST_POOL_CMD)
594 606 mptsas_return_to_pool(mpt, cmd);
595 607
596 608 if (config_flags & MPTSAS_CMD_TIMEOUT) {
597 609 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
598 610 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
599 611 mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
600 612 }
601 613 }
602 614
603 615 return (rval);
604 616 }
605 617
606 618 int
607 619 mptsas_send_config_request_msg(mptsas_t *mpt, uint8_t action, uint8_t pagetype,
608 620 uint32_t pageaddress, uint8_t pagenumber, uint8_t pageversion,
609 - uint8_t pagelength, uint32_t SGEflagslength, uint32_t SGEaddress32)
621 + uint8_t pagelength, uint32_t SGEflagslength, uint64_t SGEaddress)
610 622 {
611 623 pMpi2ConfigRequest_t config;
612 624 int send_numbytes;
613 625
614 626 bzero(mpt->m_hshk_memp, sizeof (MPI2_CONFIG_REQUEST));
615 627 config = (pMpi2ConfigRequest_t)mpt->m_hshk_memp;
616 628 ddi_put8(mpt->m_hshk_acc_hdl, &config->Function, MPI2_FUNCTION_CONFIG);
617 629 ddi_put8(mpt->m_hshk_acc_hdl, &config->Action, action);
618 630 ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageNumber, pagenumber);
619 631 ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageType, pagetype);
620 632 ddi_put32(mpt->m_hshk_acc_hdl, &config->PageAddress, pageaddress);
621 633 ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageVersion, pageversion);
622 634 ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageLength, pagelength);
623 635 ddi_put32(mpt->m_hshk_acc_hdl,
624 636 &config->PageBufferSGE.MpiSimple.FlagsLength, SGEflagslength);
625 637 ddi_put32(mpt->m_hshk_acc_hdl,
626 - &config->PageBufferSGE.MpiSimple.u.Address32, SGEaddress32);
638 + &config->PageBufferSGE.MpiSimple.u.Address64.Low,
639 + SGEaddress&0xfffffffful);
640 + ddi_put32(mpt->m_hshk_acc_hdl,
641 + &config->PageBufferSGE.MpiSimple.u.Address64.High,
642 + SGEaddress >> 32);
627 643 send_numbytes = sizeof (MPI2_CONFIG_REQUEST);
628 644
629 645 /*
630 646 * Post message via handshake
631 647 */
632 648 if (mptsas_send_handshake_msg(mpt, (caddr_t)config, send_numbytes,
633 649 mpt->m_hshk_acc_hdl)) {
634 650 return (-1);
635 651 }
636 652 return (0);
637 653 }
638 654
639 655 int
640 656 mptsas_send_extended_config_request_msg(mptsas_t *mpt, uint8_t action,
641 657 uint8_t extpagetype, uint32_t pageaddress, uint8_t pagenumber,
642 658 uint8_t pageversion, uint16_t extpagelength,
643 - uint32_t SGEflagslength, uint32_t SGEaddress32)
659 + uint32_t SGEflagslength, uint64_t SGEaddress)
644 660 {
645 661 pMpi2ConfigRequest_t config;
646 662 int send_numbytes;
647 663
648 664 bzero(mpt->m_hshk_memp, sizeof (MPI2_CONFIG_REQUEST));
649 665 config = (pMpi2ConfigRequest_t)mpt->m_hshk_memp;
650 666 ddi_put8(mpt->m_hshk_acc_hdl, &config->Function, MPI2_FUNCTION_CONFIG);
651 667 ddi_put8(mpt->m_hshk_acc_hdl, &config->Action, action);
652 668 ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageNumber, pagenumber);
653 669 ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageType,
654 670 MPI2_CONFIG_PAGETYPE_EXTENDED);
655 671 ddi_put8(mpt->m_hshk_acc_hdl, &config->ExtPageType, extpagetype);
656 672 ddi_put32(mpt->m_hshk_acc_hdl, &config->PageAddress, pageaddress);
657 673 ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageVersion, pageversion);
658 674 ddi_put16(mpt->m_hshk_acc_hdl, &config->ExtPageLength, extpagelength);
659 675 ddi_put32(mpt->m_hshk_acc_hdl,
660 676 &config->PageBufferSGE.MpiSimple.FlagsLength, SGEflagslength);
661 677 ddi_put32(mpt->m_hshk_acc_hdl,
662 - &config->PageBufferSGE.MpiSimple.u.Address32, SGEaddress32);
678 + &config->PageBufferSGE.MpiSimple.u.Address64.Low,
679 + SGEaddress&0xfffffffful);
680 + ddi_put32(mpt->m_hshk_acc_hdl,
681 + &config->PageBufferSGE.MpiSimple.u.Address64.High,
682 + SGEaddress >> 32);
663 683 send_numbytes = sizeof (MPI2_CONFIG_REQUEST);
664 684
665 685 /*
666 686 * Post message via handshake
667 687 */
668 688 if (mptsas_send_handshake_msg(mpt, (caddr_t)config, send_numbytes,
669 689 mpt->m_hshk_acc_hdl)) {
670 690 return (-1);
671 691 }
672 692 return (0);
673 693 }
674 694
675 695 int
676 696 mptsas_ioc_wait_for_response(mptsas_t *mpt)
677 697 {
678 698 int polls = 0;
679 699
680 700 while ((ddi_get32(mpt->m_datap,
681 701 &mpt->m_reg->HostInterruptStatus) & MPI2_HIS_IOP_DOORBELL_STATUS)) {
682 702 drv_usecwait(1000);
683 703 if (polls++ > 60000) {
684 704 return (-1);
685 705 }
686 706 }
687 707 return (0);
688 708 }
689 709
690 710 int
691 711 mptsas_ioc_wait_for_doorbell(mptsas_t *mpt)
692 712 {
693 713 int polls = 0;
694 714
695 715 while ((ddi_get32(mpt->m_datap,
696 716 &mpt->m_reg->HostInterruptStatus) & MPI2_HIM_DIM) == 0) {
697 717 drv_usecwait(1000);
698 718 if (polls++ > 300000) {
699 719 return (-1);
700 720 }
701 721 }
702 722 return (0);
703 723 }
704 724
705 725 int
706 726 mptsas_send_handshake_msg(mptsas_t *mpt, caddr_t memp, int numbytes,
707 727 ddi_acc_handle_t accessp)
708 728 {
709 729 int i;
710 730
711 731 /*
712 732 * clean pending doorbells
713 733 */
714 734 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptStatus, 0);
715 735 ddi_put32(mpt->m_datap, &mpt->m_reg->Doorbell,
716 736 ((MPI2_FUNCTION_HANDSHAKE << MPI2_DOORBELL_FUNCTION_SHIFT) |
717 737 ((numbytes / 4) << MPI2_DOORBELL_ADD_DWORDS_SHIFT)));
718 738
719 739 if (mptsas_ioc_wait_for_doorbell(mpt)) {
720 740 NDBG19(("mptsas_send_handshake failed. Doorbell not ready\n"));
721 741 return (-1);
722 742 }
723 743
724 744 /*
725 745 * clean pending doorbells again
726 746 */
727 747 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptStatus, 0);
728 748
729 749 if (mptsas_ioc_wait_for_response(mpt)) {
730 750 NDBG19(("mptsas_send_handshake failed. Doorbell not "
731 751 "cleared\n"));
732 752 return (-1);
733 753 }
734 754
735 755 /*
736 756 * post handshake message
737 757 */
738 758 for (i = 0; (i < numbytes / 4); i++, memp += 4) {
739 759 ddi_put32(mpt->m_datap, &mpt->m_reg->Doorbell,
740 760 ddi_get32(accessp, (uint32_t *)((void *)(memp))));
741 761 if (mptsas_ioc_wait_for_response(mpt)) {
742 762 NDBG19(("mptsas_send_handshake failed posting "
743 763 "message\n"));
744 764 return (-1);
745 765 }
746 766 }
747 767
748 768 if (mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) {
749 769 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
750 770 ddi_fm_acc_err_clear(mpt->m_datap, DDI_FME_VER0);
751 771 return (-1);
752 772 }
753 773
754 774 return (0);
755 775 }
756 776
757 777 int
758 778 mptsas_get_handshake_msg(mptsas_t *mpt, caddr_t memp, int numbytes,
759 779 ddi_acc_handle_t accessp)
760 780 {
761 781 int i, totalbytes, bytesleft;
762 782 uint16_t val;
763 783
764 784 /*
765 785 * wait for doorbell
766 786 */
767 787 if (mptsas_ioc_wait_for_doorbell(mpt)) {
768 788 NDBG19(("mptsas_get_handshake failed. Doorbell not ready\n"));
769 789 return (-1);
770 790 }
771 791
772 792 /*
773 793 * get first 2 bytes of handshake message to determine how much
774 794 * data we will be getting
775 795 */
776 796 for (i = 0; i < 2; i++, memp += 2) {
777 797 val = (ddi_get32(mpt->m_datap,
778 798 &mpt->m_reg->Doorbell) & MPI2_DOORBELL_DATA_MASK);
779 799 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptStatus, 0);
780 800 if (mptsas_ioc_wait_for_doorbell(mpt)) {
781 801 NDBG19(("mptsas_get_handshake failure getting initial"
782 802 " data\n"));
783 803 return (-1);
784 804 }
785 805 ddi_put16(accessp, (uint16_t *)((void *)(memp)), val);
786 806 if (i == 1) {
787 807 totalbytes = (val & 0xFF) * 2;
788 808 }
789 809 }
790 810
791 811 /*
792 812 * If we are expecting less bytes than the message wants to send
793 813 * we simply save as much as we expected and then throw out the rest
794 814 * later
795 815 */
796 816 if (totalbytes > (numbytes / 2)) {
797 817 bytesleft = ((numbytes / 2) - 2);
798 818 } else {
799 819 bytesleft = (totalbytes - 2);
800 820 }
801 821
802 822 /*
803 823 * Get the rest of the data
804 824 */
805 825 for (i = 0; i < bytesleft; i++, memp += 2) {
806 826 val = (ddi_get32(mpt->m_datap,
807 827 &mpt->m_reg->Doorbell) & MPI2_DOORBELL_DATA_MASK);
808 828 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptStatus, 0);
809 829 if (mptsas_ioc_wait_for_doorbell(mpt)) {
810 830 NDBG19(("mptsas_get_handshake failure getting"
811 831 " main data\n"));
812 832 return (-1);
813 833 }
814 834 ddi_put16(accessp, (uint16_t *)((void *)(memp)), val);
815 835 }
816 836
817 837 /*
818 838 * Sometimes the device will send more data than is expected
819 839 * This data is not used by us but needs to be cleared from
820 840 * ioc doorbell. So we just read the values and throw
821 841 * them out.
822 842 */
823 843 if (totalbytes > (numbytes / 2)) {
824 844 for (i = (numbytes / 2); i < totalbytes; i++) {
825 845 val = (ddi_get32(mpt->m_datap,
826 846 &mpt->m_reg->Doorbell) &
827 847 MPI2_DOORBELL_DATA_MASK);
828 848 ddi_put32(mpt->m_datap,
829 849 &mpt->m_reg->HostInterruptStatus, 0);
830 850 if (mptsas_ioc_wait_for_doorbell(mpt)) {
831 851 NDBG19(("mptsas_get_handshake failure getting "
832 852 "extra garbage data\n"));
833 853 return (-1);
834 854 }
835 855 }
836 856 }
837 857
838 858 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptStatus, 0);
839 859
840 860 if (mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) {
841 861 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
842 862 ddi_fm_acc_err_clear(mpt->m_datap, DDI_FME_VER0);
843 863 return (-1);
844 864 }
845 865
846 866 return (0);
847 867 }
848 868
849 869 int
850 870 mptsas_kick_start(mptsas_t *mpt)
851 871 {
852 872 int polls = 0;
853 873 uint32_t diag_reg, ioc_state, saved_HCB_size;
854 874
855 875 /*
856 876 * Start a hard reset. Write magic number and wait 500 mSeconds.
857 877 */
858 878 MPTSAS_ENABLE_DRWE(mpt);
859 879 drv_usecwait(500000);
860 880
861 881 /*
862 882 * Read the current Diag Reg and save the Host Controlled Boot size.
863 883 */
864 884 diag_reg = ddi_get32(mpt->m_datap, &mpt->m_reg->HostDiagnostic);
865 885 saved_HCB_size = ddi_get32(mpt->m_datap, &mpt->m_reg->HCBSize);
866 886
867 887 /*
868 888 * Set Reset Adapter bit and wait 50 mSeconds.
869 889 */
870 890 diag_reg |= MPI2_DIAG_RESET_ADAPTER;
871 891 ddi_put32(mpt->m_datap, &mpt->m_reg->HostDiagnostic, diag_reg);
872 892 drv_usecwait(50000);
873 893
874 894 /*
875 895 * Poll, waiting for Reset Adapter bit to clear. 300 Seconds max
876 896 * (600000 * 500 = 300,000,000 uSeconds, 300 seconds).
877 897 * If no more adapter (all FF's), just return failure.
878 898 */
879 899 for (polls = 0; polls < 600000; polls++) {
880 900 diag_reg = ddi_get32(mpt->m_datap,
881 901 &mpt->m_reg->HostDiagnostic);
882 902 if (diag_reg == 0xFFFFFFFF) {
883 903 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
884 904 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
885 905 return (DDI_FAILURE);
886 906 }
887 907 if (!(diag_reg & MPI2_DIAG_RESET_ADAPTER)) {
888 908 break;
889 909 }
890 910 drv_usecwait(500);
891 911 }
892 912 if (polls == 600000) {
893 913 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
894 914 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
895 915 return (DDI_FAILURE);
896 916 }
897 917
898 918 /*
899 919 * Check if adapter is in Host Boot Mode. If so, restart adapter
900 920 * assuming the HCB points to good FW.
901 921 * Set BootDeviceSel to HCDW (Host Code and Data Window).
902 922 */
903 923 if (diag_reg & MPI2_DIAG_HCB_MODE) {
904 924 diag_reg &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;
905 925 diag_reg |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;
906 926 ddi_put32(mpt->m_datap, &mpt->m_reg->HostDiagnostic, diag_reg);
907 927
908 928 /*
909 929 * Re-enable the HCDW.
910 930 */
911 931 ddi_put32(mpt->m_datap, &mpt->m_reg->HCBSize,
912 932 (saved_HCB_size | MPI2_HCB_SIZE_HCB_ENABLE));
913 933 }
914 934
915 935 /*
916 936 * Restart the adapter.
917 937 */
918 938 diag_reg &= ~MPI2_DIAG_HOLD_IOC_RESET;
919 939 ddi_put32(mpt->m_datap, &mpt->m_reg->HostDiagnostic, diag_reg);
920 940
921 941 /*
922 942 * Disable writes to the Host Diag register.
923 943 */
924 944 ddi_put32(mpt->m_datap, &mpt->m_reg->WriteSequence,
925 945 MPI2_WRSEQ_FLUSH_KEY_VALUE);
926 946
927 947 /*
928 948 * Wait 60 seconds max for FW to come to ready state.
929 949 */
930 950 for (polls = 0; polls < 60000; polls++) {
931 951 ioc_state = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
932 952 if (ioc_state == 0xFFFFFFFF) {
933 953 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
934 954 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
935 955 return (DDI_FAILURE);
936 956 }
937 957 if ((ioc_state & MPI2_IOC_STATE_MASK) ==
938 958 MPI2_IOC_STATE_READY) {
939 959 break;
940 960 }
941 961 drv_usecwait(1000);
942 962 }
943 963 if (polls == 60000) {
944 964 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
945 965 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
946 966 return (DDI_FAILURE);
947 967 }
948 968
949 969 /*
950 970 * Clear the ioc ack events queue.
951 971 */
952 972 mptsas_destroy_ioc_event_cmd(mpt);
953 973
954 974 return (DDI_SUCCESS);
955 975 }
956 976
957 977 int
958 978 mptsas_ioc_reset(mptsas_t *mpt, int first_time)
959 979 {
960 980 int polls = 0;
961 981 uint32_t reset_msg;
962 982 uint32_t ioc_state;
963 983
964 984 ioc_state = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
965 985 /*
966 986 * If chip is already in ready state then there is nothing to do.
967 987 */
968 988 if (ioc_state == MPI2_IOC_STATE_READY) {
969 989 return (MPTSAS_NO_RESET);
970 990 }
971 991 /*
972 992 * If the chip is already operational, we just need to send
973 993 * it a message unit reset to put it back in the ready state
974 994 */
975 995 if (ioc_state & MPI2_IOC_STATE_OPERATIONAL) {
976 996 /*
977 997 * If the first time, try MUR anyway, because we haven't even
978 998 * queried the card for m_event_replay and other capabilities.
979 999 * Other platforms do it this way, we can still do a hard
980 1000 * reset if we need to, MUR takes less time than a full
981 1001 * adapter reset, and there are reports that some HW
982 1002 * combinations will lock up when receiving a hard reset.
983 1003 */
984 1004 if ((first_time || mpt->m_event_replay) &&
985 1005 (mpt->m_softstate & MPTSAS_SS_MSG_UNIT_RESET)) {
986 1006 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
987 1007 reset_msg = MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET;
988 1008 ddi_put32(mpt->m_datap, &mpt->m_reg->Doorbell,
989 1009 (reset_msg << MPI2_DOORBELL_FUNCTION_SHIFT));
990 1010 if (mptsas_ioc_wait_for_response(mpt)) {
991 1011 NDBG19(("mptsas_ioc_reset failure sending "
992 1012 "message_unit_reset\n"));
993 1013 goto hard_reset;
994 1014 }
995 1015
996 1016 /*
997 1017 * Wait no more than 60 seconds for chip to become
998 1018 * ready.
999 1019 */
1000 1020 while ((ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell) &
1001 1021 MPI2_IOC_STATE_READY) == 0x0) {
1002 1022 drv_usecwait(1000);
1003 1023 if (polls++ > 60000) {
1004 1024 goto hard_reset;
1005 1025 }
1006 1026 }
1007 1027
1008 1028 /*
1009 1029 * Save the last reset mode done on IOC which will be
1010 1030 * helpful while resuming from suspension.
1011 1031 */
1012 1032 mpt->m_softstate |= MPTSAS_DID_MSG_UNIT_RESET;
1013 1033
1014 1034 /*
1015 1035 * the message unit reset would do reset operations
1016 1036 * clear reply and request queue, so we should clear
1017 1037 * ACK event cmd.
1018 1038 */
1019 1039 mptsas_destroy_ioc_event_cmd(mpt);
1020 1040 return (MPTSAS_SUCCESS_MUR);
1021 1041 }
1022 1042 }
1023 1043 hard_reset:
1024 1044 mpt->m_softstate &= ~MPTSAS_DID_MSG_UNIT_RESET;
1025 1045 if (mptsas_kick_start(mpt) == DDI_FAILURE) {
1026 1046 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
1027 1047 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
1028 1048 return (MPTSAS_RESET_FAIL);
1029 1049 }
1030 1050 return (MPTSAS_SUCCESS_HARDRESET);
1031 1051 }
1032 1052
1033 1053
1034 1054 int
1035 1055 mptsas_request_from_pool(mptsas_t *mpt, mptsas_cmd_t **cmd,
1036 1056 struct scsi_pkt **pkt)
1037 1057 {
1038 1058 m_event_struct_t *ioc_cmd = NULL;
1039 1059
1040 1060 ioc_cmd = kmem_zalloc(M_EVENT_STRUCT_SIZE, KM_SLEEP);
1041 1061 if (ioc_cmd == NULL) {
1042 1062 return (DDI_FAILURE);
1043 1063 }
1044 1064 ioc_cmd->m_event_linkp = NULL;
1045 1065 mptsas_ioc_event_cmdq_add(mpt, ioc_cmd);
1046 1066 *cmd = &(ioc_cmd->m_event_cmd);
1047 1067 *pkt = &(ioc_cmd->m_event_pkt);
1048 1068
1049 1069 return (DDI_SUCCESS);
1050 1070 }
1051 1071
1052 1072 void
1053 1073 mptsas_return_to_pool(mptsas_t *mpt, mptsas_cmd_t *cmd)
1054 1074 {
1055 1075 m_event_struct_t *ioc_cmd = NULL;
1056 1076
1057 1077 ioc_cmd = mptsas_ioc_event_find_by_cmd(mpt, cmd);
1058 1078 if (ioc_cmd == NULL) {
1059 1079 return;
1060 1080 }
1061 1081
1062 1082 mptsas_ioc_event_cmdq_delete(mpt, ioc_cmd);
1063 1083 kmem_free(ioc_cmd, M_EVENT_STRUCT_SIZE);
1064 1084 ioc_cmd = NULL;
1065 1085 }
1066 1086
1067 1087 /*
1068 1088 * NOTE: We should be able to queue TM requests in the controller to make this
1069 1089 * a lot faster. If resetting all targets, for example, we can load the hi
1070 1090 * priority queue with its limit and the controller will reply as they are
1071 1091 * completed. This way, we don't have to poll for one reply at a time.
1072 1092 * Think about enhancing this later.
1073 1093 */
1074 1094 int
1075 1095 mptsas_ioc_task_management(mptsas_t *mpt, int task_type, uint16_t dev_handle,
1076 1096 int lun, uint8_t *reply, uint32_t reply_size, int mode)
1077 1097 {
1078 1098 /*
1079 1099 * In order to avoid allocating variables on the stack,
↓ open down ↓ |
407 lines elided |
↑ open up ↑ |
1080 1100 * we make use of the pre-existing mptsas_cmd_t and
1081 1101 * scsi_pkt which are included in the mptsas_t which
1082 1102 * is passed to this routine.
1083 1103 */
1084 1104
1085 1105 pMpi2SCSITaskManagementRequest_t task;
1086 1106 int rval = FALSE;
1087 1107 mptsas_cmd_t *cmd;
1088 1108 struct scsi_pkt *pkt;
1089 1109 mptsas_slots_t *slots = mpt->m_active;
1090 - uint32_t request_desc_low, i;
1110 + uint32_t i;
1111 + uint64_t request_desc;
1091 1112 pMPI2DefaultReply_t reply_msg;
1092 1113
1093 1114 /*
1094 1115 * Can't start another task management routine.
1095 1116 */
1096 1117 if (slots->m_slot[MPTSAS_TM_SLOT(mpt)] != NULL) {
1097 1118 mptsas_log(mpt, CE_WARN, "Can only start 1 task management"
1098 1119 " command at a time\n");
1099 1120 return (FALSE);
1100 1121 }
1101 1122
1102 1123 cmd = &(mpt->m_event_task_mgmt.m_event_cmd);
1103 1124 pkt = &(mpt->m_event_task_mgmt.m_event_pkt);
1104 1125
1105 1126 bzero((caddr_t)cmd, sizeof (*cmd));
1106 1127 bzero((caddr_t)pkt, scsi_pkt_size());
1107 1128
1108 1129 pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb[0];
1109 1130 pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
1110 1131 pkt->pkt_ha_private = (opaque_t)cmd;
1111 1132 pkt->pkt_flags = (FLAG_NOINTR | FLAG_HEAD);
1112 1133 pkt->pkt_time = 60;
1113 1134 pkt->pkt_address.a_target = dev_handle;
1114 1135 pkt->pkt_address.a_lun = (uchar_t)lun;
1115 1136 cmd->cmd_pkt = pkt;
1116 1137 cmd->cmd_scblen = 1;
1117 1138 cmd->cmd_flags = CFLAG_TM_CMD;
1118 1139 cmd->cmd_slot = MPTSAS_TM_SLOT(mpt);
1119 1140
1120 1141 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = cmd;
1121 1142
1122 1143 /*
1123 1144 * Store the TM message in memory location corresponding to the TM slot
1124 1145 * number.
1125 1146 */
1126 1147 task = (pMpi2SCSITaskManagementRequest_t)(mpt->m_req_frame +
1127 1148 (mpt->m_req_frame_size * cmd->cmd_slot));
1128 1149 bzero(task, mpt->m_req_frame_size);
1129 1150
1130 1151 /*
1131 1152 * form message for requested task
1132 1153 */
1133 1154 mptsas_init_std_hdr(mpt->m_acc_req_frame_hdl, task, dev_handle, lun, 0,
1134 1155 MPI2_FUNCTION_SCSI_TASK_MGMT);
1135 1156
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
1136 1157 /*
1137 1158 * Set the task type
1138 1159 */
1139 1160 ddi_put8(mpt->m_acc_req_frame_hdl, &task->TaskType, task_type);
1140 1161
1141 1162 /*
1142 1163 * Send TM request using High Priority Queue.
1143 1164 */
1144 1165 (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
1145 1166 DDI_DMA_SYNC_FORDEV);
1146 - request_desc_low = (cmd->cmd_slot << 16) +
1167 + request_desc = (cmd->cmd_slot << 16) +
1147 1168 MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
1148 - MPTSAS_START_CMD(mpt, request_desc_low, 0);
1169 + MPTSAS_START_CMD(mpt, request_desc);
1149 1170 rval = mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
1150 1171
1151 1172 if (pkt->pkt_reason == CMD_INCOMPLETE)
1152 1173 rval = FALSE;
1153 1174
1154 1175 /*
1155 1176 * If a reply frame was used and there is a reply buffer to copy the
1156 1177 * reply data into, copy it. If this fails, log a message, but don't
1157 1178 * fail the TM request.
1158 1179 */
1159 1180 if (cmd->cmd_rfm && reply) {
1160 1181 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
1161 1182 DDI_DMA_SYNC_FORCPU);
1162 1183 reply_msg = (pMPI2DefaultReply_t)
1163 1184 (mpt->m_reply_frame + (cmd->cmd_rfm -
1164 - mpt->m_reply_frame_dma_addr));
1185 + (mpt->m_reply_frame_dma_addr&0xfffffffful)));
1165 1186 if (reply_size > sizeof (MPI2_SCSI_TASK_MANAGE_REPLY)) {
1166 1187 reply_size = sizeof (MPI2_SCSI_TASK_MANAGE_REPLY);
1167 1188 }
1168 1189 mutex_exit(&mpt->m_mutex);
1169 1190 for (i = 0; i < reply_size; i++) {
1170 1191 if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
1171 1192 mode)) {
1172 1193 mptsas_log(mpt, CE_WARN, "failed to copy out "
1173 1194 "reply data for TM request");
1174 1195 break;
1175 1196 }
1176 1197 }
1177 1198 mutex_enter(&mpt->m_mutex);
1178 1199 }
1179 1200
1180 1201 /*
1181 1202 * clear the TM slot before returning
1182 1203 */
1183 1204 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = NULL;
1184 1205
1185 1206 /*
1186 1207 * If we lost our task management command
1187 1208 * we need to reset the ioc
1188 1209 */
1189 1210 if (rval == FALSE) {
1190 1211 mptsas_log(mpt, CE_WARN, "mptsas_ioc_task_management failed "
1191 1212 "try to reset ioc to recovery!");
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
1192 1213 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
1193 1214 if (mptsas_restart_ioc(mpt)) {
1194 1215 mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
1195 1216 rval = FAILED;
1196 1217 }
1197 1218 }
1198 1219
1199 1220 return (rval);
1200 1221 }
1201 1222
1223 +/*
1224 + * Complete firmware download frame for v2.0 cards.
1225 + */
1226 +static void
1227 +mptsas_uflash2(pMpi2FWDownloadRequest fwdownload,
1228 + ddi_acc_handle_t acc_hdl, uint32_t size, uint8_t type,
1229 + ddi_dma_cookie_t flsh_cookie)
1230 +{
1231 + pMpi2FWDownloadTCSGE_t tcsge;
1232 + pMpi2SGESimple64_t sge;
1233 + uint32_t flagslength;
1234 +
1235 + ddi_put8(acc_hdl, &fwdownload->Function,
1236 + MPI2_FUNCTION_FW_DOWNLOAD);
1237 + ddi_put8(acc_hdl, &fwdownload->ImageType, type);
1238 + ddi_put8(acc_hdl, &fwdownload->MsgFlags,
1239 + MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT);
1240 + ddi_put32(acc_hdl, &fwdownload->TotalImageSize, size);
1241 +
1242 + tcsge = (pMpi2FWDownloadTCSGE_t)&fwdownload->SGL;
1243 + ddi_put8(acc_hdl, &tcsge->ContextSize, 0);
1244 + ddi_put8(acc_hdl, &tcsge->DetailsLength, 12);
1245 + ddi_put8(acc_hdl, &tcsge->Flags, 0);
1246 + ddi_put32(acc_hdl, &tcsge->ImageOffset, 0);
1247 + ddi_put32(acc_hdl, &tcsge->ImageSize, size);
1248 +
1249 + sge = (pMpi2SGESimple64_t)(tcsge + 1);
1250 + flagslength = size;
1251 + flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
1252 + MPI2_SGE_FLAGS_END_OF_BUFFER |
1253 + MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1254 + MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
1255 + MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1256 + MPI2_SGE_FLAGS_HOST_TO_IOC |
1257 + MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
1258 + ddi_put32(acc_hdl, &sge->FlagsLength, flagslength);
1259 + ddi_put32(acc_hdl, &sge->Address.Low,
1260 + flsh_cookie.dmac_address);
1261 + ddi_put32(acc_hdl, &sge->Address.High,
1262 + (uint32_t)(flsh_cookie.dmac_laddress >> 32));
1263 +}
1264 +
1265 +/*
1266 + * Complete firmware download frame for v2.5 cards.
1267 + */
1268 +static void
1269 +mptsas_uflash25(pMpi25FWDownloadRequest fwdownload,
1270 + ddi_acc_handle_t acc_hdl, uint32_t size, uint8_t type,
1271 + ddi_dma_cookie_t flsh_cookie)
1272 +{
1273 + pMpi2IeeeSgeSimple64_t sge;
1274 + uint8_t flags;
1275 +
1276 + ddi_put8(acc_hdl, &fwdownload->Function,
1277 + MPI2_FUNCTION_FW_DOWNLOAD);
1278 + ddi_put8(acc_hdl, &fwdownload->ImageType, type);
1279 + ddi_put8(acc_hdl, &fwdownload->MsgFlags,
1280 + MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT);
1281 + ddi_put32(acc_hdl, &fwdownload->TotalImageSize, size);
1282 +
1283 + ddi_put32(acc_hdl, &fwdownload->ImageOffset, 0);
1284 + ddi_put32(acc_hdl, &fwdownload->ImageSize, size);
1285 +
1286 + sge = (pMpi2IeeeSgeSimple64_t)&fwdownload->SGL;
1287 + flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
1288 + MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR |
1289 + MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
1290 + ddi_put8(acc_hdl, &sge->Flags, flags);
1291 + ddi_put32(acc_hdl, &sge->Length, size);
1292 + ddi_put32(acc_hdl, &sge->Address.Low,
1293 + flsh_cookie.dmac_address);
1294 + ddi_put32(acc_hdl, &sge->Address.High,
1295 + (uint32_t)(flsh_cookie.dmac_laddress >> 32));
1296 +}
1297 +
1298 +static int mptsas_enable_mpi25_flashupdate = 0;
1299 +
1202 1300 int
1203 1301 mptsas_update_flash(mptsas_t *mpt, caddr_t ptrbuffer, uint32_t size,
1204 1302 uint8_t type, int mode)
1205 1303 {
1206 1304
1207 1305 /*
1208 1306 * In order to avoid allocating variables on the stack,
1209 1307 * we make use of the pre-existing mptsas_cmd_t and
1210 1308 * scsi_pkt which are included in the mptsas_t which
1211 1309 * is passed to this routine.
1212 1310 */
1213 1311
1214 1312 ddi_dma_attr_t flsh_dma_attrs;
1215 1313 ddi_dma_cookie_t flsh_cookie;
1216 1314 ddi_dma_handle_t flsh_dma_handle;
1217 1315 ddi_acc_handle_t flsh_accessp;
1218 1316 caddr_t memp, flsh_memp;
1219 - uint32_t flagslength;
1220 - pMpi2FWDownloadRequest fwdownload;
1221 - pMpi2FWDownloadTCSGE_t tcsge;
1222 - pMpi2SGESimple64_t sge;
1223 1317 mptsas_cmd_t *cmd;
1224 1318 struct scsi_pkt *pkt;
1225 1319 int i;
1226 1320 int rvalue = 0;
1227 - uint32_t request_desc_low;
1321 + uint64_t request_desc;
1322 +
1323 + if (mpt->m_MPI25) {
1324 + /*
1325 + * The code is there but not tested yet.
1326 + * User has to know there are risks here.
1327 + */
1328 + mptsas_log(mpt, CE_WARN, "mptsas_update_flash(): "
1329 + "Updating firmware through MPI 2.5 has not been "
1330 + "tested yet!\n"
1331 + "To enable set mptsas_enable_mpi25_flashupdate to 1\n");
1332 + if (!mptsas_enable_mpi25_flashupdate)
1333 + return (-1);
1334 + }
1228 1335
1229 1336 if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
1230 1337 mptsas_log(mpt, CE_WARN, "mptsas_update_flash(): allocation "
1231 1338 "failed. event ack command pool is full\n");
1232 1339 return (rvalue);
1233 1340 }
1234 1341
1235 1342 bzero((caddr_t)cmd, sizeof (*cmd));
1236 1343 bzero((caddr_t)pkt, scsi_pkt_size());
1237 1344 cmd->ioc_cmd_slot = (uint32_t)rvalue;
1238 1345
1239 1346 /*
1240 1347 * dynamically create a customized dma attribute structure
1241 1348 * that describes the flash file.
1242 1349 */
1243 1350 flsh_dma_attrs = mpt->m_msg_dma_attr;
1244 1351 flsh_dma_attrs.dma_attr_sgllen = 1;
1245 1352
1246 1353 if (mptsas_dma_addr_create(mpt, flsh_dma_attrs, &flsh_dma_handle,
1247 1354 &flsh_accessp, &flsh_memp, size, &flsh_cookie) == FALSE) {
1248 1355 mptsas_log(mpt, CE_WARN,
1249 1356 "(unable to allocate dma resource.");
1250 1357 mptsas_return_to_pool(mpt, cmd);
1251 1358 return (-1);
1252 1359 }
1253 1360
1254 1361 bzero(flsh_memp, size);
1255 1362
1256 1363 for (i = 0; i < size; i++) {
1257 1364 (void) ddi_copyin(ptrbuffer + i, flsh_memp + i, 1, mode);
1258 1365 }
1259 1366 (void) ddi_dma_sync(flsh_dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV);
1260 1367
1261 1368 /*
1262 1369 * form a cmd/pkt to store the fw download message
1263 1370 */
1264 1371 pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb[0];
1265 1372 pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
1266 1373 pkt->pkt_ha_private = (opaque_t)cmd;
1267 1374 pkt->pkt_flags = FLAG_HEAD;
1268 1375 pkt->pkt_time = 60;
1269 1376 cmd->cmd_pkt = pkt;
1270 1377 cmd->cmd_scblen = 1;
1271 1378 cmd->cmd_flags = CFLAG_CMDIOC | CFLAG_FW_CMD;
1272 1379
1273 1380 /*
1274 1381 * Save the command in a slot
1275 1382 */
1276 1383 if (mptsas_save_cmd(mpt, cmd) == FALSE) {
1277 1384 mptsas_dma_addr_destroy(&flsh_dma_handle, &flsh_accessp);
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
1278 1385 mptsas_return_to_pool(mpt, cmd);
1279 1386 return (-1);
1280 1387 }
1281 1388
1282 1389 /*
1283 1390 * Fill in fw download message
1284 1391 */
1285 1392 ASSERT(cmd->cmd_slot != 0);
1286 1393 memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
1287 1394 bzero(memp, mpt->m_req_frame_size);
1288 - fwdownload = (void *)memp;
1289 - ddi_put8(mpt->m_acc_req_frame_hdl, &fwdownload->Function,
1290 - MPI2_FUNCTION_FW_DOWNLOAD);
1291 - ddi_put8(mpt->m_acc_req_frame_hdl, &fwdownload->ImageType, type);
1292 - ddi_put8(mpt->m_acc_req_frame_hdl, &fwdownload->MsgFlags,
1293 - MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT);
1294 - ddi_put32(mpt->m_acc_req_frame_hdl, &fwdownload->TotalImageSize, size);
1295 1395
1296 - tcsge = (pMpi2FWDownloadTCSGE_t)&fwdownload->SGL;
1297 - ddi_put8(mpt->m_acc_req_frame_hdl, &tcsge->ContextSize, 0);
1298 - ddi_put8(mpt->m_acc_req_frame_hdl, &tcsge->DetailsLength, 12);
1299 - ddi_put8(mpt->m_acc_req_frame_hdl, &tcsge->Flags, 0);
1300 - ddi_put32(mpt->m_acc_req_frame_hdl, &tcsge->ImageOffset, 0);
1301 - ddi_put32(mpt->m_acc_req_frame_hdl, &tcsge->ImageSize, size);
1302 -
1303 - sge = (pMpi2SGESimple64_t)(tcsge + 1);
1304 - flagslength = size;
1305 - flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
1306 - MPI2_SGE_FLAGS_END_OF_BUFFER |
1307 - MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1308 - MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
1309 - MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1310 - MPI2_SGE_FLAGS_HOST_TO_IOC |
1311 - MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
1312 - ddi_put32(mpt->m_acc_req_frame_hdl, &sge->FlagsLength, flagslength);
1313 - ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.Low,
1314 - flsh_cookie.dmac_address);
1315 - ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.High,
1316 - (uint32_t)(flsh_cookie.dmac_laddress >> 32));
1396 + if (mpt->m_MPI25)
1397 + mptsas_uflash25((pMpi25FWDownloadRequest)memp,
1398 + mpt->m_acc_req_frame_hdl, size, type, flsh_cookie);
1399 + else
1400 + mptsas_uflash2((pMpi2FWDownloadRequest)memp,
1401 + mpt->m_acc_req_frame_hdl, size, type, flsh_cookie);
1317 1402
1318 1403 /*
1319 1404 * Start command
1320 1405 */
1321 1406 (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
1322 1407 DDI_DMA_SYNC_FORDEV);
1323 - request_desc_low = (cmd->cmd_slot << 16) +
1408 + request_desc = (cmd->cmd_slot << 16) +
1324 1409 MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1325 1410 cmd->cmd_rfm = NULL;
1326 - MPTSAS_START_CMD(mpt, request_desc_low, 0);
1411 + MPTSAS_START_CMD(mpt, request_desc);
1327 1412
1328 1413 rvalue = 0;
1329 1414 (void) cv_reltimedwait(&mpt->m_fw_cv, &mpt->m_mutex,
1330 1415 drv_usectohz(60 * MICROSEC), TR_CLOCK_TICK);
1331 1416 if (!(cmd->cmd_flags & CFLAG_FINISHED)) {
1332 1417 mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
1333 1418 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
1334 1419 mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
1335 1420 }
1336 1421 rvalue = -1;
1337 1422 }
1338 1423 mptsas_remove_cmd(mpt, cmd);
1339 1424 mptsas_dma_addr_destroy(&flsh_dma_handle, &flsh_accessp);
1340 1425
1341 1426 return (rvalue);
1342 1427 }
1343 1428
1344 1429 static int
1345 1430 mptsas_sasdevpage_0_cb(mptsas_t *mpt, caddr_t page_memp,
1346 1431 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1347 1432 va_list ap)
1348 1433 {
1349 1434 #ifndef __lock_lint
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
1350 1435 _NOTE(ARGUNUSED(ap))
1351 1436 #endif
1352 1437 pMpi2SasDevicePage0_t sasdevpage;
1353 1438 int rval = DDI_SUCCESS, i;
1354 1439 uint8_t *sas_addr = NULL;
1355 1440 uint8_t tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
1356 1441 uint16_t *devhdl, *bay_num, *enclosure;
1357 1442 uint64_t *sas_wwn;
1358 1443 uint32_t *dev_info;
1359 1444 uint8_t *physport, *phynum;
1360 - uint16_t *pdevhdl;
1445 + uint16_t *pdevhdl, *io_flags;
1361 1446 uint32_t page_address;
1362 1447
1363 1448 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) &&
1364 1449 (iocstatus != MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)) {
1365 1450 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_device_page0 "
1366 1451 "header: IOCStatus=0x%x, IOCLogInfo=0x%x",
1367 1452 iocstatus, iocloginfo);
1368 1453 rval = DDI_FAILURE;
1369 1454 return (rval);
1370 1455 }
1371 1456 page_address = va_arg(ap, uint32_t);
1372 1457 /*
1373 1458 * The INVALID_PAGE status is normal if using GET_NEXT_HANDLE and there
1374 1459 * are no more pages. If everything is OK up to this point but the
1375 1460 * status is INVALID_PAGE, change rval to FAILURE and quit. Also,
1376 1461 * signal that device traversal is complete.
1377 1462 */
1378 1463 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
1379 1464 if ((page_address & MPI2_SAS_DEVICE_PGAD_FORM_MASK) ==
1380 1465 MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE) {
1381 1466 mpt->m_done_traverse_dev = 1;
1382 1467 }
1383 1468 rval = DDI_FAILURE;
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
1384 1469 return (rval);
1385 1470 }
1386 1471 devhdl = va_arg(ap, uint16_t *);
1387 1472 sas_wwn = va_arg(ap, uint64_t *);
1388 1473 dev_info = va_arg(ap, uint32_t *);
1389 1474 physport = va_arg(ap, uint8_t *);
1390 1475 phynum = va_arg(ap, uint8_t *);
1391 1476 pdevhdl = va_arg(ap, uint16_t *);
1392 1477 bay_num = va_arg(ap, uint16_t *);
1393 1478 enclosure = va_arg(ap, uint16_t *);
1394 -
1479 + io_flags = va_arg(ap, uint16_t *);
1395 1480
1396 1481 sasdevpage = (pMpi2SasDevicePage0_t)page_memp;
1397 1482
1398 1483 *dev_info = ddi_get32(accessp, &sasdevpage->DeviceInfo);
1399 1484 *devhdl = ddi_get16(accessp, &sasdevpage->DevHandle);
1400 1485 sas_addr = (uint8_t *)(&sasdevpage->SASAddress);
1401 1486 for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) {
1402 1487 tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i);
1403 1488 }
1404 1489 bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE);
1405 1490 *sas_wwn = LE_64(*sas_wwn);
1406 1491 *physport = ddi_get8(accessp, &sasdevpage->PhysicalPort);
1407 1492 *phynum = ddi_get8(accessp, &sasdevpage->PhyNum);
1408 1493 *pdevhdl = ddi_get16(accessp, &sasdevpage->ParentDevHandle);
1409 1494 *bay_num = ddi_get16(accessp, &sasdevpage->Slot);
1410 1495 *enclosure = ddi_get16(accessp, &sasdevpage->EnclosureHandle);
1496 + *io_flags = ddi_get16(accessp, &sasdevpage->Flags);
1497 +
1498 + if (*io_flags & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) {
1499 + /*
1500 + * Leave a messages about FP cabability in the log.
1501 + */
1502 + mptsas_log(mpt, CE_CONT,
1503 + "!w%016"PRIx64" FastPath Capable%s", *sas_wwn,
1504 + (*io_flags &
1505 + MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)?
1506 + " and Enabled":" but Disabled");
1507 + }
1508 +
1411 1509 return (rval);
1412 1510 }
1413 1511
1414 1512 /*
1415 1513 * Request MPI configuration page SAS device page 0 to get DevHandle, device
1416 1514 * info and SAS address.
1417 1515 */
1418 1516 int
1419 1517 mptsas_get_sas_device_page0(mptsas_t *mpt, uint32_t page_address,
1420 1518 uint16_t *dev_handle, uint64_t *sas_wwn, uint32_t *dev_info,
1421 1519 uint8_t *physport, uint8_t *phynum, uint16_t *pdev_handle,
1422 - uint16_t *bay_num, uint16_t *enclosure)
1520 + uint16_t *bay_num, uint16_t *enclosure, uint16_t *io_flags)
1423 1521 {
1424 1522 int rval = DDI_SUCCESS;
1425 1523
1426 1524 ASSERT(mutex_owned(&mpt->m_mutex));
1427 1525
1428 1526 /*
1429 1527 * Get the header and config page. reply contains the reply frame,
1430 1528 * which holds status info for the request.
1431 1529 */
1432 1530 rval = mptsas_access_config_page(mpt,
1433 1531 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
1434 1532 MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, page_address,
1435 1533 mptsas_sasdevpage_0_cb, page_address, dev_handle, sas_wwn,
1436 1534 dev_info, physport, phynum, pdev_handle,
1437 - bay_num, enclosure);
1535 + bay_num, enclosure, io_flags);
1438 1536
1439 1537 return (rval);
1440 1538 }
1441 1539
1442 1540 static int
1443 1541 mptsas_sasexpdpage_0_cb(mptsas_t *mpt, caddr_t page_memp,
1444 1542 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1445 1543 va_list ap)
1446 1544 {
1447 1545 #ifndef __lock_lint
1448 1546 _NOTE(ARGUNUSED(ap))
1449 1547 #endif
1450 1548 pMpi2ExpanderPage0_t expddevpage;
1451 1549 int rval = DDI_SUCCESS, i;
1452 1550 uint8_t *sas_addr = NULL;
1453 1551 uint8_t tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
1454 1552 uint16_t *devhdl;
1455 1553 uint64_t *sas_wwn;
1456 1554 uint8_t physport;
1457 1555 mptsas_phymask_t *phymask;
1458 1556 uint16_t *pdevhdl;
1459 1557 uint32_t page_address;
1460 1558
1461 1559 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) &&
1462 1560 (iocstatus != MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)) {
1463 1561 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_expander_page0 "
1464 1562 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
1465 1563 iocstatus, iocloginfo);
1466 1564 rval = DDI_FAILURE;
1467 1565 return (rval);
1468 1566 }
1469 1567 page_address = va_arg(ap, uint32_t);
1470 1568 /*
1471 1569 * The INVALID_PAGE status is normal if using GET_NEXT_HANDLE and there
1472 1570 * are no more pages. If everything is OK up to this point but the
1473 1571 * status is INVALID_PAGE, change rval to FAILURE and quit. Also,
1474 1572 * signal that device traversal is complete.
1475 1573 */
1476 1574 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
1477 1575 if ((page_address & MPI2_SAS_EXPAND_PGAD_FORM_MASK) ==
1478 1576 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL) {
1479 1577 mpt->m_done_traverse_smp = 1;
1480 1578 }
1481 1579 rval = DDI_FAILURE;
1482 1580 return (rval);
1483 1581 }
1484 1582 devhdl = va_arg(ap, uint16_t *);
1485 1583 sas_wwn = va_arg(ap, uint64_t *);
1486 1584 phymask = va_arg(ap, mptsas_phymask_t *);
1487 1585 pdevhdl = va_arg(ap, uint16_t *);
1488 1586
1489 1587 expddevpage = (pMpi2ExpanderPage0_t)page_memp;
1490 1588
1491 1589 *devhdl = ddi_get16(accessp, &expddevpage->DevHandle);
1492 1590 physport = ddi_get8(accessp, &expddevpage->PhysicalPort);
1493 1591 *phymask = mptsas_physport_to_phymask(mpt, physport);
1494 1592 *pdevhdl = ddi_get16(accessp, &expddevpage->ParentDevHandle);
1495 1593 sas_addr = (uint8_t *)(&expddevpage->SASAddress);
1496 1594 for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) {
1497 1595 tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i);
1498 1596 }
1499 1597 bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE);
1500 1598 *sas_wwn = LE_64(*sas_wwn);
1501 1599
1502 1600 return (rval);
1503 1601 }
1504 1602
1505 1603 /*
1506 1604 * Request MPI configuration page SAS device page 0 to get DevHandle, phymask
1507 1605 * and SAS address.
1508 1606 */
1509 1607 int
1510 1608 mptsas_get_sas_expander_page0(mptsas_t *mpt, uint32_t page_address,
1511 1609 mptsas_smp_t *info)
1512 1610 {
1513 1611 int rval = DDI_SUCCESS;
1514 1612
1515 1613 ASSERT(mutex_owned(&mpt->m_mutex));
1516 1614
1517 1615 /*
1518 1616 * Get the header and config page. reply contains the reply frame,
1519 1617 * which holds status info for the request.
1520 1618 */
1521 1619 rval = mptsas_access_config_page(mpt,
1522 1620 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
1523 1621 MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, page_address,
1524 1622 mptsas_sasexpdpage_0_cb, page_address, &info->m_devhdl,
1525 1623 &info->m_addr.mta_wwn, &info->m_addr.mta_phymask, &info->m_pdevhdl);
1526 1624
1527 1625 return (rval);
1528 1626 }
1529 1627
1530 1628 static int
1531 1629 mptsas_sasportpage_0_cb(mptsas_t *mpt, caddr_t page_memp,
1532 1630 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1533 1631 va_list ap)
1534 1632 {
1535 1633 #ifndef __lock_lint
1536 1634 _NOTE(ARGUNUSED(ap))
1537 1635 #endif
1538 1636 int rval = DDI_SUCCESS, i;
1539 1637 uint8_t *sas_addr = NULL;
1540 1638 uint64_t *sas_wwn;
1541 1639 uint8_t tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
1542 1640 uint8_t *portwidth;
1543 1641 pMpi2SasPortPage0_t sasportpage;
1544 1642
1545 1643 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
1546 1644 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_port_page0 "
1547 1645 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
1548 1646 iocstatus, iocloginfo);
1549 1647 rval = DDI_FAILURE;
1550 1648 return (rval);
1551 1649 }
1552 1650 sas_wwn = va_arg(ap, uint64_t *);
1553 1651 portwidth = va_arg(ap, uint8_t *);
1554 1652
1555 1653 sasportpage = (pMpi2SasPortPage0_t)page_memp;
1556 1654 sas_addr = (uint8_t *)(&sasportpage->SASAddress);
1557 1655 for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) {
1558 1656 tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i);
1559 1657 }
1560 1658 bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE);
1561 1659 *sas_wwn = LE_64(*sas_wwn);
1562 1660 *portwidth = ddi_get8(accessp, &sasportpage->PortWidth);
1563 1661 return (rval);
1564 1662 }
1565 1663
1566 1664 /*
1567 1665 * Request MPI configuration page SAS port page 0 to get initiator SAS address
1568 1666 * and port width.
1569 1667 */
1570 1668 int
1571 1669 mptsas_get_sas_port_page0(mptsas_t *mpt, uint32_t page_address,
1572 1670 uint64_t *sas_wwn, uint8_t *portwidth)
1573 1671 {
1574 1672 int rval = DDI_SUCCESS;
1575 1673
1576 1674 ASSERT(mutex_owned(&mpt->m_mutex));
1577 1675
1578 1676 /*
1579 1677 * Get the header and config page. reply contains the reply frame,
1580 1678 * which holds status info for the request.
1581 1679 */
1582 1680 rval = mptsas_access_config_page(mpt,
1583 1681 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
1584 1682 MPI2_CONFIG_EXTPAGETYPE_SAS_PORT, 0, page_address,
1585 1683 mptsas_sasportpage_0_cb, sas_wwn, portwidth);
1586 1684
1587 1685 return (rval);
1588 1686 }
1589 1687
1590 1688 static int
1591 1689 mptsas_sasiou_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
1592 1690 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1593 1691 va_list ap)
1594 1692 {
1595 1693 #ifndef __lock_lint
1596 1694 _NOTE(ARGUNUSED(ap))
1597 1695 #endif
1598 1696 int rval = DDI_SUCCESS;
1599 1697 pMpi2SasIOUnitPage0_t sasioupage0;
1600 1698 int i, num_phys;
1601 1699 uint32_t cpdi[MPTSAS_MAX_PHYS], *retrypage0, *readpage1;
1602 1700 uint8_t port_flags;
1603 1701
1604 1702 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
1605 1703 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_io_unit_page0 "
1606 1704 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
1607 1705 iocstatus, iocloginfo);
1608 1706 rval = DDI_FAILURE;
1609 1707 return (rval);
1610 1708 }
1611 1709 readpage1 = va_arg(ap, uint32_t *);
1612 1710 retrypage0 = va_arg(ap, uint32_t *);
1613 1711
1614 1712 sasioupage0 = (pMpi2SasIOUnitPage0_t)page_memp;
1615 1713
1616 1714 num_phys = ddi_get8(accessp, &sasioupage0->NumPhys);
1617 1715 /*
1618 1716 * ASSERT that the num_phys value in SAS IO Unit Page 0 is the same as
1619 1717 * was initially set. This should never change throughout the life of
1620 1718 * the driver.
1621 1719 */
1622 1720 ASSERT(num_phys == mpt->m_num_phys);
1623 1721 for (i = 0; i < num_phys; i++) {
1624 1722 cpdi[i] = ddi_get32(accessp,
1625 1723 &sasioupage0->PhyData[i].
1626 1724 ControllerPhyDeviceInfo);
1627 1725 port_flags = ddi_get8(accessp,
1628 1726 &sasioupage0->PhyData[i].PortFlags);
1629 1727 mpt->m_phy_info[i].port_num =
1630 1728 ddi_get8(accessp,
1631 1729 &sasioupage0->PhyData[i].Port);
1632 1730 mpt->m_phy_info[i].ctrl_devhdl =
1633 1731 ddi_get16(accessp, &sasioupage0->
1634 1732 PhyData[i].ControllerDevHandle);
1635 1733 mpt->m_phy_info[i].attached_devhdl =
1636 1734 ddi_get16(accessp, &sasioupage0->
1637 1735 PhyData[i].AttachedDevHandle);
1638 1736 mpt->m_phy_info[i].phy_device_type = cpdi[i];
1639 1737 mpt->m_phy_info[i].port_flags = port_flags;
1640 1738
1641 1739 if (port_flags & DISCOVERY_IN_PROGRESS) {
1642 1740 *retrypage0 = *retrypage0 + 1;
1643 1741 break;
1644 1742 } else {
1645 1743 *retrypage0 = 0;
1646 1744 }
1647 1745 if (!(port_flags & AUTO_PORT_CONFIGURATION)) {
1648 1746 /*
1649 1747 * some PHY configuration described in
1650 1748 * SAS IO Unit Page1
1651 1749 */
1652 1750 *readpage1 = 1;
1653 1751 }
1654 1752 }
1655 1753
1656 1754 return (rval);
1657 1755 }
1658 1756
1659 1757 static int
1660 1758 mptsas_sasiou_page_1_cb(mptsas_t *mpt, caddr_t page_memp,
1661 1759 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1662 1760 va_list ap)
1663 1761 {
1664 1762 #ifndef __lock_lint
1665 1763 _NOTE(ARGUNUSED(ap))
1666 1764 #endif
1667 1765 int rval = DDI_SUCCESS;
1668 1766 pMpi2SasIOUnitPage1_t sasioupage1;
1669 1767 int i, num_phys;
1670 1768 uint32_t cpdi[MPTSAS_MAX_PHYS];
1671 1769 uint8_t port_flags;
1672 1770
1673 1771 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
1674 1772 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_io_unit_page1 "
1675 1773 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
1676 1774 iocstatus, iocloginfo);
1677 1775 rval = DDI_FAILURE;
1678 1776 return (rval);
1679 1777 }
1680 1778
1681 1779 sasioupage1 = (pMpi2SasIOUnitPage1_t)page_memp;
1682 1780 num_phys = ddi_get8(accessp, &sasioupage1->NumPhys);
1683 1781 /*
1684 1782 * ASSERT that the num_phys value in SAS IO Unit Page 1 is the same as
1685 1783 * was initially set. This should never change throughout the life of
1686 1784 * the driver.
1687 1785 */
1688 1786 ASSERT(num_phys == mpt->m_num_phys);
1689 1787 for (i = 0; i < num_phys; i++) {
1690 1788 cpdi[i] = ddi_get32(accessp, &sasioupage1->PhyData[i].
1691 1789 ControllerPhyDeviceInfo);
1692 1790 port_flags = ddi_get8(accessp,
1693 1791 &sasioupage1->PhyData[i].PortFlags);
1694 1792 mpt->m_phy_info[i].port_num =
1695 1793 ddi_get8(accessp,
1696 1794 &sasioupage1->PhyData[i].Port);
1697 1795 mpt->m_phy_info[i].port_flags = port_flags;
1698 1796 mpt->m_phy_info[i].phy_device_type = cpdi[i];
1699 1797 }
1700 1798 return (rval);
1701 1799 }
1702 1800
1703 1801 /*
1704 1802 * Read IO unit page 0 to get information for each PHY. If needed, Read IO Unit
1705 1803 * page1 to update the PHY information. This is the message passing method of
1706 1804 * this function which should be called except during initialization.
1707 1805 */
1708 1806 int
1709 1807 mptsas_get_sas_io_unit_page(mptsas_t *mpt)
1710 1808 {
1711 1809 int rval = DDI_SUCCESS, state;
1712 1810 uint32_t readpage1 = 0, retrypage0 = 0;
1713 1811
1714 1812 ASSERT(mutex_owned(&mpt->m_mutex));
1715 1813
1716 1814 /*
1717 1815 * Now we cycle through the state machine. Here's what happens:
1718 1816 * 1. Read IO unit page 0 and set phy information
1719 1817 * 2. See if Read IO unit page1 is needed because of port configuration
1720 1818 * 3. Read IO unit page 1 and update phy information.
1721 1819 */
1722 1820 state = IOUC_READ_PAGE0;
1723 1821 while (state != IOUC_DONE) {
1724 1822 if (state == IOUC_READ_PAGE0) {
1725 1823 rval = mptsas_access_config_page(mpt,
1726 1824 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
1727 1825 MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, 0,
1728 1826 mptsas_sasiou_page_0_cb, &readpage1,
1729 1827 &retrypage0);
1730 1828 } else if (state == IOUC_READ_PAGE1) {
1731 1829 rval = mptsas_access_config_page(mpt,
1732 1830 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
1733 1831 MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 1, 0,
1734 1832 mptsas_sasiou_page_1_cb);
1735 1833 }
1736 1834
1737 1835 if (rval == DDI_SUCCESS) {
1738 1836 switch (state) {
1739 1837 case IOUC_READ_PAGE0:
1740 1838 /*
1741 1839 * retry 30 times if discovery is in process
1742 1840 */
1743 1841 if (retrypage0 && (retrypage0 < 30)) {
1744 1842 drv_usecwait(1000 * 100);
1745 1843 state = IOUC_READ_PAGE0;
1746 1844 break;
1747 1845 } else if (retrypage0 == 30) {
1748 1846 mptsas_log(mpt, CE_WARN,
1749 1847 "!Discovery in progress, can't "
1750 1848 "verify IO unit config, then "
1751 1849 "after 30 times retry, give "
1752 1850 "up!");
1753 1851 state = IOUC_DONE;
1754 1852 rval = DDI_FAILURE;
1755 1853 break;
1756 1854 }
1757 1855
1758 1856 if (readpage1 == 0) {
1759 1857 state = IOUC_DONE;
1760 1858 rval = DDI_SUCCESS;
1761 1859 break;
1762 1860 }
1763 1861
1764 1862 state = IOUC_READ_PAGE1;
1765 1863 break;
1766 1864
1767 1865 case IOUC_READ_PAGE1:
1768 1866 state = IOUC_DONE;
1769 1867 rval = DDI_SUCCESS;
1770 1868 break;
1771 1869 }
1772 1870 } else {
1773 1871 return (rval);
1774 1872 }
1775 1873 }
1776 1874
1777 1875 return (rval);
1778 1876 }
1779 1877
1780 1878 static int
1781 1879 mptsas_biospage_3_cb(mptsas_t *mpt, caddr_t page_memp,
1782 1880 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
1783 1881 va_list ap)
1784 1882 {
1785 1883 #ifndef __lock_lint
1786 1884 _NOTE(ARGUNUSED(ap))
1787 1885 #endif
1788 1886 pMpi2BiosPage3_t sasbiospage;
1789 1887 int rval = DDI_SUCCESS;
1790 1888 uint32_t *bios_version;
1791 1889
1792 1890 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) &&
1793 1891 (iocstatus != MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)) {
1794 1892 mptsas_log(mpt, CE_WARN, "mptsas_get_bios_page3 header: "
1795 1893 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, iocloginfo);
1796 1894 rval = DDI_FAILURE;
1797 1895 return (rval);
1798 1896 }
1799 1897 bios_version = va_arg(ap, uint32_t *);
1800 1898 sasbiospage = (pMpi2BiosPage3_t)page_memp;
1801 1899 *bios_version = ddi_get32(accessp, &sasbiospage->BiosVersion);
1802 1900
1803 1901 return (rval);
1804 1902 }
1805 1903
1806 1904 /*
1807 1905 * Request MPI configuration page BIOS page 3 to get BIOS version. Since all
1808 1906 * other information in this page is not needed, just ignore it.
1809 1907 */
1810 1908 int
1811 1909 mptsas_get_bios_page3(mptsas_t *mpt, uint32_t *bios_version)
1812 1910 {
1813 1911 int rval = DDI_SUCCESS;
1814 1912
1815 1913 ASSERT(mutex_owned(&mpt->m_mutex));
1816 1914
1817 1915 /*
1818 1916 * Get the header and config page. reply contains the reply frame,
1819 1917 * which holds status info for the request.
1820 1918 */
1821 1919 rval = mptsas_access_config_page(mpt,
1822 1920 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, MPI2_CONFIG_PAGETYPE_BIOS, 3,
1823 1921 0, mptsas_biospage_3_cb, bios_version);
1824 1922
1825 1923 return (rval);
1826 1924 }
1827 1925
1828 1926 /*
1829 1927 * Read IO unit page 0 to get information for each PHY. If needed, Read IO Unit
1830 1928 * page1 to update the PHY information. This is the handshaking version of
1831 1929 * this function, which should be called during initialization only.
1832 1930 */
1833 1931 int
1834 1932 mptsas_get_sas_io_unit_page_hndshk(mptsas_t *mpt)
1835 1933 {
1836 1934 ddi_dma_attr_t recv_dma_attrs, page_dma_attrs;
1837 1935 ddi_dma_cookie_t page_cookie;
1838 1936 ddi_dma_handle_t recv_dma_handle, page_dma_handle;
1839 1937 ddi_acc_handle_t recv_accessp, page_accessp;
1840 1938 pMpi2ConfigReply_t configreply;
1841 1939 pMpi2SasIOUnitPage0_t sasioupage0;
1842 1940 pMpi2SasIOUnitPage1_t sasioupage1;
1843 1941 int recv_numbytes;
1844 1942 caddr_t recv_memp, page_memp;
1845 1943 int i, num_phys, start_phy = 0;
1846 1944 int page0_size =
1847 1945 sizeof (MPI2_CONFIG_PAGE_SASIOUNIT_0) +
1848 1946 (sizeof (MPI2_SAS_IO_UNIT0_PHY_DATA) * (MPTSAS_MAX_PHYS - 1));
1849 1947 int page1_size =
↓ open down ↓ |
402 lines elided |
↑ open up ↑ |
1850 1948 sizeof (MPI2_CONFIG_PAGE_SASIOUNIT_1) +
1851 1949 (sizeof (MPI2_SAS_IO_UNIT1_PHY_DATA) * (MPTSAS_MAX_PHYS - 1));
1852 1950 uint32_t flags_length;
1853 1951 uint32_t cpdi[MPTSAS_MAX_PHYS];
1854 1952 uint32_t readpage1 = 0, retrypage0 = 0;
1855 1953 uint16_t iocstatus;
1856 1954 uint8_t port_flags, page_number, action;
1857 1955 uint32_t reply_size = 256; /* Big enough for any page */
1858 1956 uint_t state;
1859 1957 int rval = DDI_FAILURE;
1958 + boolean_t free_recv = B_FALSE, free_page = B_FALSE;
1860 1959
1861 1960 /*
1862 1961 * Initialize our "state machine". This is a bit convoluted,
1863 1962 * but it keeps us from having to do the ddi allocations numerous
1864 1963 * times.
1865 1964 */
1866 1965
1867 1966 NDBG20(("mptsas_get_sas_io_unit_page_hndshk enter"));
1868 1967 ASSERT(mutex_owned(&mpt->m_mutex));
1869 1968 state = IOUC_READ_PAGE0;
1870 1969
1871 1970 /*
1872 1971 * dynamically create a customized dma attribute structure
1873 1972 * that describes mpt's config reply page request structure.
1874 1973 */
1875 1974 recv_dma_attrs = mpt->m_msg_dma_attr;
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
1876 1975 recv_dma_attrs.dma_attr_sgllen = 1;
1877 1976 recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
1878 1977
1879 1978 if (mptsas_dma_addr_create(mpt, recv_dma_attrs,
1880 1979 &recv_dma_handle, &recv_accessp, &recv_memp,
1881 1980 (sizeof (MPI2_CONFIG_REPLY)), NULL) == FALSE) {
1882 1981 mptsas_log(mpt, CE_WARN,
1883 1982 "mptsas_get_sas_io_unit_page_hndshk: recv dma failed");
1884 1983 goto cleanup;
1885 1984 }
1985 + /* Now safe to call mptsas_dma_addr_destroy(recv_dma_handle). */
1986 + free_recv = B_TRUE;
1886 1987
1887 1988 page_dma_attrs = mpt->m_msg_dma_attr;
1888 1989 page_dma_attrs.dma_attr_sgllen = 1;
1889 1990 page_dma_attrs.dma_attr_granular = reply_size;
1890 1991
1891 1992 if (mptsas_dma_addr_create(mpt, page_dma_attrs,
1892 1993 &page_dma_handle, &page_accessp, &page_memp,
1893 1994 reply_size, &page_cookie) == FALSE) {
1894 1995 mptsas_log(mpt, CE_WARN,
1895 1996 "mptsas_get_sas_io_unit_page_hndshk: page dma failed");
1896 1997 goto cleanup;
1897 1998 }
1999 + /* Now safe to call mptsas_dma_addr_destroy(page_dma_handle). */
2000 + free_page = B_TRUE;
1898 2001
1899 2002 /*
1900 2003 * Now we cycle through the state machine. Here's what happens:
1901 2004 * 1. Read IO unit page 0 and set phy information
1902 2005 * 2. See if Read IO unit page1 is needed because of port configuration
1903 2006 * 3. Read IO unit page 1 and update phy information.
1904 2007 */
1905 2008
1906 2009 sasioupage0 = (pMpi2SasIOUnitPage0_t)page_memp;
1907 2010 sasioupage1 = (pMpi2SasIOUnitPage1_t)page_memp;
1908 2011
1909 2012 while (state != IOUC_DONE) {
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
1910 2013 switch (state) {
1911 2014 case IOUC_READ_PAGE0:
1912 2015 page_number = 0;
1913 2016 action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1914 2017 flags_length = (uint32_t)page0_size;
1915 2018 flags_length |= ((uint32_t)(
1916 2019 MPI2_SGE_FLAGS_LAST_ELEMENT |
1917 2020 MPI2_SGE_FLAGS_END_OF_BUFFER |
1918 2021 MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1919 2022 MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
1920 - MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
2023 + MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1921 2024 MPI2_SGE_FLAGS_IOC_TO_HOST |
1922 2025 MPI2_SGE_FLAGS_END_OF_LIST) <<
1923 2026 MPI2_SGE_FLAGS_SHIFT);
1924 2027
1925 2028 break;
1926 2029
1927 2030 case IOUC_READ_PAGE1:
1928 2031 page_number = 1;
1929 2032 action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1930 2033 flags_length = (uint32_t)page1_size;
1931 2034 flags_length |= ((uint32_t)(
1932 2035 MPI2_SGE_FLAGS_LAST_ELEMENT |
1933 2036 MPI2_SGE_FLAGS_END_OF_BUFFER |
1934 2037 MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1935 2038 MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
1936 - MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
2039 + MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1937 2040 MPI2_SGE_FLAGS_IOC_TO_HOST |
1938 2041 MPI2_SGE_FLAGS_END_OF_LIST) <<
1939 2042 MPI2_SGE_FLAGS_SHIFT);
1940 2043
1941 2044 break;
1942 2045 default:
1943 2046 break;
1944 2047 }
1945 2048
1946 2049 bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
1947 2050 configreply = (pMpi2ConfigReply_t)recv_memp;
1948 2051 recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
1949 2052
1950 2053 if (mptsas_send_extended_config_request_msg(mpt,
1951 2054 MPI2_CONFIG_ACTION_PAGE_HEADER,
1952 2055 MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
1953 2056 0, page_number, 0, 0, 0, 0)) {
1954 2057 goto cleanup;
1955 2058 }
1956 2059
1957 2060 if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
1958 2061 recv_accessp)) {
1959 2062 goto cleanup;
1960 2063 }
1961 2064
1962 2065 iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus);
1963 2066 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
1964 2067
1965 2068 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
1966 2069 mptsas_log(mpt, CE_WARN,
1967 2070 "mptsas_get_sas_io_unit_page_hndshk: read page "
1968 2071 "header iocstatus = 0x%x", iocstatus);
1969 2072 goto cleanup;
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
1970 2073 }
1971 2074
1972 2075 if (action != MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
1973 2076 bzero(page_memp, reply_size);
1974 2077 }
1975 2078
1976 2079 if (mptsas_send_extended_config_request_msg(mpt, action,
1977 2080 MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, page_number,
1978 2081 ddi_get8(recv_accessp, &configreply->Header.PageVersion),
1979 2082 ddi_get16(recv_accessp, &configreply->ExtPageLength),
1980 - flags_length, page_cookie.dmac_address)) {
2083 + flags_length, page_cookie.dmac_laddress)) {
1981 2084 goto cleanup;
1982 2085 }
1983 2086
1984 2087 if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
1985 2088 recv_accessp)) {
1986 2089 goto cleanup;
1987 2090 }
1988 2091
1989 2092 iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus);
1990 2093 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
1991 2094
1992 2095 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
1993 2096 mptsas_log(mpt, CE_WARN,
1994 2097 "mptsas_get_sas_io_unit_page_hndshk: IO unit "
1995 2098 "config failed for action %d, iocstatus = 0x%x",
1996 2099 action, iocstatus);
1997 2100 goto cleanup;
1998 2101 }
1999 2102
2000 2103 switch (state) {
2001 2104 case IOUC_READ_PAGE0:
2002 2105 if ((ddi_dma_sync(page_dma_handle, 0, 0,
2003 2106 DDI_DMA_SYNC_FORCPU)) != DDI_SUCCESS) {
2004 2107 goto cleanup;
2005 2108 }
2006 2109
2007 2110 num_phys = ddi_get8(page_accessp,
2008 2111 &sasioupage0->NumPhys);
2009 2112 ASSERT(num_phys == mpt->m_num_phys);
2010 2113 if (num_phys > MPTSAS_MAX_PHYS) {
2011 2114 mptsas_log(mpt, CE_WARN, "Number of phys "
2012 2115 "supported by HBA (%d) is more than max "
2013 2116 "supported by driver (%d). Driver will "
2014 2117 "not attach.", num_phys,
2015 2118 MPTSAS_MAX_PHYS);
2016 2119 rval = DDI_FAILURE;
2017 2120 goto cleanup;
2018 2121 }
2019 2122 for (i = start_phy; i < num_phys; i++, start_phy = i) {
2020 2123 cpdi[i] = ddi_get32(page_accessp,
2021 2124 &sasioupage0->PhyData[i].
2022 2125 ControllerPhyDeviceInfo);
2023 2126 port_flags = ddi_get8(page_accessp,
2024 2127 &sasioupage0->PhyData[i].PortFlags);
2025 2128
2026 2129 mpt->m_phy_info[i].port_num =
2027 2130 ddi_get8(page_accessp,
2028 2131 &sasioupage0->PhyData[i].Port);
2029 2132 mpt->m_phy_info[i].ctrl_devhdl =
2030 2133 ddi_get16(page_accessp, &sasioupage0->
2031 2134 PhyData[i].ControllerDevHandle);
2032 2135 mpt->m_phy_info[i].attached_devhdl =
2033 2136 ddi_get16(page_accessp, &sasioupage0->
2034 2137 PhyData[i].AttachedDevHandle);
2035 2138 mpt->m_phy_info[i].phy_device_type = cpdi[i];
2036 2139 mpt->m_phy_info[i].port_flags = port_flags;
2037 2140
2038 2141 if (port_flags & DISCOVERY_IN_PROGRESS) {
2039 2142 retrypage0++;
2040 2143 NDBG20(("Discovery in progress, can't "
2041 2144 "verify IO unit config, then NO.%d"
2042 2145 " times retry", retrypage0));
2043 2146 break;
2044 2147 } else {
2045 2148 retrypage0 = 0;
2046 2149 }
2047 2150 if (!(port_flags & AUTO_PORT_CONFIGURATION)) {
2048 2151 /*
2049 2152 * some PHY configuration described in
2050 2153 * SAS IO Unit Page1
2051 2154 */
2052 2155 readpage1 = 1;
2053 2156 }
2054 2157 }
2055 2158
2056 2159 /*
2057 2160 * retry 30 times if discovery is in process
2058 2161 */
2059 2162 if (retrypage0 && (retrypage0 < 30)) {
2060 2163 drv_usecwait(1000 * 100);
2061 2164 state = IOUC_READ_PAGE0;
2062 2165 break;
2063 2166 } else if (retrypage0 == 30) {
2064 2167 mptsas_log(mpt, CE_WARN,
2065 2168 "!Discovery in progress, can't "
2066 2169 "verify IO unit config, then after"
2067 2170 " 30 times retry, give up!");
2068 2171 state = IOUC_DONE;
2069 2172 rval = DDI_FAILURE;
2070 2173 break;
2071 2174 }
2072 2175
2073 2176 if (readpage1 == 0) {
2074 2177 state = IOUC_DONE;
2075 2178 rval = DDI_SUCCESS;
2076 2179 break;
2077 2180 }
2078 2181
2079 2182 state = IOUC_READ_PAGE1;
2080 2183 break;
2081 2184
2082 2185 case IOUC_READ_PAGE1:
2083 2186 if ((ddi_dma_sync(page_dma_handle, 0, 0,
2084 2187 DDI_DMA_SYNC_FORCPU)) != DDI_SUCCESS) {
2085 2188 goto cleanup;
2086 2189 }
2087 2190
2088 2191 num_phys = ddi_get8(page_accessp,
2089 2192 &sasioupage1->NumPhys);
2090 2193 ASSERT(num_phys == mpt->m_num_phys);
2091 2194 if (num_phys > MPTSAS_MAX_PHYS) {
2092 2195 mptsas_log(mpt, CE_WARN, "Number of phys "
2093 2196 "supported by HBA (%d) is more than max "
2094 2197 "supported by driver (%d). Driver will "
2095 2198 "not attach.", num_phys,
2096 2199 MPTSAS_MAX_PHYS);
2097 2200 rval = DDI_FAILURE;
2098 2201 goto cleanup;
2099 2202 }
2100 2203 for (i = 0; i < num_phys; i++) {
2101 2204 cpdi[i] = ddi_get32(page_accessp,
2102 2205 &sasioupage1->PhyData[i].
2103 2206 ControllerPhyDeviceInfo);
2104 2207 port_flags = ddi_get8(page_accessp,
2105 2208 &sasioupage1->PhyData[i].PortFlags);
2106 2209 mpt->m_phy_info[i].port_num =
2107 2210 ddi_get8(page_accessp,
2108 2211 &sasioupage1->PhyData[i].Port);
2109 2212 mpt->m_phy_info[i].port_flags = port_flags;
2110 2213 mpt->m_phy_info[i].phy_device_type = cpdi[i];
2111 2214
2112 2215 }
2113 2216
2114 2217 state = IOUC_DONE;
2115 2218 rval = DDI_SUCCESS;
2116 2219 break;
2117 2220 }
2118 2221 }
2119 2222 if ((mptsas_check_dma_handle(recv_dma_handle) != DDI_SUCCESS) ||
2120 2223 (mptsas_check_dma_handle(page_dma_handle) != DDI_SUCCESS)) {
2121 2224 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2122 2225 rval = DDI_FAILURE;
↓ open down ↓ |
132 lines elided |
↑ open up ↑ |
2123 2226 goto cleanup;
2124 2227 }
2125 2228 if ((mptsas_check_acc_handle(recv_accessp) != DDI_SUCCESS) ||
2126 2229 (mptsas_check_acc_handle(page_accessp) != DDI_SUCCESS)) {
2127 2230 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2128 2231 rval = DDI_FAILURE;
2129 2232 goto cleanup;
2130 2233 }
2131 2234
2132 2235 cleanup:
2133 - mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
2134 - mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2236 + if (free_recv)
2237 + mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
2238 + if (free_page)
2239 + mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2135 2240 if (rval != DDI_SUCCESS) {
2136 2241 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
2137 2242 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
2138 2243 }
2139 2244 return (rval);
2140 2245 }
2141 2246
2142 2247 /*
2143 2248 * mptsas_get_manufacture_page5
2144 2249 *
2145 2250 * This function will retrieve the base WWID from the adapter. Since this
2146 2251 * function is only called during the initialization process, use handshaking.
2147 2252 */
2148 2253 int
2149 2254 mptsas_get_manufacture_page5(mptsas_t *mpt)
2150 2255 {
2151 2256 ddi_dma_attr_t recv_dma_attrs, page_dma_attrs;
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
2152 2257 ddi_dma_cookie_t page_cookie;
2153 2258 ddi_dma_handle_t recv_dma_handle, page_dma_handle;
2154 2259 ddi_acc_handle_t recv_accessp, page_accessp;
2155 2260 pMpi2ConfigReply_t configreply;
2156 2261 caddr_t recv_memp, page_memp;
2157 2262 int recv_numbytes;
2158 2263 pMpi2ManufacturingPage5_t m5;
2159 2264 uint32_t flagslength;
2160 2265 int rval = DDI_SUCCESS;
2161 2266 uint_t iocstatus;
2267 + boolean_t free_recv = B_FALSE, free_page = B_FALSE;
2162 2268
2163 2269 MPTSAS_DISABLE_INTR(mpt);
2164 2270
2165 2271 if (mptsas_send_config_request_msg(mpt, MPI2_CONFIG_ACTION_PAGE_HEADER,
2166 2272 MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 5, 0, 0, 0, 0)) {
2167 2273 rval = DDI_FAILURE;
2168 2274 goto done;
2169 2275 }
2170 2276
2171 2277 /*
2172 2278 * dynamically create a customized dma attribute structure
2173 2279 * that describes the MPT's config reply page request structure.
2174 2280 */
2175 2281 recv_dma_attrs = mpt->m_msg_dma_attr;
2176 2282 recv_dma_attrs.dma_attr_sgllen = 1;
2177 2283 recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
2178 2284
2179 2285 if (mptsas_dma_addr_create(mpt, recv_dma_attrs,
2180 2286 &recv_dma_handle, &recv_accessp, &recv_memp,
2181 2287 (sizeof (MPI2_CONFIG_REPLY)), NULL) == FALSE) {
2288 + rval = DDI_FAILURE;
2182 2289 goto done;
2183 2290 }
2291 + /* Now safe to call mptsas_dma_addr_destroy(recv_dma_handle). */
2292 + free_recv = B_TRUE;
2184 2293
2185 2294 bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
2186 2295 configreply = (pMpi2ConfigReply_t)recv_memp;
2187 2296 recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
2188 2297
2189 2298 /*
2190 2299 * get config reply message
2191 2300 */
2192 2301 if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2193 2302 recv_accessp)) {
2194 2303 rval = DDI_FAILURE;
2195 2304 goto done;
2196 2305 }
2197 2306
2198 2307 if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2199 2308 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page5 update: "
2200 2309 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2201 2310 ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2202 2311 goto done;
2203 2312 }
2204 2313
2205 2314 /*
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
2206 2315 * dynamically create a customized dma attribute structure
2207 2316 * that describes the MPT's config page structure.
2208 2317 */
2209 2318 page_dma_attrs = mpt->m_msg_dma_attr;
2210 2319 page_dma_attrs.dma_attr_sgllen = 1;
2211 2320 page_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_PAGE_MAN_5));
2212 2321
2213 2322 if (mptsas_dma_addr_create(mpt, page_dma_attrs, &page_dma_handle,
2214 2323 &page_accessp, &page_memp, (sizeof (MPI2_CONFIG_PAGE_MAN_5)),
2215 2324 &page_cookie) == FALSE) {
2325 + rval = DDI_FAILURE;
2216 2326 goto done;
2217 2327 }
2328 + /* Now safe to call mptsas_dma_addr_destroy(page_dma_handle). */
2329 + free_page = B_TRUE;
2330 +
2218 2331 bzero(page_memp, sizeof (MPI2_CONFIG_PAGE_MAN_5));
2219 2332 m5 = (pMpi2ManufacturingPage5_t)page_memp;
2333 + NDBG20(("mptsas_get_manufacture_page5: paddr 0x%x%08x",
2334 + (uint32_t)(page_cookie.dmac_laddress>>32),
2335 + (uint32_t)(page_cookie.dmac_laddress&0xfffffffful)));
2220 2336
2221 2337 /*
2222 2338 * Give reply address to IOC to store config page in and send
2223 2339 * config request out.
2224 2340 */
2225 2341
2226 2342 flagslength = sizeof (MPI2_CONFIG_PAGE_MAN_5);
2227 2343 flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
2228 2344 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2229 - MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
2345 + MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
2230 2346 MPI2_SGE_FLAGS_IOC_TO_HOST |
2231 2347 MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
2232 2348
2233 2349 if (mptsas_send_config_request_msg(mpt,
2234 2350 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
2235 2351 MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 5,
2236 2352 ddi_get8(recv_accessp, &configreply->Header.PageVersion),
2237 2353 ddi_get8(recv_accessp, &configreply->Header.PageLength),
2238 - flagslength, page_cookie.dmac_address)) {
2354 + flagslength, page_cookie.dmac_laddress)) {
2239 2355 rval = DDI_FAILURE;
2240 2356 goto done;
2241 2357 }
2242 2358
2243 2359 /*
2244 2360 * get reply view handshake
2245 2361 */
2246 2362 if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2247 2363 recv_accessp)) {
2248 2364 rval = DDI_FAILURE;
2249 2365 goto done;
2250 2366 }
2251 2367
2252 2368 if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2253 2369 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page5 config: "
2254 2370 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2255 2371 ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2256 2372 goto done;
2257 2373 }
2258 2374
2259 2375 (void) ddi_dma_sync(page_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU);
2260 2376
2261 2377 /*
2262 2378 * Fusion-MPT stores fields in little-endian format. This is
2263 2379 * why the low-order 32 bits are stored first.
2264 2380 */
2265 2381 mpt->un.sasaddr.m_base_wwid_lo =
2266 2382 ddi_get32(page_accessp, (uint32_t *)(void *)&m5->Phy[0].WWID);
2267 2383 mpt->un.sasaddr.m_base_wwid_hi =
2268 2384 ddi_get32(page_accessp, (uint32_t *)(void *)&m5->Phy[0].WWID + 1);
2269 2385
2270 2386 if (ddi_prop_update_int64(DDI_DEV_T_NONE, mpt->m_dip,
2271 2387 "base-wwid", mpt->un.m_base_wwid) != DDI_PROP_SUCCESS) {
2272 2388 NDBG2(("%s%d: failed to create base-wwid property",
2273 2389 ddi_driver_name(mpt->m_dip), ddi_get_instance(mpt->m_dip)));
2274 2390 }
2275 2391
2276 2392 /*
2277 2393 * Set the number of PHYs present.
2278 2394 */
2279 2395 mpt->m_num_phys = ddi_get8(page_accessp, (uint8_t *)&m5->NumPhys);
2280 2396
2281 2397 if (ddi_prop_update_int(DDI_DEV_T_NONE, mpt->m_dip,
2282 2398 "num-phys", mpt->m_num_phys) != DDI_PROP_SUCCESS) {
2283 2399 NDBG2(("%s%d: failed to create num-phys property",
2284 2400 ddi_driver_name(mpt->m_dip), ddi_get_instance(mpt->m_dip)));
2285 2401 }
2286 2402
2287 2403 mptsas_log(mpt, CE_NOTE, "!mpt%d: Initiator WWNs: 0x%016llx-0x%016llx",
2288 2404 mpt->m_instance, (unsigned long long)mpt->un.m_base_wwid,
2289 2405 (unsigned long long)mpt->un.m_base_wwid + mpt->m_num_phys - 1);
2290 2406
2291 2407 if ((mptsas_check_dma_handle(recv_dma_handle) != DDI_SUCCESS) ||
2292 2408 (mptsas_check_dma_handle(page_dma_handle) != DDI_SUCCESS)) {
2293 2409 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2294 2410 rval = DDI_FAILURE;
2295 2411 goto done;
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
2296 2412 }
2297 2413 if ((mptsas_check_acc_handle(recv_accessp) != DDI_SUCCESS) ||
2298 2414 (mptsas_check_acc_handle(page_accessp) != DDI_SUCCESS)) {
2299 2415 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2300 2416 rval = DDI_FAILURE;
2301 2417 }
2302 2418 done:
2303 2419 /*
2304 2420 * free up memory
2305 2421 */
2306 - mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
2307 - mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2422 + if (free_recv)
2423 + mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
2424 + if (free_page)
2425 + mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2308 2426 MPTSAS_ENABLE_INTR(mpt);
2309 2427
2310 2428 return (rval);
2311 2429 }
2312 2430
2313 2431 static int
2314 2432 mptsas_sasphypage_0_cb(mptsas_t *mpt, caddr_t page_memp,
2315 2433 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
2316 2434 va_list ap)
2317 2435 {
2318 2436 #ifndef __lock_lint
2319 2437 _NOTE(ARGUNUSED(ap))
2320 2438 #endif
2321 2439 pMpi2SasPhyPage0_t sasphypage;
2322 2440 int rval = DDI_SUCCESS;
2323 2441 uint16_t *owner_devhdl, *attached_devhdl;
2324 2442 uint8_t *attached_phy_identify;
2325 2443 uint32_t *attached_phy_info;
2326 2444 uint8_t *programmed_link_rate;
2327 2445 uint8_t *hw_link_rate;
2328 2446 uint8_t *change_count;
2329 2447 uint32_t *phy_info;
2330 2448 uint8_t *negotiated_link_rate;
2331 2449 uint32_t page_address;
2332 2450
2333 2451 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) &&
2334 2452 (iocstatus != MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)) {
2335 2453 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_expander_page0 "
2336 2454 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
2337 2455 iocstatus, iocloginfo);
2338 2456 rval = DDI_FAILURE;
2339 2457 return (rval);
2340 2458 }
2341 2459 page_address = va_arg(ap, uint32_t);
2342 2460 /*
2343 2461 * The INVALID_PAGE status is normal if using GET_NEXT_HANDLE and there
2344 2462 * are no more pages. If everything is OK up to this point but the
2345 2463 * status is INVALID_PAGE, change rval to FAILURE and quit. Also,
2346 2464 * signal that device traversal is complete.
2347 2465 */
2348 2466 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
2349 2467 if ((page_address & MPI2_SAS_EXPAND_PGAD_FORM_MASK) ==
2350 2468 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL) {
2351 2469 mpt->m_done_traverse_smp = 1;
2352 2470 }
2353 2471 rval = DDI_FAILURE;
2354 2472 return (rval);
2355 2473 }
2356 2474 owner_devhdl = va_arg(ap, uint16_t *);
2357 2475 attached_devhdl = va_arg(ap, uint16_t *);
2358 2476 attached_phy_identify = va_arg(ap, uint8_t *);
2359 2477 attached_phy_info = va_arg(ap, uint32_t *);
2360 2478 programmed_link_rate = va_arg(ap, uint8_t *);
2361 2479 hw_link_rate = va_arg(ap, uint8_t *);
2362 2480 change_count = va_arg(ap, uint8_t *);
2363 2481 phy_info = va_arg(ap, uint32_t *);
2364 2482 negotiated_link_rate = va_arg(ap, uint8_t *);
2365 2483
2366 2484 sasphypage = (pMpi2SasPhyPage0_t)page_memp;
2367 2485
2368 2486 *owner_devhdl =
2369 2487 ddi_get16(accessp, &sasphypage->OwnerDevHandle);
2370 2488 *attached_devhdl =
2371 2489 ddi_get16(accessp, &sasphypage->AttachedDevHandle);
2372 2490 *attached_phy_identify =
2373 2491 ddi_get8(accessp, &sasphypage->AttachedPhyIdentifier);
2374 2492 *attached_phy_info =
2375 2493 ddi_get32(accessp, &sasphypage->AttachedPhyInfo);
2376 2494 *programmed_link_rate =
2377 2495 ddi_get8(accessp, &sasphypage->ProgrammedLinkRate);
2378 2496 *hw_link_rate =
2379 2497 ddi_get8(accessp, &sasphypage->HwLinkRate);
2380 2498 *change_count =
2381 2499 ddi_get8(accessp, &sasphypage->ChangeCount);
2382 2500 *phy_info =
2383 2501 ddi_get32(accessp, &sasphypage->PhyInfo);
2384 2502 *negotiated_link_rate =
2385 2503 ddi_get8(accessp, &sasphypage->NegotiatedLinkRate);
2386 2504
2387 2505 return (rval);
2388 2506 }
2389 2507
2390 2508 /*
2391 2509 * Request MPI configuration page SAS phy page 0 to get DevHandle, phymask
2392 2510 * and SAS address.
2393 2511 */
2394 2512 int
2395 2513 mptsas_get_sas_phy_page0(mptsas_t *mpt, uint32_t page_address,
2396 2514 smhba_info_t *info)
2397 2515 {
2398 2516 int rval = DDI_SUCCESS;
2399 2517
2400 2518 ASSERT(mutex_owned(&mpt->m_mutex));
2401 2519
2402 2520 /*
2403 2521 * Get the header and config page. reply contains the reply frame,
2404 2522 * which holds status info for the request.
2405 2523 */
2406 2524 rval = mptsas_access_config_page(mpt,
2407 2525 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
2408 2526 MPI2_CONFIG_EXTPAGETYPE_SAS_PHY, 0, page_address,
2409 2527 mptsas_sasphypage_0_cb, page_address, &info->owner_devhdl,
2410 2528 &info->attached_devhdl, &info->attached_phy_identify,
2411 2529 &info->attached_phy_info, &info->programmed_link_rate,
2412 2530 &info->hw_link_rate, &info->change_count,
2413 2531 &info->phy_info, &info->negotiated_link_rate);
2414 2532
2415 2533 return (rval);
2416 2534 }
2417 2535
2418 2536 static int
2419 2537 mptsas_sasphypage_1_cb(mptsas_t *mpt, caddr_t page_memp,
2420 2538 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
2421 2539 va_list ap)
2422 2540 {
2423 2541 #ifndef __lock_lint
2424 2542 _NOTE(ARGUNUSED(ap))
2425 2543 #endif
2426 2544 pMpi2SasPhyPage1_t sasphypage;
2427 2545 int rval = DDI_SUCCESS;
2428 2546
2429 2547 uint32_t *invalid_dword_count;
2430 2548 uint32_t *running_disparity_error_count;
2431 2549 uint32_t *loss_of_dword_sync_count;
2432 2550 uint32_t *phy_reset_problem_count;
2433 2551 uint32_t page_address;
2434 2552
2435 2553 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) &&
2436 2554 (iocstatus != MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)) {
2437 2555 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_expander_page1 "
2438 2556 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
2439 2557 iocstatus, iocloginfo);
2440 2558 rval = DDI_FAILURE;
2441 2559 return (rval);
2442 2560 }
2443 2561 page_address = va_arg(ap, uint32_t);
2444 2562 /*
2445 2563 * The INVALID_PAGE status is normal if using GET_NEXT_HANDLE and there
2446 2564 * are no more pages. If everything is OK up to this point but the
2447 2565 * status is INVALID_PAGE, change rval to FAILURE and quit. Also,
2448 2566 * signal that device traversal is complete.
2449 2567 */
2450 2568 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
2451 2569 if ((page_address & MPI2_SAS_EXPAND_PGAD_FORM_MASK) ==
2452 2570 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL) {
2453 2571 mpt->m_done_traverse_smp = 1;
2454 2572 }
2455 2573 rval = DDI_FAILURE;
2456 2574 return (rval);
2457 2575 }
2458 2576
2459 2577 invalid_dword_count = va_arg(ap, uint32_t *);
2460 2578 running_disparity_error_count = va_arg(ap, uint32_t *);
2461 2579 loss_of_dword_sync_count = va_arg(ap, uint32_t *);
2462 2580 phy_reset_problem_count = va_arg(ap, uint32_t *);
2463 2581
2464 2582 sasphypage = (pMpi2SasPhyPage1_t)page_memp;
2465 2583
2466 2584 *invalid_dword_count =
2467 2585 ddi_get32(accessp, &sasphypage->InvalidDwordCount);
2468 2586 *running_disparity_error_count =
2469 2587 ddi_get32(accessp, &sasphypage->RunningDisparityErrorCount);
2470 2588 *loss_of_dword_sync_count =
2471 2589 ddi_get32(accessp, &sasphypage->LossDwordSynchCount);
2472 2590 *phy_reset_problem_count =
2473 2591 ddi_get32(accessp, &sasphypage->PhyResetProblemCount);
2474 2592
2475 2593 return (rval);
2476 2594 }
2477 2595
2478 2596 /*
2479 2597 * Request MPI configuration page SAS phy page 0 to get DevHandle, phymask
2480 2598 * and SAS address.
2481 2599 */
2482 2600 int
2483 2601 mptsas_get_sas_phy_page1(mptsas_t *mpt, uint32_t page_address,
2484 2602 smhba_info_t *info)
2485 2603 {
2486 2604 int rval = DDI_SUCCESS;
2487 2605
2488 2606 ASSERT(mutex_owned(&mpt->m_mutex));
2489 2607
2490 2608 /*
2491 2609 * Get the header and config page. reply contains the reply frame,
2492 2610 * which holds status info for the request.
2493 2611 */
2494 2612 rval = mptsas_access_config_page(mpt,
2495 2613 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
2496 2614 MPI2_CONFIG_EXTPAGETYPE_SAS_PHY, 1, page_address,
2497 2615 mptsas_sasphypage_1_cb, page_address,
2498 2616 &info->invalid_dword_count,
2499 2617 &info->running_disparity_error_count,
2500 2618 &info->loss_of_dword_sync_count,
2501 2619 &info->phy_reset_problem_count);
2502 2620
2503 2621 return (rval);
2504 2622 }
2505 2623 /*
2506 2624 * mptsas_get_manufacture_page0
2507 2625 *
2508 2626 * This function will retrieve the base
2509 2627 * Chip name, Board Name,Board Trace number from the adapter.
2510 2628 * Since this function is only called during the
2511 2629 * initialization process, use handshaking.
2512 2630 */
2513 2631 int
2514 2632 mptsas_get_manufacture_page0(mptsas_t *mpt)
2515 2633 {
2516 2634 ddi_dma_attr_t recv_dma_attrs, page_dma_attrs;
2517 2635 ddi_dma_cookie_t page_cookie;
↓ open down ↓ |
200 lines elided |
↑ open up ↑ |
2518 2636 ddi_dma_handle_t recv_dma_handle, page_dma_handle;
2519 2637 ddi_acc_handle_t recv_accessp, page_accessp;
2520 2638 pMpi2ConfigReply_t configreply;
2521 2639 caddr_t recv_memp, page_memp;
2522 2640 int recv_numbytes;
2523 2641 pMpi2ManufacturingPage0_t m0;
2524 2642 uint32_t flagslength;
2525 2643 int rval = DDI_SUCCESS;
2526 2644 uint_t iocstatus;
2527 2645 uint8_t i = 0;
2646 + boolean_t free_recv = B_FALSE, free_page = B_FALSE;
2528 2647
2529 2648 MPTSAS_DISABLE_INTR(mpt);
2530 2649
2531 2650 if (mptsas_send_config_request_msg(mpt, MPI2_CONFIG_ACTION_PAGE_HEADER,
2532 2651 MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, 0, 0, 0, 0)) {
2533 2652 rval = DDI_FAILURE;
2534 2653 goto done;
2535 2654 }
2536 2655
2537 2656 /*
2538 2657 * dynamically create a customized dma attribute structure
2539 2658 * that describes the MPT's config reply page request structure.
2540 2659 */
2541 2660 recv_dma_attrs = mpt->m_msg_dma_attr;
2542 2661 recv_dma_attrs.dma_attr_sgllen = 1;
2543 2662 recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
2544 2663
2545 2664 if (mptsas_dma_addr_create(mpt, recv_dma_attrs, &recv_dma_handle,
2546 2665 &recv_accessp, &recv_memp, (sizeof (MPI2_CONFIG_REPLY)),
2547 2666 NULL) == FALSE) {
2667 + rval = DDI_FAILURE;
2548 2668 goto done;
2549 2669 }
2670 + /* Now safe to call mptsas_dma_addr_destroy(recv_dma_handle). */
2671 + free_recv = B_TRUE;
2672 +
2550 2673 bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
2551 2674 configreply = (pMpi2ConfigReply_t)recv_memp;
2552 2675 recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
2553 2676
2554 2677 /*
2555 2678 * get config reply message
2556 2679 */
2557 2680 if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2558 2681 recv_accessp)) {
2559 2682 rval = DDI_FAILURE;
2560 2683 goto done;
2561 2684 }
2562 2685
2563 2686 if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2564 2687 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page5 update: "
2565 2688 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2566 2689 ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2567 2690 goto done;
2568 2691 }
2569 2692
2570 2693 /*
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
2571 2694 * dynamically create a customized dma attribute structure
2572 2695 * that describes the MPT's config page structure.
2573 2696 */
2574 2697 page_dma_attrs = mpt->m_msg_dma_attr;
2575 2698 page_dma_attrs.dma_attr_sgllen = 1;
2576 2699 page_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_PAGE_MAN_0));
2577 2700
2578 2701 if (mptsas_dma_addr_create(mpt, page_dma_attrs, &page_dma_handle,
2579 2702 &page_accessp, &page_memp, (sizeof (MPI2_CONFIG_PAGE_MAN_0)),
2580 2703 &page_cookie) == FALSE) {
2704 + rval = DDI_FAILURE;
2581 2705 goto done;
2582 2706 }
2707 + /* Now safe to call mptsas_dma_addr_destroy(page_dma_handle). */
2708 + free_page = B_TRUE;
2709 +
2583 2710 bzero(page_memp, sizeof (MPI2_CONFIG_PAGE_MAN_0));
2584 2711 m0 = (pMpi2ManufacturingPage0_t)page_memp;
2585 2712
2586 2713 /*
2587 2714 * Give reply address to IOC to store config page in and send
2588 2715 * config request out.
2589 2716 */
2590 2717
2591 2718 flagslength = sizeof (MPI2_CONFIG_PAGE_MAN_0);
2592 2719 flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
2593 2720 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2594 - MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
2721 + MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
2595 2722 MPI2_SGE_FLAGS_IOC_TO_HOST |
2596 2723 MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
2597 2724
2598 2725 if (mptsas_send_config_request_msg(mpt,
2599 2726 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
2600 2727 MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 0,
2601 2728 ddi_get8(recv_accessp, &configreply->Header.PageVersion),
2602 2729 ddi_get8(recv_accessp, &configreply->Header.PageLength),
2603 - flagslength, page_cookie.dmac_address)) {
2730 + flagslength, page_cookie.dmac_laddress)) {
2604 2731 rval = DDI_FAILURE;
2605 2732 goto done;
2606 2733 }
2607 2734
2608 2735 /*
2609 2736 * get reply view handshake
2610 2737 */
2611 2738 if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
2612 2739 recv_accessp)) {
2613 2740 rval = DDI_FAILURE;
2614 2741 goto done;
2615 2742 }
2616 2743
2617 2744 if (iocstatus = ddi_get16(recv_accessp, &configreply->IOCStatus)) {
2618 2745 mptsas_log(mpt, CE_WARN, "mptsas_get_manufacture_page0 config: "
2619 2746 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
2620 2747 ddi_get32(recv_accessp, &configreply->IOCLogInfo));
2621 2748 goto done;
2622 2749 }
2623 2750
2624 2751 (void) ddi_dma_sync(page_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU);
2625 2752
2626 2753 /*
2627 2754 * Fusion-MPT stores fields in little-endian format. This is
2628 2755 * why the low-order 32 bits are stored first.
2629 2756 */
2630 2757
2631 2758 for (i = 0; i < 16; i++) {
2632 2759 mpt->m_MANU_page0.ChipName[i] =
2633 2760 ddi_get8(page_accessp,
2634 2761 (uint8_t *)(void *)&m0->ChipName[i]);
2635 2762 }
2636 2763
2637 2764 for (i = 0; i < 8; i++) {
2638 2765 mpt->m_MANU_page0.ChipRevision[i] =
2639 2766 ddi_get8(page_accessp,
2640 2767 (uint8_t *)(void *)&m0->ChipRevision[i]);
2641 2768 }
2642 2769
2643 2770 for (i = 0; i < 16; i++) {
2644 2771 mpt->m_MANU_page0.BoardName[i] =
2645 2772 ddi_get8(page_accessp,
2646 2773 (uint8_t *)(void *)&m0->BoardName[i]);
2647 2774 }
2648 2775
2649 2776 for (i = 0; i < 16; i++) {
2650 2777 mpt->m_MANU_page0.BoardAssembly[i] =
2651 2778 ddi_get8(page_accessp,
2652 2779 (uint8_t *)(void *)&m0->BoardAssembly[i]);
2653 2780 }
2654 2781
2655 2782 for (i = 0; i < 16; i++) {
2656 2783 mpt->m_MANU_page0.BoardTracerNumber[i] =
2657 2784 ddi_get8(page_accessp,
2658 2785 (uint8_t *)(void *)&m0->BoardTracerNumber[i]);
2659 2786 }
2660 2787
2661 2788 if ((mptsas_check_dma_handle(recv_dma_handle) != DDI_SUCCESS) ||
2662 2789 (mptsas_check_dma_handle(page_dma_handle) != DDI_SUCCESS)) {
2663 2790 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2664 2791 rval = DDI_FAILURE;
2665 2792 goto done;
↓ open down ↓ |
52 lines elided |
↑ open up ↑ |
2666 2793 }
2667 2794 if ((mptsas_check_acc_handle(recv_accessp) != DDI_SUCCESS) ||
2668 2795 (mptsas_check_acc_handle(page_accessp) != DDI_SUCCESS)) {
2669 2796 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2670 2797 rval = DDI_FAILURE;
2671 2798 }
2672 2799 done:
2673 2800 /*
2674 2801 * free up memory
2675 2802 */
2676 - mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
2677 - mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2803 + if (free_recv)
2804 + mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
2805 + if (free_page)
2806 + mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
2678 2807 MPTSAS_ENABLE_INTR(mpt);
2679 2808
2680 2809 return (rval);
2681 2810 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX