summaryrefslogtreecommitdiffstats
path: root/sys/dev/mpt
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2006-07-12 07:48:50 +0000
committermjacob <mjacob@FreeBSD.org>2006-07-12 07:48:50 +0000
commit9a40fa9b7bf171d69a8ce95aea8796a91a2da740 (patch)
treebf1c462115d3d85e5d474f22bfa3841ea226e263 /sys/dev/mpt
parent28f98ccfdd66889c31e291841195972ae9306525 (diff)
downloadFreeBSD-src-9a40fa9b7bf171d69a8ce95aea8796a91a2da740.zip
FreeBSD-src-9a40fa9b7bf171d69a8ce95aea8796a91a2da740.tar.gz
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.
Diffstat (limited to 'sys/dev/mpt')
-rw-r--r--sys/dev/mpt/mpt.c39
-rw-r--r--sys/dev/mpt/mpt.h11
-rw-r--r--sys/dev/mpt/mpt_cam.c87
-rw-r--r--sys/dev/mpt/mpt_debug.c15
-rw-r--r--sys/dev/mpt/mpt_pci.c33
5 files changed, 147 insertions, 38 deletions
diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c
index 2c289d3..24ef254 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 bfc1349..d2ccbd5 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 1a53679..6539974 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;
+ /*
+ * Check our flags to make sure we support the role we want.
+ */
+ doit = 0;
+ role = 0;
+ fl = le32toh(fc.Flags);;
+
+ 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 (doit) {
- const char *cc;
- mpt_lprt(mpt, MPT_PRT_INFO,
- "FC Port Page 1: New Flags %x \n", fl);
+ 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 f5546ad..53b0c26 100644
--- a/sys/dev/mpt/mpt_debug.c
+++ b/sys/dev/mpt/mpt_debug.c
@@ -801,6 +801,21 @@ mpt_dump_sgl(SGE_IO_UNION *su, int offset)
}
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)
{
uint32_t *pReq = req->req_vbuf;
diff --git a/sys/dev/mpt/mpt_pci.c b/sys/dev/mpt/mpt_pci.c
index 32f2ebe..47bbf7b 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
OpenPOWER on IntegriCloud