Skip to content

Commit 464fd64

Browse files
Michael CyrNicholas Bellinger
authored andcommitted
ibmvscsis: Enable Logical Partition Migration Support
Changes to support a new mechanism from phyp to better synchronize the logical partition migration (LPM) of the client partition. This includes a new VIOCTL to register that we support this new functionality, and 2 new Transport Event types, and finally another new VIOCTL to let phyp know once we're ready for the Suspend. Signed-off-by: Michael Cyr <mikecyr@us.ibm.com> Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
1 parent 12bdcbd commit 464fd64

File tree

3 files changed

+162
-16
lines changed

3 files changed

+162
-16
lines changed

drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c

Lines changed: 135 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ static long ibmvscsis_unregister_command_q(struct scsi_info *vscsi)
155155
qrc = h_free_crq(vscsi->dds.unit_id);
156156
switch (qrc) {
157157
case H_SUCCESS:
158+
spin_lock_bh(&vscsi->intr_lock);
159+
vscsi->flags &= ~PREP_FOR_SUSPEND_FLAGS;
160+
spin_unlock_bh(&vscsi->intr_lock);
158161
break;
159162

160163
case H_HARDWARE:
@@ -422,6 +425,9 @@ static void ibmvscsis_disconnect(struct work_struct *work)
422425
new_state = vscsi->new_state;
423426
vscsi->new_state = 0;
424427

428+
vscsi->flags |= DISCONNECT_SCHEDULED;
429+
vscsi->flags &= ~SCHEDULE_DISCONNECT;
430+
425431
pr_debug("disconnect: flags 0x%x, state 0x%hx\n", vscsi->flags,
426432
vscsi->state);
427433

@@ -802,6 +808,13 @@ static long ibmvscsis_establish_new_q(struct scsi_info *vscsi)
802808
long rc = ADAPT_SUCCESS;
803809
uint format;
804810

811+
rc = h_vioctl(vscsi->dds.unit_id, H_ENABLE_PREPARE_FOR_SUSPEND, 30000,
812+
0, 0, 0, 0);
813+
if (rc == H_SUCCESS)
814+
vscsi->flags |= PREP_FOR_SUSPEND_ENABLED;
815+
else if (rc != H_NOT_FOUND)
816+
pr_err("Error from Enable Prepare for Suspend: %ld\n", rc);
817+
805818
vscsi->flags &= PRESERVE_FLAG_FIELDS;
806819
vscsi->rsp_q_timer.timer_pops = 0;
807820
vscsi->debit = 0;
@@ -950,6 +963,63 @@ static void ibmvscsis_free_cmd_resources(struct scsi_info *vscsi,
950963
}
951964
}
952965

966+
/**
967+
* ibmvscsis_ready_for_suspend() - Helper function to call VIOCTL
968+
* @vscsi: Pointer to our adapter structure
969+
* @idle: Indicates whether we were called from adapter_idle. This
970+
* is important to know if we need to do a disconnect, since if
971+
* we're called from adapter_idle, we're still processing the
972+
* current disconnect, so we can't just call post_disconnect.
973+
*
974+
* This function is called when the adapter is idle when phyp has sent
975+
* us a Prepare for Suspend Transport Event.
976+
*
977+
* EXECUTION ENVIRONMENT:
978+
* Process or interrupt environment called with interrupt lock held
979+
*/
980+
static long ibmvscsis_ready_for_suspend(struct scsi_info *vscsi, bool idle)
981+
{
982+
long rc = 0;
983+
struct viosrp_crq *crq;
984+
985+
/* See if there is a Resume event in the queue */
986+
crq = vscsi->cmd_q.base_addr + vscsi->cmd_q.index;
987+
988+
pr_debug("ready_suspend: flags 0x%x, state 0x%hx crq_valid:%x\n",
989+
vscsi->flags, vscsi->state, (int)crq->valid);
990+
991+
if (!(vscsi->flags & PREP_FOR_SUSPEND_ABORTED) && !(crq->valid)) {
992+
rc = h_vioctl(vscsi->dds.unit_id, H_READY_FOR_SUSPEND, 0, 0, 0,
993+
0, 0);
994+
if (rc) {
995+
pr_err("Ready for Suspend Vioctl failed: %ld\n", rc);
996+
rc = 0;
997+
}
998+
} else if (((vscsi->flags & PREP_FOR_SUSPEND_OVERWRITE) &&
999+
(vscsi->flags & PREP_FOR_SUSPEND_ABORTED)) ||
1000+
((crq->valid) && ((crq->valid != VALID_TRANS_EVENT) ||
1001+
(crq->format != RESUME_FROM_SUSP)))) {
1002+
if (idle) {
1003+
vscsi->state = ERR_DISCONNECT_RECONNECT;
1004+
ibmvscsis_reset_queue(vscsi);
1005+
rc = -1;
1006+
} else if (vscsi->state == CONNECTED) {
1007+
ibmvscsis_post_disconnect(vscsi,
1008+
ERR_DISCONNECT_RECONNECT, 0);
1009+
}
1010+
1011+
vscsi->flags &= ~PREP_FOR_SUSPEND_OVERWRITE;
1012+
1013+
if ((crq->valid) && ((crq->valid != VALID_TRANS_EVENT) ||
1014+
(crq->format != RESUME_FROM_SUSP)))
1015+
pr_err("Invalid element in CRQ after Prepare for Suspend");
1016+
}
1017+
1018+
vscsi->flags &= ~(PREP_FOR_SUSPEND_PENDING | PREP_FOR_SUSPEND_ABORTED);
1019+
1020+
return rc;
1021+
}
1022+
9531023
/**
9541024
* ibmvscsis_trans_event() - Handle a Transport Event
9551025
* @vscsi: Pointer to our adapter structure
@@ -974,18 +1044,8 @@ static long ibmvscsis_trans_event(struct scsi_info *vscsi,
9741044
case PARTNER_FAILED:
9751045
case PARTNER_DEREGISTER:
9761046
ibmvscsis_delete_client_info(vscsi, true);
977-
break;
978-
979-
default:
980-
rc = ERROR;
981-
dev_err(&vscsi->dev, "trans_event: invalid format %d\n",
982-
(uint)crq->format);
983-
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT,
984-
RESPONSE_Q_DOWN);
985-
break;
986-
}
987-
988-
if (rc == ADAPT_SUCCESS) {
1047+
if (crq->format == MIGRATED)
1048+
vscsi->flags &= ~PREP_FOR_SUSPEND_OVERWRITE;
9891049
switch (vscsi->state) {
9901050
case NO_QUEUE:
9911051
case ERR_DISCONNECTED:
@@ -1034,6 +1094,60 @@ static long ibmvscsis_trans_event(struct scsi_info *vscsi,
10341094
vscsi->flags |= (RESPONSE_Q_DOWN | TRANS_EVENT);
10351095
break;
10361096
}
1097+
break;
1098+
1099+
case PREPARE_FOR_SUSPEND:
1100+
pr_debug("Prep for Suspend, crq status = 0x%x\n",
1101+
(int)crq->status);
1102+
switch (vscsi->state) {
1103+
case ERR_DISCONNECTED:
1104+
case WAIT_CONNECTION:
1105+
case CONNECTED:
1106+
ibmvscsis_ready_for_suspend(vscsi, false);
1107+
break;
1108+
case SRP_PROCESSING:
1109+
vscsi->resume_state = vscsi->state;
1110+
vscsi->flags |= PREP_FOR_SUSPEND_PENDING;
1111+
if (crq->status == CRQ_ENTRY_OVERWRITTEN)
1112+
vscsi->flags |= PREP_FOR_SUSPEND_OVERWRITE;
1113+
ibmvscsis_post_disconnect(vscsi, WAIT_IDLE, 0);
1114+
break;
1115+
case NO_QUEUE:
1116+
case UNDEFINED:
1117+
case UNCONFIGURING:
1118+
case WAIT_ENABLED:
1119+
case ERR_DISCONNECT:
1120+
case ERR_DISCONNECT_RECONNECT:
1121+
case WAIT_IDLE:
1122+
pr_err("Invalid state for Prepare for Suspend Trans Event: 0x%x\n",
1123+
vscsi->state);
1124+
break;
1125+
}
1126+
break;
1127+
1128+
case RESUME_FROM_SUSP:
1129+
pr_debug("Resume from Suspend, crq status = 0x%x\n",
1130+
(int)crq->status);
1131+
if (vscsi->flags & PREP_FOR_SUSPEND_PENDING) {
1132+
vscsi->flags |= PREP_FOR_SUSPEND_ABORTED;
1133+
} else {
1134+
if ((crq->status == CRQ_ENTRY_OVERWRITTEN) ||
1135+
(vscsi->flags & PREP_FOR_SUSPEND_OVERWRITE)) {
1136+
ibmvscsis_post_disconnect(vscsi,
1137+
ERR_DISCONNECT_RECONNECT,
1138+
0);
1139+
vscsi->flags &= ~PREP_FOR_SUSPEND_OVERWRITE;
1140+
}
1141+
}
1142+
break;
1143+
1144+
default:
1145+
rc = ERROR;
1146+
dev_err(&vscsi->dev, "trans_event: invalid format %d\n",
1147+
(uint)crq->format);
1148+
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT,
1149+
RESPONSE_Q_DOWN);
1150+
break;
10371151
}
10381152

10391153
rc = vscsi->flags & SCHEDULE_DISCONNECT;
@@ -1201,6 +1315,7 @@ static struct ibmvscsis_cmd *ibmvscsis_get_free_cmd(struct scsi_info *vscsi)
12011315
static void ibmvscsis_adapter_idle(struct scsi_info *vscsi)
12021316
{
12031317
int free_qs = false;
1318+
long rc = 0;
12041319

12051320
pr_debug("adapter_idle: flags 0x%x, state 0x%hx\n", vscsi->flags,
12061321
vscsi->state);
@@ -1240,7 +1355,14 @@ static void ibmvscsis_adapter_idle(struct scsi_info *vscsi)
12401355
vscsi->rsp_q_timer.timer_pops = 0;
12411356
vscsi->debit = 0;
12421357
vscsi->credit = 0;
1243-
if (vscsi->flags & TRANS_EVENT) {
1358+
if (vscsi->flags & PREP_FOR_SUSPEND_PENDING) {
1359+
vscsi->state = vscsi->resume_state;
1360+
vscsi->resume_state = 0;
1361+
rc = ibmvscsis_ready_for_suspend(vscsi, true);
1362+
vscsi->flags &= ~DISCONNECT_SCHEDULED;
1363+
if (rc)
1364+
break;
1365+
} else if (vscsi->flags & TRANS_EVENT) {
12441366
vscsi->state = WAIT_CONNECTION;
12451367
vscsi->flags &= PRESERVE_FLAG_FIELDS;
12461368
} else {

drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,14 @@ struct scsi_info {
262262
#define DISCONNECT_SCHEDULED 0x00800
263263
/* remove function is sleeping */
264264
#define CFG_SLEEPING 0x01000
265+
/* Register for Prepare for Suspend Transport Events */
266+
#define PREP_FOR_SUSPEND_ENABLED 0x02000
267+
/* Prepare for Suspend event sent */
268+
#define PREP_FOR_SUSPEND_PENDING 0x04000
269+
/* Resume from Suspend event sent */
270+
#define PREP_FOR_SUSPEND_ABORTED 0x08000
271+
/* Prepare for Suspend event overwrote another CRQ entry */
272+
#define PREP_FOR_SUSPEND_OVERWRITE 0x10000
265273
u32 flags;
266274
/* adapter lock */
267275
spinlock_t intr_lock;
@@ -272,6 +280,7 @@ struct scsi_info {
272280
/* used in crq, to tag what iu the response is for */
273281
u64 empty_iu_tag;
274282
uint new_state;
283+
uint resume_state;
275284
/* control block for the response queue timer */
276285
struct timer_cb rsp_q_timer;
277286
/* keep last client to enable proper accounting */
@@ -324,17 +333,29 @@ struct scsi_info {
324333
#define TARGET_STOP(VSCSI) (long)(((VSCSI)->state & DONT_PROCESS_STATE) | \
325334
((VSCSI)->flags & BLOCK))
326335

336+
#define PREP_FOR_SUSPEND_FLAGS (PREP_FOR_SUSPEND_ENABLED | \
337+
PREP_FOR_SUSPEND_PENDING | \
338+
PREP_FOR_SUSPEND_ABORTED | \
339+
PREP_FOR_SUSPEND_OVERWRITE)
340+
327341
/* flag bit that are not reset during disconnect */
328-
#define PRESERVE_FLAG_FIELDS 0
342+
#define PRESERVE_FLAG_FIELDS (PREP_FOR_SUSPEND_FLAGS)
329343

330344
#define vio_iu(IUE) ((union viosrp_iu *)((IUE)->sbuf->buf))
331345

332346
#define READ_CMD(cdb) (((cdb)[0] & 0x1F) == 8)
333347
#define WRITE_CMD(cdb) (((cdb)[0] & 0x1F) == 0xA)
334348

335349
#ifndef H_GET_PARTNER_INFO
336-
#define H_GET_PARTNER_INFO 0x0000000000000008LL
350+
#define H_GET_PARTNER_INFO 0x0000000000000008LL
351+
#endif
352+
#ifndef H_ENABLE_PREPARE_FOR_SUSPEND
353+
#define H_ENABLE_PREPARE_FOR_SUSPEND 0x000000000000001DLL
337354
#endif
355+
#ifndef H_READY_FOR_SUSPEND
356+
#define H_READY_FOR_SUSPEND 0x000000000000001ELL
357+
#endif
358+
338359

339360
#define h_copy_rdma(l, sa, sb, da, db) \
340361
plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db)

drivers/scsi/ibmvscsi_tgt/libsrp.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,13 @@ enum srp_trans_event {
3030
UNUSED_FORMAT = 0,
3131
PARTNER_FAILED = 1,
3232
PARTNER_DEREGISTER = 2,
33-
MIGRATED = 6
33+
MIGRATED = 6,
34+
PREPARE_FOR_SUSPEND = 9,
35+
RESUME_FROM_SUSP = 0xA
3436
};
3537

3638
enum srp_status {
39+
CRQ_ENTRY_OVERWRITTEN = 0x20,
3740
HEADER_DESCRIPTOR = 0xF1,
3841
PING = 0xF5,
3942
PING_RESPONSE = 0xF6

0 commit comments

Comments
 (0)