scsi: ibmvscsis: Rearrange functions for future patches
This patch reorders functions in a manner necessary for a follow-on patch. It also makes some minor styling changes (mostly removing extra spaces) and fixes some typos. There are no code changes in this patch, with one exception: due to the reordering of the functions, I needed to explicitly declare a function at the top of the file. However, this will be removed in the next patch, since the code requiring the predeclaration will be removed. Signed-off-by: Michael Cyr <mikecyr@us.ibm.com> Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com> Tested-by: Steven Royer <seroyer@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
c1f7cf0aee
commit
79fac9c9b7
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -61,6 +61,8 @@ static long ibmvscsis_parse_command(struct scsi_info *vscsi,
|
|||||||
|
|
||||||
static void ibmvscsis_adapter_idle(struct scsi_info *vscsi);
|
static void ibmvscsis_adapter_idle(struct scsi_info *vscsi);
|
||||||
|
|
||||||
|
static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state);
|
||||||
|
|
||||||
static void ibmvscsis_determine_resid(struct se_cmd *se_cmd,
|
static void ibmvscsis_determine_resid(struct se_cmd *se_cmd,
|
||||||
struct srp_rsp *rsp)
|
struct srp_rsp *rsp)
|
||||||
{
|
{
|
||||||
@ -81,7 +83,7 @@ static void ibmvscsis_determine_resid(struct se_cmd *se_cmd,
|
|||||||
}
|
}
|
||||||
} else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
|
} else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
|
||||||
if (se_cmd->data_direction == DMA_TO_DEVICE) {
|
if (se_cmd->data_direction == DMA_TO_DEVICE) {
|
||||||
/* residual data from an overflow write */
|
/* residual data from an overflow write */
|
||||||
rsp->flags = SRP_RSP_FLAG_DOOVER;
|
rsp->flags = SRP_RSP_FLAG_DOOVER;
|
||||||
rsp->data_out_res_cnt = cpu_to_be32(residual_count);
|
rsp->data_out_res_cnt = cpu_to_be32(residual_count);
|
||||||
} else if (se_cmd->data_direction == DMA_FROM_DEVICE) {
|
} else if (se_cmd->data_direction == DMA_FROM_DEVICE) {
|
||||||
@ -101,7 +103,7 @@ static void ibmvscsis_determine_resid(struct se_cmd *se_cmd,
|
|||||||
* and the function returns TRUE.
|
* and the function returns TRUE.
|
||||||
*
|
*
|
||||||
* EXECUTION ENVIRONMENT:
|
* EXECUTION ENVIRONMENT:
|
||||||
* Interrupt or Process environment
|
* Interrupt or Process environment
|
||||||
*/
|
*/
|
||||||
static bool connection_broken(struct scsi_info *vscsi)
|
static bool connection_broken(struct scsi_info *vscsi)
|
||||||
{
|
{
|
||||||
@ -324,7 +326,7 @@ static struct viosrp_crq *ibmvscsis_cmd_q_dequeue(uint mask,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ibmvscsis_send_init_message() - send initialize message to the client
|
* ibmvscsis_send_init_message() - send initialize message to the client
|
||||||
* @vscsi: Pointer to our adapter structure
|
* @vscsi: Pointer to our adapter structure
|
||||||
* @format: Which Init Message format to send
|
* @format: Which Init Message format to send
|
||||||
*
|
*
|
||||||
@ -382,13 +384,13 @@ static long ibmvscsis_check_init_msg(struct scsi_info *vscsi, uint *format)
|
|||||||
vscsi->cmd_q.base_addr);
|
vscsi->cmd_q.base_addr);
|
||||||
if (crq) {
|
if (crq) {
|
||||||
*format = (uint)(crq->format);
|
*format = (uint)(crq->format);
|
||||||
rc = ERROR;
|
rc = ERROR;
|
||||||
crq->valid = INVALIDATE_CMD_RESP_EL;
|
crq->valid = INVALIDATE_CMD_RESP_EL;
|
||||||
dma_rmb();
|
dma_rmb();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*format = (uint)(crq->format);
|
*format = (uint)(crq->format);
|
||||||
rc = ERROR;
|
rc = ERROR;
|
||||||
crq->valid = INVALIDATE_CMD_RESP_EL;
|
crq->valid = INVALIDATE_CMD_RESP_EL;
|
||||||
dma_rmb();
|
dma_rmb();
|
||||||
}
|
}
|
||||||
@ -396,166 +398,6 @@ static long ibmvscsis_check_init_msg(struct scsi_info *vscsi, uint *format)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ibmvscsis_establish_new_q() - Establish new CRQ queue
|
|
||||||
* @vscsi: Pointer to our adapter structure
|
|
||||||
* @new_state: New state being established after resetting the queue
|
|
||||||
*
|
|
||||||
* Must be called with interrupt lock held.
|
|
||||||
*/
|
|
||||||
static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state)
|
|
||||||
{
|
|
||||||
long rc = ADAPT_SUCCESS;
|
|
||||||
uint format;
|
|
||||||
|
|
||||||
vscsi->flags &= PRESERVE_FLAG_FIELDS;
|
|
||||||
vscsi->rsp_q_timer.timer_pops = 0;
|
|
||||||
vscsi->debit = 0;
|
|
||||||
vscsi->credit = 0;
|
|
||||||
|
|
||||||
rc = vio_enable_interrupts(vscsi->dma_dev);
|
|
||||||
if (rc) {
|
|
||||||
pr_warn("reset_queue: failed to enable interrupts, rc %ld\n",
|
|
||||||
rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ibmvscsis_check_init_msg(vscsi, &format);
|
|
||||||
if (rc) {
|
|
||||||
dev_err(&vscsi->dev, "reset_queue: check_init_msg failed, rc %ld\n",
|
|
||||||
rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format == UNUSED_FORMAT && new_state == WAIT_CONNECTION) {
|
|
||||||
rc = ibmvscsis_send_init_message(vscsi, INIT_MSG);
|
|
||||||
switch (rc) {
|
|
||||||
case H_SUCCESS:
|
|
||||||
case H_DROPPED:
|
|
||||||
case H_CLOSED:
|
|
||||||
rc = ADAPT_SUCCESS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case H_PARAMETER:
|
|
||||||
case H_HARDWARE:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
vscsi->state = UNDEFINED;
|
|
||||||
rc = H_HARDWARE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ibmvscsis_reset_queue() - Reset CRQ Queue
|
|
||||||
* @vscsi: Pointer to our adapter structure
|
|
||||||
* @new_state: New state to establish after resetting the queue
|
|
||||||
*
|
|
||||||
* This function calls h_free_q and then calls h_reg_q and does all
|
|
||||||
* of the bookkeeping to get us back to where we can communicate.
|
|
||||||
*
|
|
||||||
* Actually, we don't always call h_free_crq. A problem was discovered
|
|
||||||
* where one partition would close and reopen his queue, which would
|
|
||||||
* cause his partner to get a transport event, which would cause him to
|
|
||||||
* close and reopen his queue, which would cause the original partition
|
|
||||||
* to get a transport event, etc., etc. To prevent this, we don't
|
|
||||||
* actually close our queue if the client initiated the reset, (i.e.
|
|
||||||
* either we got a transport event or we have detected that the client's
|
|
||||||
* queue is gone)
|
|
||||||
*
|
|
||||||
* EXECUTION ENVIRONMENT:
|
|
||||||
* Process environment, called with interrupt lock held
|
|
||||||
*/
|
|
||||||
static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state)
|
|
||||||
{
|
|
||||||
int bytes;
|
|
||||||
long rc = ADAPT_SUCCESS;
|
|
||||||
|
|
||||||
pr_debug("reset_queue: flags 0x%x\n", vscsi->flags);
|
|
||||||
|
|
||||||
/* don't reset, the client did it for us */
|
|
||||||
if (vscsi->flags & (CLIENT_FAILED | TRANS_EVENT)) {
|
|
||||||
vscsi->flags &= PRESERVE_FLAG_FIELDS;
|
|
||||||
vscsi->rsp_q_timer.timer_pops = 0;
|
|
||||||
vscsi->debit = 0;
|
|
||||||
vscsi->credit = 0;
|
|
||||||
vscsi->state = new_state;
|
|
||||||
vio_enable_interrupts(vscsi->dma_dev);
|
|
||||||
} else {
|
|
||||||
rc = ibmvscsis_free_command_q(vscsi);
|
|
||||||
if (rc == ADAPT_SUCCESS) {
|
|
||||||
vscsi->state = new_state;
|
|
||||||
|
|
||||||
bytes = vscsi->cmd_q.size * PAGE_SIZE;
|
|
||||||
rc = h_reg_crq(vscsi->dds.unit_id,
|
|
||||||
vscsi->cmd_q.crq_token, bytes);
|
|
||||||
if (rc == H_CLOSED || rc == H_SUCCESS) {
|
|
||||||
rc = ibmvscsis_establish_new_q(vscsi,
|
|
||||||
new_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc != ADAPT_SUCCESS) {
|
|
||||||
pr_debug("reset_queue: reg_crq rc %ld\n", rc);
|
|
||||||
|
|
||||||
vscsi->state = ERR_DISCONNECTED;
|
|
||||||
vscsi->flags |= RESPONSE_Q_DOWN;
|
|
||||||
ibmvscsis_free_command_q(vscsi);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vscsi->state = ERR_DISCONNECTED;
|
|
||||||
vscsi->flags |= RESPONSE_Q_DOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ibmvscsis_free_cmd_resources() - Free command resources
|
|
||||||
* @vscsi: Pointer to our adapter structure
|
|
||||||
* @cmd: Command which is not longer in use
|
|
||||||
*
|
|
||||||
* Must be called with interrupt lock held.
|
|
||||||
*/
|
|
||||||
static void ibmvscsis_free_cmd_resources(struct scsi_info *vscsi,
|
|
||||||
struct ibmvscsis_cmd *cmd)
|
|
||||||
{
|
|
||||||
struct iu_entry *iue = cmd->iue;
|
|
||||||
|
|
||||||
switch (cmd->type) {
|
|
||||||
case TASK_MANAGEMENT:
|
|
||||||
case SCSI_CDB:
|
|
||||||
/*
|
|
||||||
* When the queue goes down this value is cleared, so it
|
|
||||||
* cannot be cleared in this general purpose function.
|
|
||||||
*/
|
|
||||||
if (vscsi->debit)
|
|
||||||
vscsi->debit -= 1;
|
|
||||||
break;
|
|
||||||
case ADAPTER_MAD:
|
|
||||||
vscsi->flags &= ~PROCESSING_MAD;
|
|
||||||
break;
|
|
||||||
case UNSET_TYPE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_err(&vscsi->dev, "free_cmd_resources unknown type %d\n",
|
|
||||||
cmd->type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd->iue = NULL;
|
|
||||||
list_add_tail(&cmd->list, &vscsi->free_cmd);
|
|
||||||
srp_iu_put(iue);
|
|
||||||
|
|
||||||
if (list_empty(&vscsi->active_q) && list_empty(&vscsi->schedule_q) &&
|
|
||||||
list_empty(&vscsi->waiting_rsp) && (vscsi->flags & WAIT_FOR_IDLE)) {
|
|
||||||
vscsi->flags &= ~WAIT_FOR_IDLE;
|
|
||||||
complete(&vscsi->wait_idle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ibmvscsis_disconnect() - Helper function to disconnect
|
* ibmvscsis_disconnect() - Helper function to disconnect
|
||||||
* @work: Pointer to work_struct, gives access to our adapter structure
|
* @work: Pointer to work_struct, gives access to our adapter structure
|
||||||
@ -589,7 +431,7 @@ static void ibmvscsis_disconnect(struct work_struct *work)
|
|||||||
* should transitition to the new state
|
* should transitition to the new state
|
||||||
*/
|
*/
|
||||||
switch (vscsi->state) {
|
switch (vscsi->state) {
|
||||||
/* Should never be called while in this state. */
|
/* Should never be called while in this state. */
|
||||||
case NO_QUEUE:
|
case NO_QUEUE:
|
||||||
/*
|
/*
|
||||||
* Can never transition from this state;
|
* Can never transition from this state;
|
||||||
@ -805,6 +647,316 @@ static void ibmvscsis_post_disconnect(struct scsi_info *vscsi, uint new_state,
|
|||||||
vscsi->flags, vscsi->new_state);
|
vscsi->flags, vscsi->new_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ibmvscsis_handle_init_compl_msg() - Respond to an Init Complete Message
|
||||||
|
* @vscsi: Pointer to our adapter structure
|
||||||
|
*
|
||||||
|
* Must be called with interrupt lock held.
|
||||||
|
*/
|
||||||
|
static long ibmvscsis_handle_init_compl_msg(struct scsi_info *vscsi)
|
||||||
|
{
|
||||||
|
long rc = ADAPT_SUCCESS;
|
||||||
|
|
||||||
|
switch (vscsi->state) {
|
||||||
|
case NO_QUEUE:
|
||||||
|
case ERR_DISCONNECT:
|
||||||
|
case ERR_DISCONNECT_RECONNECT:
|
||||||
|
case ERR_DISCONNECTED:
|
||||||
|
case UNCONFIGURING:
|
||||||
|
case UNDEFINED:
|
||||||
|
rc = ERROR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WAIT_CONNECTION:
|
||||||
|
vscsi->state = CONNECTED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WAIT_IDLE:
|
||||||
|
case SRP_PROCESSING:
|
||||||
|
case CONNECTED:
|
||||||
|
case WAIT_ENABLED:
|
||||||
|
case PART_UP_WAIT_ENAB:
|
||||||
|
default:
|
||||||
|
rc = ERROR;
|
||||||
|
dev_err(&vscsi->dev, "init_msg: invalid state %d to get init compl msg\n",
|
||||||
|
vscsi->state);
|
||||||
|
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ibmvscsis_handle_init_msg() - Respond to an Init Message
|
||||||
|
* @vscsi: Pointer to our adapter structure
|
||||||
|
*
|
||||||
|
* Must be called with interrupt lock held.
|
||||||
|
*/
|
||||||
|
static long ibmvscsis_handle_init_msg(struct scsi_info *vscsi)
|
||||||
|
{
|
||||||
|
long rc = ADAPT_SUCCESS;
|
||||||
|
|
||||||
|
switch (vscsi->state) {
|
||||||
|
case WAIT_ENABLED:
|
||||||
|
vscsi->state = PART_UP_WAIT_ENAB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WAIT_CONNECTION:
|
||||||
|
rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG);
|
||||||
|
switch (rc) {
|
||||||
|
case H_SUCCESS:
|
||||||
|
vscsi->state = CONNECTED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H_PARAMETER:
|
||||||
|
dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
|
||||||
|
rc);
|
||||||
|
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H_DROPPED:
|
||||||
|
dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
|
||||||
|
rc);
|
||||||
|
rc = ERROR;
|
||||||
|
ibmvscsis_post_disconnect(vscsi,
|
||||||
|
ERR_DISCONNECT_RECONNECT, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H_CLOSED:
|
||||||
|
pr_warn("init_msg: failed to send, rc %ld\n", rc);
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNDEFINED:
|
||||||
|
rc = ERROR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNCONFIGURING:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PART_UP_WAIT_ENAB:
|
||||||
|
case CONNECTED:
|
||||||
|
case SRP_PROCESSING:
|
||||||
|
case WAIT_IDLE:
|
||||||
|
case NO_QUEUE:
|
||||||
|
case ERR_DISCONNECT:
|
||||||
|
case ERR_DISCONNECT_RECONNECT:
|
||||||
|
case ERR_DISCONNECTED:
|
||||||
|
default:
|
||||||
|
rc = ERROR;
|
||||||
|
dev_err(&vscsi->dev, "init_msg: invalid state %d to get init msg\n",
|
||||||
|
vscsi->state);
|
||||||
|
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ibmvscsis_init_msg() - Respond to an init message
|
||||||
|
* @vscsi: Pointer to our adapter structure
|
||||||
|
* @crq: Pointer to CRQ element containing the Init Message
|
||||||
|
*
|
||||||
|
* EXECUTION ENVIRONMENT:
|
||||||
|
* Interrupt, interrupt lock held
|
||||||
|
*/
|
||||||
|
static long ibmvscsis_init_msg(struct scsi_info *vscsi, struct viosrp_crq *crq)
|
||||||
|
{
|
||||||
|
long rc = ADAPT_SUCCESS;
|
||||||
|
|
||||||
|
pr_debug("init_msg: state 0x%hx\n", vscsi->state);
|
||||||
|
|
||||||
|
rc = h_vioctl(vscsi->dds.unit_id, H_GET_PARTNER_INFO,
|
||||||
|
(u64)vscsi->map_ioba | ((u64)PAGE_SIZE << 32), 0, 0, 0,
|
||||||
|
0);
|
||||||
|
if (rc == H_SUCCESS) {
|
||||||
|
vscsi->client_data.partition_number =
|
||||||
|
be64_to_cpu(*(u64 *)vscsi->map_buf);
|
||||||
|
pr_debug("init_msg, part num %d\n",
|
||||||
|
vscsi->client_data.partition_number);
|
||||||
|
} else {
|
||||||
|
pr_debug("init_msg h_vioctl rc %ld\n", rc);
|
||||||
|
rc = ADAPT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crq->format == INIT_MSG) {
|
||||||
|
rc = ibmvscsis_handle_init_msg(vscsi);
|
||||||
|
} else if (crq->format == INIT_COMPLETE_MSG) {
|
||||||
|
rc = ibmvscsis_handle_init_compl_msg(vscsi);
|
||||||
|
} else {
|
||||||
|
rc = ERROR;
|
||||||
|
dev_err(&vscsi->dev, "init_msg: invalid format %d\n",
|
||||||
|
(uint)crq->format);
|
||||||
|
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ibmvscsis_establish_new_q() - Establish new CRQ queue
|
||||||
|
* @vscsi: Pointer to our adapter structure
|
||||||
|
* @new_state: New state being established after resetting the queue
|
||||||
|
*
|
||||||
|
* Must be called with interrupt lock held.
|
||||||
|
*/
|
||||||
|
static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state)
|
||||||
|
{
|
||||||
|
long rc = ADAPT_SUCCESS;
|
||||||
|
uint format;
|
||||||
|
|
||||||
|
vscsi->flags &= PRESERVE_FLAG_FIELDS;
|
||||||
|
vscsi->rsp_q_timer.timer_pops = 0;
|
||||||
|
vscsi->debit = 0;
|
||||||
|
vscsi->credit = 0;
|
||||||
|
|
||||||
|
rc = vio_enable_interrupts(vscsi->dma_dev);
|
||||||
|
if (rc) {
|
||||||
|
pr_warn("reset_queue: failed to enable interrupts, rc %ld\n",
|
||||||
|
rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ibmvscsis_check_init_msg(vscsi, &format);
|
||||||
|
if (rc) {
|
||||||
|
dev_err(&vscsi->dev, "reset_queue: check_init_msg failed, rc %ld\n",
|
||||||
|
rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == UNUSED_FORMAT && new_state == WAIT_CONNECTION) {
|
||||||
|
rc = ibmvscsis_send_init_message(vscsi, INIT_MSG);
|
||||||
|
switch (rc) {
|
||||||
|
case H_SUCCESS:
|
||||||
|
case H_DROPPED:
|
||||||
|
case H_CLOSED:
|
||||||
|
rc = ADAPT_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H_PARAMETER:
|
||||||
|
case H_HARDWARE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
vscsi->state = UNDEFINED;
|
||||||
|
rc = H_HARDWARE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ibmvscsis_reset_queue() - Reset CRQ Queue
|
||||||
|
* @vscsi: Pointer to our adapter structure
|
||||||
|
* @new_state: New state to establish after resetting the queue
|
||||||
|
*
|
||||||
|
* This function calls h_free_q and then calls h_reg_q and does all
|
||||||
|
* of the bookkeeping to get us back to where we can communicate.
|
||||||
|
*
|
||||||
|
* Actually, we don't always call h_free_crq. A problem was discovered
|
||||||
|
* where one partition would close and reopen his queue, which would
|
||||||
|
* cause his partner to get a transport event, which would cause him to
|
||||||
|
* close and reopen his queue, which would cause the original partition
|
||||||
|
* to get a transport event, etc., etc. To prevent this, we don't
|
||||||
|
* actually close our queue if the client initiated the reset, (i.e.
|
||||||
|
* either we got a transport event or we have detected that the client's
|
||||||
|
* queue is gone)
|
||||||
|
*
|
||||||
|
* EXECUTION ENVIRONMENT:
|
||||||
|
* Process environment, called with interrupt lock held
|
||||||
|
*/
|
||||||
|
static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state)
|
||||||
|
{
|
||||||
|
int bytes;
|
||||||
|
long rc = ADAPT_SUCCESS;
|
||||||
|
|
||||||
|
pr_debug("reset_queue: flags 0x%x\n", vscsi->flags);
|
||||||
|
|
||||||
|
/* don't reset, the client did it for us */
|
||||||
|
if (vscsi->flags & (CLIENT_FAILED | TRANS_EVENT)) {
|
||||||
|
vscsi->flags &= PRESERVE_FLAG_FIELDS;
|
||||||
|
vscsi->rsp_q_timer.timer_pops = 0;
|
||||||
|
vscsi->debit = 0;
|
||||||
|
vscsi->credit = 0;
|
||||||
|
vscsi->state = new_state;
|
||||||
|
vio_enable_interrupts(vscsi->dma_dev);
|
||||||
|
} else {
|
||||||
|
rc = ibmvscsis_free_command_q(vscsi);
|
||||||
|
if (rc == ADAPT_SUCCESS) {
|
||||||
|
vscsi->state = new_state;
|
||||||
|
|
||||||
|
bytes = vscsi->cmd_q.size * PAGE_SIZE;
|
||||||
|
rc = h_reg_crq(vscsi->dds.unit_id,
|
||||||
|
vscsi->cmd_q.crq_token, bytes);
|
||||||
|
if (rc == H_CLOSED || rc == H_SUCCESS) {
|
||||||
|
rc = ibmvscsis_establish_new_q(vscsi,
|
||||||
|
new_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != ADAPT_SUCCESS) {
|
||||||
|
pr_debug("reset_queue: reg_crq rc %ld\n", rc);
|
||||||
|
|
||||||
|
vscsi->state = ERR_DISCONNECTED;
|
||||||
|
vscsi->flags |= RESPONSE_Q_DOWN;
|
||||||
|
ibmvscsis_free_command_q(vscsi);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vscsi->state = ERR_DISCONNECTED;
|
||||||
|
vscsi->flags |= RESPONSE_Q_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ibmvscsis_free_cmd_resources() - Free command resources
|
||||||
|
* @vscsi: Pointer to our adapter structure
|
||||||
|
* @cmd: Command which is not longer in use
|
||||||
|
*
|
||||||
|
* Must be called with interrupt lock held.
|
||||||
|
*/
|
||||||
|
static void ibmvscsis_free_cmd_resources(struct scsi_info *vscsi,
|
||||||
|
struct ibmvscsis_cmd *cmd)
|
||||||
|
{
|
||||||
|
struct iu_entry *iue = cmd->iue;
|
||||||
|
|
||||||
|
switch (cmd->type) {
|
||||||
|
case TASK_MANAGEMENT:
|
||||||
|
case SCSI_CDB:
|
||||||
|
/*
|
||||||
|
* When the queue goes down this value is cleared, so it
|
||||||
|
* cannot be cleared in this general purpose function.
|
||||||
|
*/
|
||||||
|
if (vscsi->debit)
|
||||||
|
vscsi->debit -= 1;
|
||||||
|
break;
|
||||||
|
case ADAPTER_MAD:
|
||||||
|
vscsi->flags &= ~PROCESSING_MAD;
|
||||||
|
break;
|
||||||
|
case UNSET_TYPE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(&vscsi->dev, "free_cmd_resources unknown type %d\n",
|
||||||
|
cmd->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->iue = NULL;
|
||||||
|
list_add_tail(&cmd->list, &vscsi->free_cmd);
|
||||||
|
srp_iu_put(iue);
|
||||||
|
|
||||||
|
if (list_empty(&vscsi->active_q) && list_empty(&vscsi->schedule_q) &&
|
||||||
|
list_empty(&vscsi->waiting_rsp) && (vscsi->flags & WAIT_FOR_IDLE)) {
|
||||||
|
vscsi->flags &= ~WAIT_FOR_IDLE;
|
||||||
|
complete(&vscsi->wait_idle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ibmvscsis_trans_event() - Handle a Transport Event
|
* ibmvscsis_trans_event() - Handle a Transport Event
|
||||||
* @vscsi: Pointer to our adapter structure
|
* @vscsi: Pointer to our adapter structure
|
||||||
@ -895,7 +1047,7 @@ static long ibmvscsis_trans_event(struct scsi_info *vscsi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = vscsi->flags & SCHEDULE_DISCONNECT;
|
rc = vscsi->flags & SCHEDULE_DISCONNECT;
|
||||||
|
|
||||||
pr_debug("Leaving trans_event: flags 0x%x, state 0x%hx, rc %ld\n",
|
pr_debug("Leaving trans_event: flags 0x%x, state 0x%hx, rc %ld\n",
|
||||||
vscsi->flags, vscsi->state, rc);
|
vscsi->flags, vscsi->state, rc);
|
||||||
@ -1220,7 +1372,7 @@ static long ibmvscsis_copy_crq_packet(struct scsi_info *vscsi,
|
|||||||
* @iue: Information Unit containing the Adapter Info MAD request
|
* @iue: Information Unit containing the Adapter Info MAD request
|
||||||
*
|
*
|
||||||
* EXECUTION ENVIRONMENT:
|
* EXECUTION ENVIRONMENT:
|
||||||
* Interrupt adpater lock is held
|
* Interrupt adapter lock is held
|
||||||
*/
|
*/
|
||||||
static long ibmvscsis_adapter_info(struct scsi_info *vscsi,
|
static long ibmvscsis_adapter_info(struct scsi_info *vscsi,
|
||||||
struct iu_entry *iue)
|
struct iu_entry *iue)
|
||||||
@ -1691,7 +1843,7 @@ static void ibmvscsis_send_mad_resp(struct scsi_info *vscsi,
|
|||||||
* @crq: Pointer to the CRQ entry containing the MAD request
|
* @crq: Pointer to the CRQ entry containing the MAD request
|
||||||
*
|
*
|
||||||
* EXECUTION ENVIRONMENT:
|
* EXECUTION ENVIRONMENT:
|
||||||
* Interrupt called with adapter lock held
|
* Interrupt, called with adapter lock held
|
||||||
*/
|
*/
|
||||||
static long ibmvscsis_mad(struct scsi_info *vscsi, struct viosrp_crq *crq)
|
static long ibmvscsis_mad(struct scsi_info *vscsi, struct viosrp_crq *crq)
|
||||||
{
|
{
|
||||||
@ -1864,7 +2016,7 @@ static long ibmvscsis_srp_login_rej(struct scsi_info *vscsi,
|
|||||||
break;
|
break;
|
||||||
case H_PERMISSION:
|
case H_PERMISSION:
|
||||||
if (connection_broken(vscsi))
|
if (connection_broken(vscsi))
|
||||||
flag_bits = RESPONSE_Q_DOWN | CLIENT_FAILED;
|
flag_bits = RESPONSE_Q_DOWN | CLIENT_FAILED;
|
||||||
dev_err(&vscsi->dev, "login_rej: error copying to client, rc %ld\n",
|
dev_err(&vscsi->dev, "login_rej: error copying to client, rc %ld\n",
|
||||||
rc);
|
rc);
|
||||||
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT,
|
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT,
|
||||||
@ -2186,156 +2338,6 @@ static long ibmvscsis_ping_response(struct scsi_info *vscsi)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ibmvscsis_handle_init_compl_msg() - Respond to an Init Complete Message
|
|
||||||
* @vscsi: Pointer to our adapter structure
|
|
||||||
*
|
|
||||||
* Must be called with interrupt lock held.
|
|
||||||
*/
|
|
||||||
static long ibmvscsis_handle_init_compl_msg(struct scsi_info *vscsi)
|
|
||||||
{
|
|
||||||
long rc = ADAPT_SUCCESS;
|
|
||||||
|
|
||||||
switch (vscsi->state) {
|
|
||||||
case NO_QUEUE:
|
|
||||||
case ERR_DISCONNECT:
|
|
||||||
case ERR_DISCONNECT_RECONNECT:
|
|
||||||
case ERR_DISCONNECTED:
|
|
||||||
case UNCONFIGURING:
|
|
||||||
case UNDEFINED:
|
|
||||||
rc = ERROR;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WAIT_CONNECTION:
|
|
||||||
vscsi->state = CONNECTED;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WAIT_IDLE:
|
|
||||||
case SRP_PROCESSING:
|
|
||||||
case CONNECTED:
|
|
||||||
case WAIT_ENABLED:
|
|
||||||
case PART_UP_WAIT_ENAB:
|
|
||||||
default:
|
|
||||||
rc = ERROR;
|
|
||||||
dev_err(&vscsi->dev, "init_msg: invalid state %d to get init compl msg\n",
|
|
||||||
vscsi->state);
|
|
||||||
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ibmvscsis_handle_init_msg() - Respond to an Init Message
|
|
||||||
* @vscsi: Pointer to our adapter structure
|
|
||||||
*
|
|
||||||
* Must be called with interrupt lock held.
|
|
||||||
*/
|
|
||||||
static long ibmvscsis_handle_init_msg(struct scsi_info *vscsi)
|
|
||||||
{
|
|
||||||
long rc = ADAPT_SUCCESS;
|
|
||||||
|
|
||||||
switch (vscsi->state) {
|
|
||||||
case WAIT_ENABLED:
|
|
||||||
vscsi->state = PART_UP_WAIT_ENAB;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WAIT_CONNECTION:
|
|
||||||
rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG);
|
|
||||||
switch (rc) {
|
|
||||||
case H_SUCCESS:
|
|
||||||
vscsi->state = CONNECTED;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case H_PARAMETER:
|
|
||||||
dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
|
|
||||||
rc);
|
|
||||||
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case H_DROPPED:
|
|
||||||
dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
|
|
||||||
rc);
|
|
||||||
rc = ERROR;
|
|
||||||
ibmvscsis_post_disconnect(vscsi,
|
|
||||||
ERR_DISCONNECT_RECONNECT, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case H_CLOSED:
|
|
||||||
pr_warn("init_msg: failed to send, rc %ld\n", rc);
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UNDEFINED:
|
|
||||||
rc = ERROR;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UNCONFIGURING:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PART_UP_WAIT_ENAB:
|
|
||||||
case CONNECTED:
|
|
||||||
case SRP_PROCESSING:
|
|
||||||
case WAIT_IDLE:
|
|
||||||
case NO_QUEUE:
|
|
||||||
case ERR_DISCONNECT:
|
|
||||||
case ERR_DISCONNECT_RECONNECT:
|
|
||||||
case ERR_DISCONNECTED:
|
|
||||||
default:
|
|
||||||
rc = ERROR;
|
|
||||||
dev_err(&vscsi->dev, "init_msg: invalid state %d to get init msg\n",
|
|
||||||
vscsi->state);
|
|
||||||
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ibmvscsis_init_msg() - Respond to an init message
|
|
||||||
* @vscsi: Pointer to our adapter structure
|
|
||||||
* @crq: Pointer to CRQ element containing the Init Message
|
|
||||||
*
|
|
||||||
* EXECUTION ENVIRONMENT:
|
|
||||||
* Interrupt, interrupt lock held
|
|
||||||
*/
|
|
||||||
static long ibmvscsis_init_msg(struct scsi_info *vscsi, struct viosrp_crq *crq)
|
|
||||||
{
|
|
||||||
long rc = ADAPT_SUCCESS;
|
|
||||||
|
|
||||||
pr_debug("init_msg: state 0x%hx\n", vscsi->state);
|
|
||||||
|
|
||||||
rc = h_vioctl(vscsi->dds.unit_id, H_GET_PARTNER_INFO,
|
|
||||||
(u64)vscsi->map_ioba | ((u64)PAGE_SIZE << 32), 0, 0, 0,
|
|
||||||
0);
|
|
||||||
if (rc == H_SUCCESS) {
|
|
||||||
vscsi->client_data.partition_number =
|
|
||||||
be64_to_cpu(*(u64 *)vscsi->map_buf);
|
|
||||||
pr_debug("init_msg, part num %d\n",
|
|
||||||
vscsi->client_data.partition_number);
|
|
||||||
} else {
|
|
||||||
pr_debug("init_msg h_vioctl rc %ld\n", rc);
|
|
||||||
rc = ADAPT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crq->format == INIT_MSG) {
|
|
||||||
rc = ibmvscsis_handle_init_msg(vscsi);
|
|
||||||
} else if (crq->format == INIT_COMPLETE_MSG) {
|
|
||||||
rc = ibmvscsis_handle_init_compl_msg(vscsi);
|
|
||||||
} else {
|
|
||||||
rc = ERROR;
|
|
||||||
dev_err(&vscsi->dev, "init_msg: invalid format %d\n",
|
|
||||||
(uint)crq->format);
|
|
||||||
ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ibmvscsis_parse_command() - Parse an element taken from the cmd rsp queue.
|
* ibmvscsis_parse_command() - Parse an element taken from the cmd rsp queue.
|
||||||
* @vscsi: Pointer to our adapter structure
|
* @vscsi: Pointer to our adapter structure
|
||||||
@ -2391,7 +2393,7 @@ static long ibmvscsis_parse_command(struct scsi_info *vscsi,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VALID_TRANS_EVENT:
|
case VALID_TRANS_EVENT:
|
||||||
rc = ibmvscsis_trans_event(vscsi, crq);
|
rc = ibmvscsis_trans_event(vscsi, crq);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VALID_INIT_MSG:
|
case VALID_INIT_MSG:
|
||||||
@ -3270,7 +3272,7 @@ static void ibmvscsis_handle_crq(unsigned long data)
|
|||||||
/*
|
/*
|
||||||
* if we are in a path where we are waiting for all pending commands
|
* if we are in a path where we are waiting for all pending commands
|
||||||
* to complete because we received a transport event and anything in
|
* to complete because we received a transport event and anything in
|
||||||
* the command queue is for a new connection, do nothing
|
* the command queue is for a new connection, do nothing
|
||||||
*/
|
*/
|
||||||
if (TARGET_STOP(vscsi)) {
|
if (TARGET_STOP(vscsi)) {
|
||||||
vio_enable_interrupts(vscsi->dma_dev);
|
vio_enable_interrupts(vscsi->dma_dev);
|
||||||
@ -3314,7 +3316,7 @@ cmd_work:
|
|||||||
* everything but transport events on the queue
|
* everything but transport events on the queue
|
||||||
*
|
*
|
||||||
* need to decrement the queue index so we can
|
* need to decrement the queue index so we can
|
||||||
* look at the elment again
|
* look at the element again
|
||||||
*/
|
*/
|
||||||
if (vscsi->cmd_q.index)
|
if (vscsi->cmd_q.index)
|
||||||
vscsi->cmd_q.index -= 1;
|
vscsi->cmd_q.index -= 1;
|
||||||
@ -3983,10 +3985,10 @@ static struct attribute *ibmvscsis_dev_attrs[] = {
|
|||||||
ATTRIBUTE_GROUPS(ibmvscsis_dev);
|
ATTRIBUTE_GROUPS(ibmvscsis_dev);
|
||||||
|
|
||||||
static struct class ibmvscsis_class = {
|
static struct class ibmvscsis_class = {
|
||||||
.name = "ibmvscsis",
|
.name = "ibmvscsis",
|
||||||
.dev_release = ibmvscsis_dev_release,
|
.dev_release = ibmvscsis_dev_release,
|
||||||
.class_attrs = ibmvscsis_class_attrs,
|
.class_attrs = ibmvscsis_class_attrs,
|
||||||
.dev_groups = ibmvscsis_dev_groups,
|
.dev_groups = ibmvscsis_dev_groups,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct vio_device_id ibmvscsis_device_table[] = {
|
static struct vio_device_id ibmvscsis_device_table[] = {
|
||||||
|
Loading…
Reference in New Issue
Block a user