From 92953c6e0aa77d4febcca6dd691e8192910c8a28 Mon Sep 17 00:00:00 2001 From: Benjamin Block Date: Fri, 25 Oct 2019 18:12:43 +0200 Subject: 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.com Reviewed-by: Steffen Maier Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_fsf.c | 46 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'drivers/s390/scsi/zfcp_fsf.c') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index cf63916814cc..d8f0e446fe13 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -585,6 +585,8 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) &adapter->status); break; case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: + req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE; + fc_host_node_name(shost) = 0; fc_host_port_name(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) zfcp_fsf_exchange_port_evaluate(req); break; case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: + req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE; + zfcp_fsf_exchange_port_evaluate(req); zfcp_fsf_link_down_info_eval(req, &qtcb->header.fsf_status_qual.link_down_info); @@ -1278,6 +1282,19 @@ out: 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, struct fsf_qtcb_bottom_config *data) { @@ -1309,9 +1326,16 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); spin_unlock_irq(&qdio->req_q_lock); + if (!retval) { /* NOTE: ONLY TOUCH SYNC req AGAIN ON 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); @@ -1369,10 +1393,17 @@ out: } /** - * zfcp_fsf_exchange_port_data_sync - request information about local port - * @qdio: pointer to struct zfcp_qdio - * @data: pointer to struct fsf_qtcb_bottom_port - * Returns: 0 on success, error otherwise + * zfcp_fsf_exchange_port_data_sync() - Request information about local port. + * @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 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, struct fsf_qtcb_bottom_port *data) @@ -1408,10 +1439,15 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, if (!retval) { /* NOTE: ONLY TOUCH SYNC req AGAIN ON 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); - return retval; out_unlock: -- cgit v1.2.3 From 7e418833e68948cb9ed15262889173b7db2960cb Mon Sep 17 00:00:00 2001 From: Benjamin Block Date: Fri, 25 Oct 2019 18:12:44 +0200 Subject: scsi: zfcp: diagnostics buffer caching and use for exchange port data The FCP channel exposes two central interfaces to receive information about the local FCP-Adapter/-Port: Exchange Port and Exchange Config Data. Using these commands can negatively impact the adapter if we allow them to be sent at a very high rate. The later parts of this patchset will introduce new user-interfaces to receive more diagnostics from the adapter. To prevent any negative impact from using those, this patch adds a simple caching-mechanism that will prevent a malicious/faulty userspace-application from generating an abnormal high amount of Exchange Port/Config Data traffic. Relevant diagnostic data that is received via Exchange Config/Port Data is cached in buffers associated with the corresponding adapter-struct. Each buffer is associated with a timestamp that signals how old the data is, and, added via a following patch in this series, lets userspace-interfaces determine when the data is too old and needs to be updated. Buffer-updates are made during the normal response path of the corresponding command. With this patch only the output of the Exchange Port Data command is captured. Link: https://lore.kernel.org/r/054ca020ce0a53dc0d9176428bea373898944e6a.1572018130.git.bblock@linux.ibm.com Reviewed-by: Steffen Maier Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/Makefile | 2 +- drivers/s390/scsi/zfcp_aux.c | 8 +++- drivers/s390/scsi/zfcp_def.h | 3 +- drivers/s390/scsi/zfcp_diag.c | 93 +++++++++++++++++++++++++++++++++++++++++++ drivers/s390/scsi/zfcp_diag.h | 60 ++++++++++++++++++++++++++++ drivers/s390/scsi/zfcp_fsf.c | 12 ++++++ 6 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 drivers/s390/scsi/zfcp_diag.c create mode 100644 drivers/s390/scsi/zfcp_diag.h (limited to 'drivers/s390/scsi/zfcp_fsf.c') diff --git a/drivers/s390/scsi/Makefile b/drivers/s390/scsi/Makefile index 9dda431ec8f3..352056eb0dd1 100644 --- a/drivers/s390/scsi/Makefile +++ b/drivers/s390/scsi/Makefile @@ -5,6 +5,6 @@ zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_dbf.o zfcp_erp.o \ zfcp_fc.o zfcp_fsf.o zfcp_qdio.o zfcp_scsi.o zfcp_sysfs.o \ - zfcp_unit.o + zfcp_unit.o zfcp_diag.o obj-$(CONFIG_ZFCP) += zfcp.o diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index e390f8c6d5f3..a19189d7b3f3 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -4,7 +4,7 @@ * * Module interface and handling of zfcp data structures. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ /* @@ -25,6 +25,7 @@ * Martin Petermann * Sven Schuetz * Steffen Maier + * Benjamin Block */ #define KMSG_COMPONENT "zfcp" @@ -36,6 +37,7 @@ #include "zfcp_ext.h" #include "zfcp_fc.h" #include "zfcp_reqlist.h" +#include "zfcp_diag.h" #define ZFCP_BUS_ID_SIZE 20 @@ -356,6 +358,9 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) adapter->erp_action.adapter = adapter; + if (zfcp_diag_adapter_setup(adapter)) + goto failed; + if (zfcp_qdio_setup(adapter)) goto failed; @@ -449,6 +454,7 @@ void zfcp_adapter_release(struct kref *ref) dev_set_drvdata(&adapter->ccw_device->dev, NULL); zfcp_fc_gs_destroy(adapter); zfcp_free_low_mem_buffers(adapter); + zfcp_diag_adapter_free(adapter); kfree(adapter->req_list); kfree(adapter->fc_stats); kfree(adapter->stats_reset_data); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index f5acdb67442e..8cc0eefe4ccc 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -4,7 +4,7 @@ * * Global definitions for the zfcp device driver. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ #ifndef ZFCP_DEF_H @@ -198,6 +198,7 @@ struct zfcp_adapter { struct device_dma_parameters dma_parms; struct zfcp_fc_events events; unsigned long next_port_scan; + struct zfcp_diag_adapter *diagnostics; }; struct zfcp_port { diff --git a/drivers/s390/scsi/zfcp_diag.c b/drivers/s390/scsi/zfcp_diag.c new file mode 100644 index 000000000000..fa1b25f3ec3c --- /dev/null +++ b/drivers/s390/scsi/zfcp_diag.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * zfcp device driver + * + * Functions to handle diagnostics. + * + * Copyright IBM Corp. 2018 + */ + +#include +#include +#include +#include +#include + +#include "zfcp_diag.h" +#include "zfcp_ext.h" +#include "zfcp_def.h" + +/* Max age of data in a diagnostics buffer before it needs a refresh (in ms). */ +#define ZFCP_DIAG_MAX_AGE (5 * 1000) + +/** + * zfcp_diag_adapter_setup() - Setup storage for adapter diagnostics. + * @adapter: the adapter to setup diagnostics for. + * + * Creates the data-structures to store the diagnostics for an adapter. This + * overwrites whatever was stored before at &zfcp_adapter->diagnostics! + * + * Return: + * * 0 - Everyting is OK + * * -ENOMEM - Could not allocate all/parts of the data-structures; + * &zfcp_adapter->diagnostics remains unchanged + */ +int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter) +{ + struct zfcp_diag_adapter *diag; + struct zfcp_diag_header *hdr; + + diag = kzalloc(sizeof(*diag), GFP_KERNEL); + if (diag == NULL) + return -ENOMEM; + + /* setup header for port_data */ + hdr = &diag->port_data.header; + + spin_lock_init(&hdr->access_lock); + hdr->buffer = &diag->port_data.data; + hdr->buffer_size = sizeof(diag->port_data.data); + /* set the timestamp so that the first test on age will always fail */ + hdr->timestamp = jiffies - msecs_to_jiffies(ZFCP_DIAG_MAX_AGE); + + adapter->diagnostics = diag; + return 0; +} + +/** + * zfcp_diag_adapter_free() - Frees all adapter diagnostics allocations. + * @adapter: the adapter whose diagnostic structures should be freed. + * + * Frees all data-structures in the given adapter that store diagnostics + * information. Can savely be called with partially setup diagnostics. + */ +void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter) +{ + kfree(adapter->diagnostics); + adapter->diagnostics = NULL; +} + +/** + * zfcp_diag_update_xdata() - Update a diagnostics buffer. + * @hdr: the meta data to update. + * @data: data to use for the update. + * @incomplete: flag stating whether the data in @data is incomplete. + */ +void zfcp_diag_update_xdata(struct zfcp_diag_header *const hdr, + const void *const data, const bool incomplete) +{ + const unsigned long capture_timestamp = jiffies; + unsigned long flags; + + spin_lock_irqsave(&hdr->access_lock, flags); + + /* make sure we never go into the past with an update */ + if (!time_after_eq(capture_timestamp, hdr->timestamp)) + goto out; + + hdr->timestamp = capture_timestamp; + hdr->incomplete = incomplete; + memcpy(hdr->buffer, data, hdr->buffer_size); +out: + spin_unlock_irqrestore(&hdr->access_lock, flags); +} diff --git a/drivers/s390/scsi/zfcp_diag.h b/drivers/s390/scsi/zfcp_diag.h new file mode 100644 index 000000000000..2a933326b6e4 --- /dev/null +++ b/drivers/s390/scsi/zfcp_diag.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * zfcp device driver + * + * Definitions for handling diagnostics in the the zfcp device driver. + * + * Copyright IBM Corp. 2018 + */ + +#ifndef ZFCP_DIAG_H +#define ZFCP_DIAG_H + +#include + +#include "zfcp_fsf.h" +#include "zfcp_def.h" + +/** + * struct zfcp_diag_header - general part of a diagnostic buffer. + * @access_lock: lock protecting all the data in this buffer. + * @updating: flag showing that an update for this buffer is currently running. + * @incomplete: flag showing that the data in @buffer is incomplete. + * @timestamp: time in jiffies when the data of this buffer was last captured. + * @buffer: implementation-depending data of this buffer + * @buffer_size: size of @buffer + */ +struct zfcp_diag_header { + spinlock_t access_lock; + + /* Flags */ + u64 updating :1; + u64 incomplete :1; + + unsigned long timestamp; + + void *buffer; + size_t buffer_size; +}; + +/** + * struct zfcp_diag_adapter - central storage for all diagnostics concerning an + * adapter. + * @port_data: data retrieved using exchange port data. + * @port_data.header: header with metadata for the cache in @port_data.data. + * @port_data.data: cached QTCB Bottom of command exchange port data. + */ +struct zfcp_diag_adapter { + struct { + struct zfcp_diag_header header; + struct fsf_qtcb_bottom_port data; + } port_data; +}; + +int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter); +void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter); + +void zfcp_diag_update_xdata(struct zfcp_diag_header *const hdr, + const void *const data, const bool incomplete); + +#endif /* ZFCP_DIAG_H */ diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index d8f0e446fe13..883bbfd67a62 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -11,6 +11,7 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include +#include #include #include #include @@ -19,6 +20,7 @@ #include "zfcp_dbf.h" #include "zfcp_qdio.h" #include "zfcp_reqlist.h" +#include "zfcp_diag.h" /* timeout for FSF requests sent during scsi_eh: abort or FCP TMF */ #define ZFCP_FSF_SCSI_ER_TIMEOUT (10*HZ) @@ -655,16 +657,26 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) { + struct zfcp_diag_header *const diag_hdr = + &req->adapter->diagnostics->port_data.header; struct fsf_qtcb *qtcb = req->qtcb; + struct fsf_qtcb_bottom_port *bottom = &qtcb->bottom.port; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; switch (qtcb->header.fsf_status) { case FSF_GOOD: + /* + * usually we wait with an update till the cache is too old, + * but because we have the data available, update it anyway + */ + zfcp_diag_update_xdata(diag_hdr, bottom, false); + zfcp_fsf_exchange_port_evaluate(req); break; case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: + zfcp_diag_update_xdata(diag_hdr, bottom, true); req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE; zfcp_fsf_exchange_port_evaluate(req); -- cgit v1.2.3 From 088210233e6fc039fd2c0bfe44b06bb94328d09e Mon Sep 17 00:00:00 2001 From: Benjamin Block Date: Fri, 25 Oct 2019 18:12:45 +0200 Subject: scsi: zfcp: add diagnostics buffer for exchange config data In the same vein as the previous patch, add diagnostic data capture for the Exchange Config Data command. Link: https://lore.kernel.org/r/7d8ac0a6cad403fa8f8b888693476a84e80a277b.1572018131.git.bblock@linux.ibm.com Reviewed-by: Steffen Maier Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_diag.c | 14 ++++++++++++-- drivers/s390/scsi/zfcp_diag.h | 7 +++++++ drivers/s390/scsi/zfcp_fsf.c | 9 +++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers/s390/scsi/zfcp_fsf.c') diff --git a/drivers/s390/scsi/zfcp_diag.c b/drivers/s390/scsi/zfcp_diag.c index fa1b25f3ec3c..d7d2db85b32e 100644 --- a/drivers/s390/scsi/zfcp_diag.c +++ b/drivers/s390/scsi/zfcp_diag.c @@ -34,6 +34,9 @@ */ int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter) { + /* set the timestamp so that the first test on age will always fail */ + const unsigned long initial_timestamp = + jiffies - msecs_to_jiffies(ZFCP_DIAG_MAX_AGE); struct zfcp_diag_adapter *diag; struct zfcp_diag_header *hdr; @@ -47,8 +50,15 @@ int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter) spin_lock_init(&hdr->access_lock); hdr->buffer = &diag->port_data.data; hdr->buffer_size = sizeof(diag->port_data.data); - /* set the timestamp so that the first test on age will always fail */ - hdr->timestamp = jiffies - msecs_to_jiffies(ZFCP_DIAG_MAX_AGE); + hdr->timestamp = initial_timestamp; + + /* setup header for config_data */ + hdr = &diag->config_data.header; + + spin_lock_init(&hdr->access_lock); + hdr->buffer = &diag->config_data.data; + hdr->buffer_size = sizeof(diag->config_data.data); + hdr->timestamp = initial_timestamp; adapter->diagnostics = diag; return 0; diff --git a/drivers/s390/scsi/zfcp_diag.h b/drivers/s390/scsi/zfcp_diag.h index 2a933326b6e4..a3eb21cc201d 100644 --- a/drivers/s390/scsi/zfcp_diag.h +++ b/drivers/s390/scsi/zfcp_diag.h @@ -43,12 +43,19 @@ struct zfcp_diag_header { * @port_data: data retrieved using exchange port data. * @port_data.header: header with metadata for the cache in @port_data.data. * @port_data.data: cached QTCB Bottom of command exchange port data. + * @config_data: data retrieved using exchange config data. + * @config_data.header: header with metadata for the cache in @config_data.data. + * @config_data.data: cached QTCB Bottom of command exchange config data. */ struct zfcp_diag_adapter { struct { struct zfcp_diag_header header; struct fsf_qtcb_bottom_port data; } port_data; + struct { + struct zfcp_diag_header header; + struct fsf_qtcb_bottom_config data; + } config_data; }; int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 883bbfd67a62..0fff060de5ac 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -556,6 +556,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; + struct zfcp_diag_header *const diag_hdr = + &adapter->diagnostics->config_data.header; struct fsf_qtcb *qtcb = req->qtcb; struct fsf_qtcb_bottom_config *bottom = &qtcb->bottom.config; struct Scsi_Host *shost = adapter->scsi_host; @@ -572,6 +574,12 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) switch (qtcb->header.fsf_status) { case FSF_GOOD: + /* + * usually we wait with an update till the cache is too old, + * but because we have the data available, update it anyway + */ + zfcp_diag_update_xdata(diag_hdr, bottom, false); + if (zfcp_fsf_exchange_config_evaluate(req)) return; @@ -587,6 +595,7 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) &adapter->status); break; case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: + zfcp_diag_update_xdata(diag_hdr, bottom, true); req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE; fc_host_node_name(shost) = 0; -- cgit v1.2.3 From a10a61e807b0a226b78e2041843cbf0521bd0c35 Mon Sep 17 00:00:00 2001 From: Benjamin Block Date: Fri, 25 Oct 2019 18:12:46 +0200 Subject: scsi: zfcp: support retrieval of SFP Data via Exchange Port Data A new FCP channel feature allows us to read the diagnostics from our local SFP transceivers. To make use of that add a flag (FSF_FEATURE_REQUEST_SFP_DATA) to the feature-set we request from the FCP channel. Whether the channel actually implements this can be determined via an other new flag (FSF_FEATURE_REPORT_SFP_DATA), that is set in the adapter_features field of the adapter structure after Exchange Config Data finished. Also add the corresponding definitions in the QTCB Bottom for Exchange Port Data. These new definitions are only valid, if FSF_FEATURE_REPORT_SFP_DATA is set. Link: https://lore.kernel.org/r/ee1eba4de71eb06b4d82207ad4f428429346156f.1572018132.git.bblock@linux.ibm.com Reviewed-by: Steffen Maier Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_fsf.c | 6 ++++-- drivers/s390/scsi/zfcp_fsf.h | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers/s390/scsi/zfcp_fsf.c') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 0fff060de5ac..223a805f0b0b 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1286,7 +1286,8 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) req->qtcb->bottom.config.feature_selection = FSF_FEATURE_NOTIFICATION_LOST | - FSF_FEATURE_UPDATE_ALERT; + FSF_FEATURE_UPDATE_ALERT | + FSF_FEATURE_REQUEST_SFP_DATA; req->erp_action = erp_action; req->handler = zfcp_fsf_exchange_config_data_handler; erp_action->fsf_req_id = req->req_id; @@ -1339,7 +1340,8 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, req->qtcb->bottom.config.feature_selection = FSF_FEATURE_NOTIFICATION_LOST | - FSF_FEATURE_UPDATE_ALERT; + FSF_FEATURE_UPDATE_ALERT | + FSF_FEATURE_REQUEST_SFP_DATA; if (data) req->data = data; diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 2c658b66318c..2b1e4da1944f 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -163,6 +163,8 @@ #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 #define FSF_FEATURE_UPDATE_ALERT 0x00000100 #define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 +#define FSF_FEATURE_REQUEST_SFP_DATA 0x00000200 +#define FSF_FEATURE_REPORT_SFP_DATA 0x00000800 #define FSF_FEATURE_DIF_PROT_TYPE1 0x00010000 #define FSF_FEATURE_DIX_PROT_TCPIP 0x00020000 @@ -407,7 +409,24 @@ struct fsf_qtcb_bottom_port { u8 cp_util; u8 cb_util; u8 a_util; - u8 res2[253]; + u8 res2; + u16 temperature; + u16 vcc; + u16 tx_bias; + u16 tx_power; + u16 rx_power; + union { + u16 raw; + struct { + u16 fec_active :1; + u16:7; + u16 connector_type :2; + u16 sfp_invalid :1; + u16 optical_port :1; + u16 port_tx_type :4; + }; + } sfp_flags; + u8 res3[240]; } __attribute__ ((packed)); union fsf_qtcb_bottom { -- cgit v1.2.3