From b4c618c099443efcc9c2d8ffd4eb115009aa4329 Mon Sep 17 00:00:00 2001 From: Matt Jacob Date: Wed, 12 Jul 2006 07:48:50 +0000 Subject: [PATCH] Fix config page writes to not strip out the attributes when you actually go write the config page. This fixes the long standing problem about updating NVRAM on Fibre Channel cards and seems so far to not break SPI config page writes. Put back role setting into mpt. That is, you can set a desired role for mpt as a hint. On the next reboot, it'll pick that up and redo the NVRAM settings appropriately and warn you that this won't take effect until the next reboot. This saves people the step of having to find a BIOS utilities disk to set target and/or initiator role for the MPT cards. --- sys/dev/mpt/mpt.c | 39 +++++++++++++----- sys/dev/mpt/mpt.h | 11 +++-- sys/dev/mpt/mpt_cam.c | 89 +++++++++++++++++++++++++++++++---------- sys/dev/mpt/mpt_debug.c | 15 +++++++ sys/dev/mpt/mpt_pci.c | 33 +++++++++++++-- 5 files changed, 148 insertions(+), 39 deletions(-) diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c index 2c289d3a76f..24ef2543056 100644 --- a/sys/dev/mpt/mpt.c +++ b/sys/dev/mpt/mpt.c @@ -1640,13 +1640,26 @@ mpt_write_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress, hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); return (-1); } - hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK, + +#if 0 + /* + * We shouldn't mask off other bits here. + */ + hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK; +#endif req = mpt_get_request(mpt, sleep_ok); if (req == NULL) return (-1); - memcpy(((caddr_t)req->req_vbuf)+MPT_RQSL(mpt), hdr, len); + memcpy(((caddr_t)req->req_vbuf) + MPT_RQSL(mpt), hdr, len); + + /* + * There isn't any point in restoring stripped out attributes + * if you then mask them going down to issue the request. + */ + +#if 0 /* Restore stripped out attributes */ hdr->PageType |= hdr_attr; @@ -1655,6 +1668,13 @@ mpt_write_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress, hdr->PageType & MPI_CONFIG_PAGETYPE_MASK, PageAddress, req->req_pbuf + MPT_RQSL(mpt), len, sleep_ok, timeout_ms); +#else + error = mpt_issue_cfg_req(mpt, req, Action, hdr->PageVersion, + hdr->PageLength, hdr->PageNumber, + hdr->PageType, PageAddress, + req->req_pbuf + MPT_RQSL(mpt), + len, sleep_ok, timeout_ms); +#endif if (error != 0) { mpt_prt(mpt, "mpt_write_cfg_page timed out\n"); return (-1); @@ -1936,6 +1956,9 @@ mpt_sysctl_attach(struct mpt_softc *mpt) SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "debug", CTLFLAG_RW, &mpt->verbose, 0, "Debugging/Verbose level"); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "role", CTLFLAG_RD, &mpt->role, 0, + "HBA role"); #endif } @@ -2454,9 +2477,11 @@ mpt_configure_ioc(struct mpt_softc *mpt) mpt->mpt_max_devices = pfp.MaxDevices; /* - * Set our expected role with what this port supports. + * Set our role with what this port supports. + * + * Note this might be changed later in different modules + * if this is different from what is wanted. */ - mpt->role = MPT_ROLE_NONE; if (pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { mpt->role |= MPT_ROLE_INITIATOR; @@ -2464,12 +2489,6 @@ mpt_configure_ioc(struct mpt_softc *mpt) if (pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { mpt->role |= MPT_ROLE_TARGET; } - if (mpt->role == MPT_ROLE_NONE) { - mpt_prt(mpt, "port does not support either target or " - "initiator role\n"); - return (ENXIO); - } - if (mpt_enable_ioc(mpt, 0) != MPT_OK) { mpt_prt(mpt, "unable to initialize IOC\n"); return (ENXIO); diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h index bfc134949d4..d2ccbd5949b 100644 --- a/sys/dev/mpt/mpt.h +++ b/sys/dev/mpt/mpt.h @@ -490,13 +490,12 @@ struct mpt_softc { int mpt_locksetup; #endif uint32_t mpt_pers_mask; - uint32_t : 8, + uint32_t unit : 8, - : 1, + : 3, twildcard : 1, tenabled : 1, - role : 2, /* none, ini, target, both */ - : 1, + do_cfg_role : 1, raid_enabled : 1, raid_mwce_set : 1, getreqwaiter : 1, @@ -508,6 +507,9 @@ struct mpt_softc { is_sas : 1, is_fc : 1; + u_int cfg_role; + u_int role; /* role: none, ini, target, both */ + u_int verbose; /* @@ -942,6 +944,7 @@ int mpt_decode_value(mpt_decode_entry_t *table, u_int num_entries, const char *name, u_int value, u_int *cur_column, u_int wrap_point); +void mpt_dump_data(struct mpt_softc *, const char *, void *, int); void mpt_dump_request(struct mpt_softc *, request_t *); enum { diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c index 1a53679683a..653997433f3 100644 --- a/sys/dev/mpt/mpt_cam.c +++ b/sys/dev/mpt/mpt_cam.c @@ -436,49 +436,96 @@ mpt_read_config_info_fc(struct mpt_softc *mpt) static int mpt_set_initial_config_fc(struct mpt_softc *mpt) { -#if 0 + CONFIG_PAGE_FC_PORT_1 fc; U32 fl; int r, doit = 0; - - if ((mpt->role & MPT_ROLE_TARGET) == 0) { - return (0); - } + int role; r = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &fc.Header, FALSE, 5000); if (r) { + mpt_prt(mpt, "failed to read FC page 1 header\n"); return (mpt_fc_reset_link(mpt, 1)); } - r = mpt_read_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, 0, + r = mpt_read_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_NVRAM, 0, &fc.Header, sizeof (fc), FALSE, 5000); if (r) { + mpt_prt(mpt, "failed to read FC page 1\n"); return (mpt_fc_reset_link(mpt, 1)); } - fl = le32toh(fc.Flags); - if ((fl & MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID) == 0) { - fl |= MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID; - doit = 1; - } - if (doit) { - const char *cc; + /* + * Check our flags to make sure we support the role we want. + */ + doit = 0; + role = 0; + fl = le32toh(fc.Flags);; - mpt_lprt(mpt, MPT_PRT_INFO, - "FC Port Page 1: New Flags %x \n", fl); + if (fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT) { + role |= MPT_ROLE_INITIATOR; + } + if (fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG) { + role |= MPT_ROLE_TARGET; + } + + fl &= ~MPI_FCPORTPAGE1_FLAGS_PROT_MASK; + + if (mpt->do_cfg_role == 0) { + role = mpt->cfg_role; + } else { + mpt->do_cfg_role = 0; + } + + if (role != mpt->cfg_role) { + if (mpt->cfg_role & MPT_ROLE_INITIATOR) { + if ((role & MPT_ROLE_INITIATOR) == 0) { + mpt_prt(mpt, "adding initiator role\n"); + fl |= MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT; + doit++; + } else { + mpt_prt(mpt, "keeping initiator role\n"); + } + } else if (role & MPT_ROLE_INITIATOR) { + mpt_prt(mpt, "removing initiator role\n"); + doit++; + } + if (mpt->cfg_role & MPT_ROLE_TARGET) { + if ((role & MPT_ROLE_TARGET) == 0) { + mpt_prt(mpt, "adding target role\n"); + fl |= MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG; + doit++; + } else { + mpt_prt(mpt, "keeping target role\n"); + } + } else if (role & MPT_ROLE_TARGET) { + mpt_prt(mpt, "removing target role\n"); + doit++; + } + mpt->role = mpt->cfg_role; + } + + if (fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG) { + if ((fl & MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID) == 0) { + mpt_prt(mpt, "adding OXID option\n"); + fl |= MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID; + doit++; + } + } + + if (doit) { fc.Flags = htole32(fl); r = mpt_write_cfg_page(mpt, - MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, 0, &fc.Header, + MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM, 0, &fc.Header, sizeof(fc), FALSE, 5000); if (r != 0) { - cc = "FC PORT PAGE1 UPDATE: FAILED\n"; - } else { - cc = "FC PORT PAGE1 UPDATED: SYSTEM NEEDS RESET\n"; + mpt_prt(mpt, "failed to update NVRAM with changes\n"); + return (0); } - mpt_prt(mpt, cc); + mpt_prt(mpt, "NOTE: NVRAM changes will not take " + "effect until next reboot or IOC reset\n"); } -#endif return (0); } diff --git a/sys/dev/mpt/mpt_debug.c b/sys/dev/mpt/mpt_debug.c index f5546ad0303..53b0c26431c 100644 --- a/sys/dev/mpt/mpt_debug.c +++ b/sys/dev/mpt/mpt_debug.c @@ -800,6 +800,21 @@ mpt_dump_sgl(SGE_IO_UNION *su, int offset) } while ((flags & MPI_SGE_FLAGS_END_OF_LIST) == 0 && nxtaddr < lim); } +void +mpt_dump_data(struct mpt_softc *mpt, const char *msg, void *addr, int len) +{ + int offset; + uint8_t *cp = addr; + mpt_prt(mpt, "%s:", msg); + for (offset = 0; offset < len; offset++) { + if ((offset & 0xf) == 0) { + mpt_prtc(mpt, "\n"); + } + mpt_prtc(mpt, " %02x", cp[offset]); + } + mpt_prtc(mpt, "\n"); +} + void mpt_dump_request(struct mpt_softc *mpt, request_t *req) { diff --git a/sys/dev/mpt/mpt_pci.c b/sys/dev/mpt/mpt_pci.c index 32f2ebe0b6d..47bbf7bc793 100644 --- a/sys/dev/mpt/mpt_pci.c +++ b/sys/dev/mpt/mpt_pci.c @@ -213,8 +213,9 @@ mpt_pci_probe(device_t dev) { char *desc; - if (pci_get_vendor(dev) != PCI_VENDOR_LSI) + if (pci_get_vendor(dev) != PCI_VENDOR_LSI) { return (ENXIO); + } switch ((pci_get_device(dev) & ~1)) { case PCI_PRODUCT_LSI_FC909: @@ -295,6 +296,29 @@ mpt_set_options(struct mpt_softc *mpt) mpt->verbose = MPT_PRT_DEBUG3; } } + + mpt->cfg_role = MPT_ROLE_DEFAULT; + bitmap = 0; + if (getenv_int("mpt_nil_role", &bitmap)) { + if (bitmap & (1 << mpt->unit)) { + mpt->cfg_role = 0; + } + mpt->do_cfg_role = 1; + } + bitmap = 0; + if (getenv_int("mpt_tgt_role", &bitmap)) { + if (bitmap & (1 << mpt->unit)) { + mpt->cfg_role |= MPT_ROLE_TARGET; + } + mpt->do_cfg_role = 1; + } + bitmap = 0; + if (getenv_int("mpt_ini_role", &bitmap)) { + if (bitmap & (1 << mpt->unit)) { + mpt->cfg_role |= MPT_ROLE_INITIATOR; + } + mpt->do_cfg_role = 1; + } } #else static void @@ -312,11 +336,12 @@ mpt_set_options(struct mpt_softc *mpt) device_get_unit(mpt->dev), "debug", &tval) == 0 && tval != 0) { mpt->verbose = tval; } - tval = 0; + tval = -1; if (resource_int_value(device_get_name(mpt->dev), - device_get_unit(mpt->dev), "role", &tval) == 0 && tval != 0 && + device_get_unit(mpt->dev), "role", &tval) == 0 && tval >= 0 && tval <= 3) { - mpt->role = tval; + mpt->cfg_role = tval; + mpt->do_cfg_role = 1; } } #endif