1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <misc/cxl.h>
16#include <asm/unaligned.h>
17
18#include <scsi/scsi_host.h>
19#include <uapi/scsi/cxlflash_ioctl.h>
20
21#include "sislite.h"
22#include "common.h"
23#include "vlun.h"
24#include "superpipe.h"
25
26
27
28
29
30
31
32
33static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid)
34{
35 struct cxlflash_cfg *cfg = shost_priv(sdev->host);
36 struct device *dev = &cfg->dev->dev;
37 struct llun_info *lli = NULL;
38
39 lli = kzalloc(sizeof(*lli), GFP_KERNEL);
40 if (unlikely(!lli)) {
41 dev_err(dev, "%s: could not allocate lli\n", __func__);
42 goto out;
43 }
44
45 lli->sdev = sdev;
46 lli->host_no = sdev->host->host_no;
47 lli->in_table = false;
48
49 memcpy(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN);
50out:
51 return lli;
52}
53
54
55
56
57
58
59
60
61static struct glun_info *create_global(struct scsi_device *sdev, u8 *wwid)
62{
63 struct cxlflash_cfg *cfg = shost_priv(sdev->host);
64 struct device *dev = &cfg->dev->dev;
65 struct glun_info *gli = NULL;
66
67 gli = kzalloc(sizeof(*gli), GFP_KERNEL);
68 if (unlikely(!gli)) {
69 dev_err(dev, "%s: could not allocate gli\n", __func__);
70 goto out;
71 }
72
73 mutex_init(&gli->mutex);
74 memcpy(gli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN);
75out:
76 return gli;
77}
78
79
80
81
82
83
84
85
86static struct llun_info *lookup_local(struct cxlflash_cfg *cfg, u8 *wwid)
87{
88 struct llun_info *lli, *temp;
89
90 list_for_each_entry_safe(lli, temp, &cfg->lluns, list)
91 if (!memcmp(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN))
92 return lli;
93
94 return NULL;
95}
96
97
98
99
100
101
102
103static struct glun_info *lookup_global(u8 *wwid)
104{
105 struct glun_info *gli, *temp;
106
107 list_for_each_entry_safe(gli, temp, &global.gluns, list)
108 if (!memcmp(gli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN))
109 return gli;
110
111 return NULL;
112}
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
135{
136 struct cxlflash_cfg *cfg = shost_priv(sdev->host);
137 struct device *dev = &cfg->dev->dev;
138 struct llun_info *lli = NULL;
139 struct glun_info *gli = NULL;
140
141 if (unlikely(!wwid))
142 goto out;
143
144 lli = lookup_local(cfg, wwid);
145 if (lli)
146 goto out;
147
148 lli = create_local(sdev, wwid);
149 if (unlikely(!lli))
150 goto out;
151
152 gli = lookup_global(wwid);
153 if (gli) {
154 lli->parent = gli;
155 list_add(&lli->list, &cfg->lluns);
156 goto out;
157 }
158
159 gli = create_global(sdev, wwid);
160 if (unlikely(!gli)) {
161 kfree(lli);
162 lli = NULL;
163 goto out;
164 }
165
166 lli->parent = gli;
167 list_add(&lli->list, &cfg->lluns);
168
169 list_add(&gli->list, &global.gluns);
170
171out:
172 dev_dbg(dev, "%s: returning lli=%p, gli=%p\n", __func__, lli, gli);
173 return lli;
174}
175
176
177
178
179
180void cxlflash_term_local_luns(struct cxlflash_cfg *cfg)
181{
182 struct llun_info *lli, *temp;
183
184 mutex_lock(&global.mutex);
185 list_for_each_entry_safe(lli, temp, &cfg->lluns, list) {
186 list_del(&lli->list);
187 kfree(lli);
188 }
189 mutex_unlock(&global.mutex);
190}
191
192
193
194
195void cxlflash_list_init(void)
196{
197 INIT_LIST_HEAD(&global.gluns);
198 mutex_init(&global.mutex);
199 global.err_page = NULL;
200}
201
202
203
204
205void cxlflash_term_global_luns(void)
206{
207 struct glun_info *gli, *temp;
208
209 mutex_lock(&global.mutex);
210 list_for_each_entry_safe(gli, temp, &global.gluns, list) {
211 list_del(&gli->list);
212 cxlflash_ba_terminate(&gli->blka.ba_lun);
213 kfree(gli);
214 }
215 mutex_unlock(&global.mutex);
216}
217
218
219
220
221
222
223
224
225
226
227
228
229int cxlflash_manage_lun(struct scsi_device *sdev,
230 struct dk_cxlflash_manage_lun *manage)
231{
232 struct cxlflash_cfg *cfg = shost_priv(sdev->host);
233 struct device *dev = &cfg->dev->dev;
234 struct llun_info *lli = NULL;
235 int rc = 0;
236 u64 flags = manage->hdr.flags;
237 u32 chan = sdev->channel;
238
239 mutex_lock(&global.mutex);
240 lli = find_and_create_lun(sdev, manage->wwid);
241 dev_dbg(dev, "%s: WWID=%016llx%016llx, flags=%016llx lli=%p\n",
242 __func__, get_unaligned_be64(&manage->wwid[0]),
243 get_unaligned_be64(&manage->wwid[8]), manage->hdr.flags, lli);
244 if (unlikely(!lli)) {
245 rc = -ENOMEM;
246 goto out;
247 }
248
249 if (flags & DK_CXLFLASH_MANAGE_LUN_ENABLE_SUPERPIPE) {
250
251
252
253
254
255 lli->port_sel |= CHAN2PORTMASK(chan);
256 lli->lun_id[chan] = lun_to_lunid(sdev->lun);
257 sdev->hostdata = lli;
258 } else if (flags & DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE) {
259 if (lli->parent->mode != MODE_NONE)
260 rc = -EBUSY;
261 else {
262
263
264
265
266 sdev->hostdata = NULL;
267 lli->port_sel &= ~CHAN2PORTMASK(chan);
268 if (lli->port_sel == 0U)
269 lli->in_table = false;
270 }
271 }
272
273 dev_dbg(dev, "%s: port_sel=%08x chan=%u lun_id=%016llx\n",
274 __func__, lli->port_sel, chan, lli->lun_id[chan]);
275
276out:
277 mutex_unlock(&global.mutex);
278 dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
279 return rc;
280}
281