summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/ctl/ctl.c93
-rw-r--r--sys/cam/ctl/ctl.h2
-rw-r--r--sys/cam/ctl/ctl_io.h13
3 files changed, 106 insertions, 2 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index c172afb..6e0ff8e3 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -613,6 +613,14 @@ alloc:
ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg->port, sizeof(msg->port) + i,
M_WAITOK);
free(msg, M_CTL);
+
+ if (lun->flags & CTL_LUN_PRIMARY_SC) {
+ for (i = 0; i < CTL_NUM_MODE_PAGES; i++) {
+ ctl_isc_announce_mode(lun, -1,
+ lun->mode_pages.index[i].page_code & SMPH_PC_MASK,
+ lun->mode_pages.index[i].subpage);
+ }
+ }
}
void
@@ -712,6 +720,38 @@ ctl_isc_announce_iid(struct ctl_port *port, int iid)
free(msg, M_CTL);
}
+void
+ctl_isc_announce_mode(struct ctl_lun *lun, uint32_t initidx,
+ uint8_t page, uint8_t subpage)
+{
+ struct ctl_softc *softc = lun->ctl_softc;
+ union ctl_ha_msg msg;
+ int i;
+
+ if (softc->ha_link != CTL_HA_LINK_ONLINE)
+ return;
+ for (i = 0; i < CTL_NUM_MODE_PAGES; i++) {
+ if ((lun->mode_pages.index[i].page_code & SMPH_PC_MASK) ==
+ page && lun->mode_pages.index[i].subpage == subpage)
+ break;
+ }
+ if (i == CTL_NUM_MODE_PAGES)
+ return;
+ bzero(&msg.mode, sizeof(msg.mode));
+ msg.hdr.msg_type = CTL_MSG_MODE_SYNC;
+ msg.hdr.nexus.targ_port = initidx / CTL_MAX_INIT_PER_PORT;
+ msg.hdr.nexus.initid = initidx % CTL_MAX_INIT_PER_PORT;
+ msg.hdr.nexus.targ_lun = lun->lun;
+ msg.hdr.nexus.targ_mapped_lun = lun->lun;
+ msg.mode.page_code = page;
+ msg.mode.subpage = subpage;
+ msg.mode.page_len = lun->mode_pages.index[i].page_len;
+ memcpy(msg.mode.data, lun->mode_pages.index[i].page_data,
+ msg.mode.page_len);
+ ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg.mode, sizeof(msg.mode),
+ M_WAITOK);
+}
+
static void
ctl_isc_ha_link_up(struct ctl_softc *softc)
{
@@ -1043,6 +1083,44 @@ ctl_isc_login(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
}
}
+static void
+ctl_isc_mode_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
+{
+ struct ctl_lun *lun;
+ int i;
+ uint32_t initidx, targ_lun;
+
+ targ_lun = msg->hdr.nexus.targ_mapped_lun;
+ mtx_lock(&softc->ctl_lock);
+ if ((targ_lun >= CTL_MAX_LUNS) ||
+ ((lun = softc->ctl_luns[targ_lun]) == NULL)) {
+ mtx_unlock(&softc->ctl_lock);
+ return;
+ }
+ mtx_lock(&lun->lun_lock);
+ mtx_unlock(&softc->ctl_lock);
+ if (lun->flags & CTL_LUN_DISABLED) {
+ mtx_unlock(&lun->lun_lock);
+ return;
+ }
+ for (i = 0; i < CTL_NUM_MODE_PAGES; i++) {
+ if ((lun->mode_pages.index[i].page_code & SMPH_PC_MASK) ==
+ msg->mode.page_code &&
+ lun->mode_pages.index[i].subpage == msg->mode.subpage)
+ break;
+ }
+ if (i == CTL_NUM_MODE_PAGES) {
+ mtx_unlock(&lun->lun_lock);
+ return;
+ }
+ memcpy(lun->mode_pages.index[i].page_data, msg->mode.data,
+ lun->mode_pages.index[i].page_len);
+ initidx = ctl_get_initindex(&msg->hdr.nexus);
+ if (initidx != -1)
+ ctl_est_ua_all(lun, initidx, CTL_UA_MODE_CHANGE);
+ mtx_unlock(&lun->lun_lock);
+}
+
/*
* ISC (Inter Shelf Communication) event handler. Events from the HA
* subsystem come in here.
@@ -1322,6 +1400,9 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
case CTL_MSG_LOGIN:
ctl_isc_login(softc, msg, param);
break;
+ case CTL_MSG_MODE_SYNC:
+ ctl_isc_mode_sync(softc, msg, param);
+ break;
default:
printf("Received HA message of unknown type %d\n",
msg->hdr.msg_type);
@@ -5954,7 +6035,11 @@ ctl_control_page_handler(struct ctl_scsiio *ctsio,
if (set_ua != 0)
ctl_est_ua_all(lun, initidx, CTL_UA_MODE_CHANGE);
mtx_unlock(&lun->lun_lock);
-
+ if (set_ua) {
+ ctl_isc_announce_mode(lun,
+ ctl_get_initindex(&ctsio->io_hdr.nexus),
+ page_index->page_code, page_index->subpage);
+ }
return (0);
}
@@ -5991,7 +6076,11 @@ ctl_caching_sp_handler(struct ctl_scsiio *ctsio,
if (set_ua != 0)
ctl_est_ua_all(lun, initidx, CTL_UA_MODE_CHANGE);
mtx_unlock(&lun->lun_lock);
-
+ if (set_ua) {
+ ctl_isc_announce_mode(lun,
+ ctl_get_initindex(&ctsio->io_hdr.nexus),
+ page_index->page_code, page_index->subpage);
+ }
return (0);
}
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index c024336..9fd6cce 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -193,6 +193,8 @@ void ctl_clr_ua_allluns(struct ctl_softc *ctl_softc, uint32_t initidx,
void ctl_isc_announce_lun(struct ctl_lun *lun);
void ctl_isc_announce_port(struct ctl_port *port);
void ctl_isc_announce_iid(struct ctl_port *port, int iid);
+void ctl_isc_announce_mode(struct ctl_lun *lun, uint32_t initidx,
+ uint8_t page, uint8_t subpage);
/*
* KPI to manipulate LUN/port options
diff --git a/sys/cam/ctl/ctl_io.h b/sys/cam/ctl/ctl_io.h
index a9ed1d0..17fce7e 100644
--- a/sys/cam/ctl/ctl_io.h
+++ b/sys/cam/ctl/ctl_io.h
@@ -198,6 +198,7 @@ typedef enum {
CTL_MSG_LUN_SYNC, /* Information about LUN. */
CTL_MSG_IID_SYNC, /* Information about initiator. */
CTL_MSG_LOGIN, /* Information about HA peer. */
+ CTL_MSG_MODE_SYNC, /* Mode page current content. */
CTL_MSG_FAILOVER /* Fake, never sent though the wire */
} ctl_msg_type;
@@ -533,6 +534,17 @@ struct ctl_ha_msg_iid {
uint8_t data[];
};
+/*
+ * Used for CTL_MSG_MODE_SYNC.
+ */
+struct ctl_ha_msg_mode {
+ struct ctl_ha_msg_hdr hdr;
+ uint8_t page_code;
+ uint8_t subpage;
+ uint16_t page_len;
+ uint8_t data[];
+};
+
union ctl_ha_msg {
struct ctl_ha_msg_hdr hdr;
struct ctl_ha_msg_task task;
@@ -544,6 +556,7 @@ union ctl_ha_msg {
struct ctl_ha_msg_lun lun;
struct ctl_ha_msg_iid iid;
struct ctl_ha_msg_login login;
+ struct ctl_ha_msg_mode mode;
};
struct ctl_prio {
OpenPOWER on IntegriCloud