Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * zfcp device driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Functions to handle diagnostics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Copyright IBM Corp. 2018
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/kernfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include "zfcp_diag.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "zfcp_ext.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "zfcp_def.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) static DECLARE_WAIT_QUEUE_HEAD(__zfcp_diag_publish_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * zfcp_diag_adapter_setup() - Setup storage for adapter diagnostics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * @adapter: the adapter to setup diagnostics for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * Creates the data-structures to store the diagnostics for an adapter. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * overwrites whatever was stored before at &zfcp_adapter->diagnostics!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * * 0	     - Everyting is OK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * * -ENOMEM - Could not allocate all/parts of the data-structures;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  *	       &zfcp_adapter->diagnostics remains unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	struct zfcp_diag_adapter *diag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	struct zfcp_diag_header *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	diag = kzalloc(sizeof(*diag), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	if (diag == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	diag->max_age = (5 * 1000); /* default value: 5 s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	/* setup header for port_data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	hdr = &diag->port_data.header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	spin_lock_init(&hdr->access_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	hdr->buffer = &diag->port_data.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	hdr->buffer_size = sizeof(diag->port_data.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	/* set the timestamp so that the first test on age will always fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	/* setup header for config_data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	hdr = &diag->config_data.header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	spin_lock_init(&hdr->access_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	hdr->buffer = &diag->config_data.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	hdr->buffer_size = sizeof(diag->config_data.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	/* set the timestamp so that the first test on age will always fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	adapter->diagnostics = diag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * zfcp_diag_adapter_free() - Frees all adapter diagnostics allocations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * @adapter: the adapter whose diagnostic structures should be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * Frees all data-structures in the given adapter that store diagnostics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * information. Can savely be called with partially setup diagnostics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	kfree(adapter->diagnostics);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	adapter->diagnostics = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * zfcp_diag_sysfs_setup() - Setup the sysfs-group for adapter-diagnostics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * @adapter: target adapter to which the group should be added.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * Return: 0 on success; Something else otherwise (see sysfs_create_group()).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) int zfcp_diag_sysfs_setup(struct zfcp_adapter *const adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	int rc = sysfs_create_group(&adapter->ccw_device->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 				    &zfcp_sysfs_diag_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		adapter->diagnostics->sysfs_established = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)  * zfcp_diag_sysfs_destroy() - Remove the sysfs-group for adapter-diagnostics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)  * @adapter: target adapter from which the group should be removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) void zfcp_diag_sysfs_destroy(struct zfcp_adapter *const adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	if (adapter->diagnostics == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	    !adapter->diagnostics->sysfs_established)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	 * We need this state-handling so we can prevent warnings being printed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	 * on the kernel-console in case we have to abort a halfway done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	 * zfcp_adapter_enqueue(), in which the sysfs-group was not yet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	 * established. sysfs_remove_group() does this checking as well, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	 * still prints a warning in case we try to remove a group that has not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	 * been established before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	adapter->diagnostics->sysfs_established = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	sysfs_remove_group(&adapter->ccw_device->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			   &zfcp_sysfs_diag_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  * zfcp_diag_update_xdata() - Update a diagnostics buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * @hdr: the meta data to update.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * @data: data to use for the update.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * @incomplete: flag stating whether the data in @data is incomplete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) void zfcp_diag_update_xdata(struct zfcp_diag_header *const hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			    const void *const data, const bool incomplete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	const unsigned long capture_timestamp = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	spin_lock_irqsave(&hdr->access_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	/* make sure we never go into the past with an update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	if (!time_after_eq(capture_timestamp, hdr->timestamp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	hdr->timestamp = capture_timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	hdr->incomplete = incomplete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	memcpy(hdr->buffer, data, hdr->buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	spin_unlock_irqrestore(&hdr->access_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  * zfcp_diag_update_port_data_buffer() - Implementation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  *					 &typedef zfcp_diag_update_buffer_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  *					 to collect and update Port Data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  * @adapter: Adapter to collect Port Data from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  * This call is SYNCHRONOUS ! It blocks till the respective command has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  * finished completely, or has failed in some way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)  * * 0		- Successfully retrieved new Diagnostics and Updated the buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)  *		  this also includes cases where data was retrieved, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)  *		  incomplete; you'll have to check the flag ``incomplete``
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  *		  of &struct zfcp_diag_header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)  * * see zfcp_fsf_exchange_port_data_sync() for possible error-codes (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)  *   excluding -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int zfcp_diag_update_port_data_buffer(struct zfcp_adapter *const adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	rc = zfcp_fsf_exchange_port_data_sync(adapter->qdio, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	if (rc == -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		rc = 0; /* signaling incomplete via struct zfcp_diag_header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	/* buffer-data was updated in zfcp_fsf_exchange_port_data_handler() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  * zfcp_diag_update_config_data_buffer() - Implementation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  *					   &typedef zfcp_diag_update_buffer_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  *					   to collect and update Config Data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * @adapter: Adapter to collect Config Data from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * This call is SYNCHRONOUS ! It blocks till the respective command has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * finished completely, or has failed in some way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  * * 0		- Successfully retrieved new Diagnostics and Updated the buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  *		  this also includes cases where data was retrieved, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  *		  incomplete; you'll have to check the flag ``incomplete``
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  *		  of &struct zfcp_diag_header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  * * see zfcp_fsf_exchange_config_data_sync() for possible error-codes (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  *   excluding -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int zfcp_diag_update_config_data_buffer(struct zfcp_adapter *const adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	rc = zfcp_fsf_exchange_config_data_sync(adapter->qdio, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	if (rc == -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		rc = 0; /* signaling incomplete via struct zfcp_diag_header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	/* buffer-data was updated in zfcp_fsf_exchange_config_data_handler() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int __zfcp_diag_update_buffer(struct zfcp_adapter *const adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 				     struct zfcp_diag_header *const hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 				     zfcp_diag_update_buffer_func buffer_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 				     unsigned long *const flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	__must_hold(hdr->access_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	if (hdr->updating == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		rc = wait_event_interruptible_lock_irq(__zfcp_diag_publish_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 						       hdr->updating == 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 						       hdr->access_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		rc = (rc == 0 ? -EAGAIN : -EINTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		hdr->updating = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		spin_unlock_irqrestore(&hdr->access_lock, *flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		/* unlocked, because update function sleeps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		rc = buffer_update(adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		spin_lock_irqsave(&hdr->access_lock, *flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		hdr->updating = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		 * every thread waiting here went via an interruptible wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		 * so its fine to only wake those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		wake_up_interruptible_all(&__zfcp_diag_publish_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) __zfcp_diag_test_buffer_age_isfresh(const struct zfcp_diag_adapter *const diag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 				    const struct zfcp_diag_header *const hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	__must_hold(hdr->access_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	const unsigned long now = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	 * Should not happen (data is from the future).. if it does, still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	 * signal that it needs refresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	if (!time_after_eq(now, hdr->timestamp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	if (jiffies_to_msecs(now - hdr->timestamp) >= diag->max_age)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)  * zfcp_diag_update_buffer_limited() - Collect diagnostics and update a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)  *				       diagnostics buffer rate limited.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)  * @adapter: Adapter to collect the diagnostics from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)  * @hdr: buffer-header for which to update with the collected diagnostics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)  * @buffer_update: Specific implementation for collecting and updating.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)  * This function will cause an update of the given @hdr by calling the also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)  * given @buffer_update function. If called by multiple sources at the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)  * time, it will synchornize the update by only allowing one source to call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)  * @buffer_update and the others to wait for that source to complete instead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)  * (the wait is interruptible).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)  * Additionally this version is rate-limited and will only exit if either the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)  * buffer is fresh enough (within the limit) - it will do nothing if the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  * is fresh enough to begin with -, or if the source/thread that started this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  * update is the one that made the update (to prevent endless loops).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)  * * 0		- If the update was successfully published and/or the buffer is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)  *		  fresh enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)  * * -EINTR	- If the thread went into the wait-state and was interrupted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)  * * whatever @buffer_update returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int zfcp_diag_update_buffer_limited(struct zfcp_adapter *const adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 				    struct zfcp_diag_header *const hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 				    zfcp_diag_update_buffer_func buffer_update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	spin_lock_irqsave(&hdr->access_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	for (rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	     !__zfcp_diag_test_buffer_age_isfresh(adapter->diagnostics, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	     rc = 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		rc = __zfcp_diag_update_buffer(adapter, hdr, buffer_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 					       &flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		if (rc != -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	spin_unlock_irqrestore(&hdr->access_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }