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