Deleted Added
full compact
mpr.c (321416) mpr.c (322661)
1/*-
2 * Copyright (c) 2009 Yahoo! Inc.
3 * Copyright (c) 2011-2015 LSI Corp.
4 * Copyright (c) 2013-2016 Avago Technologies
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 16 unchanged lines hidden (view full) ---

25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
29 *
30 */
31
32#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009 Yahoo! Inc.
3 * Copyright (c) 2011-2015 LSI Corp.
4 * Copyright (c) 2013-2016 Avago Technologies
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 16 unchanged lines hidden (view full) ---

25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
29 *
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: stable/10/sys/dev/mpr/mpr.c 321416 2017-07-24 14:42:45Z ken $");
33__FBSDID("$FreeBSD: stable/10/sys/dev/mpr/mpr.c 322661 2017-08-18 15:38:08Z ken $");
34
35/* Communications core for Avago Technologies (LSI) MPT3 */
36
37/* TODO Move headers to mprvar */
38#include <sys/types.h>
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/kernel.h>

--- 334 unchanged lines hidden (view full) ---

376 "with error %d\n", __func__, error);
377 return (error);
378 } else {
379 panic("%s failed to get IOC Facts with error %d\n",
380 __func__, error);
381 }
382 }
383
34
35/* Communications core for Avago Technologies (LSI) MPT3 */
36
37/* TODO Move headers to mprvar */
38#include <sys/types.h>
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/kernel.h>

--- 334 unchanged lines hidden (view full) ---

376 "with error %d\n", __func__, error);
377 return (error);
378 } else {
379 panic("%s failed to get IOC Facts with error %d\n",
380 __func__, error);
381 }
382 }
383
384 mpr_print_iocfacts(sc, sc->facts);
384 MPR_DPRINT_PAGE(sc, MPR_XINFO, iocfacts, sc->facts);
385
386 snprintf(sc->fw_version, sizeof(sc->fw_version),
387 "%02d.%02d.%02d.%02d",
388 sc->facts->FWVersion.Struct.Major,
389 sc->facts->FWVersion.Struct.Minor,
390 sc->facts->FWVersion.Struct.Unit,
391 sc->facts->FWVersion.Struct.Dev);
392

--- 38 unchanged lines hidden (view full) ---

431 if (sc->ir_firmware != saved_mode) {
432 mpr_dprint(sc, MPR_FAULT, "%s new IR/IT mode in IOC "
433 "Facts does not match previous mode\n", __func__);
434 }
435 }
436
437 /* Only deallocate and reallocate if relevant IOC Facts have changed */
438 reallocating = FALSE;
385
386 snprintf(sc->fw_version, sizeof(sc->fw_version),
387 "%02d.%02d.%02d.%02d",
388 sc->facts->FWVersion.Struct.Major,
389 sc->facts->FWVersion.Struct.Minor,
390 sc->facts->FWVersion.Struct.Unit,
391 sc->facts->FWVersion.Struct.Dev);
392

--- 38 unchanged lines hidden (view full) ---

431 if (sc->ir_firmware != saved_mode) {
432 mpr_dprint(sc, MPR_FAULT, "%s new IR/IT mode in IOC "
433 "Facts does not match previous mode\n", __func__);
434 }
435 }
436
437 /* Only deallocate and reallocate if relevant IOC Facts have changed */
438 reallocating = FALSE;
439 sc->mpr_flags &= ~MPR_FLAGS_REALLOCATED;
440
439 if ((!attaching) &&
440 ((saved_facts.MsgVersion != sc->facts->MsgVersion) ||
441 (saved_facts.HeaderVersion != sc->facts->HeaderVersion) ||
442 (saved_facts.MaxChainDepth != sc->facts->MaxChainDepth) ||
443 (saved_facts.RequestCredit != sc->facts->RequestCredit) ||
444 (saved_facts.ProductID != sc->facts->ProductID) ||
445 (saved_facts.IOCCapabilities != sc->facts->IOCCapabilities) ||
446 (saved_facts.IOCRequestFrameSize !=

--- 6 unchanged lines hidden (view full) ---

453 (saved_facts.HighPriorityCredit != sc->facts->HighPriorityCredit) ||
454 (saved_facts.MaxReplyDescriptorPostQueueDepth !=
455 sc->facts->MaxReplyDescriptorPostQueueDepth) ||
456 (saved_facts.ReplyFrameSize != sc->facts->ReplyFrameSize) ||
457 (saved_facts.MaxVolumes != sc->facts->MaxVolumes) ||
458 (saved_facts.MaxPersistentEntries !=
459 sc->facts->MaxPersistentEntries))) {
460 reallocating = TRUE;
441 if ((!attaching) &&
442 ((saved_facts.MsgVersion != sc->facts->MsgVersion) ||
443 (saved_facts.HeaderVersion != sc->facts->HeaderVersion) ||
444 (saved_facts.MaxChainDepth != sc->facts->MaxChainDepth) ||
445 (saved_facts.RequestCredit != sc->facts->RequestCredit) ||
446 (saved_facts.ProductID != sc->facts->ProductID) ||
447 (saved_facts.IOCCapabilities != sc->facts->IOCCapabilities) ||
448 (saved_facts.IOCRequestFrameSize !=

--- 6 unchanged lines hidden (view full) ---

455 (saved_facts.HighPriorityCredit != sc->facts->HighPriorityCredit) ||
456 (saved_facts.MaxReplyDescriptorPostQueueDepth !=
457 sc->facts->MaxReplyDescriptorPostQueueDepth) ||
458 (saved_facts.ReplyFrameSize != sc->facts->ReplyFrameSize) ||
459 (saved_facts.MaxVolumes != sc->facts->MaxVolumes) ||
460 (saved_facts.MaxPersistentEntries !=
461 sc->facts->MaxPersistentEntries))) {
462 reallocating = TRUE;
463
464 /* Record that we reallocated everything */
465 sc->mpr_flags |= MPR_FLAGS_REALLOCATED;
461 }
462
463 /*
464 * Some things should be done if attaching or re-allocating after a Diag
465 * Reset, but are not needed after a Diag Reset if the FW has not
466 * changed.
467 */
468 if (attaching || reallocating) {

--- 1008 unchanged lines hidden (view full) ---

1477
1478 return (0);
1479}
1480
1481/* Get the driver parameter tunables. Lowest priority are the driver defaults.
1482 * Next are the global settings, if they exist. Highest are the per-unit
1483 * settings, if they exist.
1484 */
466 }
467
468 /*
469 * Some things should be done if attaching or re-allocating after a Diag
470 * Reset, but are not needed after a Diag Reset if the FW has not
471 * changed.
472 */
473 if (attaching || reallocating) {

--- 1008 unchanged lines hidden (view full) ---

1482
1483 return (0);
1484}
1485
1486/* Get the driver parameter tunables. Lowest priority are the driver defaults.
1487 * Next are the global settings, if they exist. Highest are the per-unit
1488 * settings, if they exist.
1489 */
1485static void
1490void
1486mpr_get_tunables(struct mpr_softc *sc)
1487{
1488 char tmpstr[80];
1489
1490 /* XXX default to some debugging for now */
1491 sc->mpr_debug = MPR_INFO | MPR_FAULT;
1492 sc->disable_msix = 0;
1493 sc->disable_msi = 0;

--- 159 unchanged lines hidden (view full) ---

1653 &sc->prp_page_alloc_fail, "PRP page allocation failures");
1654}
1655
1656int
1657mpr_attach(struct mpr_softc *sc)
1658{
1659 int error;
1660
1491mpr_get_tunables(struct mpr_softc *sc)
1492{
1493 char tmpstr[80];
1494
1495 /* XXX default to some debugging for now */
1496 sc->mpr_debug = MPR_INFO | MPR_FAULT;
1497 sc->disable_msix = 0;
1498 sc->disable_msi = 0;

--- 159 unchanged lines hidden (view full) ---

1658 &sc->prp_page_alloc_fail, "PRP page allocation failures");
1659}
1660
1661int
1662mpr_attach(struct mpr_softc *sc)
1663{
1664 int error;
1665
1661 mpr_get_tunables(sc);
1662
1663 MPR_FUNCTRACE(sc);
1664
1665 mtx_init(&sc->mpr_mtx, "MPR lock", NULL, MTX_DEF);
1666 callout_init_mtx(&sc->periodic, &sc->mpr_mtx, 0);
1667 callout_init_mtx(&sc->device_check_callout, &sc->mpr_mtx, 0);
1668 TAILQ_INIT(&sc->event_list);
1669 timevalclear(&sc->lastfail);
1670

--- 98 unchanged lines hidden (view full) ---

1769}
1770
1771static void
1772mpr_log_evt_handler(struct mpr_softc *sc, uintptr_t data,
1773 MPI2_EVENT_NOTIFICATION_REPLY *event)
1774{
1775 MPI2_EVENT_DATA_LOG_ENTRY_ADDED *entry;
1776
1666 MPR_FUNCTRACE(sc);
1667
1668 mtx_init(&sc->mpr_mtx, "MPR lock", NULL, MTX_DEF);
1669 callout_init_mtx(&sc->periodic, &sc->mpr_mtx, 0);
1670 callout_init_mtx(&sc->device_check_callout, &sc->mpr_mtx, 0);
1671 TAILQ_INIT(&sc->event_list);
1672 timevalclear(&sc->lastfail);
1673

--- 98 unchanged lines hidden (view full) ---

1772}
1773
1774static void
1775mpr_log_evt_handler(struct mpr_softc *sc, uintptr_t data,
1776 MPI2_EVENT_NOTIFICATION_REPLY *event)
1777{
1778 MPI2_EVENT_DATA_LOG_ENTRY_ADDED *entry;
1779
1777 mpr_print_event(sc, event);
1780 MPR_DPRINT_EVENT(sc, generic, event);
1778
1779 switch (event->Event) {
1780 case MPI2_EVENT_LOG_DATA:
1781 mpr_dprint(sc, MPR_EVENT, "MPI2_EVENT_LOG_DATA:\n");
1782 if (sc->mpr_debug & MPR_EVENT)
1783 hexdump(event->EventData, event->EventDataLength, NULL,
1784 0);
1785 break;

--- 398 unchanged lines hidden (view full) ---

2184}
2185
2186static void
2187mpr_reregister_events_complete(struct mpr_softc *sc, struct mpr_command *cm)
2188{
2189 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
2190
2191 if (cm->cm_reply)
1781
1782 switch (event->Event) {
1783 case MPI2_EVENT_LOG_DATA:
1784 mpr_dprint(sc, MPR_EVENT, "MPI2_EVENT_LOG_DATA:\n");
1785 if (sc->mpr_debug & MPR_EVENT)
1786 hexdump(event->EventData, event->EventDataLength, NULL,
1787 0);
1788 break;

--- 398 unchanged lines hidden (view full) ---

2187}
2188
2189static void
2190mpr_reregister_events_complete(struct mpr_softc *sc, struct mpr_command *cm)
2191{
2192 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
2193
2194 if (cm->cm_reply)
2192 mpr_print_event(sc,
2195 MPR_DPRINT_EVENT(sc, generic,
2193 (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply);
2194
2195 mpr_free_command(sc, cm);
2196
2197 /* next, send a port enable */
2198 mprsas_startup(sc);
2199}
2200

--- 25 unchanged lines hidden (view full) ---

2226 return (error);
2227}
2228
2229int
2230mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle,
2231 uint8_t *mask)
2232{
2233 MPI2_EVENT_NOTIFICATION_REQUEST *evtreq;
2196 (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply);
2197
2198 mpr_free_command(sc, cm);
2199
2200 /* next, send a port enable */
2201 mprsas_startup(sc);
2202}
2203

--- 25 unchanged lines hidden (view full) ---

2229 return (error);
2230}
2231
2232int
2233mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle,
2234 uint8_t *mask)
2235{
2236 MPI2_EVENT_NOTIFICATION_REQUEST *evtreq;
2234 MPI2_EVENT_NOTIFICATION_REPLY *reply;
2235 struct mpr_command *cm;
2237 MPI2_EVENT_NOTIFICATION_REPLY *reply = NULL;
2238 struct mpr_command *cm = NULL;
2236 struct mpr_event_handle *eh;
2237 int error, i;
2238
2239 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
2240
2241 if ((mask != NULL) && (handle != NULL))
2242 bcopy(mask, &handle->mask[0], 16);
2243 memset(sc->event_mask, 0xff, 16);

--- 16 unchanged lines hidden (view full) ---

2260 bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16);
2261 }
2262#else
2263 bcopy(sc->event_mask, (uint8_t *)&evtreq->EventMasks, 16);
2264#endif
2265 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
2266 cm->cm_data = NULL;
2267
2239 struct mpr_event_handle *eh;
2240 int error, i;
2241
2242 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
2243
2244 if ((mask != NULL) && (handle != NULL))
2245 bcopy(mask, &handle->mask[0], 16);
2246 memset(sc->event_mask, 0xff, 16);

--- 16 unchanged lines hidden (view full) ---

2263 bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16);
2264 }
2265#else
2266 bcopy(sc->event_mask, (uint8_t *)&evtreq->EventMasks, 16);
2267#endif
2268 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
2269 cm->cm_data = NULL;
2270
2268 error = mpr_request_polled(sc, cm);
2269 reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply;
2271 error = mpr_request_polled(sc, &cm);
2272 if (cm != NULL)
2273 reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply;
2270 if ((reply == NULL) ||
2271 (reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
2272 error = ENXIO;
2273
2274 if (reply)
2274 if ((reply == NULL) ||
2275 (reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
2276 error = ENXIO;
2277
2278 if (reply)
2275 mpr_print_event(sc, reply);
2279 MPR_DPRINT_EVENT(sc, generic, reply);
2276
2277 mpr_dprint(sc, MPR_TRACE, "%s finished error %d\n", __func__, error);
2278
2280
2281 mpr_dprint(sc, MPR_TRACE, "%s finished error %d\n", __func__, error);
2282
2279 mpr_free_command(sc, cm);
2283 if (cm != NULL)
2284 mpr_free_command(sc, cm);
2280 return (error);
2281}
2282
2283static int
2284mpr_reregister_events(struct mpr_softc *sc)
2285{
2286 MPI2_EVENT_NOTIFICATION_REQUEST *evtreq;
2287 struct mpr_command *cm;

--- 969 unchanged lines hidden (view full) ---

3257}
3258
3259/*
3260 * This is the routine to enqueue commands synchronously. An error of
3261 * EINPROGRESS from mpr_map_command() is ignored since the command will
3262 * be executed and enqueued automatically. Other errors come from msleep().
3263 */
3264int
2285 return (error);
2286}
2287
2288static int
2289mpr_reregister_events(struct mpr_softc *sc)
2290{
2291 MPI2_EVENT_NOTIFICATION_REQUEST *evtreq;
2292 struct mpr_command *cm;

--- 969 unchanged lines hidden (view full) ---

3262}
3263
3264/*
3265 * This is the routine to enqueue commands synchronously. An error of
3266 * EINPROGRESS from mpr_map_command() is ignored since the command will
3267 * be executed and enqueued automatically. Other errors come from msleep().
3268 */
3269int
3265mpr_wait_command(struct mpr_softc *sc, struct mpr_command *cm, int timeout,
3270mpr_wait_command(struct mpr_softc *sc, struct mpr_command **cmp, int timeout,
3266 int sleep_flag)
3267{
3268 int error, rc;
3269 struct timeval cur_time, start_time;
3271 int sleep_flag)
3272{
3273 int error, rc;
3274 struct timeval cur_time, start_time;
3275 struct mpr_command *cm = *cmp;
3270
3271 if (sc->mpr_flags & MPR_FLAGS_DIAGRESET)
3272 return EBUSY;
3273
3274 cm->cm_complete = NULL;
3275 cm->cm_flags |= (MPR_CM_FLAGS_WAKEUP + MPR_CM_FLAGS_POLLED);
3276 error = mpr_map_command(sc, cm);
3277 if ((error != 0) && (error != EINPROGRESS))

--- 38 unchanged lines hidden (view full) ---

3316
3317 if (error == EWOULDBLOCK) {
3318 mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s, timeout=%d,"
3319 " elapsed=%jd\n", __func__, timeout,
3320 (intmax_t)cur_time.tv_sec);
3321 rc = mpr_reinit(sc);
3322 mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" :
3323 "failed");
3276
3277 if (sc->mpr_flags & MPR_FLAGS_DIAGRESET)
3278 return EBUSY;
3279
3280 cm->cm_complete = NULL;
3281 cm->cm_flags |= (MPR_CM_FLAGS_WAKEUP + MPR_CM_FLAGS_POLLED);
3282 error = mpr_map_command(sc, cm);
3283 if ((error != 0) && (error != EINPROGRESS))

--- 38 unchanged lines hidden (view full) ---

3322
3323 if (error == EWOULDBLOCK) {
3324 mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s, timeout=%d,"
3325 " elapsed=%jd\n", __func__, timeout,
3326 (intmax_t)cur_time.tv_sec);
3327 rc = mpr_reinit(sc);
3328 mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" :
3329 "failed");
3330 if (sc->mpr_flags & MPR_FLAGS_REALLOCATED) {
3331 /*
3332 * Tell the caller that we freed the command in a
3333 * reinit.
3334 */
3335 *cmp = NULL;
3336 }
3324 error = ETIMEDOUT;
3325 }
3326 return (error);
3327}
3328
3329/*
3330 * This is the routine to enqueue a command synchonously and poll for
3331 * completion. Its use should be rare.
3332 */
3333int
3337 error = ETIMEDOUT;
3338 }
3339 return (error);
3340}
3341
3342/*
3343 * This is the routine to enqueue a command synchonously and poll for
3344 * completion. Its use should be rare.
3345 */
3346int
3334mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm)
3347mpr_request_polled(struct mpr_softc *sc, struct mpr_command **cmp)
3335{
3348{
3336 int error, timeout = 0, rc;
3349 int error, rc;
3337 struct timeval cur_time, start_time;
3350 struct timeval cur_time, start_time;
3351 struct mpr_command *cm = *cmp;
3338
3339 error = 0;
3340
3341 cm->cm_flags |= MPR_CM_FLAGS_POLLED;
3342 cm->cm_complete = NULL;
3343 mpr_map_command(sc, cm);
3344
3352
3353 error = 0;
3354
3355 cm->cm_flags |= MPR_CM_FLAGS_POLLED;
3356 cm->cm_complete = NULL;
3357 mpr_map_command(sc, cm);
3358
3345 getmicrotime(&start_time);
3359 getmicrouptime(&start_time);
3346 while ((cm->cm_flags & MPR_CM_FLAGS_COMPLETE) == 0) {
3347 mpr_intr_locked(sc);
3348
3349 if (mtx_owned(&sc->mpr_mtx))
3350 msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0,
3351 "mprpoll", hz/20);
3352 else
3353 pause("mprpoll", hz/20);
3354
3355 /*
3356 * Check for real-time timeout and fail if more than 60 seconds.
3357 */
3360 while ((cm->cm_flags & MPR_CM_FLAGS_COMPLETE) == 0) {
3361 mpr_intr_locked(sc);
3362
3363 if (mtx_owned(&sc->mpr_mtx))
3364 msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0,
3365 "mprpoll", hz/20);
3366 else
3367 pause("mprpoll", hz/20);
3368
3369 /*
3370 * Check for real-time timeout and fail if more than 60 seconds.
3371 */
3358 getmicrotime(&cur_time);
3359 timeout = cur_time.tv_sec - start_time.tv_sec;
3360 if (timeout > 60) {
3372 getmicrouptime(&cur_time);
3373 timevalsub(&cur_time, &start_time);
3374 if (cur_time.tv_sec > 60) {
3361 mpr_dprint(sc, MPR_FAULT, "polling failed\n");
3362 error = ETIMEDOUT;
3363 break;
3364 }
3365 }
3366
3367 if (error) {
3368 mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__);
3369 rc = mpr_reinit(sc);
3370 mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" :
3371 "failed");
3375 mpr_dprint(sc, MPR_FAULT, "polling failed\n");
3376 error = ETIMEDOUT;
3377 break;
3378 }
3379 }
3380
3381 if (error) {
3382 mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__);
3383 rc = mpr_reinit(sc);
3384 mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" :
3385 "failed");
3386
3387 if (sc->mpr_flags & MPR_FLAGS_REALLOCATED) {
3388 /*
3389 * Tell the caller that we freed the command in a
3390 * reinit.
3391 */
3392 *cmp = NULL;
3393 }
3372 }
3373 return (error);
3374}
3375
3376/*
3377 * The MPT driver had a verbose interface for config pages. In this driver,
3378 * reduce it to much simplier terms, similar to the Linux driver.
3379 */

--- 49 unchanged lines hidden (view full) ---

3429 cm->cm_sge = NULL;
3430 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
3431
3432 cm->cm_complete_data = params;
3433 if (params->callback != NULL) {
3434 cm->cm_complete = mpr_config_complete;
3435 return (mpr_map_command(sc, cm));
3436 } else {
3394 }
3395 return (error);
3396}
3397
3398/*
3399 * The MPT driver had a verbose interface for config pages. In this driver,
3400 * reduce it to much simplier terms, similar to the Linux driver.
3401 */

--- 49 unchanged lines hidden (view full) ---

3451 cm->cm_sge = NULL;
3452 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
3453
3454 cm->cm_complete_data = params;
3455 if (params->callback != NULL) {
3456 cm->cm_complete = mpr_config_complete;
3457 return (mpr_map_command(sc, cm));
3458 } else {
3437 error = mpr_wait_command(sc, cm, 0, CAN_SLEEP);
3459 error = mpr_wait_command(sc, &cm, 0, CAN_SLEEP);
3438 if (error) {
3439 mpr_dprint(sc, MPR_FAULT,
3440 "Error %d reading config page\n", error);
3460 if (error) {
3461 mpr_dprint(sc, MPR_FAULT,
3462 "Error %d reading config page\n", error);
3441 mpr_free_command(sc, cm);
3463 if (cm != NULL)
3464 mpr_free_command(sc, cm);
3442 return (error);
3443 }
3444 mpr_config_complete(sc, cm);
3445 }
3446
3447 return (0);
3448}
3449

--- 56 unchanged lines hidden ---
3465 return (error);
3466 }
3467 mpr_config_complete(sc, cm);
3468 }
3469
3470 return (0);
3471}
3472

--- 56 unchanged lines hidden ---