^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) }