Commit 92953c6e authored by Benjamin Block's avatar Benjamin Block Committed by Martin K. Petersen

scsi: zfcp: signal incomplete or error for sync exchange config/port data

Adds a new FSF-Request status flag (ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE)
that signal that the data received using Exchange Config Data or Exchange
Port Data was incomplete. This new flags is set in the respective handlers
during the response path.

With this patch, only the synchronous FSF-functions for each command got
support for the new flag, otherwise it is transparent.

Together with this new flag and already existing status flags the
synchronous FSF-functions are extended to now detect whether the received
data is complete, incomplete or completely invalid (this includes cases
where a command ran into a timeout). This is now signaled back to the
caller, where previously only failures on the request path would result in
a bad return-code.

For complete data the return-code remains 0. For incomplete data a new
return-code -EAGAIN is added to the function-interface. For completely
invalid data the already existing return-code -EIO is reused - formerly
this was used to signal failures on the request path.

Existing callers of the FSF-functions are adjusted so that they behave as
before for return-code 0 and -EAGAIN, to not change the user-interface. As
-EIO existed all along, it was already exposed to the user - and needed
handling - and will now also be exposed in this new special case.

Link: https://lore.kernel.org/r/e14f0702fa2b00a4d1f37c7981a13f2dd1ea2c83.1572018130.git.bblock@linux.ibm.comReviewed-by: default avatarSteffen Maier <maier@linux.ibm.com>
Signed-off-by: default avatarBenjamin Block <bblock@linux.ibm.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7b10db55
...@@ -86,6 +86,7 @@ ...@@ -86,6 +86,7 @@
#define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED 0x00000080 #define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED 0x00000080
#define ZFCP_STATUS_FSFREQ_TMFUNCFAILED 0x00000200 #define ZFCP_STATUS_FSFREQ_TMFUNCFAILED 0x00000200
#define ZFCP_STATUS_FSFREQ_DISMISSED 0x00001000 #define ZFCP_STATUS_FSFREQ_DISMISSED 0x00001000
#define ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE 0x00020000
/************************* STRUCTURE DEFINITIONS *****************************/ /************************* STRUCTURE DEFINITIONS *****************************/
......
...@@ -585,6 +585,8 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) ...@@ -585,6 +585,8 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
&adapter->status); &adapter->status);
break; break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE;
fc_host_node_name(shost) = 0; fc_host_node_name(shost) = 0;
fc_host_port_name(shost) = 0; fc_host_port_name(shost) = 0;
fc_host_port_id(shost) = 0; fc_host_port_id(shost) = 0;
...@@ -663,6 +665,8 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) ...@@ -663,6 +665,8 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
zfcp_fsf_exchange_port_evaluate(req); zfcp_fsf_exchange_port_evaluate(req);
break; break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE;
zfcp_fsf_exchange_port_evaluate(req); zfcp_fsf_exchange_port_evaluate(req);
zfcp_fsf_link_down_info_eval(req, zfcp_fsf_link_down_info_eval(req,
&qtcb->header.fsf_status_qual.link_down_info); &qtcb->header.fsf_status_qual.link_down_info);
...@@ -1278,6 +1282,19 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) ...@@ -1278,6 +1282,19 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
return retval; return retval;
} }
/**
* zfcp_fsf_exchange_config_data_sync() - Request information about FCP channel.
* @qdio: pointer to the QDIO-Queue to use for sending the command.
* @data: pointer to the QTCB-Bottom for storing the result of the command,
* might be %NULL.
*
* Returns:
* * 0 - Exchange Config Data was successful, @data is complete
* * -EIO - Exchange Config Data was not successful, @data is invalid
* * -EAGAIN - @data contains incomplete data
* * -ENOMEM - Some memory allocation failed along the way
*/
int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
struct fsf_qtcb_bottom_config *data) struct fsf_qtcb_bottom_config *data)
{ {
...@@ -1309,9 +1326,16 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, ...@@ -1309,9 +1326,16 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req); retval = zfcp_fsf_req_send(req);
spin_unlock_irq(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
if (!retval) { if (!retval) {
/* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */ /* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */
wait_for_completion(&req->completion); wait_for_completion(&req->completion);
if (req->status &
(ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_DISMISSED))
retval = -EIO;
else if (req->status & ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE)
retval = -EAGAIN;
} }
zfcp_fsf_req_free(req); zfcp_fsf_req_free(req);
...@@ -1369,10 +1393,17 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) ...@@ -1369,10 +1393,17 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
} }
/** /**
* zfcp_fsf_exchange_port_data_sync - request information about local port * zfcp_fsf_exchange_port_data_sync() - Request information about local port.
* @qdio: pointer to struct zfcp_qdio * @qdio: pointer to the QDIO-Queue to use for sending the command.
* @data: pointer to struct fsf_qtcb_bottom_port * @data: pointer to the QTCB-Bottom for storing the result of the command,
* Returns: 0 on success, error otherwise * might be %NULL.
*
* Returns:
* * 0 - Exchange Port Data was successful, @data is complete
* * -EIO - Exchange Port Data was not successful, @data is invalid
* * -EAGAIN - @data contains incomplete data
* * -ENOMEM - Some memory allocation failed along the way
* * -EOPNOTSUPP - This operation is not supported
*/ */
int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
struct fsf_qtcb_bottom_port *data) struct fsf_qtcb_bottom_port *data)
...@@ -1408,10 +1439,15 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, ...@@ -1408,10 +1439,15 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
if (!retval) { if (!retval) {
/* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */ /* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */
wait_for_completion(&req->completion); wait_for_completion(&req->completion);
if (req->status &
(ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_DISMISSED))
retval = -EIO;
else if (req->status & ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE)
retval = -EAGAIN;
} }
zfcp_fsf_req_free(req); zfcp_fsf_req_free(req);
return retval; return retval;
out_unlock: out_unlock:
......
...@@ -605,7 +605,7 @@ zfcp_scsi_get_fc_host_stats(struct Scsi_Host *host) ...@@ -605,7 +605,7 @@ zfcp_scsi_get_fc_host_stats(struct Scsi_Host *host)
return NULL; return NULL;
ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data); ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
if (ret) { if (ret != 0 && ret != -EAGAIN) {
kfree(data); kfree(data);
return NULL; return NULL;
} }
...@@ -634,7 +634,7 @@ static void zfcp_scsi_reset_fc_host_stats(struct Scsi_Host *shost) ...@@ -634,7 +634,7 @@ static void zfcp_scsi_reset_fc_host_stats(struct Scsi_Host *shost)
return; return;
ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data); ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
if (ret) if (ret != 0 && ret != -EAGAIN)
kfree(data); kfree(data);
else { else {
adapter->stats_reset = jiffies/HZ; adapter->stats_reset = jiffies/HZ;
......
...@@ -577,7 +577,7 @@ static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev, ...@@ -577,7 +577,7 @@ static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
return -ENOMEM; return -ENOMEM;
retval = zfcp_fsf_exchange_port_data_sync(adapter->qdio, qtcb_port); retval = zfcp_fsf_exchange_port_data_sync(adapter->qdio, qtcb_port);
if (!retval) if (retval == 0 || retval == -EAGAIN)
retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util, retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
qtcb_port->cb_util, qtcb_port->a_util); qtcb_port->cb_util, qtcb_port->a_util);
kfree(qtcb_port); kfree(qtcb_port);
...@@ -603,7 +603,7 @@ static int zfcp_sysfs_adapter_ex_config(struct device *dev, ...@@ -603,7 +603,7 @@ static int zfcp_sysfs_adapter_ex_config(struct device *dev,
return -ENOMEM; return -ENOMEM;
retval = zfcp_fsf_exchange_config_data_sync(adapter->qdio, qtcb_config); retval = zfcp_fsf_exchange_config_data_sync(adapter->qdio, qtcb_config);
if (!retval) if (retval == 0 || retval == -EAGAIN)
*stat_inf = qtcb_config->stat_info; *stat_inf = qtcb_config->stat_info;
kfree(qtcb_config); kfree(qtcb_config);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment