^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * CXL Flash Device Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Written by: Manoj N. Kumar <manoj@linux.vnet.ibm.com>, IBM Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2015 IBM Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <uapi/scsi/cxlflash_ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "sislite.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "vlun.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "superpipe.h"
^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) * create_local() - allocate and initialize a local LUN information structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * @sdev: SCSI device associated with LUN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * @wwid: World Wide Node Name for LUN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Return: Allocated local llun_info structure on success, NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct cxlflash_cfg *cfg = shost_priv(sdev->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct device *dev = &cfg->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct llun_info *lli = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) lli = kzalloc(sizeof(*lli), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (unlikely(!lli)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) dev_err(dev, "%s: could not allocate lli\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) lli->sdev = sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) lli->host_no = sdev->host->host_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) lli->in_table = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) memcpy(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return lli;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * create_global() - allocate and initialize a global LUN information structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * @sdev: SCSI device associated with LUN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * @wwid: World Wide Node Name for LUN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Return: Allocated global glun_info structure on success, NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static struct glun_info *create_global(struct scsi_device *sdev, u8 *wwid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct cxlflash_cfg *cfg = shost_priv(sdev->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct device *dev = &cfg->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct glun_info *gli = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) gli = kzalloc(sizeof(*gli), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (unlikely(!gli)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) dev_err(dev, "%s: could not allocate gli\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) mutex_init(&gli->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) memcpy(gli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return gli;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * lookup_local() - find a local LUN information structure by WWID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * @cfg: Internal structure associated with the host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * @wwid: WWID associated with LUN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * Return: Found local lun_info structure on success, NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static struct llun_info *lookup_local(struct cxlflash_cfg *cfg, u8 *wwid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct llun_info *lli, *temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) list_for_each_entry_safe(lli, temp, &cfg->lluns, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!memcmp(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return lli;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * lookup_global() - find a global LUN information structure by WWID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @wwid: WWID associated with LUN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Return: Found global lun_info structure on success, NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static struct glun_info *lookup_global(u8 *wwid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct glun_info *gli, *temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) list_for_each_entry_safe(gli, temp, &global.gluns, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (!memcmp(gli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return gli;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * find_and_create_lun() - find or create a local LUN information structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * @sdev: SCSI device associated with LUN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * @wwid: WWID associated with LUN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * The LUN is kept both in a local list (per adapter) and in a global list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * (across all adapters). Certain attributes of the LUN are local to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * adapter (such as index, port selection mask, etc.).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * The block allocation map is shared across all adapters (i.e. associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * wih the global list). Since different attributes are associated with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * the per adapter and global entries, allocate two separate structures for each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * LUN (one local, one global).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * Keep a pointer back from the local to the global entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * This routine assumes the caller holds the global mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * Return: Found/Allocated local lun_info structure on success, NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct cxlflash_cfg *cfg = shost_priv(sdev->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct device *dev = &cfg->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct llun_info *lli = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct glun_info *gli = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (unlikely(!wwid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) lli = lookup_local(cfg, wwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (lli)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) lli = create_local(sdev, wwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (unlikely(!lli))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) gli = lookup_global(wwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (gli) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) lli->parent = gli;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) list_add(&lli->list, &cfg->lluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) gli = create_global(sdev, wwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (unlikely(!gli)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) kfree(lli);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) lli = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) lli->parent = gli;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) list_add(&lli->list, &cfg->lluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) list_add(&gli->list, &global.gluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) dev_dbg(dev, "%s: returning lli=%p, gli=%p\n", __func__, lli, gli);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return lli;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * cxlflash_term_local_luns() - Delete all entries from local LUN list, free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * @cfg: Internal structure associated with the host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) void cxlflash_term_local_luns(struct cxlflash_cfg *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct llun_info *lli, *temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) mutex_lock(&global.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) list_for_each_entry_safe(lli, temp, &cfg->lluns, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) list_del(&lli->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) kfree(lli);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) mutex_unlock(&global.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * cxlflash_list_init() - initializes the global LUN list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) void cxlflash_list_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) INIT_LIST_HEAD(&global.gluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) mutex_init(&global.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) global.err_page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * cxlflash_term_global_luns() - frees resources associated with global LUN list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) void cxlflash_term_global_luns(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct glun_info *gli, *temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) mutex_lock(&global.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) list_for_each_entry_safe(gli, temp, &global.gluns, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) list_del(&gli->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) cxlflash_ba_terminate(&gli->blka.ba_lun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) kfree(gli);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) mutex_unlock(&global.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * cxlflash_manage_lun() - handles LUN management activities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * @sdev: SCSI device associated with LUN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * @manage: Manage ioctl data structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * This routine is used to notify the driver about a LUN's WWID and associate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * SCSI devices (sdev) with a global LUN instance. Additionally it serves to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * change a LUN's operating mode: legacy or superpipe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * Return: 0 on success, -errno on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int cxlflash_manage_lun(struct scsi_device *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct dk_cxlflash_manage_lun *manage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct cxlflash_cfg *cfg = shost_priv(sdev->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct device *dev = &cfg->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct llun_info *lli = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) u64 flags = manage->hdr.flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u32 chan = sdev->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) mutex_lock(&global.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) lli = find_and_create_lun(sdev, manage->wwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) dev_dbg(dev, "%s: WWID=%016llx%016llx, flags=%016llx lli=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) __func__, get_unaligned_be64(&manage->wwid[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) get_unaligned_be64(&manage->wwid[8]), manage->hdr.flags, lli);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (unlikely(!lli)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (flags & DK_CXLFLASH_MANAGE_LUN_ENABLE_SUPERPIPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * Update port selection mask based upon channel, store off LUN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * in unpacked, AFU-friendly format, and hang LUN reference in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * the sdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) lli->port_sel |= CHAN2PORTMASK(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) lli->lun_id[chan] = lun_to_lunid(sdev->lun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) sdev->hostdata = lli;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) } else if (flags & DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (lli->parent->mode != MODE_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * Clean up local LUN for this port and reset table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * tracking when no more references exist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) sdev->hostdata = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) lli->port_sel &= ~CHAN2PORTMASK(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (lli->port_sel == 0U)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) lli->in_table = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) dev_dbg(dev, "%s: port_sel=%08x chan=%u lun_id=%016llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) __func__, lli->port_sel, chan, lli->lun_id[chan]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) mutex_unlock(&global.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }