Merge branch '5.18/scsi-fixes' into 5.19/scsi-staging
Pull in 5.18 fixes branch which contains a bunch of fixes required for the lpfc driver update. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Коммит
08c84a75dd
|
@ -10369,6 +10369,7 @@ F: include/linux/isapnp.h
|
|||
ISCSI
|
||||
M: Lee Duncan <lduncan@suse.com>
|
||||
M: Chris Leech <cleech@redhat.com>
|
||||
M: Mike Christie <michael.christie@oracle.com>
|
||||
L: open-iscsi@googlegroups.com
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
|
@ -6658,13 +6658,13 @@ static int mpt_summary_proc_show(struct seq_file *m, void *v)
|
|||
static int mpt_version_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
u8 cb_idx;
|
||||
int scsi, fc, sas, lan, ctl, targ, dmp;
|
||||
int scsi, fc, sas, lan, ctl, targ;
|
||||
char *drvname;
|
||||
|
||||
seq_printf(m, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
|
||||
seq_printf(m, " Fusion MPT base driver\n");
|
||||
|
||||
scsi = fc = sas = lan = ctl = targ = dmp = 0;
|
||||
scsi = fc = sas = lan = ctl = targ = 0;
|
||||
for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
|
||||
drvname = NULL;
|
||||
if (MptCallbacks[cb_idx]) {
|
||||
|
|
|
@ -317,14 +317,18 @@ enum {
|
|||
};
|
||||
|
||||
struct aha152x_cmd_priv {
|
||||
struct scsi_pointer scsi_pointer;
|
||||
char *ptr;
|
||||
int this_residual;
|
||||
struct scatterlist *buffer;
|
||||
int status;
|
||||
int message;
|
||||
int sent_command;
|
||||
int phase;
|
||||
};
|
||||
|
||||
static struct scsi_pointer *aha152x_scsi_pointer(struct scsi_cmnd *cmd)
|
||||
static struct aha152x_cmd_priv *aha152x_priv(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct aha152x_cmd_priv *acmd = scsi_cmd_priv(cmd);
|
||||
|
||||
return &acmd->scsi_pointer;
|
||||
return scsi_cmd_priv(cmd);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Jürgen Fischer");
|
||||
|
@ -890,17 +894,16 @@ void aha152x_release(struct Scsi_Host *shpnt)
|
|||
static int setup_expected_interrupts(struct Scsi_Host *shpnt)
|
||||
{
|
||||
if(CURRENT_SC) {
|
||||
struct scsi_pointer *scsi_pointer =
|
||||
aha152x_scsi_pointer(CURRENT_SC);
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(CURRENT_SC);
|
||||
|
||||
scsi_pointer->phase |= 1 << 16;
|
||||
acp->phase |= 1 << 16;
|
||||
|
||||
if (scsi_pointer->phase & selecting) {
|
||||
if (acp->phase & selecting) {
|
||||
SETPORT(SSTAT1, SELTO);
|
||||
SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
|
||||
SETPORT(SIMODE1, ENSELTIMO);
|
||||
} else {
|
||||
SETPORT(SIMODE0, (scsi_pointer->phase & spiordy) ? ENSPIORDY : 0);
|
||||
SETPORT(SIMODE0, (acp->phase & spiordy) ? ENSPIORDY : 0);
|
||||
SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
|
||||
}
|
||||
} else if(STATE==seldi) {
|
||||
|
@ -924,17 +927,16 @@ static int setup_expected_interrupts(struct Scsi_Host *shpnt)
|
|||
static int aha152x_internal_queue(struct scsi_cmnd *SCpnt,
|
||||
struct completion *complete, int phase)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = aha152x_scsi_pointer(SCpnt);
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(SCpnt);
|
||||
struct Scsi_Host *shpnt = SCpnt->device->host;
|
||||
unsigned long flags;
|
||||
|
||||
scsi_pointer->phase = not_issued | phase;
|
||||
scsi_pointer->Status = 0x1; /* Ilegal status by SCSI standard */
|
||||
scsi_pointer->Message = 0;
|
||||
scsi_pointer->have_data_in = 0;
|
||||
scsi_pointer->sent_command = 0;
|
||||
acp->phase = not_issued | phase;
|
||||
acp->status = 0x1; /* Illegal status by SCSI standard */
|
||||
acp->message = 0;
|
||||
acp->sent_command = 0;
|
||||
|
||||
if (scsi_pointer->phase & (resetting | check_condition)) {
|
||||
if (acp->phase & (resetting | check_condition)) {
|
||||
if (!SCpnt->host_scribble || SCSEM(SCpnt) || SCNEXT(SCpnt)) {
|
||||
scmd_printk(KERN_ERR, SCpnt, "cannot reuse command\n");
|
||||
return FAILED;
|
||||
|
@ -957,15 +959,15 @@ static int aha152x_internal_queue(struct scsi_cmnd *SCpnt,
|
|||
SCp.phase : current state of the command */
|
||||
|
||||
if ((phase & resetting) || !scsi_sglist(SCpnt)) {
|
||||
scsi_pointer->ptr = NULL;
|
||||
scsi_pointer->this_residual = 0;
|
||||
acp->ptr = NULL;
|
||||
acp->this_residual = 0;
|
||||
scsi_set_resid(SCpnt, 0);
|
||||
scsi_pointer->buffer = NULL;
|
||||
acp->buffer = NULL;
|
||||
} else {
|
||||
scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
|
||||
scsi_pointer->buffer = scsi_sglist(SCpnt);
|
||||
scsi_pointer->ptr = SG_ADDRESS(scsi_pointer->buffer);
|
||||
scsi_pointer->this_residual = scsi_pointer->buffer->length;
|
||||
acp->buffer = scsi_sglist(SCpnt);
|
||||
acp->ptr = SG_ADDRESS(acp->buffer);
|
||||
acp->this_residual = acp->buffer->length;
|
||||
}
|
||||
|
||||
DO_LOCK(flags);
|
||||
|
@ -1015,7 +1017,7 @@ static void reset_done(struct scsi_cmnd *SCpnt)
|
|||
|
||||
static void aha152x_scsi_done(struct scsi_cmnd *SCpnt)
|
||||
{
|
||||
if (aha152x_scsi_pointer(SCpnt)->phase & resetting)
|
||||
if (aha152x_priv(SCpnt)->phase & resetting)
|
||||
reset_done(SCpnt);
|
||||
else
|
||||
scsi_done(SCpnt);
|
||||
|
@ -1101,7 +1103,7 @@ static int aha152x_device_reset(struct scsi_cmnd * SCpnt)
|
|||
|
||||
DO_LOCK(flags);
|
||||
|
||||
if (aha152x_scsi_pointer(SCpnt)->phase & resetted) {
|
||||
if (aha152x_priv(SCpnt)->phase & resetted) {
|
||||
HOSTDATA(shpnt)->commands--;
|
||||
if (!HOSTDATA(shpnt)->commands)
|
||||
SETPORT(PORTA, 0);
|
||||
|
@ -1395,31 +1397,30 @@ static void busfree_run(struct Scsi_Host *shpnt)
|
|||
SETPORT(SSTAT1, CLRBUSFREE);
|
||||
|
||||
if(CURRENT_SC) {
|
||||
struct scsi_pointer *scsi_pointer =
|
||||
aha152x_scsi_pointer(CURRENT_SC);
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(CURRENT_SC);
|
||||
|
||||
#if defined(AHA152X_STAT)
|
||||
action++;
|
||||
#endif
|
||||
scsi_pointer->phase &= ~syncneg;
|
||||
acp->phase &= ~syncneg;
|
||||
|
||||
if (scsi_pointer->phase & completed) {
|
||||
if (acp->phase & completed) {
|
||||
/* target sent COMMAND COMPLETE */
|
||||
done(shpnt, scsi_pointer->Status, DID_OK);
|
||||
done(shpnt, acp->status, DID_OK);
|
||||
|
||||
} else if (scsi_pointer->phase & aborted) {
|
||||
done(shpnt, scsi_pointer->Status, DID_ABORT);
|
||||
} else if (acp->phase & aborted) {
|
||||
done(shpnt, acp->status, DID_ABORT);
|
||||
|
||||
} else if (scsi_pointer->phase & resetted) {
|
||||
done(shpnt, scsi_pointer->Status, DID_RESET);
|
||||
} else if (acp->phase & resetted) {
|
||||
done(shpnt, acp->status, DID_RESET);
|
||||
|
||||
} else if (scsi_pointer->phase & disconnected) {
|
||||
} else if (acp->phase & disconnected) {
|
||||
/* target sent DISCONNECT */
|
||||
#if defined(AHA152X_STAT)
|
||||
HOSTDATA(shpnt)->disconnections++;
|
||||
#endif
|
||||
append_SC(&DISCONNECTED_SC, CURRENT_SC);
|
||||
scsi_pointer->phase |= 1 << 16;
|
||||
acp->phase |= 1 << 16;
|
||||
CURRENT_SC = NULL;
|
||||
|
||||
} else {
|
||||
|
@ -1438,24 +1439,23 @@ static void busfree_run(struct Scsi_Host *shpnt)
|
|||
action++;
|
||||
#endif
|
||||
|
||||
if (aha152x_scsi_pointer(DONE_SC)->phase & check_condition) {
|
||||
if (aha152x_priv(DONE_SC)->phase & check_condition) {
|
||||
struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
|
||||
struct aha152x_scdata *sc = SCDATA(cmd);
|
||||
|
||||
scsi_eh_restore_cmnd(cmd, &sc->ses);
|
||||
|
||||
aha152x_scsi_pointer(cmd)->Status = SAM_STAT_CHECK_CONDITION;
|
||||
aha152x_priv(cmd)->status = SAM_STAT_CHECK_CONDITION;
|
||||
|
||||
HOSTDATA(shpnt)->commands--;
|
||||
if (!HOSTDATA(shpnt)->commands)
|
||||
SETPORT(PORTA, 0); /* turn led off */
|
||||
} else if (aha152x_scsi_pointer(DONE_SC)->Status ==
|
||||
SAM_STAT_CHECK_CONDITION) {
|
||||
} else if (aha152x_priv(DONE_SC)->status == SAM_STAT_CHECK_CONDITION) {
|
||||
#if defined(AHA152X_STAT)
|
||||
HOSTDATA(shpnt)->busfree_with_check_condition++;
|
||||
#endif
|
||||
|
||||
if(!(aha152x_scsi_pointer(DONE_SC)->phase & not_issued)) {
|
||||
if (!(aha152x_priv(DONE_SC)->phase & not_issued)) {
|
||||
struct aha152x_scdata *sc;
|
||||
struct scsi_cmnd *ptr = DONE_SC;
|
||||
DONE_SC=NULL;
|
||||
|
@ -1480,7 +1480,7 @@ static void busfree_run(struct Scsi_Host *shpnt)
|
|||
if (!HOSTDATA(shpnt)->commands)
|
||||
SETPORT(PORTA, 0); /* turn led off */
|
||||
|
||||
if (!(aha152x_scsi_pointer(ptr)->phase & resetting)) {
|
||||
if (!(aha152x_priv(ptr)->phase & resetting)) {
|
||||
kfree(ptr->host_scribble);
|
||||
ptr->host_scribble=NULL;
|
||||
}
|
||||
|
@ -1503,13 +1503,12 @@ static void busfree_run(struct Scsi_Host *shpnt)
|
|||
DO_UNLOCK(flags);
|
||||
|
||||
if(CURRENT_SC) {
|
||||
struct scsi_pointer *scsi_pointer =
|
||||
aha152x_scsi_pointer(CURRENT_SC);
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(CURRENT_SC);
|
||||
|
||||
#if defined(AHA152X_STAT)
|
||||
action++;
|
||||
#endif
|
||||
scsi_pointer->phase |= selecting;
|
||||
acp->phase |= selecting;
|
||||
|
||||
/* clear selection timeout */
|
||||
SETPORT(SSTAT1, SELTO);
|
||||
|
@ -1537,13 +1536,13 @@ static void busfree_run(struct Scsi_Host *shpnt)
|
|||
*/
|
||||
static void seldo_run(struct Scsi_Host *shpnt)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(CURRENT_SC);
|
||||
|
||||
SETPORT(SCSISIG, 0);
|
||||
SETPORT(SSTAT1, CLRBUSFREE);
|
||||
SETPORT(SSTAT1, CLRPHASECHG);
|
||||
|
||||
scsi_pointer->phase &= ~(selecting | not_issued);
|
||||
acp->phase &= ~(selecting | not_issued);
|
||||
|
||||
SETPORT(SCSISEQ, 0);
|
||||
|
||||
|
@ -1558,12 +1557,12 @@ static void seldo_run(struct Scsi_Host *shpnt)
|
|||
|
||||
ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
|
||||
|
||||
if (scsi_pointer->phase & aborting) {
|
||||
if (acp->phase & aborting) {
|
||||
ADDMSGO(ABORT);
|
||||
} else if (scsi_pointer->phase & resetting) {
|
||||
} else if (acp->phase & resetting) {
|
||||
ADDMSGO(BUS_DEVICE_RESET);
|
||||
} else if (SYNCNEG==0 && SYNCHRONOUS) {
|
||||
scsi_pointer->phase |= syncneg;
|
||||
acp->phase |= syncneg;
|
||||
MSGOLEN += spi_populate_sync_msg(&MSGO(MSGOLEN), 50, 8);
|
||||
SYNCNEG=1; /* negotiation in progress */
|
||||
}
|
||||
|
@ -1578,7 +1577,7 @@ static void seldo_run(struct Scsi_Host *shpnt)
|
|||
*/
|
||||
static void selto_run(struct Scsi_Host *shpnt)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
struct aha152x_cmd_priv *acp;
|
||||
|
||||
SETPORT(SCSISEQ, 0);
|
||||
SETPORT(SSTAT1, CLRSELTIMO);
|
||||
|
@ -1586,9 +1585,10 @@ static void selto_run(struct Scsi_Host *shpnt)
|
|||
if (!CURRENT_SC)
|
||||
return;
|
||||
|
||||
scsi_pointer->phase &= ~selecting;
|
||||
acp = aha152x_priv(CURRENT_SC);
|
||||
acp->phase &= ~selecting;
|
||||
|
||||
if (scsi_pointer->phase & aborted)
|
||||
if (acp->phase & aborted)
|
||||
done(shpnt, SAM_STAT_GOOD, DID_ABORT);
|
||||
else if (TESTLO(SSTAT0, SELINGO))
|
||||
done(shpnt, SAM_STAT_GOOD, DID_BUS_BUSY);
|
||||
|
@ -1616,10 +1616,9 @@ static void seldi_run(struct Scsi_Host *shpnt)
|
|||
SETPORT(SSTAT1, CLRPHASECHG);
|
||||
|
||||
if(CURRENT_SC) {
|
||||
struct scsi_pointer *scsi_pointer =
|
||||
aha152x_scsi_pointer(CURRENT_SC);
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(CURRENT_SC);
|
||||
|
||||
if (!(scsi_pointer->phase & not_issued))
|
||||
if (!(acp->phase & not_issued))
|
||||
scmd_printk(KERN_ERR, CURRENT_SC,
|
||||
"command should not have been issued yet\n");
|
||||
|
||||
|
@ -1676,7 +1675,7 @@ static void seldi_run(struct Scsi_Host *shpnt)
|
|||
static void msgi_run(struct Scsi_Host *shpnt)
|
||||
{
|
||||
for(;;) {
|
||||
struct scsi_pointer *scsi_pointer;
|
||||
struct aha152x_cmd_priv *acp;
|
||||
int sstat1 = GETPORT(SSTAT1);
|
||||
|
||||
if(sstat1 & (PHASECHG|PHASEMIS|BUSFREE) || !(sstat1 & REQINIT))
|
||||
|
@ -1714,9 +1713,9 @@ static void msgi_run(struct Scsi_Host *shpnt)
|
|||
continue;
|
||||
}
|
||||
|
||||
scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
scsi_pointer->Message = MSGI(0);
|
||||
scsi_pointer->phase &= ~disconnected;
|
||||
acp = aha152x_priv(CURRENT_SC);
|
||||
acp->message = MSGI(0);
|
||||
acp->phase &= ~disconnected;
|
||||
|
||||
MSGILEN=0;
|
||||
|
||||
|
@ -1724,8 +1723,8 @@ static void msgi_run(struct Scsi_Host *shpnt)
|
|||
continue;
|
||||
}
|
||||
|
||||
scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
scsi_pointer->Message = MSGI(0);
|
||||
acp = aha152x_priv(CURRENT_SC);
|
||||
acp->message = MSGI(0);
|
||||
|
||||
switch (MSGI(0)) {
|
||||
case DISCONNECT:
|
||||
|
@ -1733,11 +1732,11 @@ static void msgi_run(struct Scsi_Host *shpnt)
|
|||
scmd_printk(KERN_WARNING, CURRENT_SC,
|
||||
"target was not allowed to disconnect\n");
|
||||
|
||||
scsi_pointer->phase |= disconnected;
|
||||
acp->phase |= disconnected;
|
||||
break;
|
||||
|
||||
case COMMAND_COMPLETE:
|
||||
scsi_pointer->phase |= completed;
|
||||
acp->phase |= completed;
|
||||
break;
|
||||
|
||||
case MESSAGE_REJECT:
|
||||
|
@ -1867,11 +1866,9 @@ static void msgi_end(struct Scsi_Host *shpnt)
|
|||
*/
|
||||
static void msgo_init(struct Scsi_Host *shpnt)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
|
||||
if(MSGOLEN==0) {
|
||||
if ((scsi_pointer->phase & syncneg) && SYNCNEG==2 &&
|
||||
SYNCRATE==0) {
|
||||
if ((aha152x_priv(CURRENT_SC)->phase & syncneg) &&
|
||||
SYNCNEG == 2 && SYNCRATE == 0) {
|
||||
ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
|
||||
} else {
|
||||
scmd_printk(KERN_INFO, CURRENT_SC,
|
||||
|
@ -1888,7 +1885,7 @@ static void msgo_init(struct Scsi_Host *shpnt)
|
|||
*/
|
||||
static void msgo_run(struct Scsi_Host *shpnt)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(CURRENT_SC);
|
||||
|
||||
while(MSGO_I<MSGOLEN) {
|
||||
if (TESTLO(SSTAT0, SPIORDY))
|
||||
|
@ -1901,13 +1898,13 @@ static void msgo_run(struct Scsi_Host *shpnt)
|
|||
|
||||
|
||||
if (MSGO(MSGO_I) & IDENTIFY_BASE)
|
||||
scsi_pointer->phase |= identified;
|
||||
acp->phase |= identified;
|
||||
|
||||
if (MSGO(MSGO_I)==ABORT)
|
||||
scsi_pointer->phase |= aborted;
|
||||
acp->phase |= aborted;
|
||||
|
||||
if (MSGO(MSGO_I)==BUS_DEVICE_RESET)
|
||||
scsi_pointer->phase |= resetted;
|
||||
acp->phase |= resetted;
|
||||
|
||||
SETPORT(SCSIDAT, MSGO(MSGO_I++));
|
||||
}
|
||||
|
@ -1936,7 +1933,7 @@ static void msgo_end(struct Scsi_Host *shpnt)
|
|||
*/
|
||||
static void cmd_init(struct Scsi_Host *shpnt)
|
||||
{
|
||||
if (aha152x_scsi_pointer(CURRENT_SC)->sent_command) {
|
||||
if (aha152x_priv(CURRENT_SC)->sent_command) {
|
||||
scmd_printk(KERN_ERR, CURRENT_SC,
|
||||
"command already sent\n");
|
||||
done(shpnt, SAM_STAT_GOOD, DID_ERROR);
|
||||
|
@ -1967,7 +1964,7 @@ static void cmd_end(struct Scsi_Host *shpnt)
|
|||
"command sent incompletely (%d/%d)\n",
|
||||
CMD_I, CURRENT_SC->cmd_len);
|
||||
else
|
||||
aha152x_scsi_pointer(CURRENT_SC)->sent_command++;
|
||||
aha152x_priv(CURRENT_SC)->sent_command++;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1979,7 +1976,7 @@ static void status_run(struct Scsi_Host *shpnt)
|
|||
if (TESTLO(SSTAT0, SPIORDY))
|
||||
return;
|
||||
|
||||
aha152x_scsi_pointer(CURRENT_SC)->Status = GETPORT(SCSIDAT);
|
||||
aha152x_priv(CURRENT_SC)->status = GETPORT(SCSIDAT);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2003,7 +2000,7 @@ static void datai_init(struct Scsi_Host *shpnt)
|
|||
|
||||
static void datai_run(struct Scsi_Host *shpnt)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer;
|
||||
struct aha152x_cmd_priv *acp;
|
||||
unsigned long the_time;
|
||||
int fifodata, data_count;
|
||||
|
||||
|
@ -2041,36 +2038,35 @@ static void datai_run(struct Scsi_Host *shpnt)
|
|||
fifodata = GETPORT(FIFOSTAT);
|
||||
}
|
||||
|
||||
scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
if (scsi_pointer->this_residual > 0) {
|
||||
while (fifodata > 0 && scsi_pointer->this_residual > 0) {
|
||||
data_count = fifodata > scsi_pointer->this_residual ?
|
||||
scsi_pointer->this_residual :
|
||||
fifodata;
|
||||
acp = aha152x_priv(CURRENT_SC);
|
||||
if (acp->this_residual > 0) {
|
||||
while (fifodata > 0 && acp->this_residual > 0) {
|
||||
data_count = fifodata > acp->this_residual ?
|
||||
acp->this_residual : fifodata;
|
||||
fifodata -= data_count;
|
||||
|
||||
if (data_count & 1) {
|
||||
SETPORT(DMACNTRL0, ENDMA|_8BIT);
|
||||
*scsi_pointer->ptr++ = GETPORT(DATAPORT);
|
||||
scsi_pointer->this_residual--;
|
||||
*acp->ptr++ = GETPORT(DATAPORT);
|
||||
acp->this_residual--;
|
||||
DATA_LEN++;
|
||||
SETPORT(DMACNTRL0, ENDMA);
|
||||
}
|
||||
|
||||
if (data_count > 1) {
|
||||
data_count >>= 1;
|
||||
insw(DATAPORT, scsi_pointer->ptr, data_count);
|
||||
scsi_pointer->ptr += 2 * data_count;
|
||||
scsi_pointer->this_residual -= 2 * data_count;
|
||||
insw(DATAPORT, acp->ptr, data_count);
|
||||
acp->ptr += 2 * data_count;
|
||||
acp->this_residual -= 2 * data_count;
|
||||
DATA_LEN += 2 * data_count;
|
||||
}
|
||||
|
||||
if (scsi_pointer->this_residual == 0 &&
|
||||
!sg_is_last(scsi_pointer->buffer)) {
|
||||
if (acp->this_residual == 0 &&
|
||||
!sg_is_last(acp->buffer)) {
|
||||
/* advance to next buffer */
|
||||
scsi_pointer->buffer = sg_next(scsi_pointer->buffer);
|
||||
scsi_pointer->ptr = SG_ADDRESS(scsi_pointer->buffer);
|
||||
scsi_pointer->this_residual = scsi_pointer->buffer->length;
|
||||
acp->buffer = sg_next(acp->buffer);
|
||||
acp->ptr = SG_ADDRESS(acp->buffer);
|
||||
acp->this_residual = acp->buffer->length;
|
||||
}
|
||||
}
|
||||
} else if (fifodata > 0) {
|
||||
|
@ -2138,15 +2134,15 @@ static void datao_init(struct Scsi_Host *shpnt)
|
|||
|
||||
static void datao_run(struct Scsi_Host *shpnt)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(CURRENT_SC);
|
||||
unsigned long the_time;
|
||||
int data_count;
|
||||
|
||||
/* until phase changes or all data sent */
|
||||
while (TESTLO(DMASTAT, INTSTAT) && scsi_pointer->this_residual > 0) {
|
||||
while (TESTLO(DMASTAT, INTSTAT) && acp->this_residual > 0) {
|
||||
data_count = 128;
|
||||
if (data_count > scsi_pointer->this_residual)
|
||||
data_count = scsi_pointer->this_residual;
|
||||
if (data_count > acp->this_residual)
|
||||
data_count = acp->this_residual;
|
||||
|
||||
if(TESTLO(DMASTAT, DFIFOEMP)) {
|
||||
scmd_printk(KERN_ERR, CURRENT_SC,
|
||||
|
@ -2157,26 +2153,25 @@ static void datao_run(struct Scsi_Host *shpnt)
|
|||
|
||||
if(data_count & 1) {
|
||||
SETPORT(DMACNTRL0,WRITE_READ|ENDMA|_8BIT);
|
||||
SETPORT(DATAPORT, *scsi_pointer->ptr++);
|
||||
scsi_pointer->this_residual--;
|
||||
SETPORT(DATAPORT, *acp->ptr++);
|
||||
acp->this_residual--;
|
||||
CMD_INC_RESID(CURRENT_SC, -1);
|
||||
SETPORT(DMACNTRL0,WRITE_READ|ENDMA);
|
||||
}
|
||||
|
||||
if(data_count > 1) {
|
||||
data_count >>= 1;
|
||||
outsw(DATAPORT, scsi_pointer->ptr, data_count);
|
||||
scsi_pointer->ptr += 2 * data_count;
|
||||
scsi_pointer->this_residual -= 2 * data_count;
|
||||
outsw(DATAPORT, acp->ptr, data_count);
|
||||
acp->ptr += 2 * data_count;
|
||||
acp->this_residual -= 2 * data_count;
|
||||
CMD_INC_RESID(CURRENT_SC, -2 * data_count);
|
||||
}
|
||||
|
||||
if (scsi_pointer->this_residual == 0 &&
|
||||
!sg_is_last(scsi_pointer->buffer)) {
|
||||
if (acp->this_residual == 0 && !sg_is_last(acp->buffer)) {
|
||||
/* advance to next buffer */
|
||||
scsi_pointer->buffer = sg_next(scsi_pointer->buffer);
|
||||
scsi_pointer->ptr = SG_ADDRESS(scsi_pointer->buffer);
|
||||
scsi_pointer->this_residual = scsi_pointer->buffer->length;
|
||||
acp->buffer = sg_next(acp->buffer);
|
||||
acp->ptr = SG_ADDRESS(acp->buffer);
|
||||
acp->this_residual = acp->buffer->length;
|
||||
}
|
||||
|
||||
the_time=jiffies + 100*HZ;
|
||||
|
@ -2192,7 +2187,7 @@ static void datao_run(struct Scsi_Host *shpnt)
|
|||
|
||||
static void datao_end(struct Scsi_Host *shpnt)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(CURRENT_SC);
|
||||
|
||||
if(TESTLO(DMASTAT, DFIFOEMP)) {
|
||||
u32 datao_cnt = GETSTCNT();
|
||||
|
@ -2211,10 +2206,9 @@ static void datao_end(struct Scsi_Host *shpnt)
|
|||
sg = sg_next(sg);
|
||||
}
|
||||
|
||||
scsi_pointer->buffer = sg;
|
||||
scsi_pointer->ptr = SG_ADDRESS(scsi_pointer->buffer) + done;
|
||||
scsi_pointer->this_residual = scsi_pointer->buffer->length -
|
||||
done;
|
||||
acp->buffer = sg;
|
||||
acp->ptr = SG_ADDRESS(acp->buffer) + done;
|
||||
acp->this_residual = acp->buffer->length - done;
|
||||
}
|
||||
|
||||
SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
|
||||
|
@ -2229,7 +2223,6 @@ static void datao_end(struct Scsi_Host *shpnt)
|
|||
*/
|
||||
static int update_state(struct Scsi_Host *shpnt)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = aha152x_scsi_pointer(CURRENT_SC);
|
||||
int dataphase=0;
|
||||
unsigned int stat0 = GETPORT(SSTAT0);
|
||||
unsigned int stat1 = GETPORT(SSTAT1);
|
||||
|
@ -2244,7 +2237,7 @@ static int update_state(struct Scsi_Host *shpnt)
|
|||
} else if (stat0 & SELDI && PREVSTATE == busfree) {
|
||||
STATE=seldi;
|
||||
} else if (stat0 & SELDO && CURRENT_SC &&
|
||||
(scsi_pointer->phase & selecting)) {
|
||||
(aha152x_priv(CURRENT_SC)->phase & selecting)) {
|
||||
STATE=seldo;
|
||||
} else if(stat1 & SELTO) {
|
||||
STATE=selto;
|
||||
|
@ -2376,8 +2369,7 @@ static void is_complete(struct Scsi_Host *shpnt)
|
|||
SETPORT(SXFRCTL0, CH1);
|
||||
SETPORT(DMACNTRL0, 0);
|
||||
if(CURRENT_SC)
|
||||
aha152x_scsi_pointer(CURRENT_SC)->phase &=
|
||||
~spiordy;
|
||||
aha152x_priv(CURRENT_SC)->phase &= ~spiordy;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2399,8 +2391,7 @@ static void is_complete(struct Scsi_Host *shpnt)
|
|||
SETPORT(DMACNTRL0, 0);
|
||||
SETPORT(SXFRCTL0, CH1|SPIOEN);
|
||||
if(CURRENT_SC)
|
||||
aha152x_scsi_pointer(CURRENT_SC)->phase |=
|
||||
spiordy;
|
||||
aha152x_priv(CURRENT_SC)->phase |= spiordy;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2490,7 +2481,7 @@ static void disp_enintr(struct Scsi_Host *shpnt)
|
|||
*/
|
||||
static void show_command(struct scsi_cmnd *ptr)
|
||||
{
|
||||
const int phase = aha152x_scsi_pointer(ptr)->phase;
|
||||
const int phase = aha152x_priv(ptr)->phase;
|
||||
|
||||
scsi_print_command(ptr);
|
||||
scmd_printk(KERN_DEBUG, ptr,
|
||||
|
@ -2538,8 +2529,8 @@ static void show_queues(struct Scsi_Host *shpnt)
|
|||
|
||||
static void get_command(struct seq_file *m, struct scsi_cmnd * ptr)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = aha152x_scsi_pointer(ptr);
|
||||
const int phase = scsi_pointer->phase;
|
||||
struct aha152x_cmd_priv *acp = aha152x_priv(ptr);
|
||||
const int phase = acp->phase;
|
||||
int i;
|
||||
|
||||
seq_printf(m, "%p: target=%d; lun=%d; cmnd=( ",
|
||||
|
@ -2549,8 +2540,8 @@ static void get_command(struct seq_file *m, struct scsi_cmnd * ptr)
|
|||
seq_printf(m, "0x%02x ", ptr->cmnd[i]);
|
||||
|
||||
seq_printf(m, "); resid=%d; residual=%d; buffers=%d; phase |",
|
||||
scsi_get_resid(ptr), scsi_pointer->this_residual,
|
||||
sg_nents(scsi_pointer->buffer) - 1);
|
||||
scsi_get_resid(ptr), acp->this_residual,
|
||||
sg_nents(acp->buffer) - 1);
|
||||
|
||||
if (phase & not_issued)
|
||||
seq_puts(m, "not issued|");
|
||||
|
|
|
@ -420,8 +420,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
|
|||
|
||||
/* config registers for header type 0 devices */
|
||||
#define PCIR_MAPS 0x10
|
||||
#define PCIR_SUBVEND_0 0x2c
|
||||
#define PCIR_SUBDEV_0 0x2e
|
||||
|
||||
/****************************** PCI-X definitions *****************************/
|
||||
#define PCIXR_COMMAND 0x96
|
||||
|
|
|
@ -260,8 +260,8 @@ ahd_find_pci_device(ahd_dev_softc_t pci)
|
|||
|
||||
vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
|
||||
device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
|
||||
subvendor = ahd_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
|
||||
subdevice = ahd_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
|
||||
subvendor = ahd_pci_read_config(pci, PCI_SUBSYSTEM_VENDOR_ID, /*bytes*/2);
|
||||
subdevice = ahd_pci_read_config(pci, PCI_SUBSYSTEM_ID, /*bytes*/2);
|
||||
full_id = ahd_compose_id(device,
|
||||
vendor,
|
||||
subdevice,
|
||||
|
@ -298,7 +298,7 @@ ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)
|
|||
* Record if this is an HP board.
|
||||
*/
|
||||
subvendor = ahd_pci_read_config(ahd->dev_softc,
|
||||
PCIR_SUBVEND_0, /*bytes*/2);
|
||||
PCI_SUBSYSTEM_VENDOR_ID, /*bytes*/2);
|
||||
if (subvendor == SUBID_HP)
|
||||
ahd->flags |= AHD_HP_BOARD;
|
||||
|
||||
|
|
|
@ -433,8 +433,6 @@ ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
|
|||
|
||||
/* config registers for header type 0 devices */
|
||||
#define PCIR_MAPS 0x10
|
||||
#define PCIR_SUBVEND_0 0x2c
|
||||
#define PCIR_SUBDEV_0 0x2e
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
|
@ -673,8 +673,8 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
|
|||
|
||||
vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
|
||||
device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
|
||||
subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
|
||||
subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
|
||||
subvendor = ahc_pci_read_config(pci, PCI_SUBSYSTEM_VENDOR_ID, /*bytes*/2);
|
||||
subdevice = ahc_pci_read_config(pci, PCI_SUBSYSTEM_ID, /*bytes*/2);
|
||||
full_id = ahc_compose_id(device, vendor, subdevice, subvendor);
|
||||
|
||||
/*
|
||||
|
|
|
@ -1169,7 +1169,7 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
|
|||
ofld_kcqe->fcoe_conn_context_id);
|
||||
interface = tgt->port->priv;
|
||||
if (hba != interface->hba) {
|
||||
printk(KERN_ERR PFX "ERROR:ofld_cmpl: HBA mis-match\n");
|
||||
printk(KERN_ERR PFX "ERROR:ofld_cmpl: HBA mismatch\n");
|
||||
goto ofld_cmpl_err;
|
||||
}
|
||||
/*
|
||||
|
@ -1226,12 +1226,12 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
|
|||
* and enable
|
||||
*/
|
||||
if (tgt->context_id != context_id) {
|
||||
printk(KERN_ERR PFX "context id mis-match\n");
|
||||
printk(KERN_ERR PFX "context id mismatch\n");
|
||||
return;
|
||||
}
|
||||
interface = tgt->port->priv;
|
||||
if (hba != interface->hba) {
|
||||
printk(KERN_ERR PFX "bnx2fc-enbl_cmpl: HBA mis-match\n");
|
||||
printk(KERN_ERR PFX "bnx2fc-enbl_cmpl: HBA mismatch\n");
|
||||
goto enbl_cmpl_err;
|
||||
}
|
||||
if (!ofld_kcqe->completion_status)
|
||||
|
|
|
@ -1977,7 +1977,7 @@ static int bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
|
|||
if (nopin->cq_req_sn != qp->cqe_exp_seq_sn)
|
||||
break;
|
||||
|
||||
if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx))) {
|
||||
if (unlikely(test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))) {
|
||||
if (nopin->op_code == ISCSI_OP_NOOP_IN &&
|
||||
nopin->itt == (u16) RESERVED_ITT) {
|
||||
printk(KERN_ALERT "bnx2i: Unsolicited "
|
||||
|
@ -2398,7 +2398,7 @@ static void bnx2i_process_conn_destroy_cmpl(struct bnx2i_hba *hba,
|
|||
}
|
||||
|
||||
if (hba != ep->hba) {
|
||||
printk(KERN_ALERT "conn destroy- error hba mis-match\n");
|
||||
printk(KERN_ALERT "conn destroy- error hba mismatch\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2432,7 +2432,7 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba,
|
|||
}
|
||||
|
||||
if (hba != ep->hba) {
|
||||
printk(KERN_ALERT "ofld_cmpl: error hba mis-match\n");
|
||||
printk(KERN_ALERT "ofld_cmpl: error hba mismatch\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1721,7 +1721,7 @@ static int bnx2i_tear_down_conn(struct bnx2i_hba *hba,
|
|||
struct iscsi_conn *conn = ep->conn->cls_conn->dd_data;
|
||||
|
||||
/* Must suspend all rx queue activity for this ep */
|
||||
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
|
||||
set_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags);
|
||||
}
|
||||
/* CONN_DISCONNECT timeout may or may not be an issue depending
|
||||
* on what transcribed in TCP layer, different targets behave
|
||||
|
|
|
@ -1634,11 +1634,11 @@ void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
|
|||
log_debug(1 << CXGBI_DBG_PDU_RX,
|
||||
"csk 0x%p, conn 0x%p.\n", csk, conn);
|
||||
|
||||
if (unlikely(!conn || conn->suspend_rx)) {
|
||||
if (unlikely(!conn || test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))) {
|
||||
log_debug(1 << CXGBI_DBG_PDU_RX,
|
||||
"csk 0x%p, conn 0x%p, id %d, suspend_rx %lu!\n",
|
||||
"csk 0x%p, conn 0x%p, id %d, conn flags 0x%lx!\n",
|
||||
csk, conn, conn ? conn->id : 0xFF,
|
||||
conn ? conn->suspend_rx : 0xFF);
|
||||
conn ? conn->flags : 0xFF);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -442,7 +442,6 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba,
|
|||
case SAS_PROTOCOL_INTERNAL_ABORT:
|
||||
hisi_sas_task_prep_abort(hisi_hba, slot);
|
||||
break;
|
||||
fallthrough;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
#define IBMVSCSIS_VERSION "v0.2"
|
||||
|
||||
#define INITIAL_SRP_LIMIT 800
|
||||
#define INITIAL_SRP_LIMIT 1024
|
||||
#define DEFAULT_MAX_SECTORS 256
|
||||
#define MAX_TXU 1024 * 1024
|
||||
|
||||
|
|
|
@ -413,7 +413,7 @@ static void sci_controller_event_completion(struct isci_host *ihost, u32 ent)
|
|||
dev_warn(&ihost->pdev->dev,
|
||||
"%s: SCIC Controller 0x%p received "
|
||||
"event 0x%x for io request object "
|
||||
"that doesnt exist.\n",
|
||||
"that doesn't exist.\n",
|
||||
__func__,
|
||||
ihost,
|
||||
ent);
|
||||
|
@ -428,7 +428,7 @@ static void sci_controller_event_completion(struct isci_host *ihost, u32 ent)
|
|||
dev_warn(&ihost->pdev->dev,
|
||||
"%s: SCIC Controller 0x%p received "
|
||||
"event 0x%x for remote device object "
|
||||
"that doesnt exist.\n",
|
||||
"that doesn't exist.\n",
|
||||
__func__,
|
||||
ihost,
|
||||
ent);
|
||||
|
@ -462,7 +462,7 @@ static void sci_controller_event_completion(struct isci_host *ihost, u32 ent)
|
|||
} else
|
||||
dev_err(&ihost->pdev->dev,
|
||||
"%s: SCIC Controller 0x%p received event 0x%x "
|
||||
"for remote device object 0x%0x that doesnt "
|
||||
"for remote device object 0x%0x that doesn't "
|
||||
"exist.\n",
|
||||
__func__,
|
||||
ihost,
|
||||
|
|
|
@ -678,7 +678,8 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
|||
struct iscsi_task *task;
|
||||
itt_t itt;
|
||||
|
||||
if (session->state == ISCSI_STATE_TERMINATE)
|
||||
if (session->state == ISCSI_STATE_TERMINATE ||
|
||||
!test_bit(ISCSI_CONN_FLAG_BOUND, &conn->flags))
|
||||
return NULL;
|
||||
|
||||
if (opcode == ISCSI_OP_LOGIN || opcode == ISCSI_OP_TEXT) {
|
||||
|
@ -1392,8 +1393,8 @@ static bool iscsi_set_conn_failed(struct iscsi_conn *conn)
|
|||
if (conn->stop_stage == 0)
|
||||
session->state = ISCSI_STATE_FAILED;
|
||||
|
||||
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
|
||||
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
|
||||
set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
|
||||
set_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1454,7 +1455,7 @@ static int iscsi_xmit_task(struct iscsi_conn *conn, struct iscsi_task *task,
|
|||
* Do this after dropping the extra ref because if this was a requeue
|
||||
* it's removed from that list and cleanup_queued_task would miss it.
|
||||
*/
|
||||
if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
|
||||
if (test_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags)) {
|
||||
/*
|
||||
* Save the task and ref in case we weren't cleaning up this
|
||||
* task and get woken up again.
|
||||
|
@ -1532,7 +1533,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
|
|||
int rc = 0;
|
||||
|
||||
spin_lock_bh(&conn->session->frwd_lock);
|
||||
if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
|
||||
if (test_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags)) {
|
||||
ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n");
|
||||
spin_unlock_bh(&conn->session->frwd_lock);
|
||||
return -ENODATA;
|
||||
|
@ -1746,7 +1747,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
|
|||
goto fault;
|
||||
}
|
||||
|
||||
if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
|
||||
if (test_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags)) {
|
||||
reason = FAILURE_SESSION_IN_RECOVERY;
|
||||
sc->result = DID_REQUEUE << 16;
|
||||
goto fault;
|
||||
|
@ -1935,7 +1936,7 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error)
|
|||
void iscsi_suspend_queue(struct iscsi_conn *conn)
|
||||
{
|
||||
spin_lock_bh(&conn->session->frwd_lock);
|
||||
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
|
||||
set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
|
||||
spin_unlock_bh(&conn->session->frwd_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_suspend_queue);
|
||||
|
@ -1953,7 +1954,7 @@ void iscsi_suspend_tx(struct iscsi_conn *conn)
|
|||
struct Scsi_Host *shost = conn->session->host;
|
||||
struct iscsi_host *ihost = shost_priv(shost);
|
||||
|
||||
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
|
||||
set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
|
||||
if (ihost->workq)
|
||||
flush_workqueue(ihost->workq);
|
||||
}
|
||||
|
@ -1961,7 +1962,7 @@ EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
|
|||
|
||||
static void iscsi_start_tx(struct iscsi_conn *conn)
|
||||
{
|
||||
clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
|
||||
clear_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
|
||||
iscsi_conn_queue_work(conn);
|
||||
}
|
||||
|
||||
|
@ -2214,6 +2215,8 @@ void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active)
|
|||
iscsi_suspend_tx(conn);
|
||||
|
||||
spin_lock_bh(&session->frwd_lock);
|
||||
clear_bit(ISCSI_CONN_FLAG_BOUND, &conn->flags);
|
||||
|
||||
if (!is_active) {
|
||||
/*
|
||||
* if logout timed out before userspace could even send a PDU
|
||||
|
@ -3045,7 +3048,6 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
|
|||
if (!cls_conn)
|
||||
return NULL;
|
||||
conn = cls_conn->dd_data;
|
||||
memset(conn, 0, sizeof(*conn) + dd_size);
|
||||
|
||||
conn->dd_data = cls_conn->dd_data + sizeof(*conn);
|
||||
conn->session = session;
|
||||
|
@ -3318,6 +3320,8 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
|||
spin_lock_bh(&session->frwd_lock);
|
||||
if (is_leading)
|
||||
session->leadconn = conn;
|
||||
|
||||
set_bit(ISCSI_CONN_FLAG_BOUND, &conn->flags);
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
|
||||
/*
|
||||
|
@ -3330,8 +3334,8 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
|||
/*
|
||||
* Unblock xmitworker(), Login Phase will pass through.
|
||||
*/
|
||||
clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
|
||||
clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
|
||||
clear_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags);
|
||||
clear_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_conn_bind);
|
||||
|
|
|
@ -927,7 +927,7 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
|
|||
*/
|
||||
conn->last_recv = jiffies;
|
||||
|
||||
if (unlikely(conn->suspend_rx)) {
|
||||
if (unlikely(test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))) {
|
||||
ISCSI_DBG_TCP(conn, "Rx suspended!\n");
|
||||
*status = ISCSI_TCP_SUSPENDED;
|
||||
return 0;
|
||||
|
|
|
@ -897,6 +897,11 @@ enum lpfc_irq_chann_mode {
|
|||
NHT_MODE,
|
||||
};
|
||||
|
||||
enum lpfc_hba_bit_flags {
|
||||
FABRIC_COMANDS_BLOCKED,
|
||||
HBA_PCI_ERR,
|
||||
};
|
||||
|
||||
struct lpfc_hba {
|
||||
/* SCSI interface function jump table entries */
|
||||
struct lpfc_io_buf * (*lpfc_get_scsi_buf)
|
||||
|
@ -1043,7 +1048,6 @@ struct lpfc_hba {
|
|||
* Firmware supports Forced Link Speed
|
||||
* capability
|
||||
*/
|
||||
#define HBA_PCI_ERR 0x80000 /* The PCI slot is offline */
|
||||
#define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */
|
||||
#define HBA_SHORT_CMF 0x200000 /* shorter CMF timer routine */
|
||||
#define HBA_CGN_DAY_WRAP 0x400000 /* HBA Congestion info day wraps */
|
||||
|
@ -1350,7 +1354,6 @@ struct lpfc_hba {
|
|||
atomic_t fabric_iocb_count;
|
||||
struct timer_list fabric_block_timer;
|
||||
unsigned long bit_flags;
|
||||
#define FABRIC_COMANDS_BLOCKED 0
|
||||
atomic_t num_rsrc_err;
|
||||
atomic_t num_cmd_success;
|
||||
unsigned long last_rsrc_error_time;
|
||||
|
|
|
@ -670,3 +670,6 @@ struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
|
|||
uint32_t hash, uint8_t *buf);
|
||||
void lpfc_vmid_vport_cleanup(struct lpfc_vport *vport);
|
||||
int lpfc_issue_els_qfpa(struct lpfc_vport *vport);
|
||||
|
||||
void lpfc_sli_rpi_release(struct lpfc_vport *vport,
|
||||
struct lpfc_nodelist *ndlp);
|
||||
|
|
|
@ -109,8 +109,8 @@ lpfc_rport_invalid(struct fc_rport *rport)
|
|||
|
||||
ndlp = rdata->pnode;
|
||||
if (!rdata->pnode) {
|
||||
pr_err("**** %s: NULL ndlp on rport x%px SID x%x\n",
|
||||
__func__, rport, rport->scsi_target_id);
|
||||
pr_info("**** %s: NULL ndlp on rport x%px SID x%x\n",
|
||||
__func__, rport, rport->scsi_target_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -169,9 +169,10 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
|||
|
||||
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE,
|
||||
"3181 dev_loss_callbk x%06x, rport x%px flg x%x "
|
||||
"load_flag x%x refcnt %d\n",
|
||||
"load_flag x%x refcnt %d state %d xpt x%x\n",
|
||||
ndlp->nlp_DID, ndlp->rport, ndlp->nlp_flag,
|
||||
vport->load_flag, kref_read(&ndlp->kref));
|
||||
vport->load_flag, kref_read(&ndlp->kref),
|
||||
ndlp->nlp_state, ndlp->fc4_xpt_flags);
|
||||
|
||||
/* Don't schedule a worker thread event if the vport is going down.
|
||||
* The teardown process cleans up the node via lpfc_drop_node.
|
||||
|
@ -181,6 +182,11 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
|||
ndlp->rport = NULL;
|
||||
|
||||
ndlp->fc4_xpt_flags &= ~SCSI_XPT_REGD;
|
||||
/* clear the NLP_XPT_REGD if the node is not registered
|
||||
* with nvme-fc
|
||||
*/
|
||||
if (ndlp->fc4_xpt_flags == NLP_XPT_REGD)
|
||||
ndlp->fc4_xpt_flags &= ~NLP_XPT_REGD;
|
||||
|
||||
/* Remove the node reference from remote_port_add now.
|
||||
* The driver will not call remote_port_delete.
|
||||
|
@ -225,18 +231,36 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
|||
ndlp->rport = NULL;
|
||||
spin_unlock_irqrestore(&ndlp->lock, iflags);
|
||||
|
||||
/* We need to hold the node by incrementing the reference
|
||||
* count until this queued work is done
|
||||
*/
|
||||
evtp->evt_arg1 = lpfc_nlp_get(ndlp);
|
||||
if (phba->worker_thread) {
|
||||
/* We need to hold the node by incrementing the reference
|
||||
* count until this queued work is done
|
||||
*/
|
||||
evtp->evt_arg1 = lpfc_nlp_get(ndlp);
|
||||
|
||||
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||
if (evtp->evt_arg1) {
|
||||
evtp->evt = LPFC_EVT_DEV_LOSS;
|
||||
list_add_tail(&evtp->evt_listp, &phba->work_list);
|
||||
lpfc_worker_wake_up(phba);
|
||||
}
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||
} else {
|
||||
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE,
|
||||
"3188 worker thread is stopped %s x%06x, "
|
||||
" rport x%px flg x%x load_flag x%x refcnt "
|
||||
"%d\n", __func__, ndlp->nlp_DID,
|
||||
ndlp->rport, ndlp->nlp_flag,
|
||||
vport->load_flag, kref_read(&ndlp->kref));
|
||||
if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD)) {
|
||||
spin_lock_irqsave(&ndlp->lock, iflags);
|
||||
/* Node is in dev loss. No further transaction. */
|
||||
ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS;
|
||||
spin_unlock_irqrestore(&ndlp->lock, iflags);
|
||||
lpfc_disc_state_machine(vport, ndlp, NULL,
|
||||
NLP_EVT_DEVICE_RM);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||
if (evtp->evt_arg1) {
|
||||
evtp->evt = LPFC_EVT_DEV_LOSS;
|
||||
list_add_tail(&evtp->evt_listp, &phba->work_list);
|
||||
lpfc_worker_wake_up(phba);
|
||||
}
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -503,11 +527,12 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
|
|||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"0203 Devloss timeout on "
|
||||
"WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
|
||||
"NPort x%06x Data: x%x x%x x%x\n",
|
||||
"NPort x%06x Data: x%x x%x x%x refcnt %d\n",
|
||||
*name, *(name+1), *(name+2), *(name+3),
|
||||
*(name+4), *(name+5), *(name+6), *(name+7),
|
||||
ndlp->nlp_DID, ndlp->nlp_flag,
|
||||
ndlp->nlp_state, ndlp->nlp_rpi);
|
||||
ndlp->nlp_state, ndlp->nlp_rpi,
|
||||
kref_read(&ndlp->kref));
|
||||
} else {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_TRACE_EVENT,
|
||||
"0204 Devloss timeout on "
|
||||
|
@ -755,18 +780,22 @@ lpfc_work_list_done(struct lpfc_hba *phba)
|
|||
int free_evt;
|
||||
int fcf_inuse;
|
||||
uint32_t nlp_did;
|
||||
bool hba_pci_err;
|
||||
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
while (!list_empty(&phba->work_list)) {
|
||||
list_remove_head((&phba->work_list), evtp, typeof(*evtp),
|
||||
evt_listp);
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
hba_pci_err = test_bit(HBA_PCI_ERR, &phba->bit_flags);
|
||||
free_evt = 1;
|
||||
switch (evtp->evt) {
|
||||
case LPFC_EVT_ELS_RETRY:
|
||||
ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
|
||||
lpfc_els_retry_delay_handler(ndlp);
|
||||
free_evt = 0; /* evt is part of ndlp */
|
||||
if (!hba_pci_err) {
|
||||
lpfc_els_retry_delay_handler(ndlp);
|
||||
free_evt = 0; /* evt is part of ndlp */
|
||||
}
|
||||
/* decrement the node reference count held
|
||||
* for this queued work
|
||||
*/
|
||||
|
@ -788,8 +817,10 @@ lpfc_work_list_done(struct lpfc_hba *phba)
|
|||
break;
|
||||
case LPFC_EVT_RECOVER_PORT:
|
||||
ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1);
|
||||
lpfc_sli_abts_recover_port(ndlp->vport, ndlp);
|
||||
free_evt = 0;
|
||||
if (!hba_pci_err) {
|
||||
lpfc_sli_abts_recover_port(ndlp->vport, ndlp);
|
||||
free_evt = 0;
|
||||
}
|
||||
/* decrement the node reference count held for
|
||||
* this queued work
|
||||
*/
|
||||
|
@ -859,14 +890,18 @@ lpfc_work_done(struct lpfc_hba *phba)
|
|||
struct lpfc_vport **vports;
|
||||
struct lpfc_vport *vport;
|
||||
int i;
|
||||
bool hba_pci_err;
|
||||
|
||||
hba_pci_err = test_bit(HBA_PCI_ERR, &phba->bit_flags);
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
ha_copy = phba->work_ha;
|
||||
phba->work_ha = 0;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
if (hba_pci_err)
|
||||
ha_copy = 0;
|
||||
|
||||
/* First, try to post the next mailbox command to SLI4 device */
|
||||
if (phba->pci_dev_grp == LPFC_PCI_DEV_OC)
|
||||
if (phba->pci_dev_grp == LPFC_PCI_DEV_OC && !hba_pci_err)
|
||||
lpfc_sli4_post_async_mbox(phba);
|
||||
|
||||
if (ha_copy & HA_ERATT) {
|
||||
|
@ -886,7 +921,7 @@ lpfc_work_done(struct lpfc_hba *phba)
|
|||
lpfc_handle_latt(phba);
|
||||
|
||||
/* Handle VMID Events */
|
||||
if (lpfc_is_vmid_enabled(phba)) {
|
||||
if (lpfc_is_vmid_enabled(phba) && !hba_pci_err) {
|
||||
if (phba->pport->work_port_events &
|
||||
WORKER_CHECK_VMID_ISSUE_QFPA) {
|
||||
lpfc_check_vmid_qfpa_issue(phba);
|
||||
|
@ -936,6 +971,8 @@ lpfc_work_done(struct lpfc_hba *phba)
|
|||
work_port_events = vport->work_port_events;
|
||||
vport->work_port_events &= ~work_port_events;
|
||||
spin_unlock_irq(&vport->work_port_lock);
|
||||
if (hba_pci_err)
|
||||
continue;
|
||||
if (work_port_events & WORKER_DISC_TMO)
|
||||
lpfc_disc_timeout_handler(vport);
|
||||
if (work_port_events & WORKER_ELS_TMO)
|
||||
|
@ -1173,12 +1210,14 @@ lpfc_linkdown(struct lpfc_hba *phba)
|
|||
struct lpfc_vport **vports;
|
||||
LPFC_MBOXQ_t *mb;
|
||||
int i;
|
||||
int offline;
|
||||
|
||||
if (phba->link_state == LPFC_LINK_DOWN)
|
||||
return 0;
|
||||
|
||||
/* Block all SCSI stack I/Os */
|
||||
lpfc_scsi_dev_block(phba);
|
||||
offline = pci_channel_offline(phba->pcidev);
|
||||
|
||||
phba->defer_flogi_acc_flag = false;
|
||||
|
||||
|
@ -1219,7 +1258,7 @@ lpfc_linkdown(struct lpfc_hba *phba)
|
|||
lpfc_destroy_vport_work_array(phba, vports);
|
||||
|
||||
/* Clean up any SLI3 firmware default rpi's */
|
||||
if (phba->sli_rev > LPFC_SLI_REV3)
|
||||
if (phba->sli_rev > LPFC_SLI_REV3 || offline)
|
||||
goto skip_unreg_did;
|
||||
|
||||
mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
|
@ -4712,6 +4751,11 @@ lpfc_nlp_unreg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|||
spin_lock_irqsave(&ndlp->lock, iflags);
|
||||
if (!(ndlp->fc4_xpt_flags & NLP_XPT_REGD)) {
|
||||
spin_unlock_irqrestore(&ndlp->lock, iflags);
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
|
||||
"0999 %s Not regd: ndlp x%px rport x%px DID "
|
||||
"x%x FLG x%x XPT x%x\n",
|
||||
__func__, ndlp, ndlp->rport, ndlp->nlp_DID,
|
||||
ndlp->nlp_flag, ndlp->fc4_xpt_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4722,6 +4766,13 @@ lpfc_nlp_unreg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|||
ndlp->fc4_xpt_flags & SCSI_XPT_REGD) {
|
||||
vport->phba->nport_event_cnt++;
|
||||
lpfc_unregister_remote_port(ndlp);
|
||||
} else if (!ndlp->rport) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
|
||||
"1999 %s NDLP in devloss x%px DID x%x FLG x%x"
|
||||
" XPT x%x refcnt %d\n",
|
||||
__func__, ndlp, ndlp->nlp_DID, ndlp->nlp_flag,
|
||||
ndlp->fc4_xpt_flags,
|
||||
kref_read(&ndlp->kref));
|
||||
}
|
||||
|
||||
if (ndlp->fc4_xpt_flags & NVME_XPT_REGD) {
|
||||
|
@ -5371,6 +5422,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|||
ndlp->nlp_flag &= ~NLP_UNREG_INP;
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
acc_plogi = 1;
|
||||
lpfc_nlp_put(ndlp);
|
||||
}
|
||||
} else {
|
||||
lpfc_printf_vlog(vport, KERN_INFO,
|
||||
|
@ -6097,12 +6149,34 @@ lpfc_disc_flush_list(struct lpfc_vport *vport)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* lpfc_notify_xport_npr - notifies xport of node disappearance
|
||||
* @vport: Pointer to Virtual Port object.
|
||||
*
|
||||
* Transitions all ndlps to NPR state. When lpfc_nlp_set_state
|
||||
* calls lpfc_nlp_state_cleanup, the ndlp->rport is unregistered
|
||||
* and transport notified that the node is gone.
|
||||
* Return Code:
|
||||
* none
|
||||
*/
|
||||
static void
|
||||
lpfc_notify_xport_npr(struct lpfc_vport *vport)
|
||||
{
|
||||
struct lpfc_nodelist *ndlp, *next_ndlp;
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
|
||||
nlp_listp) {
|
||||
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
|
||||
}
|
||||
}
|
||||
void
|
||||
lpfc_cleanup_discovery_resources(struct lpfc_vport *vport)
|
||||
{
|
||||
lpfc_els_flush_rscn(vport);
|
||||
lpfc_els_flush_cmd(vport);
|
||||
lpfc_disc_flush_list(vport);
|
||||
if (pci_channel_offline(vport->phba->pcidev))
|
||||
lpfc_notify_xport_npr(vport);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -95,6 +95,7 @@ static void lpfc_sli4_oas_verify(struct lpfc_hba *phba);
|
|||
static uint16_t lpfc_find_cpu_handle(struct lpfc_hba *, uint16_t, int);
|
||||
static void lpfc_setup_bg(struct lpfc_hba *, struct Scsi_Host *);
|
||||
static int lpfc_sli4_cgn_parm_chg_evt(struct lpfc_hba *);
|
||||
static void lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba);
|
||||
|
||||
static struct scsi_transport_template *lpfc_transport_template = NULL;
|
||||
static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
|
||||
|
@ -1642,7 +1643,7 @@ lpfc_sli4_offline_eratt(struct lpfc_hba *phba)
|
|||
{
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
if (phba->link_state == LPFC_HBA_ERROR &&
|
||||
phba->hba_flag & HBA_PCI_ERR) {
|
||||
test_bit(HBA_PCI_ERR, &phba->bit_flags)) {
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
return;
|
||||
}
|
||||
|
@ -1985,6 +1986,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
|
|||
if (pci_channel_offline(phba->pcidev)) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"3166 pci channel is offline\n");
|
||||
lpfc_sli_flush_io_rings(phba);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2973,6 +2975,22 @@ lpfc_cleanup(struct lpfc_vport *vport)
|
|||
NLP_EVT_DEVICE_RM);
|
||||
}
|
||||
|
||||
/* This is a special case flush to return all
|
||||
* IOs before entering this loop. There are
|
||||
* two points in the code where a flush is
|
||||
* avoided if the FC_UNLOADING flag is set.
|
||||
* one is in the multipool destroy,
|
||||
* (this prevents a crash) and the other is
|
||||
* in the nvme abort handler, ( also prevents
|
||||
* a crash). Both of these exceptions are
|
||||
* cases where the slot is still accessible.
|
||||
* The flush here is only when the pci slot
|
||||
* is offline.
|
||||
*/
|
||||
if (vport->load_flag & FC_UNLOADING &&
|
||||
pci_channel_offline(phba->pcidev))
|
||||
lpfc_sli_flush_io_rings(vport->phba);
|
||||
|
||||
/* At this point, ALL ndlp's should be gone
|
||||
* because of the previous NLP_EVT_DEVICE_RM.
|
||||
* Lets wait for this to happen, if needed.
|
||||
|
@ -2985,7 +3003,7 @@ lpfc_cleanup(struct lpfc_vport *vport)
|
|||
list_for_each_entry_safe(ndlp, next_ndlp,
|
||||
&vport->fc_nodes, nlp_listp) {
|
||||
lpfc_printf_vlog(ndlp->vport, KERN_ERR,
|
||||
LOG_TRACE_EVENT,
|
||||
LOG_DISCOVERY,
|
||||
"0282 did:x%x ndlp:x%px "
|
||||
"refcnt:%d xflags x%x nflag x%x\n",
|
||||
ndlp->nlp_DID, (void *)ndlp,
|
||||
|
@ -3682,7 +3700,8 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
|
|||
struct lpfc_vport **vports;
|
||||
struct Scsi_Host *shost;
|
||||
int i;
|
||||
int offline = 0;
|
||||
int offline;
|
||||
bool hba_pci_err;
|
||||
|
||||
if (vport->fc_flag & FC_OFFLINE_MODE)
|
||||
return;
|
||||
|
@ -3692,6 +3711,7 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
|
|||
lpfc_linkdown(phba);
|
||||
|
||||
offline = pci_channel_offline(phba->pcidev);
|
||||
hba_pci_err = test_bit(HBA_PCI_ERR, &phba->bit_flags);
|
||||
|
||||
/* Issue an unreg_login to all nodes on all vports */
|
||||
vports = lpfc_create_vport_work_array(phba);
|
||||
|
@ -3715,11 +3735,14 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
|
|||
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
|
||||
spin_unlock_irq(&ndlp->lock);
|
||||
|
||||
if (offline) {
|
||||
if (offline || hba_pci_err) {
|
||||
spin_lock_irq(&ndlp->lock);
|
||||
ndlp->nlp_flag &= ~(NLP_UNREG_INP |
|
||||
NLP_RPI_REGISTERED);
|
||||
spin_unlock_irq(&ndlp->lock);
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
lpfc_sli_rpi_release(vports[i],
|
||||
ndlp);
|
||||
} else {
|
||||
lpfc_unreg_rpi(vports[i], ndlp);
|
||||
}
|
||||
|
@ -13354,8 +13377,9 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
|
|||
/* Abort all iocbs associated with the hba */
|
||||
lpfc_sli_hba_iocb_abort(phba);
|
||||
|
||||
/* Wait for completion of device XRI exchange busy */
|
||||
lpfc_sli4_xri_exchange_busy_wait(phba);
|
||||
if (!pci_channel_offline(phba->pcidev))
|
||||
/* Wait for completion of device XRI exchange busy */
|
||||
lpfc_sli4_xri_exchange_busy_wait(phba);
|
||||
|
||||
/* per-phba callback de-registration for hotplug event */
|
||||
if (phba->pport)
|
||||
|
@ -13374,15 +13398,12 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
|
|||
/* Disable FW logging to host memory */
|
||||
lpfc_ras_stop_fwlog(phba);
|
||||
|
||||
/* Unset the queues shared with the hardware then release all
|
||||
* allocated resources.
|
||||
*/
|
||||
lpfc_sli4_queue_unset(phba);
|
||||
lpfc_sli4_queue_destroy(phba);
|
||||
|
||||
/* Reset SLI4 HBA FCoE function */
|
||||
lpfc_pci_function_reset(phba);
|
||||
|
||||
/* release all queue allocated resources. */
|
||||
lpfc_sli4_queue_destroy(phba);
|
||||
|
||||
/* Free RAS DMA memory */
|
||||
if (phba->ras_fwlog.ras_enabled)
|
||||
lpfc_sli4_ras_dma_free(phba);
|
||||
|
@ -14262,6 +14283,7 @@ lpfc_sli_prep_dev_for_perm_failure(struct lpfc_hba *phba)
|
|||
"2711 PCI channel permanent disable for failure\n");
|
||||
/* Block all SCSI devices' I/Os on the host */
|
||||
lpfc_scsi_dev_block(phba);
|
||||
lpfc_sli4_prep_dev_for_reset(phba);
|
||||
|
||||
/* stop all timers */
|
||||
lpfc_stop_hba_timers(phba);
|
||||
|
@ -15057,24 +15079,28 @@ lpfc_sli4_prep_dev_for_recover(struct lpfc_hba *phba)
|
|||
static void
|
||||
lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
|
||||
{
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2826 PCI channel disable preparing for reset\n");
|
||||
int offline = pci_channel_offline(phba->pcidev);
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"2826 PCI channel disable preparing for reset offline"
|
||||
" %d\n", offline);
|
||||
|
||||
/* Block any management I/Os to the device */
|
||||
lpfc_block_mgmt_io(phba, LPFC_MBX_NO_WAIT);
|
||||
|
||||
/* Block all SCSI devices' I/Os on the host */
|
||||
lpfc_scsi_dev_block(phba);
|
||||
|
||||
/* HBA_PCI_ERR was set in io_error_detect */
|
||||
lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT);
|
||||
/* Flush all driver's outstanding I/Os as we are to reset */
|
||||
lpfc_sli_flush_io_rings(phba);
|
||||
lpfc_offline(phba);
|
||||
|
||||
/* stop all timers */
|
||||
lpfc_stop_hba_timers(phba);
|
||||
|
||||
lpfc_sli4_queue_destroy(phba);
|
||||
/* Disable interrupt and pci device */
|
||||
lpfc_sli4_disable_intr(phba);
|
||||
lpfc_sli4_queue_destroy(phba);
|
||||
pci_disable_device(phba->pcidev);
|
||||
}
|
||||
|
||||
|
@ -15123,6 +15149,7 @@ lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state)
|
|||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
|
||||
bool hba_pci_err;
|
||||
|
||||
switch (state) {
|
||||
case pci_channel_io_normal:
|
||||
|
@ -15130,17 +15157,24 @@ lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state)
|
|||
lpfc_sli4_prep_dev_for_recover(phba);
|
||||
return PCI_ERS_RESULT_CAN_RECOVER;
|
||||
case pci_channel_io_frozen:
|
||||
phba->hba_flag |= HBA_PCI_ERR;
|
||||
hba_pci_err = test_and_set_bit(HBA_PCI_ERR, &phba->bit_flags);
|
||||
/* Fatal error, prepare for slot reset */
|
||||
lpfc_sli4_prep_dev_for_reset(phba);
|
||||
if (!hba_pci_err)
|
||||
lpfc_sli4_prep_dev_for_reset(phba);
|
||||
else
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"2832 Already handling PCI error "
|
||||
"state: x%x\n", state);
|
||||
return PCI_ERS_RESULT_NEED_RESET;
|
||||
case pci_channel_io_perm_failure:
|
||||
phba->hba_flag |= HBA_PCI_ERR;
|
||||
set_bit(HBA_PCI_ERR, &phba->bit_flags);
|
||||
/* Permanent failure, prepare for device down */
|
||||
lpfc_sli4_prep_dev_for_perm_failure(phba);
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
default:
|
||||
phba->hba_flag |= HBA_PCI_ERR;
|
||||
hba_pci_err = test_and_set_bit(HBA_PCI_ERR, &phba->bit_flags);
|
||||
if (!hba_pci_err)
|
||||
lpfc_sli4_prep_dev_for_reset(phba);
|
||||
/* Unknown state, prepare and request slot reset */
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2825 Unknown PCI error state: x%x\n", state);
|
||||
|
@ -15174,17 +15208,21 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
|
|||
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
uint32_t intr_mode;
|
||||
bool hba_pci_err;
|
||||
|
||||
dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
|
||||
if (pci_enable_device_mem(pdev)) {
|
||||
printk(KERN_ERR "lpfc: Cannot re-enable "
|
||||
"PCI device after reset.\n");
|
||||
"PCI device after reset.\n");
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
}
|
||||
|
||||
pci_restore_state(pdev);
|
||||
|
||||
phba->hba_flag &= ~HBA_PCI_ERR;
|
||||
hba_pci_err = test_and_clear_bit(HBA_PCI_ERR, &phba->bit_flags);
|
||||
if (!hba_pci_err)
|
||||
dev_info(&pdev->dev,
|
||||
"hba_pci_err was not set, recovering slot reset.\n");
|
||||
/*
|
||||
* As the new kernel behavior of pci_restore_state() API call clears
|
||||
* device saved_state flag, need to save the restored state again.
|
||||
|
@ -15198,6 +15236,8 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
|
|||
psli->sli_flag &= ~LPFC_SLI_ACTIVE;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
||||
/* Init cpu_map array */
|
||||
lpfc_cpu_map_array_init(phba);
|
||||
/* Configure and enable interrupt */
|
||||
intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
|
||||
if (intr_mode == LPFC_INTR_ERROR) {
|
||||
|
@ -15239,8 +15279,6 @@ lpfc_io_resume_s4(struct pci_dev *pdev)
|
|||
*/
|
||||
if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE)) {
|
||||
/* Perform device reset */
|
||||
lpfc_offline_prep(phba, LPFC_MBX_WAIT);
|
||||
lpfc_offline(phba);
|
||||
lpfc_sli_brdrestart(phba);
|
||||
/* Bring the device back online */
|
||||
lpfc_online(phba);
|
||||
|
|
|
@ -93,6 +93,11 @@ lpfc_nvme_create_queue(struct nvme_fc_local_port *pnvme_lport,
|
|||
|
||||
lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
|
||||
vport = lport->vport;
|
||||
|
||||
if (!vport || vport->load_flag & FC_UNLOADING ||
|
||||
vport->phba->hba_flag & HBA_IOQ_FLUSH)
|
||||
return -ENODEV;
|
||||
|
||||
qhandle = kzalloc(sizeof(struct lpfc_nvme_qhandle), GFP_KERNEL);
|
||||
if (qhandle == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -267,7 +272,8 @@ lpfc_nvme_handle_lsreq(struct lpfc_hba *phba,
|
|||
return -EINVAL;
|
||||
|
||||
remoteport = lpfc_rport->remoteport;
|
||||
if (!vport->localport)
|
||||
if (!vport->localport ||
|
||||
vport->phba->hba_flag & HBA_IOQ_FLUSH)
|
||||
return -EINVAL;
|
||||
|
||||
lport = vport->localport->private;
|
||||
|
@ -559,6 +565,8 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|||
ndlp->nlp_DID, ntype, nstate);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (vport->phba->hba_flag & HBA_IOQ_FLUSH)
|
||||
return -ENODEV;
|
||||
|
||||
if (!vport->phba->sli4_hba.nvmels_wq)
|
||||
return -ENOMEM;
|
||||
|
@ -662,7 +670,8 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
|
|||
return -EINVAL;
|
||||
|
||||
vport = lport->vport;
|
||||
if (vport->load_flag & FC_UNLOADING)
|
||||
if (vport->load_flag & FC_UNLOADING ||
|
||||
vport->phba->hba_flag & HBA_IOQ_FLUSH)
|
||||
return -ENODEV;
|
||||
|
||||
atomic_inc(&lport->fc4NvmeLsRequests);
|
||||
|
@ -1516,7 +1525,8 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
|
|||
|
||||
phba = vport->phba;
|
||||
|
||||
if (unlikely(vport->load_flag & FC_UNLOADING)) {
|
||||
if ((unlikely(vport->load_flag & FC_UNLOADING)) ||
|
||||
phba->hba_flag & HBA_IOQ_FLUSH) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
|
||||
"6124 Fail IO, Driver unload\n");
|
||||
atomic_inc(&lport->xmt_fcp_err);
|
||||
|
@ -2169,8 +2179,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
|
|||
abts_nvme = 0;
|
||||
for (i = 0; i < phba->cfg_hdw_queue; i++) {
|
||||
qp = &phba->sli4_hba.hdwq[i];
|
||||
if (!vport || !vport->localport ||
|
||||
!qp || !qp->io_wq)
|
||||
if (!vport->localport || !qp || !qp->io_wq)
|
||||
return;
|
||||
|
||||
pring = qp->io_wq->pring;
|
||||
|
@ -2180,8 +2189,9 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
|
|||
abts_scsi += qp->abts_scsi_io_bufs;
|
||||
abts_nvme += qp->abts_nvme_io_bufs;
|
||||
}
|
||||
if (!vport || !vport->localport ||
|
||||
vport->phba->hba_flag & HBA_PCI_ERR)
|
||||
if (!vport->localport ||
|
||||
test_bit(HBA_PCI_ERR, &vport->phba->bit_flags) ||
|
||||
vport->load_flag & FC_UNLOADING)
|
||||
return;
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
|
@ -2541,8 +2551,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|||
* return values is ignored. The upcall is a courtesy to the
|
||||
* transport.
|
||||
*/
|
||||
if (vport->load_flag & FC_UNLOADING ||
|
||||
unlikely(vport->phba->hba_flag & HBA_PCI_ERR))
|
||||
if (vport->load_flag & FC_UNLOADING)
|
||||
(void)nvme_fc_set_remoteport_devloss(remoteport, 0);
|
||||
|
||||
ret = nvme_fc_unregister_remoteport(remoteport);
|
||||
|
|
|
@ -5929,13 +5929,15 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
|
|||
}
|
||||
|
||||
lpfc_cmd->waitq = &waitq;
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
spin_unlock(&pring_s4->ring_lock);
|
||||
else
|
||||
ret_val = lpfc_sli4_issue_abort_iotag(phba, iocb,
|
||||
lpfc_sli_abort_fcp_cmpl);
|
||||
} else {
|
||||
pring = &phba->sli.sli3_ring[LPFC_FCP_RING];
|
||||
|
||||
ret_val = lpfc_sli_issue_abort_iotag(phba, pring, iocb,
|
||||
lpfc_sli_abort_fcp_cmpl);
|
||||
ret_val = lpfc_sli_issue_abort_iotag(phba, pring, iocb,
|
||||
lpfc_sli_abort_fcp_cmpl);
|
||||
}
|
||||
|
||||
/* Make sure HBA is alive */
|
||||
lpfc_issue_hb_tmo(phba);
|
||||
|
|
|
@ -2828,6 +2828,12 @@ __lpfc_sli_rpi_release(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|||
ndlp->nlp_flag &= ~NLP_UNREG_INP;
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_sli_rpi_release(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
__lpfc_sli_rpi_release(vport, ndlp);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli_def_mbox_cmpl - Default mailbox completion handler
|
||||
* @phba: Pointer to HBA context object.
|
||||
|
@ -3715,7 +3721,15 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
unsigned long iflag;
|
||||
u32 ulp_command, ulp_status, ulp_word4, ulp_context, iotag;
|
||||
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
spin_lock_irqsave(&pring->ring_lock, iflag);
|
||||
else
|
||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||
cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
spin_unlock_irqrestore(&pring->ring_lock, iflag);
|
||||
else
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
||||
|
||||
ulp_command = get_job_cmnd(phba, saveq);
|
||||
ulp_status = get_job_ulpstatus(phba, saveq);
|
||||
|
@ -4052,10 +4066,8 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
|
|||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
||||
cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
|
||||
&rspiocbq);
|
||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||
if (unlikely(!cmdiocbq))
|
||||
break;
|
||||
if (cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED)
|
||||
|
@ -4536,42 +4548,62 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba,
|
|||
void
|
||||
lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
|
||||
{
|
||||
LIST_HEAD(completions);
|
||||
LIST_HEAD(tx_completions);
|
||||
LIST_HEAD(txcmplq_completions);
|
||||
struct lpfc_iocbq *iocb, *next_iocb;
|
||||
int offline;
|
||||
|
||||
if (pring->ringno == LPFC_ELS_RING) {
|
||||
lpfc_fabric_abort_hba(phba);
|
||||
}
|
||||
offline = pci_channel_offline(phba->pcidev);
|
||||
|
||||
/* Error everything on txq and txcmplq
|
||||
* First do the txq.
|
||||
*/
|
||||
if (phba->sli_rev >= LPFC_SLI_REV4) {
|
||||
spin_lock_irq(&pring->ring_lock);
|
||||
list_splice_init(&pring->txq, &completions);
|
||||
list_splice_init(&pring->txq, &tx_completions);
|
||||
pring->txq_cnt = 0;
|
||||
spin_unlock_irq(&pring->ring_lock);
|
||||
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
/* Next issue ABTS for everything on the txcmplq */
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
|
||||
lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL);
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
if (offline) {
|
||||
list_splice_init(&pring->txcmplq,
|
||||
&txcmplq_completions);
|
||||
} else {
|
||||
/* Next issue ABTS for everything on the txcmplq */
|
||||
list_for_each_entry_safe(iocb, next_iocb,
|
||||
&pring->txcmplq, list)
|
||||
lpfc_sli_issue_abort_iotag(phba, pring,
|
||||
iocb, NULL);
|
||||
}
|
||||
spin_unlock_irq(&pring->ring_lock);
|
||||
} else {
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
list_splice_init(&pring->txq, &completions);
|
||||
list_splice_init(&pring->txq, &tx_completions);
|
||||
pring->txq_cnt = 0;
|
||||
|
||||
/* Next issue ABTS for everything on the txcmplq */
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
|
||||
lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL);
|
||||
if (offline) {
|
||||
list_splice_init(&pring->txcmplq, &txcmplq_completions);
|
||||
} else {
|
||||
/* Next issue ABTS for everything on the txcmplq */
|
||||
list_for_each_entry_safe(iocb, next_iocb,
|
||||
&pring->txcmplq, list)
|
||||
lpfc_sli_issue_abort_iotag(phba, pring,
|
||||
iocb, NULL);
|
||||
}
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
}
|
||||
/* Make sure HBA is alive */
|
||||
lpfc_issue_hb_tmo(phba);
|
||||
|
||||
if (offline) {
|
||||
/* Cancel all the IOCBs from the completions list */
|
||||
lpfc_sli_cancel_iocbs(phba, &txcmplq_completions,
|
||||
IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED);
|
||||
} else {
|
||||
/* Make sure HBA is alive */
|
||||
lpfc_issue_hb_tmo(phba);
|
||||
}
|
||||
/* Cancel all the IOCBs from the completions list */
|
||||
lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
|
||||
lpfc_sli_cancel_iocbs(phba, &tx_completions, IOSTAT_LOCAL_REJECT,
|
||||
IOERR_SLI_ABORTED);
|
||||
}
|
||||
|
||||
|
@ -4624,11 +4656,6 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba)
|
|||
struct lpfc_iocbq *piocb, *next_iocb;
|
||||
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
if (phba->hba_flag & HBA_IOQ_FLUSH ||
|
||||
!phba->sli4_hba.hdwq) {
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
return;
|
||||
}
|
||||
/* Indicate the I/O queues are flushed */
|
||||
phba->hba_flag |= HBA_IOQ_FLUSH;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
@ -10997,6 +11024,10 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
|
|||
unsigned long iflags;
|
||||
int rc;
|
||||
|
||||
/* If the PCI channel is in offline state, do not post iocbs. */
|
||||
if (unlikely(pci_channel_offline(phba->pcidev)))
|
||||
return IOCB_ERROR;
|
||||
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
lpfc_sli_prep_wqe(phba, piocb);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "14.2.0.0"
|
||||
#define LPFC_DRIVER_VERSION "14.2.0.1"
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
/* Used for SLI 2/3 */
|
||||
|
|
|
@ -2560,6 +2560,9 @@ struct megasas_instance_template {
|
|||
#define MEGASAS_IS_LOGICAL(sdev) \
|
||||
((sdev->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1)
|
||||
|
||||
#define MEGASAS_IS_LUN_VALID(sdev) \
|
||||
(((sdev)->lun == 0) ? 1 : 0)
|
||||
|
||||
#define MEGASAS_DEV_INDEX(scp) \
|
||||
(((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \
|
||||
scp->device->id)
|
||||
|
|
|
@ -2126,6 +2126,9 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
|
|||
goto scan_target;
|
||||
}
|
||||
return -ENXIO;
|
||||
} else if (!MEGASAS_IS_LUN_VALID(sdev)) {
|
||||
sdev_printk(KERN_INFO, sdev, "%s: invalid LUN\n", __func__);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
scan_target:
|
||||
|
@ -2156,6 +2159,10 @@ static void megasas_slave_destroy(struct scsi_device *sdev)
|
|||
instance = megasas_lookup_instance(sdev->host->host_no);
|
||||
|
||||
if (MEGASAS_IS_LOGICAL(sdev)) {
|
||||
if (!MEGASAS_IS_LUN_VALID(sdev)) {
|
||||
sdev_printk(KERN_INFO, sdev, "%s: invalid LUN\n", __func__);
|
||||
return;
|
||||
}
|
||||
ld_tgt_id = MEGASAS_TARGET_ID(sdev);
|
||||
instance->ld_tgtid_status[ld_tgt_id] = LD_TARGET_ID_DELETED;
|
||||
if (megasas_dbg_lvl & LD_PD_DEBUG)
|
||||
|
|
|
@ -5716,13 +5716,12 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
|
|||
/**
|
||||
* mpt3sas_check_same_4gb_region - checks whether all reply queues in a set are
|
||||
* having same upper 32bits in their base memory address.
|
||||
* @reply_pool_start_address: Base address of a reply queue set
|
||||
* @start_address: Base address of a reply queue set
|
||||
* @pool_sz: Size of single Reply Descriptor Post Queues pool size
|
||||
*
|
||||
* Return: 1 if reply queues in a set have a same upper 32bits in their base
|
||||
* memory address, else 0.
|
||||
*/
|
||||
|
||||
static int
|
||||
mpt3sas_check_same_4gb_region(dma_addr_t start_address, u32 pool_sz)
|
||||
{
|
||||
|
|
|
@ -394,10 +394,13 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
|||
retry_count++;
|
||||
if (ioc->config_cmds.smid == smid)
|
||||
mpt3sas_base_free_smid(ioc, smid);
|
||||
if ((ioc->shost_recovery) || (ioc->config_cmds.status &
|
||||
MPT3_CMD_RESET) || ioc->pci_error_recovery)
|
||||
if (ioc->config_cmds.status & MPT3_CMD_RESET)
|
||||
goto retry_config;
|
||||
issue_host_reset = 1;
|
||||
if (ioc->shost_recovery || ioc->pci_error_recovery) {
|
||||
issue_host_reset = 0;
|
||||
r = -EFAULT;
|
||||
} else
|
||||
issue_host_reset = 1;
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
|
|
|
@ -11035,6 +11035,7 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
|
|||
{
|
||||
struct _sas_port *mpt3sas_port, *next;
|
||||
unsigned long flags;
|
||||
int port_id;
|
||||
|
||||
/* remove sibling ports attached to this expander */
|
||||
list_for_each_entry_safe(mpt3sas_port, next,
|
||||
|
@ -11055,6 +11056,8 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
|
|||
mpt3sas_port->hba_port);
|
||||
}
|
||||
|
||||
port_id = sas_expander->port->port_id;
|
||||
|
||||
mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
|
||||
sas_expander->sas_address_parent, sas_expander->port);
|
||||
|
||||
|
@ -11062,7 +11065,7 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
|
|||
"expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
|
||||
sas_expander->handle, (unsigned long long)
|
||||
sas_expander->sas_address,
|
||||
sas_expander->port->port_id);
|
||||
port_id);
|
||||
|
||||
spin_lock_irqsave(&ioc->sas_node_lock, flags);
|
||||
list_del(&sas_expander->list);
|
||||
|
|
|
@ -647,6 +647,7 @@ static struct pci_device_id mvs_pci_table[] = {
|
|||
{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
|
||||
{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
|
||||
{ PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
|
||||
{ PCI_VDEVICE(TTI, 0x2640), chip_6440 },
|
||||
{ PCI_VDEVICE(TTI, 0x2710), chip_9480 },
|
||||
{ PCI_VDEVICE(TTI, 0x2720), chip_9480 },
|
||||
{ PCI_VDEVICE(TTI, 0x2721), chip_9480 },
|
||||
|
|
|
@ -192,10 +192,11 @@ struct sym53c500_data {
|
|||
int fast_pio;
|
||||
};
|
||||
|
||||
static struct scsi_pointer *sym53c500_scsi_pointer(struct scsi_cmnd *cmd)
|
||||
{
|
||||
return scsi_cmd_priv(cmd);
|
||||
}
|
||||
struct sym53c500_cmd_priv {
|
||||
int status;
|
||||
int message;
|
||||
int phase;
|
||||
};
|
||||
|
||||
enum Phase {
|
||||
idle,
|
||||
|
@ -356,7 +357,7 @@ SYM53C500_intr(int irq, void *dev_id)
|
|||
struct sym53c500_data *data =
|
||||
(struct sym53c500_data *)dev->hostdata;
|
||||
struct scsi_cmnd *curSC = data->current_SC;
|
||||
struct scsi_pointer *scsi_pointer = sym53c500_scsi_pointer(curSC);
|
||||
struct sym53c500_cmd_priv *scp = scsi_cmd_priv(curSC);
|
||||
int fast_pio = data->fast_pio;
|
||||
|
||||
spin_lock_irqsave(dev->host_lock, flags);
|
||||
|
@ -403,12 +404,11 @@ SYM53C500_intr(int irq, void *dev_id)
|
|||
|
||||
if (int_reg & 0x20) { /* Disconnect */
|
||||
DEB(printk("SYM53C500: disconnect intr received\n"));
|
||||
if (scsi_pointer->phase != message_in) { /* Unexpected disconnect */
|
||||
if (scp->phase != message_in) { /* Unexpected disconnect */
|
||||
curSC->result = DID_NO_CONNECT << 16;
|
||||
} else { /* Command complete, return status and message */
|
||||
curSC->result = (scsi_pointer->Status & 0xff) |
|
||||
((scsi_pointer->Message & 0xff) << 8) |
|
||||
(DID_OK << 16);
|
||||
curSC->result = (scp->status & 0xff) |
|
||||
((scp->message & 0xff) << 8) | (DID_OK << 16);
|
||||
}
|
||||
goto idle_out;
|
||||
}
|
||||
|
@ -419,7 +419,7 @@ SYM53C500_intr(int irq, void *dev_id)
|
|||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
scsi_pointer->phase = data_out;
|
||||
scp->phase = data_out;
|
||||
VDEB(printk("SYM53C500: Data-Out phase\n"));
|
||||
outb(FLUSH_FIFO, port_base + CMD_REG);
|
||||
LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */
|
||||
|
@ -438,7 +438,7 @@ SYM53C500_intr(int irq, void *dev_id)
|
|||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
scsi_pointer->phase = data_in;
|
||||
scp->phase = data_in;
|
||||
VDEB(printk("SYM53C500: Data-In phase\n"));
|
||||
outb(FLUSH_FIFO, port_base + CMD_REG);
|
||||
LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */
|
||||
|
@ -453,12 +453,12 @@ SYM53C500_intr(int irq, void *dev_id)
|
|||
break;
|
||||
|
||||
case 0x02: /* COMMAND */
|
||||
scsi_pointer->phase = command_ph;
|
||||
scp->phase = command_ph;
|
||||
printk("SYM53C500: Warning: Unknown interrupt occurred in command phase!\n");
|
||||
break;
|
||||
|
||||
case 0x03: /* STATUS */
|
||||
scsi_pointer->phase = status_ph;
|
||||
scp->phase = status_ph;
|
||||
VDEB(printk("SYM53C500: Status phase\n"));
|
||||
outb(FLUSH_FIFO, port_base + CMD_REG);
|
||||
outb(INIT_CMD_COMPLETE, port_base + CMD_REG);
|
||||
|
@ -471,24 +471,22 @@ SYM53C500_intr(int irq, void *dev_id)
|
|||
|
||||
case 0x06: /* MESSAGE-OUT */
|
||||
DEB(printk("SYM53C500: Message-Out phase\n"));
|
||||
scsi_pointer->phase = message_out;
|
||||
scp->phase = message_out;
|
||||
outb(SET_ATN, port_base + CMD_REG); /* Reject the message */
|
||||
outb(MSG_ACCEPT, port_base + CMD_REG);
|
||||
break;
|
||||
|
||||
case 0x07: /* MESSAGE-IN */
|
||||
VDEB(printk("SYM53C500: Message-In phase\n"));
|
||||
scsi_pointer->phase = message_in;
|
||||
scp->phase = message_in;
|
||||
|
||||
scsi_pointer->Status = inb(port_base + SCSI_FIFO);
|
||||
scsi_pointer->Message = inb(port_base + SCSI_FIFO);
|
||||
scp->status = inb(port_base + SCSI_FIFO);
|
||||
scp->message = inb(port_base + SCSI_FIFO);
|
||||
|
||||
VDEB(printk("SCSI FIFO size=%d\n", inb(port_base + FIFO_FLAGS) & 0x1f));
|
||||
DEB(printk("Status = %02x Message = %02x\n",
|
||||
scsi_pointer->Status, scsi_pointer->Message));
|
||||
DEB(printk("Status = %02x Message = %02x\n", scp->status, scp->message));
|
||||
|
||||
if (scsi_pointer->Message == SAVE_POINTERS ||
|
||||
scsi_pointer->Message == DISCONNECT) {
|
||||
if (scp->message == SAVE_POINTERS || scp->message == DISCONNECT) {
|
||||
outb(SET_ATN, port_base + CMD_REG); /* Reject message */
|
||||
DEB(printk("Discarding SAVE_POINTERS message\n"));
|
||||
}
|
||||
|
@ -500,7 +498,7 @@ out:
|
|||
return IRQ_HANDLED;
|
||||
|
||||
idle_out:
|
||||
scsi_pointer->phase = idle;
|
||||
scp->phase = idle;
|
||||
scsi_done(curSC);
|
||||
goto out;
|
||||
}
|
||||
|
@ -548,7 +546,7 @@ SYM53C500_info(struct Scsi_Host *SChost)
|
|||
|
||||
static int SYM53C500_queue_lck(struct scsi_cmnd *SCpnt)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = sym53c500_scsi_pointer(SCpnt);
|
||||
struct sym53c500_cmd_priv *scp = scsi_cmd_priv(SCpnt);
|
||||
int i;
|
||||
int port_base = SCpnt->device->host->io_port;
|
||||
struct sym53c500_data *data =
|
||||
|
@ -565,9 +563,9 @@ static int SYM53C500_queue_lck(struct scsi_cmnd *SCpnt)
|
|||
VDEB(printk("\n"));
|
||||
|
||||
data->current_SC = SCpnt;
|
||||
scsi_pointer->phase = command_ph;
|
||||
scsi_pointer->Status = 0;
|
||||
scsi_pointer->Message = 0;
|
||||
scp->phase = command_ph;
|
||||
scp->status = 0;
|
||||
scp->message = 0;
|
||||
|
||||
/* We are locked here already by the mid layer */
|
||||
REG0(port_base);
|
||||
|
@ -682,7 +680,7 @@ static struct scsi_host_template sym53c500_driver_template = {
|
|||
.this_id = 7,
|
||||
.sg_tablesize = 32,
|
||||
.shost_groups = SYM53C500_shost_groups,
|
||||
.cmd_size = sizeof(struct scsi_pointer),
|
||||
.cmd_size = sizeof(struct sym53c500_cmd_priv),
|
||||
};
|
||||
|
||||
static int SYM53C500_config_check(struct pcmcia_device *p_dev, void *priv_data)
|
||||
|
|
|
@ -766,6 +766,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
|
|||
pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity = 0x01;
|
||||
pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt = 0x01;
|
||||
|
||||
/* Enable higher IQs and OQs, 32 to 63, bit 16 */
|
||||
if (pm8001_ha->max_q_num > 32)
|
||||
pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
|
||||
1 << 16;
|
||||
/* Disable end to end CRC checking */
|
||||
pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16);
|
||||
|
||||
|
@ -1027,6 +1031,13 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
|
|||
if (0x0000 != gst_len_mpistate)
|
||||
return -EBUSY;
|
||||
|
||||
/*
|
||||
* As per controller datasheet, after successful MPI
|
||||
* initialization minimum 500ms delay is required before
|
||||
* issuing commands.
|
||||
*/
|
||||
msleep(500);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1727,10 +1738,11 @@ static void
|
|||
pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
|
||||
{
|
||||
#ifdef PM8001_USE_MSIX
|
||||
u32 mask;
|
||||
mask = (u32)(1 << vec);
|
||||
|
||||
pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, (u32)(mask & 0xFFFFFFFF));
|
||||
if (vec < 32)
|
||||
pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, 1U << vec);
|
||||
else
|
||||
pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR_U,
|
||||
1U << (vec - 32));
|
||||
return;
|
||||
#endif
|
||||
pm80xx_chip_intx_interrupt_enable(pm8001_ha);
|
||||
|
@ -1746,12 +1758,15 @@ static void
|
|||
pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
|
||||
{
|
||||
#ifdef PM8001_USE_MSIX
|
||||
u32 mask;
|
||||
if (vec == 0xFF)
|
||||
mask = 0xFFFFFFFF;
|
||||
if (vec == 0xFF) {
|
||||
/* disable all vectors 0-31, 32-63 */
|
||||
pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 0xFFFFFFFF);
|
||||
pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U, 0xFFFFFFFF);
|
||||
} else if (vec < 32)
|
||||
pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 1U << vec);
|
||||
else
|
||||
mask = (u32)(1 << vec);
|
||||
pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, (u32)(mask & 0xFFFFFFFF));
|
||||
pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U,
|
||||
1U << (vec - 32));
|
||||
return;
|
||||
#endif
|
||||
pm80xx_chip_intx_interrupt_disable(pm8001_ha);
|
||||
|
|
|
@ -3181,124 +3181,6 @@ static int pmcraid_build_ioadl(
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pmcraid_free_sglist - Frees an allocated SG buffer list
|
||||
* @sglist: scatter/gather list pointer
|
||||
*
|
||||
* Free a DMA'able memory previously allocated with pmcraid_alloc_sglist
|
||||
*
|
||||
* Return value:
|
||||
* none
|
||||
*/
|
||||
static void pmcraid_free_sglist(struct pmcraid_sglist *sglist)
|
||||
{
|
||||
sgl_free_order(sglist->scatterlist, sglist->order);
|
||||
kfree(sglist);
|
||||
}
|
||||
|
||||
/**
|
||||
* pmcraid_alloc_sglist - Allocates memory for a SG list
|
||||
* @buflen: buffer length
|
||||
*
|
||||
* Allocates a DMA'able buffer in chunks and assembles a scatter/gather
|
||||
* list.
|
||||
*
|
||||
* Return value
|
||||
* pointer to sglist / NULL on failure
|
||||
*/
|
||||
static struct pmcraid_sglist *pmcraid_alloc_sglist(int buflen)
|
||||
{
|
||||
struct pmcraid_sglist *sglist;
|
||||
int sg_size;
|
||||
int order;
|
||||
|
||||
sg_size = buflen / (PMCRAID_MAX_IOADLS - 1);
|
||||
order = (sg_size > 0) ? get_order(sg_size) : 0;
|
||||
|
||||
/* Allocate a scatter/gather list for the DMA */
|
||||
sglist = kzalloc(sizeof(struct pmcraid_sglist), GFP_KERNEL);
|
||||
if (sglist == NULL)
|
||||
return NULL;
|
||||
|
||||
sglist->order = order;
|
||||
sgl_alloc_order(buflen, order, false, GFP_KERNEL | __GFP_ZERO,
|
||||
&sglist->num_sg);
|
||||
|
||||
return sglist;
|
||||
}
|
||||
|
||||
/**
|
||||
* pmcraid_copy_sglist - Copy user buffer to kernel buffer's SG list
|
||||
* @sglist: scatter/gather list pointer
|
||||
* @buffer: buffer pointer
|
||||
* @len: buffer length
|
||||
* @direction: data transfer direction
|
||||
*
|
||||
* Copy a user buffer into a buffer allocated by pmcraid_alloc_sglist
|
||||
*
|
||||
* Return value:
|
||||
* 0 on success / other on failure
|
||||
*/
|
||||
static int pmcraid_copy_sglist(
|
||||
struct pmcraid_sglist *sglist,
|
||||
void __user *buffer,
|
||||
u32 len,
|
||||
int direction
|
||||
)
|
||||
{
|
||||
struct scatterlist *sg;
|
||||
void *kaddr;
|
||||
int bsize_elem;
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
/* Determine the actual number of bytes per element */
|
||||
bsize_elem = PAGE_SIZE * (1 << sglist->order);
|
||||
|
||||
sg = sglist->scatterlist;
|
||||
|
||||
for (i = 0; i < (len / bsize_elem); i++, sg = sg_next(sg), buffer += bsize_elem) {
|
||||
struct page *page = sg_page(sg);
|
||||
|
||||
kaddr = kmap(page);
|
||||
if (direction == DMA_TO_DEVICE)
|
||||
rc = copy_from_user(kaddr, buffer, bsize_elem);
|
||||
else
|
||||
rc = copy_to_user(buffer, kaddr, bsize_elem);
|
||||
|
||||
kunmap(page);
|
||||
|
||||
if (rc) {
|
||||
pmcraid_err("failed to copy user data into sg list\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
sg->length = bsize_elem;
|
||||
}
|
||||
|
||||
if (len % bsize_elem) {
|
||||
struct page *page = sg_page(sg);
|
||||
|
||||
kaddr = kmap(page);
|
||||
|
||||
if (direction == DMA_TO_DEVICE)
|
||||
rc = copy_from_user(kaddr, buffer, len % bsize_elem);
|
||||
else
|
||||
rc = copy_to_user(buffer, kaddr, len % bsize_elem);
|
||||
|
||||
kunmap(page);
|
||||
|
||||
sg->length = len % bsize_elem;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
pmcraid_err("failed to copy user data into sg list\n");
|
||||
rc = -EFAULT;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* pmcraid_queuecommand_lck - Queue a mid-layer request
|
||||
* @scsi_cmd: scsi command struct
|
||||
|
@ -3454,365 +3336,6 @@ static int pmcraid_chr_fasync(int fd, struct file *filep, int mode)
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pmcraid_build_passthrough_ioadls - builds SG elements for passthrough
|
||||
* commands sent over IOCTL interface
|
||||
*
|
||||
* @cmd : pointer to struct pmcraid_cmd
|
||||
* @buflen : length of the request buffer
|
||||
* @direction : data transfer direction
|
||||
*
|
||||
* Return value
|
||||
* 0 on success, non-zero error code on failure
|
||||
*/
|
||||
static int pmcraid_build_passthrough_ioadls(
|
||||
struct pmcraid_cmd *cmd,
|
||||
int buflen,
|
||||
int direction
|
||||
)
|
||||
{
|
||||
struct pmcraid_sglist *sglist = NULL;
|
||||
struct scatterlist *sg = NULL;
|
||||
struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb;
|
||||
struct pmcraid_ioadl_desc *ioadl;
|
||||
int i;
|
||||
|
||||
sglist = pmcraid_alloc_sglist(buflen);
|
||||
|
||||
if (!sglist) {
|
||||
pmcraid_err("can't allocate memory for passthrough SGls\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sglist->num_dma_sg = dma_map_sg(&cmd->drv_inst->pdev->dev,
|
||||
sglist->scatterlist,
|
||||
sglist->num_sg, direction);
|
||||
|
||||
if (!sglist->num_dma_sg || sglist->num_dma_sg > PMCRAID_MAX_IOADLS) {
|
||||
dev_err(&cmd->drv_inst->pdev->dev,
|
||||
"Failed to map passthrough buffer!\n");
|
||||
pmcraid_free_sglist(sglist);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
cmd->sglist = sglist;
|
||||
ioarcb->request_flags0 |= NO_LINK_DESCS;
|
||||
|
||||
ioadl = pmcraid_init_ioadls(cmd, sglist->num_dma_sg);
|
||||
|
||||
/* Initialize IOADL descriptor addresses */
|
||||
for_each_sg(sglist->scatterlist, sg, sglist->num_dma_sg, i) {
|
||||
ioadl[i].data_len = cpu_to_le32(sg_dma_len(sg));
|
||||
ioadl[i].address = cpu_to_le64(sg_dma_address(sg));
|
||||
ioadl[i].flags = 0;
|
||||
}
|
||||
|
||||
/* setup the last descriptor */
|
||||
ioadl[i - 1].flags = IOADL_FLAGS_LAST_DESC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pmcraid_release_passthrough_ioadls - release passthrough ioadls
|
||||
*
|
||||
* @cmd: pointer to struct pmcraid_cmd for which ioadls were allocated
|
||||
* @buflen: size of the request buffer
|
||||
* @direction: data transfer direction
|
||||
*
|
||||
* Return value
|
||||
* 0 on success, non-zero error code on failure
|
||||
*/
|
||||
static void pmcraid_release_passthrough_ioadls(
|
||||
struct pmcraid_cmd *cmd,
|
||||
int buflen,
|
||||
int direction
|
||||
)
|
||||
{
|
||||
struct pmcraid_sglist *sglist = cmd->sglist;
|
||||
|
||||
if (buflen > 0) {
|
||||
dma_unmap_sg(&cmd->drv_inst->pdev->dev,
|
||||
sglist->scatterlist,
|
||||
sglist->num_sg,
|
||||
direction);
|
||||
pmcraid_free_sglist(sglist);
|
||||
cmd->sglist = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pmcraid_ioctl_passthrough - handling passthrough IOCTL commands
|
||||
*
|
||||
* @pinstance: pointer to adapter instance structure
|
||||
* @ioctl_cmd: ioctl code
|
||||
* @buflen: unused
|
||||
* @arg: pointer to pmcraid_passthrough_buffer user buffer
|
||||
*
|
||||
* Return value
|
||||
* 0 on success, non-zero error code on failure
|
||||
*/
|
||||
static long pmcraid_ioctl_passthrough(
|
||||
struct pmcraid_instance *pinstance,
|
||||
unsigned int ioctl_cmd,
|
||||
unsigned int buflen,
|
||||
void __user *arg
|
||||
)
|
||||
{
|
||||
struct pmcraid_passthrough_ioctl_buffer *buffer;
|
||||
struct pmcraid_ioarcb *ioarcb;
|
||||
struct pmcraid_cmd *cmd;
|
||||
struct pmcraid_cmd *cancel_cmd;
|
||||
void __user *request_buffer;
|
||||
unsigned long request_offset;
|
||||
unsigned long lock_flags;
|
||||
void __user *ioasa;
|
||||
u32 ioasc;
|
||||
int request_size;
|
||||
int buffer_size;
|
||||
u8 direction;
|
||||
int rc = 0;
|
||||
|
||||
/* If IOA reset is in progress, wait 10 secs for reset to complete */
|
||||
if (pinstance->ioa_reset_in_progress) {
|
||||
rc = wait_event_interruptible_timeout(
|
||||
pinstance->reset_wait_q,
|
||||
!pinstance->ioa_reset_in_progress,
|
||||
msecs_to_jiffies(10000));
|
||||
|
||||
if (!rc)
|
||||
return -ETIMEDOUT;
|
||||
else if (rc < 0)
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
/* If adapter is not in operational state, return error */
|
||||
if (pinstance->ioa_state != IOA_STATE_OPERATIONAL) {
|
||||
pmcraid_err("IOA is not operational\n");
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
buffer_size = sizeof(struct pmcraid_passthrough_ioctl_buffer);
|
||||
buffer = kmalloc(buffer_size, GFP_KERNEL);
|
||||
|
||||
if (!buffer) {
|
||||
pmcraid_err("no memory for passthrough buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
request_offset =
|
||||
offsetof(struct pmcraid_passthrough_ioctl_buffer, request_buffer);
|
||||
|
||||
request_buffer = arg + request_offset;
|
||||
|
||||
rc = copy_from_user(buffer, arg,
|
||||
sizeof(struct pmcraid_passthrough_ioctl_buffer));
|
||||
|
||||
ioasa = arg + offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa);
|
||||
|
||||
if (rc) {
|
||||
pmcraid_err("ioctl: can't copy passthrough buffer\n");
|
||||
rc = -EFAULT;
|
||||
goto out_free_buffer;
|
||||
}
|
||||
|
||||
request_size = le32_to_cpu(buffer->ioarcb.data_transfer_length);
|
||||
|
||||
if (buffer->ioarcb.request_flags0 & TRANSFER_DIR_WRITE) {
|
||||
direction = DMA_TO_DEVICE;
|
||||
} else {
|
||||
direction = DMA_FROM_DEVICE;
|
||||
}
|
||||
|
||||
if (request_size < 0) {
|
||||
rc = -EINVAL;
|
||||
goto out_free_buffer;
|
||||
}
|
||||
|
||||
/* check if we have any additional command parameters */
|
||||
if (le16_to_cpu(buffer->ioarcb.add_cmd_param_length)
|
||||
> PMCRAID_ADD_CMD_PARAM_LEN) {
|
||||
rc = -EINVAL;
|
||||
goto out_free_buffer;
|
||||
}
|
||||
|
||||
cmd = pmcraid_get_free_cmd(pinstance);
|
||||
|
||||
if (!cmd) {
|
||||
pmcraid_err("free command block is not available\n");
|
||||
rc = -ENOMEM;
|
||||
goto out_free_buffer;
|
||||
}
|
||||
|
||||
cmd->scsi_cmd = NULL;
|
||||
ioarcb = &(cmd->ioa_cb->ioarcb);
|
||||
|
||||
/* Copy the user-provided IOARCB stuff field by field */
|
||||
ioarcb->resource_handle = buffer->ioarcb.resource_handle;
|
||||
ioarcb->data_transfer_length = buffer->ioarcb.data_transfer_length;
|
||||
ioarcb->cmd_timeout = buffer->ioarcb.cmd_timeout;
|
||||
ioarcb->request_type = buffer->ioarcb.request_type;
|
||||
ioarcb->request_flags0 = buffer->ioarcb.request_flags0;
|
||||
ioarcb->request_flags1 = buffer->ioarcb.request_flags1;
|
||||
memcpy(ioarcb->cdb, buffer->ioarcb.cdb, PMCRAID_MAX_CDB_LEN);
|
||||
|
||||
if (buffer->ioarcb.add_cmd_param_length) {
|
||||
ioarcb->add_cmd_param_length =
|
||||
buffer->ioarcb.add_cmd_param_length;
|
||||
ioarcb->add_cmd_param_offset =
|
||||
buffer->ioarcb.add_cmd_param_offset;
|
||||
memcpy(ioarcb->add_data.u.add_cmd_params,
|
||||
buffer->ioarcb.add_data.u.add_cmd_params,
|
||||
le16_to_cpu(buffer->ioarcb.add_cmd_param_length));
|
||||
}
|
||||
|
||||
/* set hrrq number where the IOA should respond to. Note that all cmds
|
||||
* generated internally uses hrrq_id 0, exception to this is the cmd
|
||||
* block of scsi_cmd which is re-used (e.g. cancel/abort), which uses
|
||||
* hrrq_id assigned here in queuecommand
|
||||
*/
|
||||
ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) %
|
||||
pinstance->num_hrrq;
|
||||
|
||||
if (request_size) {
|
||||
rc = pmcraid_build_passthrough_ioadls(cmd,
|
||||
request_size,
|
||||
direction);
|
||||
if (rc) {
|
||||
pmcraid_err("couldn't build passthrough ioadls\n");
|
||||
goto out_free_cmd;
|
||||
}
|
||||
}
|
||||
|
||||
/* If data is being written into the device, copy the data from user
|
||||
* buffers
|
||||
*/
|
||||
if (direction == DMA_TO_DEVICE && request_size > 0) {
|
||||
rc = pmcraid_copy_sglist(cmd->sglist,
|
||||
request_buffer,
|
||||
request_size,
|
||||
direction);
|
||||
if (rc) {
|
||||
pmcraid_err("failed to copy user buffer\n");
|
||||
goto out_free_sglist;
|
||||
}
|
||||
}
|
||||
|
||||
/* passthrough ioctl is a blocking command so, put the user to sleep
|
||||
* until timeout. Note that a timeout value of 0 means, do timeout.
|
||||
*/
|
||||
cmd->cmd_done = pmcraid_internal_done;
|
||||
init_completion(&cmd->wait_for_completion);
|
||||
cmd->completion_req = 1;
|
||||
|
||||
pmcraid_info("command(%d) (CDB[0] = %x) for %x\n",
|
||||
le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle) >> 2,
|
||||
cmd->ioa_cb->ioarcb.cdb[0],
|
||||
le32_to_cpu(cmd->ioa_cb->ioarcb.resource_handle));
|
||||
|
||||
spin_lock_irqsave(pinstance->host->host_lock, lock_flags);
|
||||
_pmcraid_fire_command(cmd);
|
||||
spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags);
|
||||
|
||||
/* NOTE ! Remove the below line once abort_task is implemented
|
||||
* in firmware. This line disables ioctl command timeout handling logic
|
||||
* similar to IO command timeout handling, making ioctl commands to wait
|
||||
* until the command completion regardless of timeout value specified in
|
||||
* ioarcb
|
||||
*/
|
||||
buffer->ioarcb.cmd_timeout = 0;
|
||||
|
||||
/* If command timeout is specified put caller to wait till that time,
|
||||
* otherwise it would be blocking wait. If command gets timed out, it
|
||||
* will be aborted.
|
||||
*/
|
||||
if (buffer->ioarcb.cmd_timeout == 0) {
|
||||
wait_for_completion(&cmd->wait_for_completion);
|
||||
} else if (!wait_for_completion_timeout(
|
||||
&cmd->wait_for_completion,
|
||||
msecs_to_jiffies(le16_to_cpu(buffer->ioarcb.cmd_timeout) * 1000))) {
|
||||
|
||||
pmcraid_info("aborting cmd %d (CDB[0] = %x) due to timeout\n",
|
||||
le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle) >> 2,
|
||||
cmd->ioa_cb->ioarcb.cdb[0]);
|
||||
|
||||
spin_lock_irqsave(pinstance->host->host_lock, lock_flags);
|
||||
cancel_cmd = pmcraid_abort_cmd(cmd);
|
||||
spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags);
|
||||
|
||||
if (cancel_cmd) {
|
||||
wait_for_completion(&cancel_cmd->wait_for_completion);
|
||||
ioasc = le32_to_cpu(cancel_cmd->ioa_cb->ioasa.ioasc);
|
||||
pmcraid_return_cmd(cancel_cmd);
|
||||
|
||||
/* if abort task couldn't find the command i.e it got
|
||||
* completed prior to aborting, return good completion.
|
||||
* if command got aborted successfully or there was IOA
|
||||
* reset due to abort task itself getting timedout then
|
||||
* return -ETIMEDOUT
|
||||
*/
|
||||
if (ioasc == PMCRAID_IOASC_IOA_WAS_RESET ||
|
||||
PMCRAID_IOASC_SENSE_KEY(ioasc) == 0x00) {
|
||||
if (ioasc != PMCRAID_IOASC_GC_IOARCB_NOTFOUND)
|
||||
rc = -ETIMEDOUT;
|
||||
goto out_handle_response;
|
||||
}
|
||||
}
|
||||
|
||||
/* no command block for abort task or abort task failed to abort
|
||||
* the IOARCB, then wait for 150 more seconds and initiate reset
|
||||
* sequence after timeout
|
||||
*/
|
||||
if (!wait_for_completion_timeout(
|
||||
&cmd->wait_for_completion,
|
||||
msecs_to_jiffies(150 * 1000))) {
|
||||
pmcraid_reset_bringup(cmd->drv_inst);
|
||||
rc = -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
out_handle_response:
|
||||
/* copy entire IOASA buffer and return IOCTL success.
|
||||
* If copying IOASA to user-buffer fails, return
|
||||
* EFAULT
|
||||
*/
|
||||
if (copy_to_user(ioasa, &cmd->ioa_cb->ioasa,
|
||||
sizeof(struct pmcraid_ioasa))) {
|
||||
pmcraid_err("failed to copy ioasa buffer to user\n");
|
||||
rc = -EFAULT;
|
||||
}
|
||||
|
||||
/* If the data transfer was from device, copy the data onto user
|
||||
* buffers
|
||||
*/
|
||||
else if (direction == DMA_FROM_DEVICE && request_size > 0) {
|
||||
rc = pmcraid_copy_sglist(cmd->sglist,
|
||||
request_buffer,
|
||||
request_size,
|
||||
direction);
|
||||
if (rc) {
|
||||
pmcraid_err("failed to copy user buffer\n");
|
||||
rc = -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
out_free_sglist:
|
||||
pmcraid_release_passthrough_ioadls(cmd, request_size, direction);
|
||||
|
||||
out_free_cmd:
|
||||
pmcraid_return_cmd(cmd);
|
||||
|
||||
out_free_buffer:
|
||||
kfree(buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* pmcraid_ioctl_driver - ioctl handler for commands handled by driver itself
|
||||
*
|
||||
|
@ -3922,20 +3445,6 @@ static long pmcraid_chr_ioctl(
|
|||
|
||||
switch (_IOC_TYPE(cmd)) {
|
||||
|
||||
case PMCRAID_PASSTHROUGH_IOCTL:
|
||||
/* If ioctl code is to download microcode, we need to block
|
||||
* mid-layer requests.
|
||||
*/
|
||||
if (cmd == PMCRAID_IOCTL_DOWNLOAD_MICROCODE)
|
||||
scsi_block_requests(pinstance->host);
|
||||
|
||||
retval = pmcraid_ioctl_passthrough(pinstance, cmd,
|
||||
hdr->buffer_length, argp);
|
||||
|
||||
if (cmd == PMCRAID_IOCTL_DOWNLOAD_MICROCODE)
|
||||
scsi_unblock_requests(pinstance->host);
|
||||
break;
|
||||
|
||||
case PMCRAID_DRIVER_IOCTL:
|
||||
arg += sizeof(struct pmcraid_ioctl_header);
|
||||
retval = pmcraid_ioctl_driver(pinstance, cmd,
|
||||
|
|
|
@ -1022,41 +1022,16 @@ struct pmcraid_ioctl_header {
|
|||
|
||||
#define PMCRAID_IOCTL_SIGNATURE "PMCRAID"
|
||||
|
||||
/*
|
||||
* pmcraid_passthrough_ioctl_buffer - structure given as argument to
|
||||
* passthrough(or firmware handled) IOCTL commands. Note that ioarcb requires
|
||||
* 32-byte alignment so, it is necessary to pack this structure to avoid any
|
||||
* holes between ioctl_header and passthrough buffer
|
||||
*
|
||||
* .ioactl_header : ioctl header
|
||||
* .ioarcb : filled-up ioarcb buffer, driver always reads this buffer
|
||||
* .ioasa : buffer for ioasa, driver fills this with IOASA from firmware
|
||||
* .request_buffer: The I/O buffer (flat), driver reads/writes to this based on
|
||||
* the transfer directions passed in ioarcb.flags0. Contents
|
||||
* of this buffer are valid only when ioarcb.data_transfer_len
|
||||
* is not zero.
|
||||
*/
|
||||
struct pmcraid_passthrough_ioctl_buffer {
|
||||
struct pmcraid_ioctl_header ioctl_header;
|
||||
struct pmcraid_ioarcb ioarcb;
|
||||
struct pmcraid_ioasa ioasa;
|
||||
u8 request_buffer[];
|
||||
} __attribute__ ((packed, aligned(PMCRAID_IOARCB_ALIGNMENT)));
|
||||
|
||||
/*
|
||||
* keys to differentiate between driver handled IOCTLs and passthrough
|
||||
* IOCTLs passed to IOA. driver determines the ioctl type using macro
|
||||
* _IOC_TYPE
|
||||
*/
|
||||
#define PMCRAID_DRIVER_IOCTL 'D'
|
||||
#define PMCRAID_PASSTHROUGH_IOCTL 'F'
|
||||
|
||||
#define DRV_IOCTL(n, size) \
|
||||
_IOC(_IOC_READ|_IOC_WRITE, PMCRAID_DRIVER_IOCTL, (n), (size))
|
||||
|
||||
#define FMW_IOCTL(n, size) \
|
||||
_IOC(_IOC_READ|_IOC_WRITE, PMCRAID_PASSTHROUGH_IOCTL, (n), (size))
|
||||
|
||||
/*
|
||||
* _ARGSIZE: macro that gives size of the argument type passed to an IOCTL cmd.
|
||||
* This is to facilitate applications avoiding un-necessary memory allocations.
|
||||
|
@ -1069,12 +1044,4 @@ struct pmcraid_passthrough_ioctl_buffer {
|
|||
#define PMCRAID_IOCTL_RESET_ADAPTER \
|
||||
DRV_IOCTL(5, sizeof(struct pmcraid_ioctl_header))
|
||||
|
||||
/* passthrough/firmware handled commands */
|
||||
#define PMCRAID_IOCTL_PASSTHROUGH_COMMAND \
|
||||
FMW_IOCTL(1, sizeof(struct pmcraid_passthrough_ioctl_buffer))
|
||||
|
||||
#define PMCRAID_IOCTL_DOWNLOAD_MICROCODE \
|
||||
FMW_IOCTL(2, sizeof(struct pmcraid_passthrough_ioctl_buffer))
|
||||
|
||||
|
||||
#endif /* _PMCRAID_H */
|
||||
|
|
|
@ -860,6 +860,37 @@ static int qedi_task_xmit(struct iscsi_task *task)
|
|||
return qedi_iscsi_send_ioreq(task);
|
||||
}
|
||||
|
||||
static void qedi_offload_work(struct work_struct *work)
|
||||
{
|
||||
struct qedi_endpoint *qedi_ep =
|
||||
container_of(work, struct qedi_endpoint, offload_work);
|
||||
struct qedi_ctx *qedi;
|
||||
int wait_delay = 5 * HZ;
|
||||
int ret;
|
||||
|
||||
qedi = qedi_ep->qedi;
|
||||
|
||||
ret = qedi_iscsi_offload_conn(qedi_ep);
|
||||
if (ret) {
|
||||
QEDI_ERR(&qedi->dbg_ctx,
|
||||
"offload error: iscsi_cid=%u, qedi_ep=%p, ret=%d\n",
|
||||
qedi_ep->iscsi_cid, qedi_ep, ret);
|
||||
qedi_ep->state = EP_STATE_OFLDCONN_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = wait_event_interruptible_timeout(qedi_ep->tcp_ofld_wait,
|
||||
(qedi_ep->state ==
|
||||
EP_STATE_OFLDCONN_COMPL),
|
||||
wait_delay);
|
||||
if (ret <= 0 || qedi_ep->state != EP_STATE_OFLDCONN_COMPL) {
|
||||
qedi_ep->state = EP_STATE_OFLDCONN_FAILED;
|
||||
QEDI_ERR(&qedi->dbg_ctx,
|
||||
"Offload conn TIMEOUT iscsi_cid=%u, qedi_ep=%p\n",
|
||||
qedi_ep->iscsi_cid, qedi_ep);
|
||||
}
|
||||
}
|
||||
|
||||
static struct iscsi_endpoint *
|
||||
qedi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
|
||||
int non_blocking)
|
||||
|
@ -908,6 +939,7 @@ qedi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
|
|||
}
|
||||
qedi_ep = ep->dd_data;
|
||||
memset(qedi_ep, 0, sizeof(struct qedi_endpoint));
|
||||
INIT_WORK(&qedi_ep->offload_work, qedi_offload_work);
|
||||
qedi_ep->state = EP_STATE_IDLE;
|
||||
qedi_ep->iscsi_cid = (u32)-1;
|
||||
qedi_ep->qedi = qedi;
|
||||
|
@ -1056,12 +1088,11 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
|
|||
qedi_ep = ep->dd_data;
|
||||
qedi = qedi_ep->qedi;
|
||||
|
||||
flush_work(&qedi_ep->offload_work);
|
||||
|
||||
if (qedi_ep->state == EP_STATE_OFLDCONN_START)
|
||||
goto ep_exit_recover;
|
||||
|
||||
if (qedi_ep->state != EP_STATE_OFLDCONN_NONE)
|
||||
flush_work(&qedi_ep->offload_work);
|
||||
|
||||
if (qedi_ep->conn) {
|
||||
qedi_conn = qedi_ep->conn;
|
||||
abrt_conn = qedi_conn->abrt_conn;
|
||||
|
@ -1235,37 +1266,6 @@ static int qedi_data_avail(struct qedi_ctx *qedi, u16 vlanid)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void qedi_offload_work(struct work_struct *work)
|
||||
{
|
||||
struct qedi_endpoint *qedi_ep =
|
||||
container_of(work, struct qedi_endpoint, offload_work);
|
||||
struct qedi_ctx *qedi;
|
||||
int wait_delay = 5 * HZ;
|
||||
int ret;
|
||||
|
||||
qedi = qedi_ep->qedi;
|
||||
|
||||
ret = qedi_iscsi_offload_conn(qedi_ep);
|
||||
if (ret) {
|
||||
QEDI_ERR(&qedi->dbg_ctx,
|
||||
"offload error: iscsi_cid=%u, qedi_ep=%p, ret=%d\n",
|
||||
qedi_ep->iscsi_cid, qedi_ep, ret);
|
||||
qedi_ep->state = EP_STATE_OFLDCONN_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = wait_event_interruptible_timeout(qedi_ep->tcp_ofld_wait,
|
||||
(qedi_ep->state ==
|
||||
EP_STATE_OFLDCONN_COMPL),
|
||||
wait_delay);
|
||||
if ((ret <= 0) || (qedi_ep->state != EP_STATE_OFLDCONN_COMPL)) {
|
||||
qedi_ep->state = EP_STATE_OFLDCONN_FAILED;
|
||||
QEDI_ERR(&qedi->dbg_ctx,
|
||||
"Offload conn TIMEOUT iscsi_cid=%u, qedi_ep=%p\n",
|
||||
qedi_ep->iscsi_cid, qedi_ep);
|
||||
}
|
||||
}
|
||||
|
||||
static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
|
||||
{
|
||||
struct qedi_ctx *qedi;
|
||||
|
@ -1381,7 +1381,6 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
|
|||
qedi_ep->dst_addr, qedi_ep->dst_port);
|
||||
}
|
||||
|
||||
INIT_WORK(&qedi_ep->offload_work, qedi_offload_work);
|
||||
queue_work(qedi->offload_thread, &qedi_ep->offload_work);
|
||||
|
||||
ret = 0;
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <linux/blkdev.h>
|
||||
#include <linux/crc-t10dif.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/hrtimer.h>
|
||||
|
@ -732,9 +731,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = {
|
|||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
|
||||
};
|
||||
|
||||
static atomic_t sdebug_num_hosts;
|
||||
static DEFINE_MUTEX(add_host_mutex);
|
||||
|
||||
static int sdebug_num_hosts;
|
||||
static int sdebug_add_host = DEF_NUM_HOST; /* in sysfs this is relative */
|
||||
static int sdebug_ato = DEF_ATO;
|
||||
static int sdebug_cdb_len = DEF_CDB_LEN;
|
||||
|
@ -781,7 +778,6 @@ static int sdebug_uuid_ctl = DEF_UUID_CTL;
|
|||
static bool sdebug_random = DEF_RANDOM;
|
||||
static bool sdebug_per_host_store = DEF_PER_HOST_STORE;
|
||||
static bool sdebug_removable = DEF_REMOVABLE;
|
||||
static bool sdebug_deflect_incoming;
|
||||
static bool sdebug_clustering;
|
||||
static bool sdebug_host_lock = DEF_HOST_LOCK;
|
||||
static bool sdebug_strict = DEF_STRICT;
|
||||
|
@ -5122,10 +5118,6 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp)
|
|||
sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
|
||||
if (sdp->host->max_cmd_len != SDEBUG_MAX_CMD_LEN)
|
||||
sdp->host->max_cmd_len = SDEBUG_MAX_CMD_LEN;
|
||||
if (smp_load_acquire(&sdebug_deflect_incoming)) {
|
||||
pr_info("Exit early due to deflect_incoming\n");
|
||||
return 1;
|
||||
}
|
||||
if (devip == NULL) {
|
||||
devip = find_build_dev_info(sdp);
|
||||
if (devip == NULL)
|
||||
|
@ -5211,7 +5203,7 @@ static bool stop_queued_cmnd(struct scsi_cmnd *cmnd)
|
|||
}
|
||||
|
||||
/* Deletes (stops) timers or work queues of all queued commands */
|
||||
static void stop_all_queued(bool done_with_no_conn)
|
||||
static void stop_all_queued(void)
|
||||
{
|
||||
unsigned long iflags;
|
||||
int j, k;
|
||||
|
@ -5220,15 +5212,13 @@ static void stop_all_queued(bool done_with_no_conn)
|
|||
struct sdebug_queued_cmd *sqcp;
|
||||
struct sdebug_dev_info *devip;
|
||||
struct sdebug_defer *sd_dp;
|
||||
struct scsi_cmnd *scp;
|
||||
|
||||
for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) {
|
||||
spin_lock_irqsave(&sqp->qc_lock, iflags);
|
||||
for (k = 0; k < SDEBUG_CANQUEUE; ++k) {
|
||||
if (test_bit(k, sqp->in_use_bm)) {
|
||||
sqcp = &sqp->qc_arr[k];
|
||||
scp = sqcp->a_cmnd;
|
||||
if (!scp)
|
||||
if (sqcp->a_cmnd == NULL)
|
||||
continue;
|
||||
devip = (struct sdebug_dev_info *)
|
||||
sqcp->a_cmnd->device->hostdata;
|
||||
|
@ -5243,10 +5233,6 @@ static void stop_all_queued(bool done_with_no_conn)
|
|||
l_defer_t = SDEB_DEFER_NONE;
|
||||
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
|
||||
stop_qc_helper(sd_dp, l_defer_t);
|
||||
if (done_with_no_conn && l_defer_t != SDEB_DEFER_NONE) {
|
||||
scp->result = DID_NO_CONNECT << 16;
|
||||
scsi_done(scp);
|
||||
}
|
||||
clear_bit(k, sqp->in_use_bm);
|
||||
spin_lock_irqsave(&sqp->qc_lock, iflags);
|
||||
}
|
||||
|
@ -5389,7 +5375,7 @@ static int scsi_debug_host_reset(struct scsi_cmnd *SCpnt)
|
|||
}
|
||||
}
|
||||
spin_unlock(&sdebug_host_list_lock);
|
||||
stop_all_queued(false);
|
||||
stop_all_queued();
|
||||
if (SDEBUG_OPT_RESET_NOISE & sdebug_opts)
|
||||
sdev_printk(KERN_INFO, SCpnt->device,
|
||||
"%s: %d device(s) found\n", __func__, k);
|
||||
|
@ -5449,50 +5435,13 @@ static void sdebug_build_parts(unsigned char *ramp, unsigned long store_size)
|
|||
}
|
||||
}
|
||||
|
||||
static void sdeb_block_all_queues(void)
|
||||
static void block_unblock_all_queues(bool block)
|
||||
{
|
||||
int j;
|
||||
struct sdebug_queue *sqp;
|
||||
|
||||
for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp)
|
||||
atomic_set(&sqp->blocked, (int)true);
|
||||
}
|
||||
|
||||
static void sdeb_unblock_all_queues(void)
|
||||
{
|
||||
int j;
|
||||
struct sdebug_queue *sqp;
|
||||
|
||||
for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp)
|
||||
atomic_set(&sqp->blocked, (int)false);
|
||||
}
|
||||
|
||||
static void
|
||||
sdeb_add_n_hosts(int num_hosts)
|
||||
{
|
||||
if (num_hosts < 1)
|
||||
return;
|
||||
do {
|
||||
bool found;
|
||||
unsigned long idx;
|
||||
struct sdeb_store_info *sip;
|
||||
bool want_phs = (sdebug_fake_rw == 0) && sdebug_per_host_store;
|
||||
|
||||
found = false;
|
||||
if (want_phs) {
|
||||
xa_for_each_marked(per_store_ap, idx, sip, SDEB_XA_NOT_IN_USE) {
|
||||
sdeb_most_recent_idx = (int)idx;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (found) /* re-use case */
|
||||
sdebug_add_host_helper((int)idx);
|
||||
else
|
||||
sdebug_do_add_host(true /* make new store */);
|
||||
} else {
|
||||
sdebug_do_add_host(false);
|
||||
}
|
||||
} while (--num_hosts);
|
||||
atomic_set(&sqp->blocked, (int)block);
|
||||
}
|
||||
|
||||
/* Adjust (by rounding down) the sdebug_cmnd_count so abs(every_nth)-1
|
||||
|
@ -5505,10 +5454,10 @@ static void tweak_cmnd_count(void)
|
|||
modulo = abs(sdebug_every_nth);
|
||||
if (modulo < 2)
|
||||
return;
|
||||
sdeb_block_all_queues();
|
||||
block_unblock_all_queues(true);
|
||||
count = atomic_read(&sdebug_cmnd_count);
|
||||
atomic_set(&sdebug_cmnd_count, (count / modulo) * modulo);
|
||||
sdeb_unblock_all_queues();
|
||||
block_unblock_all_queues(false);
|
||||
}
|
||||
|
||||
static void clear_queue_stats(void)
|
||||
|
@ -5526,15 +5475,6 @@ static bool inject_on_this_cmd(void)
|
|||
return (atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) == 0;
|
||||
}
|
||||
|
||||
static int process_deflect_incoming(struct scsi_cmnd *scp)
|
||||
{
|
||||
u8 opcode = scp->cmnd[0];
|
||||
|
||||
if (opcode == SYNCHRONIZE_CACHE || opcode == SYNCHRONIZE_CACHE_16)
|
||||
return 0;
|
||||
return DID_NO_CONNECT << 16;
|
||||
}
|
||||
|
||||
#define INCLUSIVE_TIMING_MAX_NS 1000000 /* 1 millisecond */
|
||||
|
||||
/* Complete the processing of the thread that queued a SCSI command to this
|
||||
|
@ -5544,7 +5484,8 @@ static int process_deflect_incoming(struct scsi_cmnd *scp)
|
|||
*/
|
||||
static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
|
||||
int scsi_result,
|
||||
int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *),
|
||||
int (*pfp)(struct scsi_cmnd *,
|
||||
struct sdebug_dev_info *),
|
||||
int delta_jiff, int ndelay)
|
||||
{
|
||||
bool new_sd_dp;
|
||||
|
@ -5565,27 +5506,13 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
|
|||
}
|
||||
sdp = cmnd->device;
|
||||
|
||||
if (delta_jiff == 0) {
|
||||
sqp = get_queue(cmnd);
|
||||
if (atomic_read(&sqp->blocked)) {
|
||||
if (smp_load_acquire(&sdebug_deflect_incoming))
|
||||
return process_deflect_incoming(cmnd);
|
||||
else
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
}
|
||||
if (delta_jiff == 0)
|
||||
goto respond_in_thread;
|
||||
}
|
||||
|
||||
sqp = get_queue(cmnd);
|
||||
spin_lock_irqsave(&sqp->qc_lock, iflags);
|
||||
if (unlikely(atomic_read(&sqp->blocked))) {
|
||||
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
|
||||
if (smp_load_acquire(&sdebug_deflect_incoming)) {
|
||||
scsi_result = process_deflect_incoming(cmnd);
|
||||
goto respond_in_thread;
|
||||
}
|
||||
if (sdebug_verbose)
|
||||
pr_info("blocked --> SCSI_MLQUEUE_HOST_BUSY\n");
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
}
|
||||
num_in_q = atomic_read(&devip->num_in_q);
|
||||
|
@ -5774,12 +5701,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
|
|||
respond_in_thread: /* call back to mid-layer using invocation thread */
|
||||
cmnd->result = pfp != NULL ? pfp(cmnd, devip) : 0;
|
||||
cmnd->result &= ~SDEG_RES_IMMED_MASK;
|
||||
if (cmnd->result == 0 && scsi_result != 0) {
|
||||
if (cmnd->result == 0 && scsi_result != 0)
|
||||
cmnd->result = scsi_result;
|
||||
if (sdebug_verbose)
|
||||
pr_info("respond_in_thread: tag=0x%x, scp->result=0x%x\n",
|
||||
blk_mq_unique_tag(scsi_cmd_to_rq(cmnd)), scsi_result);
|
||||
}
|
||||
scsi_done(cmnd);
|
||||
return 0;
|
||||
}
|
||||
|
@ -6064,7 +5987,7 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf,
|
|||
int j, k;
|
||||
struct sdebug_queue *sqp;
|
||||
|
||||
sdeb_block_all_queues();
|
||||
block_unblock_all_queues(true);
|
||||
for (j = 0, sqp = sdebug_q_arr; j < submit_queues;
|
||||
++j, ++sqp) {
|
||||
k = find_first_bit(sqp->in_use_bm,
|
||||
|
@ -6078,7 +6001,7 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf,
|
|||
sdebug_jdelay = jdelay;
|
||||
sdebug_ndelay = 0;
|
||||
}
|
||||
sdeb_unblock_all_queues();
|
||||
block_unblock_all_queues(false);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -6104,7 +6027,7 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
|
|||
int j, k;
|
||||
struct sdebug_queue *sqp;
|
||||
|
||||
sdeb_block_all_queues();
|
||||
block_unblock_all_queues(true);
|
||||
for (j = 0, sqp = sdebug_q_arr; j < submit_queues;
|
||||
++j, ++sqp) {
|
||||
k = find_first_bit(sqp->in_use_bm,
|
||||
|
@ -6119,7 +6042,7 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
|
|||
sdebug_jdelay = ndelay ? JDELAY_OVERRIDDEN
|
||||
: DEF_JDELAY;
|
||||
}
|
||||
sdeb_unblock_all_queues();
|
||||
block_unblock_all_queues(false);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -6433,7 +6356,7 @@ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
|
|||
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
|
||||
(n <= SDEBUG_CANQUEUE) &&
|
||||
(sdebug_host_max_queue == 0)) {
|
||||
sdeb_block_all_queues();
|
||||
block_unblock_all_queues(true);
|
||||
k = 0;
|
||||
for (j = 0, sqp = sdebug_q_arr; j < submit_queues;
|
||||
++j, ++sqp) {
|
||||
|
@ -6448,7 +6371,7 @@ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
|
|||
atomic_set(&retired_max_queue, k + 1);
|
||||
else
|
||||
atomic_set(&retired_max_queue, 0);
|
||||
sdeb_unblock_all_queues();
|
||||
block_unblock_all_queues(false);
|
||||
return count;
|
||||
}
|
||||
return -EINVAL;
|
||||
|
@ -6537,48 +6460,43 @@ static DRIVER_ATTR_RW(virtual_gb);
|
|||
static ssize_t add_host_show(struct device_driver *ddp, char *buf)
|
||||
{
|
||||
/* absolute number of hosts currently active is what is shown */
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&sdebug_num_hosts));
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_num_hosts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept positive and negative values. Hex values (only positive) may be prefixed by '0x'.
|
||||
* To remove all hosts use a large negative number (e.g. -9999). The value 0 does nothing.
|
||||
* Returns -EBUSY if another add_host sysfs invocation is active.
|
||||
*/
|
||||
static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
bool found;
|
||||
unsigned long idx;
|
||||
struct sdeb_store_info *sip;
|
||||
bool want_phs = (sdebug_fake_rw == 0) && sdebug_per_host_store;
|
||||
int delta_hosts;
|
||||
|
||||
if (count == 0 || kstrtoint(buf, 0, &delta_hosts))
|
||||
if (sscanf(buf, "%d", &delta_hosts) != 1)
|
||||
return -EINVAL;
|
||||
if (sdebug_verbose)
|
||||
pr_info("prior num_hosts=%d, num_to_add=%d\n",
|
||||
atomic_read(&sdebug_num_hosts), delta_hosts);
|
||||
if (delta_hosts == 0)
|
||||
return count;
|
||||
if (mutex_trylock(&add_host_mutex) == 0)
|
||||
return -EBUSY;
|
||||
if (delta_hosts > 0) {
|
||||
sdeb_add_n_hosts(delta_hosts);
|
||||
} else if (delta_hosts < 0) {
|
||||
smp_store_release(&sdebug_deflect_incoming, true);
|
||||
sdeb_block_all_queues();
|
||||
if (delta_hosts >= atomic_read(&sdebug_num_hosts))
|
||||
stop_all_queued(true);
|
||||
do {
|
||||
if (atomic_read(&sdebug_num_hosts) < 1) {
|
||||
free_all_queued();
|
||||
break;
|
||||
found = false;
|
||||
if (want_phs) {
|
||||
xa_for_each_marked(per_store_ap, idx, sip,
|
||||
SDEB_XA_NOT_IN_USE) {
|
||||
sdeb_most_recent_idx = (int)idx;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (found) /* re-use case */
|
||||
sdebug_add_host_helper((int)idx);
|
||||
else
|
||||
sdebug_do_add_host(true);
|
||||
} else {
|
||||
sdebug_do_add_host(false);
|
||||
}
|
||||
} while (--delta_hosts);
|
||||
} else if (delta_hosts < 0) {
|
||||
do {
|
||||
sdebug_do_remove_host(false);
|
||||
} while (++delta_hosts);
|
||||
sdeb_unblock_all_queues();
|
||||
smp_store_release(&sdebug_deflect_incoming, false);
|
||||
}
|
||||
mutex_unlock(&add_host_mutex);
|
||||
if (sdebug_verbose)
|
||||
pr_info("post num_hosts=%d\n", atomic_read(&sdebug_num_hosts));
|
||||
return count;
|
||||
}
|
||||
static DRIVER_ATTR_RW(add_host);
|
||||
|
@ -7089,10 +7007,6 @@ static int __init scsi_debug_init(void)
|
|||
sdebug_add_host = 0;
|
||||
|
||||
for (k = 0; k < hosts_to_add; k++) {
|
||||
if (smp_load_acquire(&sdebug_deflect_incoming)) {
|
||||
pr_info("exit early as sdebug_deflect_incoming is set\n");
|
||||
return 0;
|
||||
}
|
||||
if (want_store && k == 0) {
|
||||
ret = sdebug_add_host_helper(idx);
|
||||
if (ret < 0) {
|
||||
|
@ -7110,12 +7024,8 @@ static int __init scsi_debug_init(void)
|
|||
}
|
||||
}
|
||||
if (sdebug_verbose)
|
||||
pr_info("built %d host(s)\n", atomic_read(&sdebug_num_hosts));
|
||||
pr_info("built %d host(s)\n", sdebug_num_hosts);
|
||||
|
||||
/*
|
||||
* Even though all the hosts have been established, due to async device (LU) scanning
|
||||
* by the scsi mid-level, there may still be devices (LUs) being set up.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
bus_unreg:
|
||||
|
@ -7131,17 +7041,12 @@ free_q_arr:
|
|||
|
||||
static void __exit scsi_debug_exit(void)
|
||||
{
|
||||
int k;
|
||||
int k = sdebug_num_hosts;
|
||||
|
||||
/* Possible race with LUs still being set up; stop them asap */
|
||||
sdeb_block_all_queues();
|
||||
smp_store_release(&sdebug_deflect_incoming, true);
|
||||
stop_all_queued(false);
|
||||
for (k = 0; atomic_read(&sdebug_num_hosts) > 0; k++)
|
||||
stop_all_queued();
|
||||
for (; k; k--)
|
||||
sdebug_do_remove_host(true);
|
||||
free_all_queued();
|
||||
if (sdebug_verbose)
|
||||
pr_info("removed %d hosts\n", k);
|
||||
driver_unregister(&sdebug_driverfs_driver);
|
||||
bus_unregister(&pseudo_lld_bus);
|
||||
root_device_unregister(pseudo_primary);
|
||||
|
@ -7311,13 +7216,13 @@ static int sdebug_add_host_helper(int per_host_idx)
|
|||
sdbg_host->dev.bus = &pseudo_lld_bus;
|
||||
sdbg_host->dev.parent = pseudo_primary;
|
||||
sdbg_host->dev.release = &sdebug_release_adapter;
|
||||
dev_set_name(&sdbg_host->dev, "adapter%d", atomic_read(&sdebug_num_hosts));
|
||||
dev_set_name(&sdbg_host->dev, "adapter%d", sdebug_num_hosts);
|
||||
|
||||
error = device_register(&sdbg_host->dev);
|
||||
if (error)
|
||||
goto clean;
|
||||
|
||||
atomic_inc(&sdebug_num_hosts);
|
||||
++sdebug_num_hosts;
|
||||
return 0;
|
||||
|
||||
clean:
|
||||
|
@ -7381,7 +7286,7 @@ static void sdebug_do_remove_host(bool the_end)
|
|||
return;
|
||||
|
||||
device_unregister(&sdbg_host->dev);
|
||||
atomic_dec(&sdebug_num_hosts);
|
||||
--sdebug_num_hosts;
|
||||
}
|
||||
|
||||
static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
|
||||
|
@ -7389,10 +7294,10 @@ static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
|
|||
int num_in_q = 0;
|
||||
struct sdebug_dev_info *devip;
|
||||
|
||||
sdeb_block_all_queues();
|
||||
block_unblock_all_queues(true);
|
||||
devip = (struct sdebug_dev_info *)sdev->hostdata;
|
||||
if (NULL == devip) {
|
||||
sdeb_unblock_all_queues();
|
||||
block_unblock_all_queues(false);
|
||||
return -ENODEV;
|
||||
}
|
||||
num_in_q = atomic_read(&devip->num_in_q);
|
||||
|
@ -7411,7 +7316,7 @@ static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
|
|||
sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d, num_in_q=%d\n",
|
||||
__func__, qdepth, num_in_q);
|
||||
}
|
||||
sdeb_unblock_all_queues();
|
||||
block_unblock_all_queues(false);
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
|
||||
|
@ -7519,12 +7424,13 @@ static int sdebug_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
|
|||
struct sdebug_defer *sd_dp;
|
||||
|
||||
sqp = sdebug_q_arr + queue_num;
|
||||
qc_idx = find_first_bit(sqp->in_use_bm, sdebug_max_queue);
|
||||
if (qc_idx >= sdebug_max_queue)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&sqp->qc_lock, iflags);
|
||||
|
||||
qc_idx = find_first_bit(sqp->in_use_bm, sdebug_max_queue);
|
||||
if (qc_idx >= sdebug_max_queue)
|
||||
goto unlock;
|
||||
|
||||
for (first = true; first || qc_idx + 1 < sdebug_max_queue; ) {
|
||||
if (first) {
|
||||
first = false;
|
||||
|
@ -7589,6 +7495,7 @@ static int sdebug_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
|
|||
break;
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
|
||||
|
||||
if (num_entries > 0)
|
||||
|
|
|
@ -30,7 +30,7 @@ static inline const char *scmd_name(const struct scsi_cmnd *scmd)
|
|||
{
|
||||
struct request *rq = scsi_cmd_to_rq((struct scsi_cmnd *)scmd);
|
||||
|
||||
if (!rq->q->disk)
|
||||
if (!rq->q || !rq->q->disk)
|
||||
return NULL;
|
||||
return rq->q->disk->disk_name;
|
||||
}
|
||||
|
|
|
@ -223,6 +223,8 @@ static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev,
|
|||
int ret;
|
||||
struct sbitmap sb_backup;
|
||||
|
||||
depth = min_t(unsigned int, depth, scsi_device_max_queue_depth(sdev));
|
||||
|
||||
/*
|
||||
* realloc if new shift is calculated, which is caused by setting
|
||||
* up one new default queue depth after calling ->slave_configure
|
||||
|
@ -245,6 +247,9 @@ static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev,
|
|||
scsi_device_max_queue_depth(sdev),
|
||||
new_shift, GFP_KERNEL,
|
||||
sdev->request_queue->node, false, true);
|
||||
if (!ret)
|
||||
sbitmap_resize(&sdev->budget_map, depth);
|
||||
|
||||
if (need_free) {
|
||||
if (ret)
|
||||
sdev->budget_map = sb_backup;
|
||||
|
|
|
@ -1384,10 +1384,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
|
|||
if (IS_ENABLED(CONFIG_BLK_DEV_BSG)) {
|
||||
sdev->bsg_dev = scsi_bsg_register_queue(sdev);
|
||||
if (IS_ERR(sdev->bsg_dev)) {
|
||||
/*
|
||||
* We're treating error on bsg register as non-fatal, so
|
||||
* pretend nothing went wrong.
|
||||
*/
|
||||
error = PTR_ERR(sdev->bsg_dev);
|
||||
sdev_printk(KERN_INFO, sdev,
|
||||
"Failed to register bsg queue, errno=%d\n",
|
||||
|
|
|
@ -86,6 +86,9 @@ struct iscsi_internal {
|
|||
struct transport_container session_cont;
|
||||
};
|
||||
|
||||
static DEFINE_IDR(iscsi_ep_idr);
|
||||
static DEFINE_MUTEX(iscsi_ep_idr_mutex);
|
||||
|
||||
static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
|
||||
|
||||
static struct workqueue_struct *iscsi_conn_cleanup_workq;
|
||||
|
@ -168,6 +171,11 @@ struct device_attribute dev_attr_##_prefix##_##_name = \
|
|||
static void iscsi_endpoint_release(struct device *dev)
|
||||
{
|
||||
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
|
||||
|
||||
mutex_lock(&iscsi_ep_idr_mutex);
|
||||
idr_remove(&iscsi_ep_idr, ep->id);
|
||||
mutex_unlock(&iscsi_ep_idr_mutex);
|
||||
|
||||
kfree(ep);
|
||||
}
|
||||
|
||||
|
@ -180,7 +188,7 @@ static ssize_t
|
|||
show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
|
||||
return sysfs_emit(buf, "%llu\n", (unsigned long long) ep->id);
|
||||
return sysfs_emit(buf, "%d\n", ep->id);
|
||||
}
|
||||
static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
|
||||
|
||||
|
@ -193,48 +201,32 @@ static struct attribute_group iscsi_endpoint_group = {
|
|||
.attrs = iscsi_endpoint_attrs,
|
||||
};
|
||||
|
||||
#define ISCSI_MAX_EPID -1
|
||||
|
||||
static int iscsi_match_epid(struct device *dev, const void *data)
|
||||
{
|
||||
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
|
||||
const uint64_t *epid = data;
|
||||
|
||||
return *epid == ep->id;
|
||||
}
|
||||
|
||||
struct iscsi_endpoint *
|
||||
iscsi_create_endpoint(int dd_size)
|
||||
{
|
||||
struct device *dev;
|
||||
struct iscsi_endpoint *ep;
|
||||
uint64_t id;
|
||||
int err;
|
||||
|
||||
for (id = 1; id < ISCSI_MAX_EPID; id++) {
|
||||
dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
|
||||
iscsi_match_epid);
|
||||
if (!dev)
|
||||
break;
|
||||
else
|
||||
put_device(dev);
|
||||
}
|
||||
if (id == ISCSI_MAX_EPID) {
|
||||
printk(KERN_ERR "Too many connections. Max supported %u\n",
|
||||
ISCSI_MAX_EPID - 1);
|
||||
return NULL;
|
||||
}
|
||||
int err, id;
|
||||
|
||||
ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
|
||||
if (!ep)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&iscsi_ep_idr_mutex);
|
||||
id = idr_alloc(&iscsi_ep_idr, ep, 0, -1, GFP_NOIO);
|
||||
if (id < 0) {
|
||||
mutex_unlock(&iscsi_ep_idr_mutex);
|
||||
printk(KERN_ERR "Could not allocate endpoint ID. Error %d.\n",
|
||||
id);
|
||||
goto free_ep;
|
||||
}
|
||||
mutex_unlock(&iscsi_ep_idr_mutex);
|
||||
|
||||
ep->id = id;
|
||||
ep->dev.class = &iscsi_endpoint_class;
|
||||
dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
|
||||
dev_set_name(&ep->dev, "ep-%d", id);
|
||||
err = device_register(&ep->dev);
|
||||
if (err)
|
||||
goto free_ep;
|
||||
goto free_id;
|
||||
|
||||
err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
|
||||
if (err)
|
||||
|
@ -248,6 +240,10 @@ unregister_dev:
|
|||
device_unregister(&ep->dev);
|
||||
return NULL;
|
||||
|
||||
free_id:
|
||||
mutex_lock(&iscsi_ep_idr_mutex);
|
||||
idr_remove(&iscsi_ep_idr, id);
|
||||
mutex_unlock(&iscsi_ep_idr_mutex);
|
||||
free_ep:
|
||||
kfree(ep);
|
||||
return NULL;
|
||||
|
@ -275,14 +271,17 @@ EXPORT_SYMBOL_GPL(iscsi_put_endpoint);
|
|||
*/
|
||||
struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
|
||||
{
|
||||
struct device *dev;
|
||||
struct iscsi_endpoint *ep;
|
||||
|
||||
dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
|
||||
iscsi_match_epid);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
mutex_lock(&iscsi_ep_idr_mutex);
|
||||
ep = idr_find(&iscsi_ep_idr, handle);
|
||||
if (!ep)
|
||||
goto unlock;
|
||||
|
||||
return iscsi_dev_to_endpoint(dev);
|
||||
get_device(&ep->dev);
|
||||
unlock:
|
||||
mutex_unlock(&iscsi_ep_idr_mutex);
|
||||
return ep;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
|
||||
|
||||
|
@ -2202,10 +2201,10 @@ static void iscsi_stop_conn(struct iscsi_cls_conn *conn, int flag)
|
|||
|
||||
switch (flag) {
|
||||
case STOP_CONN_RECOVER:
|
||||
conn->state = ISCSI_CONN_FAILED;
|
||||
WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
|
||||
break;
|
||||
case STOP_CONN_TERM:
|
||||
conn->state = ISCSI_CONN_DOWN;
|
||||
WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
|
||||
break;
|
||||
default:
|
||||
iscsi_cls_conn_printk(KERN_ERR, conn, "invalid stop flag %d\n",
|
||||
|
@ -2217,6 +2216,49 @@ static void iscsi_stop_conn(struct iscsi_cls_conn *conn, int flag)
|
|||
ISCSI_DBG_TRANS_CONN(conn, "Stopping conn done.\n");
|
||||
}
|
||||
|
||||
static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
|
||||
{
|
||||
struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
|
||||
struct iscsi_endpoint *ep;
|
||||
|
||||
ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
|
||||
WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
|
||||
|
||||
if (!conn->ep || !session->transport->ep_disconnect)
|
||||
return;
|
||||
|
||||
ep = conn->ep;
|
||||
conn->ep = NULL;
|
||||
|
||||
session->transport->unbind_conn(conn, is_active);
|
||||
session->transport->ep_disconnect(ep);
|
||||
ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
|
||||
}
|
||||
|
||||
static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn,
|
||||
struct iscsi_endpoint *ep,
|
||||
bool is_active)
|
||||
{
|
||||
/* Check if this was a conn error and the kernel took ownership */
|
||||
spin_lock_irq(&conn->lock);
|
||||
if (!test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
|
||||
spin_unlock_irq(&conn->lock);
|
||||
iscsi_ep_disconnect(conn, is_active);
|
||||
} else {
|
||||
spin_unlock_irq(&conn->lock);
|
||||
ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
|
||||
mutex_unlock(&conn->ep_mutex);
|
||||
|
||||
flush_work(&conn->cleanup_work);
|
||||
/*
|
||||
* Userspace is now done with the EP so we can release the ref
|
||||
* iscsi_cleanup_conn_work_fn took.
|
||||
*/
|
||||
iscsi_put_endpoint(ep);
|
||||
mutex_lock(&conn->ep_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static int iscsi_if_stop_conn(struct iscsi_transport *transport,
|
||||
struct iscsi_uevent *ev)
|
||||
{
|
||||
|
@ -2237,12 +2279,25 @@ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
|
|||
cancel_work_sync(&conn->cleanup_work);
|
||||
iscsi_stop_conn(conn, flag);
|
||||
} else {
|
||||
/*
|
||||
* For offload, when iscsid is restarted it won't know about
|
||||
* existing endpoints so it can't do a ep_disconnect. We clean
|
||||
* it up here for userspace.
|
||||
*/
|
||||
mutex_lock(&conn->ep_mutex);
|
||||
if (conn->ep)
|
||||
iscsi_if_disconnect_bound_ep(conn, conn->ep, true);
|
||||
mutex_unlock(&conn->ep_mutex);
|
||||
|
||||
/*
|
||||
* Figure out if it was the kernel or userspace initiating this.
|
||||
*/
|
||||
spin_lock_irq(&conn->lock);
|
||||
if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
|
||||
spin_unlock_irq(&conn->lock);
|
||||
iscsi_stop_conn(conn, flag);
|
||||
} else {
|
||||
spin_unlock_irq(&conn->lock);
|
||||
ISCSI_DBG_TRANS_CONN(conn,
|
||||
"flush kernel conn cleanup.\n");
|
||||
flush_work(&conn->cleanup_work);
|
||||
|
@ -2251,31 +2306,14 @@ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
|
|||
* Only clear for recovery to avoid extra cleanup runs during
|
||||
* termination.
|
||||
*/
|
||||
spin_lock_irq(&conn->lock);
|
||||
clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
|
||||
spin_unlock_irq(&conn->lock);
|
||||
}
|
||||
ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop done.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
|
||||
{
|
||||
struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
|
||||
struct iscsi_endpoint *ep;
|
||||
|
||||
ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
|
||||
conn->state = ISCSI_CONN_FAILED;
|
||||
|
||||
if (!conn->ep || !session->transport->ep_disconnect)
|
||||
return;
|
||||
|
||||
ep = conn->ep;
|
||||
conn->ep = NULL;
|
||||
|
||||
session->transport->unbind_conn(conn, is_active);
|
||||
session->transport->ep_disconnect(ep);
|
||||
ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
|
||||
}
|
||||
|
||||
static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct iscsi_cls_conn *conn = container_of(work, struct iscsi_cls_conn,
|
||||
|
@ -2284,18 +2322,11 @@ static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
|
|||
|
||||
mutex_lock(&conn->ep_mutex);
|
||||
/*
|
||||
* If we are not at least bound there is nothing for us to do. Userspace
|
||||
* will do a ep_disconnect call if offload is used, but will not be
|
||||
* doing a stop since there is nothing to clean up, so we have to clear
|
||||
* the cleanup bit here.
|
||||
* Get a ref to the ep, so we don't release its ID until after
|
||||
* userspace is done referencing it in iscsi_if_disconnect_bound_ep.
|
||||
*/
|
||||
if (conn->state != ISCSI_CONN_BOUND && conn->state != ISCSI_CONN_UP) {
|
||||
ISCSI_DBG_TRANS_CONN(conn, "Got error while conn is already failed. Ignoring.\n");
|
||||
clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
|
||||
mutex_unlock(&conn->ep_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn->ep)
|
||||
get_device(&conn->ep->dev);
|
||||
iscsi_ep_disconnect(conn, false);
|
||||
|
||||
if (system_state != SYSTEM_RUNNING) {
|
||||
|
@ -2340,11 +2371,12 @@ iscsi_alloc_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
|
|||
conn->dd_data = &conn[1];
|
||||
|
||||
mutex_init(&conn->ep_mutex);
|
||||
spin_lock_init(&conn->lock);
|
||||
INIT_LIST_HEAD(&conn->conn_list);
|
||||
INIT_WORK(&conn->cleanup_work, iscsi_cleanup_conn_work_fn);
|
||||
conn->transport = transport;
|
||||
conn->cid = cid;
|
||||
conn->state = ISCSI_CONN_DOWN;
|
||||
WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
|
||||
|
||||
/* this is released in the dev's release function */
|
||||
if (!get_device(&session->dev))
|
||||
|
@ -2542,9 +2574,32 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
|
|||
struct iscsi_uevent *ev;
|
||||
struct iscsi_internal *priv;
|
||||
int len = nlmsg_total_size(sizeof(*ev));
|
||||
unsigned long flags;
|
||||
int state;
|
||||
|
||||
if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags))
|
||||
queue_work(iscsi_conn_cleanup_workq, &conn->cleanup_work);
|
||||
spin_lock_irqsave(&conn->lock, flags);
|
||||
/*
|
||||
* Userspace will only do a stop call if we are at least bound. And, we
|
||||
* only need to do the in kernel cleanup if in the UP state so cmds can
|
||||
* be released to upper layers. If in other states just wait for
|
||||
* userspace to avoid races that can leave the cleanup_work queued.
|
||||
*/
|
||||
state = READ_ONCE(conn->state);
|
||||
switch (state) {
|
||||
case ISCSI_CONN_BOUND:
|
||||
case ISCSI_CONN_UP:
|
||||
if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP,
|
||||
&conn->flags)) {
|
||||
queue_work(iscsi_conn_cleanup_workq,
|
||||
&conn->cleanup_work);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ISCSI_DBG_TRANS_CONN(conn, "Got conn error in state %d\n",
|
||||
state);
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&conn->lock, flags);
|
||||
|
||||
priv = iscsi_if_transport_lookup(conn->transport);
|
||||
if (!priv)
|
||||
|
@ -2894,7 +2949,7 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
|
|||
char *data = (char*)ev + sizeof(*ev);
|
||||
struct iscsi_cls_conn *conn;
|
||||
struct iscsi_cls_session *session;
|
||||
int err = 0, value = 0;
|
||||
int err = 0, value = 0, state;
|
||||
|
||||
if (ev->u.set_param.len > PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
@ -2911,8 +2966,8 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
|
|||
session->recovery_tmo = value;
|
||||
break;
|
||||
default:
|
||||
if ((conn->state == ISCSI_CONN_BOUND) ||
|
||||
(conn->state == ISCSI_CONN_UP)) {
|
||||
state = READ_ONCE(conn->state);
|
||||
if (state == ISCSI_CONN_BOUND || state == ISCSI_CONN_UP) {
|
||||
err = transport->set_param(conn, ev->u.set_param.param,
|
||||
data, ev->u.set_param.len);
|
||||
} else {
|
||||
|
@ -2984,16 +3039,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
|
|||
}
|
||||
|
||||
mutex_lock(&conn->ep_mutex);
|
||||
/* Check if this was a conn error and the kernel took ownership */
|
||||
if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
|
||||
ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
|
||||
mutex_unlock(&conn->ep_mutex);
|
||||
|
||||
flush_work(&conn->cleanup_work);
|
||||
goto put_ep;
|
||||
}
|
||||
|
||||
iscsi_ep_disconnect(conn, false);
|
||||
iscsi_if_disconnect_bound_ep(conn, ep, false);
|
||||
mutex_unlock(&conn->ep_mutex);
|
||||
put_ep:
|
||||
iscsi_put_endpoint(ep);
|
||||
|
@ -3696,24 +3742,17 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
|
|||
return -EINVAL;
|
||||
|
||||
mutex_lock(&conn->ep_mutex);
|
||||
spin_lock_irq(&conn->lock);
|
||||
if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
|
||||
spin_unlock_irq(&conn->lock);
|
||||
mutex_unlock(&conn->ep_mutex);
|
||||
ev->r.retcode = -ENOTCONN;
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_irq(&conn->lock);
|
||||
|
||||
switch (nlh->nlmsg_type) {
|
||||
case ISCSI_UEVENT_BIND_CONN:
|
||||
if (conn->ep) {
|
||||
/*
|
||||
* For offload boot support where iscsid is restarted
|
||||
* during the pivot root stage, the ep will be intact
|
||||
* here when the new iscsid instance starts up and
|
||||
* reconnects.
|
||||
*/
|
||||
iscsi_ep_disconnect(conn, true);
|
||||
}
|
||||
|
||||
session = iscsi_session_lookup(ev->u.b_conn.sid);
|
||||
if (!session) {
|
||||
err = -EINVAL;
|
||||
|
@ -3724,7 +3763,7 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
|
|||
ev->u.b_conn.transport_eph,
|
||||
ev->u.b_conn.is_leading);
|
||||
if (!ev->r.retcode)
|
||||
conn->state = ISCSI_CONN_BOUND;
|
||||
WRITE_ONCE(conn->state, ISCSI_CONN_BOUND);
|
||||
|
||||
if (ev->r.retcode || !transport->ep_connect)
|
||||
break;
|
||||
|
@ -3743,7 +3782,8 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
|
|||
case ISCSI_UEVENT_START_CONN:
|
||||
ev->r.retcode = transport->start_conn(conn);
|
||||
if (!ev->r.retcode)
|
||||
conn->state = ISCSI_CONN_UP;
|
||||
WRITE_ONCE(conn->state, ISCSI_CONN_UP);
|
||||
|
||||
break;
|
||||
case ISCSI_UEVENT_SEND_PDU:
|
||||
pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
|
||||
|
@ -4050,10 +4090,11 @@ static ssize_t show_conn_state(struct device *dev,
|
|||
{
|
||||
struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);
|
||||
const char *state = "unknown";
|
||||
int conn_state = READ_ONCE(conn->state);
|
||||
|
||||
if (conn->state >= 0 &&
|
||||
conn->state < ARRAY_SIZE(connection_state_names))
|
||||
state = connection_state_names[conn->state];
|
||||
if (conn_state >= 0 &&
|
||||
conn_state < ARRAY_SIZE(connection_state_names))
|
||||
state = connection_state_names[conn_state];
|
||||
|
||||
return sysfs_emit(buf, "%s\n", state);
|
||||
}
|
||||
|
|
|
@ -3216,6 +3216,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
|
|||
sd_read_block_limits(sdkp);
|
||||
sd_read_block_characteristics(sdkp);
|
||||
sd_zbc_read_zones(sdkp, buffer);
|
||||
sd_read_cpr(sdkp);
|
||||
}
|
||||
|
||||
sd_print_capacity(sdkp, old_capacity);
|
||||
|
@ -3225,7 +3226,6 @@ static int sd_revalidate_disk(struct gendisk *disk)
|
|||
sd_read_app_tag_own(sdkp, buffer);
|
||||
sd_read_write_same(sdkp, buffer);
|
||||
sd_read_security(sdkp, buffer);
|
||||
sd_read_cpr(sdkp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3475,6 +3475,7 @@ static int sd_probe(struct device *dev)
|
|||
error = device_add_disk(dev, gd, NULL);
|
||||
if (error) {
|
||||
put_device(&sdkp->disk_dev);
|
||||
blk_cleanup_disk(gd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
@ -535,7 +535,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
|
|||
|
||||
scsi_autopm_get_device(sdev);
|
||||
|
||||
if (ret != CDROMCLOSETRAY && ret != CDROMEJECT) {
|
||||
if (cmd != CDROMCLOSETRAY && cmd != CDROMEJECT) {
|
||||
ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
|
||||
if (ret != -ENOSYS)
|
||||
goto put;
|
||||
|
|
|
@ -957,18 +957,6 @@ static const struct reset_control_ops ufs_qcom_reset_ops = {
|
|||
.deassert = ufs_qcom_reset_deassert,
|
||||
};
|
||||
|
||||
#define ANDROID_BOOT_DEV_MAX 30
|
||||
static char android_boot_dev[ANDROID_BOOT_DEV_MAX];
|
||||
|
||||
#ifndef MODULE
|
||||
static int __init get_android_boot_dev(char *str)
|
||||
{
|
||||
strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX);
|
||||
return 1;
|
||||
}
|
||||
__setup("androidboot.bootdevice=", get_android_boot_dev);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ufs_qcom_init - bind phy with controller
|
||||
* @hba: host controller instance
|
||||
|
@ -988,9 +976,6 @@ static int ufs_qcom_init(struct ufs_hba *hba)
|
|||
struct resource *res;
|
||||
struct ufs_clk_info *clki;
|
||||
|
||||
if (strlen(android_boot_dev) && strcmp(android_boot_dev, dev_name(dev)))
|
||||
return -ENODEV;
|
||||
|
||||
host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
|
||||
if (!host) {
|
||||
err = -ENOMEM;
|
||||
|
|
|
@ -428,6 +428,12 @@ static int ufs_intel_adl_init(struct ufs_hba *hba)
|
|||
return ufs_intel_common_init(hba);
|
||||
}
|
||||
|
||||
static int ufs_intel_mtl_init(struct ufs_hba *hba)
|
||||
{
|
||||
hba->caps |= UFSHCD_CAP_CRYPTO | UFSHCD_CAP_WB_EN;
|
||||
return ufs_intel_common_init(hba);
|
||||
}
|
||||
|
||||
static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = {
|
||||
.name = "intel-pci",
|
||||
.init = ufs_intel_common_init,
|
||||
|
@ -465,6 +471,16 @@ static struct ufs_hba_variant_ops ufs_intel_adl_hba_vops = {
|
|||
.device_reset = ufs_intel_device_reset,
|
||||
};
|
||||
|
||||
static struct ufs_hba_variant_ops ufs_intel_mtl_hba_vops = {
|
||||
.name = "intel-pci",
|
||||
.init = ufs_intel_mtl_init,
|
||||
.exit = ufs_intel_common_exit,
|
||||
.hce_enable_notify = ufs_intel_hce_enable_notify,
|
||||
.link_startup_notify = ufs_intel_link_startup_notify,
|
||||
.resume = ufs_intel_resume,
|
||||
.device_reset = ufs_intel_device_reset,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ufshcd_pci_restore(struct device *dev)
|
||||
{
|
||||
|
@ -579,6 +595,7 @@ static const struct pci_device_id ufshcd_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x98FA), (kernel_ulong_t)&ufs_intel_lkf_hba_vops },
|
||||
{ PCI_VDEVICE(INTEL, 0x51FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops },
|
||||
{ PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops },
|
||||
{ PCI_VDEVICE(INTEL, 0x7E47), (kernel_ulong_t)&ufs_intel_mtl_hba_vops },
|
||||
{ } /* terminate list */
|
||||
};
|
||||
|
||||
|
|
|
@ -820,8 +820,6 @@ struct ufs_hba {
|
|||
enum ufs_pm_level rpm_lvl;
|
||||
/* Desired UFS power management level during system PM */
|
||||
enum ufs_pm_level spm_lvl;
|
||||
struct device_attribute rpm_lvl_attr;
|
||||
struct device_attribute spm_lvl_attr;
|
||||
int pm_op_in_progress;
|
||||
|
||||
/* Auto-Hibernate Idle Timer register value */
|
||||
|
|
|
@ -867,12 +867,6 @@ static struct ufshpb_region *ufshpb_victim_lru_info(struct ufshpb_lu *hpb)
|
|||
struct ufshpb_region *rgn, *victim_rgn = NULL;
|
||||
|
||||
list_for_each_entry(rgn, &lru_info->lh_lru_rgn, list_lru_rgn) {
|
||||
if (!rgn) {
|
||||
dev_err(&hpb->sdev_ufs_lu->sdev_dev,
|
||||
"%s: no region allocated\n",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
if (ufshpb_check_srgns_issue_state(hpb, rgn))
|
||||
continue;
|
||||
|
||||
|
@ -888,6 +882,11 @@ static struct ufshpb_region *ufshpb_victim_lru_info(struct ufshpb_lu *hpb)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!victim_rgn)
|
||||
dev_err(&hpb->sdev_ufs_lu->sdev_dev,
|
||||
"%s: no region allocated\n",
|
||||
__func__);
|
||||
|
||||
return victim_rgn;
|
||||
}
|
||||
|
||||
|
|
|
@ -988,7 +988,7 @@ static struct virtio_driver virtio_scsi_driver = {
|
|||
.remove = virtscsi_remove,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
static int __init virtio_scsi_init(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
|
||||
|
@ -1020,14 +1020,14 @@ error:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
static void __exit virtio_scsi_fini(void)
|
||||
{
|
||||
unregister_virtio_driver(&virtio_scsi_driver);
|
||||
mempool_destroy(virtscsi_cmd_pool);
|
||||
kmem_cache_destroy(virtscsi_cmd_cache);
|
||||
}
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
module_init(virtio_scsi_init);
|
||||
module_exit(virtio_scsi_fini);
|
||||
|
||||
MODULE_DEVICE_TABLE(virtio, id_table);
|
||||
MODULE_DESCRIPTION("Virtio SCSI HBA driver");
|
||||
|
|
|
@ -159,6 +159,8 @@ static void zorro7xx_remove_one(struct zorro_dev *z)
|
|||
scsi_remove_host(host);
|
||||
|
||||
NCR_700_release(host);
|
||||
if (host->base > 0x01000000)
|
||||
iounmap(hostdata->base);
|
||||
kfree(hostdata);
|
||||
free_irq(host->irq, host);
|
||||
zorro_release_device(z);
|
||||
|
|
|
@ -1821,6 +1821,7 @@ static struct page *tcmu_try_get_data_page(struct tcmu_dev *udev, uint32_t dpi)
|
|||
mutex_lock(&udev->cmdr_lock);
|
||||
page = xa_load(&udev->data_pages, dpi);
|
||||
if (likely(page)) {
|
||||
get_page(page);
|
||||
mutex_unlock(&udev->cmdr_lock);
|
||||
return page;
|
||||
}
|
||||
|
@ -1877,6 +1878,7 @@ static vm_fault_t tcmu_vma_fault(struct vm_fault *vmf)
|
|||
/* For the vmalloc()ed cmd area pages */
|
||||
addr = (void *)(unsigned long)info->mem[mi].addr + offset;
|
||||
page = vmalloc_to_page(addr);
|
||||
get_page(page);
|
||||
} else {
|
||||
uint32_t dpi;
|
||||
|
||||
|
@ -1887,7 +1889,6 @@ static vm_fault_t tcmu_vma_fault(struct vm_fault *vmf)
|
|||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
get_page(page);
|
||||
vmf->page = page;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -53,8 +53,10 @@ enum {
|
|||
|
||||
#define ISID_SIZE 6
|
||||
|
||||
/* Connection suspend "bit" */
|
||||
#define ISCSI_SUSPEND_BIT 1
|
||||
/* Connection flags */
|
||||
#define ISCSI_CONN_FLAG_SUSPEND_TX BIT(0)
|
||||
#define ISCSI_CONN_FLAG_SUSPEND_RX BIT(1)
|
||||
#define ISCSI_CONN_FLAG_BOUND BIT(2)
|
||||
|
||||
#define ISCSI_ITT_MASK 0x1fff
|
||||
#define ISCSI_TOTAL_CMDS_MAX 4096
|
||||
|
@ -211,8 +213,7 @@ struct iscsi_conn {
|
|||
struct list_head cmdqueue; /* data-path cmd queue */
|
||||
struct list_head requeue; /* tasks needing another run */
|
||||
struct work_struct xmitwork; /* per-conn. xmit workqueue */
|
||||
unsigned long suspend_tx; /* suspend Tx */
|
||||
unsigned long suspend_rx; /* suspend Rx */
|
||||
unsigned long flags; /* ISCSI_CONN_FLAGs */
|
||||
|
||||
/* negotiated params */
|
||||
unsigned max_recv_dlength; /* initiator_max_recv_dsl*/
|
||||
|
|
|
@ -211,6 +211,8 @@ struct iscsi_cls_conn {
|
|||
struct mutex ep_mutex;
|
||||
struct iscsi_endpoint *ep;
|
||||
|
||||
/* Used when accessing flags and queueing work. */
|
||||
spinlock_t lock;
|
||||
unsigned long flags;
|
||||
struct work_struct cleanup_work;
|
||||
|
||||
|
@ -295,7 +297,7 @@ extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
|
|||
struct iscsi_endpoint {
|
||||
void *dd_data; /* LLD private data */
|
||||
struct device dev;
|
||||
uint64_t id;
|
||||
int id;
|
||||
struct iscsi_cls_conn *conn;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче