Merge ~fheimes/ubuntu/+source/s390-tools:s390-tools-sru-lp1903984-focal into ubuntu/+source/s390-tools:ubuntu/focal-devel

Proposed by Frank Heimes
Status: Merged
Merge reported by: Frank Heimes
Merged at revision: 2e2fee8f9b265c8eeb192b9085dd28eb0a43956f
Proposed branch: ~fheimes/ubuntu/+source/s390-tools:s390-tools-sru-lp1903984-focal
Merge into: ubuntu/+source/s390-tools:ubuntu/focal-devel
Diff against target: 1194 lines (+1160/-0)
5 files modified
debian/changelog (+17/-0)
debian/patches/s390-tools-sru-lp1902179-focal.patch (+689/-0)
debian/patches/s390-tools-sru-lp1903984-focal.patch (+49/-0)
debian/patches/s390-tools-sru-lp1908371-focal.patch (+402/-0)
debian/patches/series (+3/-0)
Reviewer Review Type Date Requested Status
Lukas Märdian (community) Approve
Review via email: mp+396775@code.launchpad.net

Description of the change

debian/patches/s390-tools-lp1903984-focal.patch
  zcryptstats: Fix handling of partial results with many domains
  - zconf/zcrypt/zcryptstats.c: code fix to pass the correct next-domain
    to the subsequent CHSC call of a partial response

debian/patches/s390-tools-sru-lp1908371-focal.patch:
  zipl command isn't working correctly in combination with the -M
  (respectively --mvdump) option.

debian/patches/s390-tools-sru-lp1902179-focal
  zcryptstats: Fix handling of partial results with many domains

Test build is available here:
https://launchpad.net/~fheimes/+archive/ubuntu/lp1903984-1908371-1902179

To post a comment you must log in.
Revision history for this message
Lukas Märdian (slyon) wrote :

Hi Frank, thank you very much for preparing this SRU! I like your extensive DEP-3 headers. I double-checked that the package builds with all new patches applied in Focal. Also, I checked it against the referenced upstream patches. I found some slight divergence there, mentioned inline.

Could you please comment on why we need to modify the upstream commit at those places, or alternatively adopt to the same changeset upstream applied? I'd like to stay as close to upstream as possible, so we won't have problems applying additional patches in the future.

Cheers,
  Lukas

review: Needs Information
Revision history for this message
Frank Heimes (fheimes) wrote :

The issue with the i Makefile (pl_tools/Makefile) especially the duplicate line "libs = $(rootdir)/libutil/libutil.a" is an artifact of a former (Ubuntu-) patch that was applied to focal.
It's not in H/devel, nor in G, but was introduced with 795d2c9 (which is Head -19).

Revision history for this message
Frank Heimes (fheimes) wrote :

Regarding the "enum target_type target_type;" line,
this line was indeed in the past commented like this:
 enum target_type target_type; /* CCW, FCP, NSS or NODE */
and with the expansion of the target types by target_type NVMe, the comment was changed to:
 enum target_type target_type; /* CCW,FCP,NVME,NSS or NODE */
and this is also upstream the case - and indeed unusual, because other comments follow the form:
/* CCW, FCP, NVME, NSS */
(means <comma><space>)
I assume that the NVME support was added by a different IBM developer, hence the different style.
Since I simply picked the upstream commit and applied it (w/o any adjustments), this little difference in style was transferred, too.

Revision history for this message
Lukas Märdian (slyon) wrote :

Okay, so as discussed on a side-channel, we're refreshing the path "debian/patches/s390-tools-sru-lp1902179-focal.patch" a bit, not to introduce any extra delta vs upstream.

See this MP for reference: https://code.launchpad.net/~slyon/ubuntu/+source/s390-tools/+git/s390-tools/+merge/396905

Build of the package with refreshed patch confirmed: https://launchpad.net/~slyon/+archive/ubuntu/testing/+build/20935925

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/debian/changelog b/debian/changelog
index 33febaf..402dbc6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,20 @@
1s390-tools (2.12.0-0ubuntu3.2) focal; urgency=medium
2
3 * debian/patches/s390-tools-sru-lp1903984-focal.patch
4 zcryptstats: Fix handling of partial results with many domains
5 Thanks to Ingo Franzki (LP: #1903984)
6 * debian/patches/s390-tools-sru-lp1908371-focal.patch:
7 zipl command isn't working correctly in combination with the -M
8 (respectively --mvdump) option.
9 cherry-picking 4 commits from s390-tools v2.15.1 to v2.14
10 Thanks to Stefan Haberland and Sven Schnelle (LP: #1908371)
11 * debian/patches/s390-tools-sru-lp1902179-focal.patch:
12 Enabling IPL (boot) from NVMe devices by adding 2 upstream commits
13 from s390-tools v2.13/2.14 as backports to this v2.12 base.
14 Thanks to Jason J. Herne (LP: #1902179)
15
16 -- Frank Heimes <frank.heimes@canonical.com> Fri, 22 Jan 2021 15:52:19 +0100
17
1s390-tools (2.12.0-0ubuntu3.1) focal; urgency=medium18s390-tools (2.12.0-0ubuntu3.1) focal; urgency=medium
219
3 * debian/patches/0082-*.patch .. 0111-*.patch (LP: #1892350)20 * debian/patches/0082-*.patch .. 0111-*.patch (LP: #1892350)
diff --git a/debian/patches/s390-tools-sru-lp1902179-focal.patch b/debian/patches/s390-tools-sru-lp1902179-focal.patch
4new file mode 10064421new file mode 100644
index 0000000..91c2dcf
--- /dev/null
+++ b/debian/patches/s390-tools-sru-lp1902179-focal.patch
@@ -0,0 +1,689 @@
1Description: Enabling IPL (boot) from NVMe devices in focal
2 These three patches are needed to enable IPL (boot on s390x) from NVMe devices
3 They are already upstream and in the groovy and hirsute versions of the s390-tools.
4 A cherry pick wasn't cleanly possible, hence these backports that are based on:
5 1b65b23b4398 "zipl: Support nvme devices" (went in v2.13.0)
6 0472b5ea5c97 "ipl-tools: Add nvme device support to lsreipl/chreipl" (went in v2.14.0)
7Author: Jason J. Herne <jjherne@linux.ibm.com>
8Origin: backports of:
9 https://github.com/ibm-s390-tools/s390-tools/commit/1b65b23b43985cb8a1da2ef399ec6def31bbcc69
10 https://github.com/ibm-s390-tools/s390-tools/commit/0472b5ea5c97f2c59a938deebe53b7f27e8a9a32
11Bug: IBM Bugzilla 188732
12Bug-IBM: https://bugs.launchpad.net/bugs/1902179
13Forwarded: not-needed
14Applied-Upstream: >= 2.14.0
15Reviewed-by: Frank Heimes <frank.heimes@canonical.com>
16Last-Update: 2021-01-22
17---
18This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
19--- a/ipl_tools/cmd_chreipl.c
20+++ b/ipl_tools/cmd_chreipl.c
21@@ -28,12 +28,14 @@
22 TT_FCP,
23 TT_NSS,
24 TT_NODE,
25+ TT_NVME,
26 };
27
28 enum reipl_type {
29 REIPL_FCP,
30 REIPL_CCW,
31- REIPL_NSS
32+ REIPL_NSS,
33+ REIPL_NVME,
34 };
35
36 static const char *const usage_chreipl =
37@@ -41,6 +43,7 @@
38 "\n"
39 " chreipl [ccw] [-d] <DEVICE> [OPTIONS]\n"
40 " chreipl [fcp] [-d] <DEVICE> [-w] <WWPN> [-l] <LUN> [OPTIONS]\n"
41+" chreipl nvme [-i] <FID> [-s] <NSID> [OPTIONS]\n"
42 " chreipl [node] <NODE|DIR> [OPTIONS]\n"
43 " chreipl nss [-n] <NAME> [OPTIONS]\n"
44 " chreipl [-h] [-v]\n"
45@@ -48,6 +51,7 @@
46 "The following re-IPL targets are supported:\n"
47 " ccw IPL from CCW device\n"
48 " fcp IPL from FCP device\n"
49+" nvme IPL from NVME device\n"
50 " nss IPL from NSS\n"
51 " node IPL from device specified by device node or directory\n"
52 "\n"
53@@ -68,6 +72,12 @@
54 " -b, --bootprog <BPROG> Bootprog specification\n"
55 " -L, --loadparm <PARM> Loadparm specification\n"
56 "\n"
57+"Options for nvme target:\n"
58+" -i, --fid <FUNCTION_ID> PCI Function ID of NVME IPL device (hex)\n"
59+" -s --nsid <NAMESPACE_ID> Namespace ID of NVME IPL device (decimal, default 1)\n"
60+" -b, --bootprog <BPROG> Bootprog specification\n"
61+" -L, --loadparm <PARM> Loadparm specification\n"
62+"\n"
63 "Options for nss target:\n"
64 " -n, --name <NAME> Identifier of the NSS\n"
65 "\n"
66@@ -84,6 +94,10 @@
67 char lun[20]; /* 18 character +0x" */
68 int lun_set;
69 char busid[10]; /* Bus ID e.g. 0.0.4711 */
70+ int fid_set;
71+ char fid[FID_MAX_LEN];
72+ int nsid_set;
73+ char nsid[11]; /* 10 decimal chars + null */
74 int busid_set;
75 char dev[15]; /* Device (e.g. dasda) */
76 int dev_set;
77@@ -92,10 +106,10 @@
78 char bootparms[4096];
79 int bootparms_set;
80 int force_set;
81- enum target_type target_type; /* CCW, FCP, NSS or NODE */
82+ enum target_type target_type; /* CCW, FCP, NVME, NSS or NODE */
83 int target_type_set;
84 int target_type_auto_mode;
85- enum reipl_type reipl_type; /* CCW, FCP, NSS */
86+ enum reipl_type reipl_type; /* CCW, FCP, NVME, NSS */
87 } l;
88
89 static void __noreturn print_usage_chreipl_exit(void)
90@@ -226,6 +240,34 @@
91 l.wwpn_set = 1;
92 }
93
94+static void set_nvme_nsid(const char *nsid)
95+{
96+ unsigned long long nsid_tmp;
97+ char *endptr;
98+
99+ nsid_tmp = strtoull(nsid, &endptr, 10);
100+ if (*endptr)
101+ ERR_EXIT("NSID \"%s\" is not a decimal number", nsid);
102+ snprintf(l.nsid, sizeof(l.nsid), "%08llu", nsid_tmp);
103+ l.nsid_set = 1;
104+}
105+
106+static void set_nvme_fid(const char *fid)
107+{
108+ unsigned long long fid_tmp;
109+ char *endptr;
110+
111+ fid_tmp = strtoull(fid, &endptr, 16);
112+ if (*endptr)
113+ ERR_EXIT("FID \"%s\" is not a hexadecimal number", fid);
114+ snprintf(l.fid, sizeof(l.fid), "0x%08llx", fid_tmp);
115+ l.fid_set = 1;
116+
117+ /* nsid defaults to 1, if not already set */
118+ if (!l.nsid_set)
119+ set_nvme_nsid("1");
120+}
121+
122 static void parse_fcp_args(char *nargv[], int nargc)
123 {
124 /*
125@@ -245,6 +287,28 @@
126 set_lun(nargv[2]);
127 }
128
129+static void parse_nvme_args(char *nargv[], int nargc)
130+{
131+ /*
132+ * we might be called like this:
133+ * chreipl nvme 0x13 1
134+ */
135+ if (l.busid_set || l.fid_set || l.nsid_set || l.dev_set)
136+ ERR_EXIT("Use either options or positional parameters");
137+ if (nargc > 2)
138+ ERR_EXIT("Too many arguments specified for \"nvme\" re-IPL "
139+ "type");
140+ else if (nargc < 1)
141+ ERR_EXIT("The \"nvme\" re-IPL type requires function id, and "
142+ "optional namespace id");
143+ set_nvme_fid(nargv[0]);
144+
145+ if (nargc == 2)
146+ set_nvme_nsid(nargv[1]);
147+ else
148+ set_nvme_nsid("1");
149+}
150+
151 static void parse_ccw_args(char *nargv[], int nargc)
152 {
153 /*
154@@ -285,6 +349,13 @@
155 dev_name[i] = 0;
156 }
157
158+static void dev_from_part_nvme(char *dev_name)
159+{
160+ char *delim = strrchr(dev_name, 'p');
161+ if (delim)
162+ *delim = 0;
163+}
164+
165 static int set_reipl_type(const char *dev_name)
166 {
167 if (strncmp(dev_name, "dasd", strlen("dasd")) == 0 ||
168@@ -292,11 +363,18 @@
169 l.reipl_type = REIPL_CCW;
170 else if (strncmp(dev_name, "sd", strlen("sd")) == 0)
171 l.reipl_type = REIPL_FCP;
172+ else if (strncmp(dev_name, "nvme", strlen("nvme")) == 0)
173+ l.reipl_type = REIPL_NVME;
174 else
175 return -1;
176
177 util_strlcpy(l.dev, dev_name, sizeof(l.dev));
178- dev_from_part(l.dev);
179+
180+ if (l.reipl_type == REIPL_NVME)
181+ dev_from_part_nvme(l.dev);
182+ else
183+ dev_from_part(l.dev);
184+
185 l.dev_set = 1;
186 return 0;
187 }
188@@ -399,6 +477,9 @@
189 case TT_FCP:
190 parse_fcp_args(nargv, nargc);
191 break;
192+ case TT_NVME:
193+ parse_nvme_args(nargv, nargc);
194+ break;
195 case TT_CCW:
196 parse_ccw_args(nargv, nargc);
197 break;
198@@ -420,6 +501,14 @@
199 "and LUN");
200 }
201
202+static void check_nvme_opts(void)
203+{
204+ if (l.nss_name_set || l.wwpn_set || l.lun_set || l.busid_set)
205+ ERR_EXIT("Invalid option for \"nvme\" target specified");
206+ if (!(l.fid_set && l.nsid_set))
207+ ERR_EXIT("The \"nvme\" target requires FID, and optional NSID");
208+}
209+
210 static void check_ccw_opts(void)
211 {
212 if (l.bootprog_set || l.lun_set || l.wwpn_set || l.nss_name_set)
213@@ -469,6 +558,8 @@
214 { "device", required_argument, NULL, 'd' },
215 { "lun", required_argument, NULL, 'l' },
216 { "wwpn", required_argument, NULL, 'w' },
217+ { "fid", required_argument, NULL, 'i' },
218+ { "nsid", required_argument, NULL, 's' },
219 { "loadparm", required_argument, NULL, 'L' },
220 { "name", required_argument, NULL, 'n' },
221 { "bootparms", required_argument, NULL, 'p' },
222@@ -476,7 +567,7 @@
223 { "version", no_argument, NULL, 'v' },
224 { NULL, 0, NULL, 0 }
225 };
226- static const char optstr[] = "hcd:vw:l:fL:b:n:p:";
227+ static const char optstr[] = "hcd:vw:l:fL:b:n:p:i:s:";
228
229 /* dont run without any argument */
230 if (argc == 1)
231@@ -488,6 +579,8 @@
232 set_target_type(TT_CCW, 0);
233 else if (strcmp(argv[1], "nss") == 0)
234 set_target_type(TT_NSS, 0);
235+ else if (strcmp(argv[1], "nvme") == 0)
236+ set_target_type(TT_NVME, 0);
237 else if (strcmp(argv[1], "node") == 0)
238 set_target_type(TT_NODE, 0);
239 else
240@@ -500,9 +593,15 @@
241 case 'd':
242 set_device(optarg);
243 break;
244+ case 'i':
245+ set_nvme_fid(optarg);
246+ break;
247 case 'l':
248 set_lun(optarg);
249 break;
250+ case 's':
251+ set_nvme_nsid(optarg);
252+ break;
253 case 'w':
254 set_wwpn(optarg);
255 break;
256@@ -650,6 +749,40 @@
257 print_fcp(0, 0);
258 }
259
260+static void chreipl_nvme(void)
261+{
262+ check_nvme_opts();
263+
264+ if (!nvme_is_device(l.fid, l.nsid) && !l.force_set) {
265+ ERR_EXIT("Could not find NVME device with fid %s and nsid %s",
266+ l.fid, l.nsid);
267+ }
268+ check_exists("reipl/nvme/fid", "\"nvme\" re-IPL target");
269+
270+ if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_FCP_MAX) {
271+ ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
272+ strlen(l.bootparms), BOOTPARMS_FCP_MAX);
273+ }
274+
275+ write_str_optional(l.loadparm, "reipl/nvme/loadparm", l.loadparm_set,
276+ "loadparm");
277+ write_str_optional(l.bootparms, "reipl/nvme/scp_data", l.bootparms_set,
278+ "boot parameters");
279+ write_str(l.fid, "reipl/nvme/fid");
280+ write_str(l.nsid, "reipl/nvme/nsid");
281+ /*
282+ * set the boot record logical block address. Master boot
283+ * record. It is always 0 for Linux
284+ */
285+ write_str("0", "reipl/nvme/br_lba");
286+ if (!l.bootprog_set)
287+ sprintf(l.bootprog, "0");
288+ write_str(l.bootprog, "reipl/nvme/bootprog");
289+ write_str("nvme", "reipl/reipl_type");
290+
291+ print_nvme(0, 0);
292+}
293+
294 static void chreipl_nss(void)
295 {
296 check_nss_opts();
297@@ -690,6 +823,13 @@
298 l.busid_set = 1;
299 chreipl_fcp();
300 break;
301+ case REIPL_NVME:
302+ nvme_fid_get(l.dev, l.fid);
303+ l.fid_set = 1;
304+ nvme_nsid_get(l.dev, l.nsid);
305+ l.nsid_set = 1;
306+ chreipl_nvme();
307+ break;
308 default:
309 ERR_EXIT("Internal error: chreipl_node");
310 }
311@@ -705,6 +845,9 @@
312 case TT_FCP:
313 chreipl_fcp();
314 break;
315+ case TT_NVME:
316+ chreipl_nvme();
317+ break;
318 case TT_NSS:
319 chreipl_nss();
320 break;
321--- a/ipl_tools/cmd_lsreipl.c
322+++ b/ipl_tools/cmd_lsreipl.c
323@@ -81,6 +81,35 @@
324 print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
325 }
326
327+void print_nvme(int show_ipl, int dump)
328+{
329+ char *dir = show_ipl ? "ipl" : "reipl/nvme";
330+ char *path_bootparms = show_ipl ? "/sys/firmware/ipl/scp_data" :
331+ "/sys/firmware/reipl/nvme/scp_data";
332+ char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
333+ "/sys/firmware/reipl/nvme/loadparm";
334+ char loadparm[9], loadparm_path[PATH_MAX];
335+
336+ if (dump)
337+ printf("%-12s nvme_dump\n", get_ipl_banner(show_ipl));
338+ else
339+ printf("%-12s nvme\n", get_ipl_banner(show_ipl));
340+
341+ print_fw_str("FID: %s\n", dir, "fid");
342+ print_fw_str("NSID: %s\n", dir, "nsid");
343+ print_fw_str("bootprog: %s\n", dir, "bootprog");
344+ print_fw_str("br_lba: %s\n", dir, "br_lba");
345+ if (access(path_loadparm, R_OK) == 0) {
346+ sprintf(loadparm_path, "%s/%s", dir, "loadparm");
347+ read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
348+ if (strcmp(loadparm, " ") == 0)
349+ loadparm[0] = 0;
350+ printf("Loadparm: \"%s\"\n", loadparm);
351+ }
352+ if (access(path_bootparms, R_OK) == 0)
353+ print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
354+}
355+
356 void print_ccw(int show_ipl)
357 {
358 char loadparm[9], loadparm_path[PATH_MAX];
359@@ -149,6 +178,10 @@
360 print_fcp(l.ipl_set, 0);
361 else if (strcmp(reipl_type_str, "fcp_dump") == 0)
362 print_fcp(l.ipl_set, 1);
363+ else if (strcmp(reipl_type_str, "nvme") == 0)
364+ print_nvme(l.ipl_set, 0);
365+ else if (strcmp(reipl_type_str, "nvme_dump") == 0)
366+ print_nvme(l.ipl_set, 1);
367 else if (strcmp(reipl_type_str, "ccw") == 0)
368 print_ccw(l.ipl_set);
369 else if (strcmp(reipl_type_str, "nss") == 0)
370--- a/ipl_tools/ipl_tools.h
371+++ b/ipl_tools/ipl_tools.h
372@@ -43,6 +43,7 @@
373
374 extern void print_ccw(int show_ipl);
375 extern void print_fcp(int show_ipl, int dump);
376+extern void print_nvme(int show_ipl, int dump);
377 extern void print_nss(int show_ipl);
378
379 /*
380@@ -71,6 +72,16 @@
381 extern void fcp_busid_get(const char *device, char *devno);
382
383 /*
384+ * NVME
385+ */
386+#define FID_MAX_LEN 11 /* 8 characters + 0x + null */
387+#define NVME_PATH_MAX (PATH_MAX + NAME_MAX + 1)
388+
389+extern void nvme_fid_get(const char *device, char *fid);
390+extern void nvme_nsid_get(const char *device, char *nsid);
391+int nvme_is_device(char *fid_str, char *nsid_str);
392+
393+/*
394 * CCW
395 */
396 extern int ccw_is_device(const char *devno);
397--- a/ipl_tools/Makefile
398+++ b/ipl_tools/Makefile
399@@ -6,7 +6,7 @@
400
401 libs = $(rootdir)/libutil/libutil.a
402
403-objects = main.o ccw.o fcp.o system.o shutdown.o \
404+objects = main.o ccw.o fcp.o nvme.o system.o shutdown.o \
405 cmd_lsshut.o cmd_chshut.o cmd_lsreipl.o cmd_chreipl.o proc.o
406
407 chreipl: $(objects) $(libs)
408@@ -40,4 +40,3 @@
409 $(DESTDIR)$(MANDIR)/man8
410
411 .PHONY: all install clean
412-
413--- a/ipl_tools/man/chreipl.8
414+++ b/ipl_tools/man/chreipl.8
415@@ -39,6 +39,9 @@
416 .RB "- " fcp :
417 Specify a FCP device for reboot
418 .TP
419+.RB "- " nvme :
420+Specify an NVMe device for reboot
421+.TP
422 .RB "- " nss :
423 Specify a named saved system (NSS) for reboot
424 .TP
425@@ -118,6 +121,11 @@
426 append kernel parameter "mem=" to restrict memory to 512 MB:
427
428 \fB# chreipl 0.0.1700 0x500507630300c562 0x401040b300000000 -p "mem=512M"\fP
429+
430+4. Next time reboot from the NVMe device with function id 0x13, namespace 1:
431+
432+\fB# chreipl nvme 0x13 1
433+
434 .SH ccw
435 Use the ccw re-IPL target for DASD devices that are accessed by the hardware
436 using channel command word (CCW) channels.
437@@ -192,6 +200,44 @@
438 .br
439
440 \fB# chreipl fcp -d 0.0.1700 -w 0x5005076... -l 0x401040b3... -b 2\fP
441+.SH nvme
442+Use the nvme re-IPL target for specifying an NVMe disk for reboot.
443+.TP
444+.BR "\-i" " or " "\-\-fid"
445+PCI Function ID of NVME IPL device (hex).
446+
447+.TP
448+.BR "\-s" " or " "\-\-nsid"
449+Namespace ID of the NVME IPL device (decimal, default 1).
450+
451+.TP
452+.BR "\-b" " or " "\-\-bootprog"
453+Specifies an entry in the boot configuration by defining the IPL boot
454+program selector. If omitted, '0' will be used.
455+
456+.TP
457+.BR "\-L" " or " "\-\-loadparm"
458+The loadparm for the nvme re-IPL target is not used to control the boot
459+configuration that is defined by the
460+.BR zipl (8)
461+boot menu. Instead it can be used to control higher level boot loaders
462+like GRUB. For more details refer to distribution specific documentation.
463+
464+.PP
465+\fBExamples:\fP
466+.br
467+
468+1. Next time reboot from the NVMe disk with function-id 0x13 and namespace 1:
469+.br
470+
471+\fB# chreipl nvme 0x13 1\fP
472+.br
473+
474+2. Use same configuration as (1) but choose boot program selector 2 and
475+use options instead of positional parameters:
476+.br
477+
478+\fB# chreipl nvme -i 0x13 -s 1 -b 2\fP
479 .SH nss
480 Use the nss re-IPL target to specify z/VM named saved systems (NSS) for
481 reboot.
482@@ -206,7 +252,7 @@
483
484 \fB# chreipl nss LINUX1\fP
485 .SH node
486-You can identify DASD or SCSI re-IPL devices indirectly through a device
487+You can identify DASD or SCSI, or NVMe re-IPL devices indirectly through a device
488 node or directory. The chreipl tool then determines the information
489 that you would otherwise have to specify with the ccw or fcp target.
490 .PP
491@@ -229,6 +275,11 @@
492
493 \fB# chreipl node /mnt/boot\fP
494
495+4. Next time reboot from the NVMe device represented by /dev/nvme0n1
496+.br
497+
498+\fB# chreipl node /dev/nvme0n1\fP
499+
500 .SH SEE ALSO
501 .BR lsreipl (8),
502 .BR zipl (8),
503--- /dev/null
504+++ b/ipl_tools/nvme.c
505@@ -0,0 +1,169 @@
506+/*
507+ * ipl_tools - Linux for System z reipl and shutdown tools
508+ *
509+ * NVMe device functions
510+ *
511+ * Copyright IBM Corp. 2020
512+ *
513+ * s390-tools is free software; you can redistribute it and/or modify
514+ * it under the terms of the MIT license. See LICENSE for details.
515+ */
516+#include <sys/types.h>
517+#include <dirent.h>
518+#include <limits.h>
519+#include <stdlib.h>
520+#include <unistd.h>
521+
522+#include "lib/util_libc.h"
523+#include "lib/util_file.h"
524+#include "ipl_tools.h"
525+
526+/*
527+ * Return the fid of a device
528+ */
529+void nvme_fid_get(const char *device, char *fid)
530+{
531+ char path[PATH_MAX], buf[FID_MAX_LEN];
532+
533+ snprintf(path, PATH_MAX, "/sys/block/%s/device/device/function_id",
534+ device);
535+ if (util_file_read_line(buf, FID_MAX_LEN, path))
536+ ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
537+
538+ util_strlcpy(fid, buf, FID_MAX_LEN);
539+}
540+/*
541+ * Return the nsid of a device
542+ */
543+void nvme_nsid_get(const char *device, char *nsid)
544+{
545+ char path[PATH_MAX], buf[FID_MAX_LEN];
546+
547+ snprintf(path, PATH_MAX, "/sys/block/%s/nsid", device);
548+ if (util_file_read_line(buf, FID_MAX_LEN, path))
549+ ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
550+
551+ util_strlcpy(nsid, buf, FID_MAX_LEN);
552+}
553+
554+static int next_entry(DIR *dir, char *in_path, char *out_path,
555+ unsigned char entry_type)
556+{
557+ struct dirent *dirent;
558+ char temp_path[NVME_PATH_MAX];
559+
560+ while ((dirent = readdir(dir)) != NULL) {
561+ if (strcmp(dirent->d_name, ".") == 0 ||
562+ strcmp(dirent->d_name, "..") == 0 ||
563+ dirent->d_type != entry_type)
564+ continue;
565+
566+ /* Resolve the symlink, if needed */
567+ if (dirent->d_type == DT_LNK) {
568+ snprintf(temp_path, sizeof(temp_path), "%s/%s", in_path,
569+ dirent->d_name);
570+ if (!realpath(temp_path, out_path))
571+ ERR_EXIT_ERRNO("Could not resolve link %s",
572+ temp_path);
573+ return 1;
574+ }
575+
576+ snprintf(out_path, NVME_PATH_MAX, "%s/%s", in_path,
577+ dirent->d_name);
578+ return 1;
579+ }
580+ return 0;
581+}
582+
583+static int nvme_getdev_by_fid(char *fidstr, char *devpath)
584+{
585+ char temp_path[PATH_MAX+19], real_path[PATH_MAX];
586+ char *sys_path = "/sys/class/nvme";
587+ u_int64_t target_fid, curfid;
588+ DIR *dir;
589+ char *end;
590+ int rc = -1;
591+
592+ target_fid = strtoul(fidstr, &end, 16);
593+ if (*end)
594+ ERR_EXIT("Invalid function_id given %s", fidstr);
595+
596+ dir = opendir(sys_path);
597+ if (!dir)
598+ ERR_EXIT("Could not open %s", sys_path);
599+
600+ errno = 0;
601+ while (next_entry(dir, sys_path, real_path, DT_LNK)) {
602+ snprintf(temp_path, sizeof(temp_path), "%s/%s", real_path,
603+ "device/function_id");
604+ if (access(temp_path, F_OK))
605+ continue;
606+
607+ if (util_file_read_ul(&curfid, 16, temp_path))
608+ ERR_EXIT("Invalid function_id found in %s", temp_path);
609+
610+ if (curfid == target_fid) {
611+ strncpy(devpath, real_path, PATH_MAX);
612+ rc = 0;
613+ break;
614+ }
615+ }
616+
617+ closedir(dir);
618+ return rc;
619+}
620+
621+static int nvme_getdev_by_nsid(char *nsid_str, char *path, char *dev_path)
622+{
623+ char full_path[NVME_PATH_MAX+1], nsid_path[sizeof(full_path)+5];
624+ char *end;
625+ u_int64_t nsid, curnsid;
626+ DIR *dir;
627+
628+ nsid = strtoul(nsid_str, &end, 10);
629+ if (*end)
630+ ERR_EXIT_ERRNO("Invalid namespace id given %s", nsid_str);
631+
632+ dir = opendir(path);
633+ if (!dir)
634+ ERR_EXIT_ERRNO("Could not open %s", path);
635+
636+ errno = 0;
637+ while (next_entry(dir, path, full_path, DT_DIR)) {
638+ snprintf(nsid_path, sizeof(nsid_path), "%s/%s", full_path,
639+ "nsid");
640+ if (access(nsid_path, F_OK))
641+ continue;
642+
643+ if (util_file_read_ul(&curnsid, 10, nsid_path))
644+ ERR_EXIT("Invalid namespace id found in %s", nsid_path);
645+
646+ if (curnsid == nsid) {
647+ strncpy(dev_path, full_path, NVME_PATH_MAX+1);
648+ closedir(dir);
649+ return 0;
650+ }
651+ }
652+ closedir(dir);
653+ return -1;
654+}
655+
656+static int nvme_getdev(char *fid_str, char *nsid_str, char *dev_path)
657+{
658+ char path_tmp[NVME_PATH_MAX];
659+
660+ if (nvme_getdev_by_fid(fid_str, path_tmp))
661+ return -1;
662+
663+ return nvme_getdev_by_nsid(nsid_str, path_tmp, dev_path);
664+}
665+
666+/*
667+ * Check if the specified fid and nsid leads to a valid nvme device
668+ */
669+int nvme_is_device(char *fid_str, char *nsid_str)
670+{
671+ char path_tmp[NVME_PATH_MAX+1];
672+
673+ return !(nvme_getdev(fid_str, nsid_str, path_tmp));
674+}
675--- a/zipl/src/disk.c
676+++ b/zipl/src/disk.c
677@@ -421,6 +421,12 @@
678 data->device = stats.st_rdev;
679 data->partnum = 0;
680 }
681+ /* NVMe path, driver name is 'blkext' */
682+ } else if (strcmp(data->drv_name, "blkext") == 0) {
683+ data->devno = -1;
684+ data->type = disk_type_scsi;
685+ data->partnum = stats.st_rdev & SCSI_PARTN_MASK;
686+ data->device = stats.st_rdev & ~SCSI_PARTN_MASK;
687 } else {
688 /* Driver name is unknown */
689 error_reason("Unsupported device driver '%s'", data->drv_name);
diff --git a/debian/patches/s390-tools-sru-lp1903984-focal.patch b/debian/patches/s390-tools-sru-lp1903984-focal.patch
0new file mode 100644690new file mode 100644
index 0000000..fc4952f
--- /dev/null
+++ b/debian/patches/s390-tools-sru-lp1903984-focal.patch
@@ -0,0 +1,49 @@
1Description: zcryptstats fails
2 The zcryptstats tool reports data for only the last two domain IDs.
3 Further, it hangs if one collect data for a complete crypto card,
4 and then one has to kill the ssh session to get back.
5 Patch/commit is:
6 cf2311f cf2311f1f1de17435b49ba8c8697be91705ba031
7 "zcryptstats: Fix handling of partial results with many domains"
8 - zconf/zcrypt/zcryptstats.c: code fix to pass the correct next-domain
9 to the subsequent CHSC call of a partial response
10Author: Ingo Franzki <ifranzki@linux.ibm.com>
11Origin: https://github.com/ibm-s390-tools/s390-tools/commit/cf2311f1f1de17435b49ba8c8697be91705ba031
12Bug-IBM: IBM Bugzilla 189183
13Bug-Ubuntu: https://bugs.launchpad.net/bugs/1903984
14Forwarded: not-needed
15Applied-Upstream: upstream accepted with > v2.15.1
16Reviewed-by: Frank Heimes <frank.heimes@canonical.com>
17Last-Update: 2021-01-19
18---
19This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
20--- a/zconf/zcrypt/zcryptstats.c
21+++ b/zconf/zcrypt/zcryptstats.c
22@@ -1178,8 +1178,14 @@
23 scdmd_area.request.header.code = 0x102d;
24 scdmd_area.request.header.length =
25 sizeof(struct chsc_scdmd_request);
26- scdmd_area.request.first_drid.ap_index = card;
27- scdmd_area.request.first_drid.domain_index = g.min_domain;
28+ if (scdmd_area.response.p) {
29+ scdmd_area.request.first_drid =
30+ scdmd_area.response.crid;
31+ } else {
32+ scdmd_area.request.first_drid.ap_index = card;
33+ scdmd_area.request.first_drid.domain_index =
34+ g.min_domain;
35+ }
36 scdmd_area.request.last_drid.ap_index = card;
37 scdmd_area.request.last_drid.domain_index = g.max_domain;
38 scdmd_area.request.s = 1;
39@@ -1217,10 +1223,6 @@
40 rc = process_apqn_measurement_data(&scdmd_area);
41 if (rc != 0)
42 break;
43-
44- if (scdmd_area.response.p)
45- scdmd_area.request.first_drid =
46- scdmd_area.response.crid;
47 } while (scdmd_area.response.p);
48
49 return rc;
diff --git a/debian/patches/s390-tools-sru-lp1908371-focal.patch b/debian/patches/s390-tools-sru-lp1908371-focal.patch
0new file mode 10064450new file mode 100644
index 0000000..7ba3725
--- /dev/null
+++ b/debian/patches/s390-tools-sru-lp1908371-focal.patch
@@ -0,0 +1,402 @@
1Description: The zipl command doesn't work correctly in combination with the -M
2 (respectively --mvdump) option. There is an error with the preparation of
3 multi-volume dumps, since the bus-ID for the first disk partition that is
4 listed in file dump_conf (DEVLIST) isn't found.
5 - include/lib/util_sys.h: declaration of new util_sys_* functions
6 - include/lib/util_file.h: declaration of two new util_file_read_* functions
7 - libutil/util_sys.c: implementation of new util_sys_* functions;
8 getting minor and major device number now based on base device
9 and prechecking if base device available util_file_read_* functions
10 - libutil/util_file.c: implementation of two new
11 - zipl/src/disk.c: removing blkext_* function set and changing code to
12 use the new util_sys_* functions
13Author: Stefan Haberland <sth@linux.ibm.com>, Sven Schnelle <svens@linux.ibm.com>
14Origin: https://github.com/ibm-s390-tools/s390-tools/commit/fa7a4dafa3d89b2e8787de102e4362e895d44b05
15 https://github.com/ibm-s390-tools/s390-tools/commit/aa8c2945cc7b047c626e75817c6a3e3924413023
16 https://github.com/ibm-s390-tools/s390-tools/commit/6802b86414b48c4f118da09c7bf7ee142a459fa0
17 https://github.com/ibm-s390-tools/s390-tools/commit/37348ef662a7052dae798e500ca8c9b769fff3e6
18Bug-IBM: IBM Bugzilla 187221
19Bug-Ubuntu: https://bugs.launchpad.net/bugs/1908371
20Forwarded: not-needed
21Applied-Upstream: >= v2.15.1
22Reviewed-by: Frank Heimes <frank.heimes@canonical.com>
23Last-Update: 2020-12-22
24---
25This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
26--- a/include/lib/util_file.h
27+++ b/include/lib/util_file.h
28@@ -12,8 +12,10 @@
29 #define LIB_UTIL_FILE_H
30
31 int util_file_read_line(char *str, size_t size, const char *fmt, ...);
32+int util_file_read_i(int *val, int base, const char *fmt, ...);
33 int util_file_read_l(long *val, int base, const char *fmt, ...);
34 int util_file_read_ll(long long *val, int base, const char *fmt, ...);
35+int util_file_read_ui(unsigned int *val, int base, const char *fmt, ...);
36 int util_file_read_ul(unsigned long *val, int base, const char *fmt, ...);
37 int util_file_read_ull(unsigned long long *val, int base, const char *fmt, ...);
38
39--- a/include/lib/util_sys.h
40+++ b/include/lib/util_sys.h
41@@ -12,6 +12,11 @@
42 #ifndef LIB_UTIL_SYS_H
43 #define LIB_UTIL_SYS_H
44
45+#include <stdbool.h>
46+
47 int util_sys_get_dev_addr(const char *dev, char *addr);
48+bool util_sys_dev_is_partition(dev_t dev);
49+int util_sys_get_partnum(dev_t dev);
50+int util_sys_get_base_dev(dev_t dev, dev_t *base_dev);
51
52 #endif /** LIB_UTIL_SYS_H @} */
53--- a/libutil/util_file.c
54+++ b/libutil/util_file.c
55@@ -282,6 +282,44 @@
56 }
57
58 /**
59+ * Read a file and convert it to signed int according to given base
60+ *
61+ * @param[out] val Buffer for value
62+ * @param[in] base Base for conversion, either 8, 10, or 16
63+ * @param[in] fmt Format string for generation of the path name
64+ * @param[in] ... Parameters for format string
65+ *
66+ * @retval 0 Integer has been read correctly
67+ * @retval -1 Error while reading file
68+ */
69+int util_file_read_i(int *val, int base, const char *fmt, ...)
70+{
71+ char path[PATH_MAX], buf[512];
72+ va_list ap;
73+ int count;
74+
75+ /* Construct the file name */
76+ UTIL_VSPRINTF(path, fmt, ap);
77+
78+ if (file_gets(buf, sizeof(buf), path))
79+ return -1;
80+ switch (base) {
81+ case 8:
82+ count = sscanf(buf, "%do", val);
83+ break;
84+ case 10:
85+ count = sscanf(buf, "%dd", val);
86+ break;
87+ case 16:
88+ count = sscanf(buf, "%dx", val);
89+ break;
90+ default:
91+ util_panic("Invalid base: %d\n", base);
92+ }
93+ return (count == 1) ? 0 : -1;
94+}
95+
96+/**
97 * Read a file and convert it to signed long according to given base
98 *
99 * @param[out] val Buffer for value
100@@ -353,6 +391,44 @@
101 break;
102 default:
103 util_panic("Invalid base: %d\n", base);
104+ }
105+ return (count == 1) ? 0 : -1;
106+}
107+
108+/**
109+ * Read a file and convert it to unsigned int according to given base
110+ *
111+ * @param[out] val Buffer for value
112+ * @param[in] base Base for conversion, either 8, 10, or 16
113+ * @param[in] fmt Format string for generation of the path name
114+ * @param[in] ... Parameters for format string
115+ *
116+ * @retval 0 Integer has been read correctly
117+ * @retval -1 Error while reading file
118+ */
119+int util_file_read_ui(unsigned int *val, int base, const char *fmt, ...)
120+{
121+ char path[PATH_MAX], buf[512];
122+ va_list ap;
123+ int count;
124+
125+ /* Construct the file name */
126+ UTIL_VSPRINTF(path, fmt, ap);
127+
128+ if (file_gets(buf, sizeof(buf), path))
129+ return -1;
130+ switch (base) {
131+ case 8:
132+ count = sscanf(buf, "%uo", val);
133+ break;
134+ case 10:
135+ count = sscanf(buf, "%uu", val);
136+ break;
137+ case 16:
138+ count = sscanf(buf, "%ux", val);
139+ break;
140+ default:
141+ util_panic("Invalid base: %d\n", base);
142 }
143 return (count == 1) ? 0 : -1;
144 }
145--- a/libutil/util_sys.c
146+++ b/libutil/util_sys.c
147@@ -11,17 +11,114 @@
148
149 #include <err.h>
150 #include <errno.h>
151+#include <linux/fs.h>
152 #include <stdlib.h>
153+#include <stdio.h>
154 #include <string.h>
155 #include <sys/stat.h>
156 #include <sys/sysmacros.h>
157 #include <unistd.h>
158
159+#include "lib/util_file.h"
160+#include "lib/util_libc.h"
161 #include "lib/util_path.h"
162 #include "lib/util_sys.h"
163
164 /* lstat() doesn't work for sysfs files, a fixed size is therefore inevitable */
165 #define READLINK_SIZE 256
166+#define PAGE_SIZE 4096
167+
168+/**
169+ * Return the partition number of a given partition.
170+ *
171+ * @param[in] dev Device node of interest
172+ *
173+ * @retval int Partition number of the device
174+ * @retval -1 Error when trying to read the partition number.
175+ */
176+int util_sys_get_partnum(dev_t dev)
177+{
178+ int partnum = -1;
179+ char *path;
180+
181+ path = util_path_sysfs("dev/block/%u:%u/partition",
182+ major(dev), minor(dev));
183+ if (util_file_read_i(&partnum, 10, path)) {
184+ warnx("Could not read from path '%s'", path);
185+ goto out;
186+ }
187+ if (partnum <= 0) {
188+ warnx("Bad partition number in '%s'", path);
189+ partnum = -1;
190+ goto out;
191+ }
192+
193+out:
194+ free(path);
195+ return partnum;
196+}
197+
198+/**
199+ * Determine if the given device is a partition.
200+ *
201+ * @param[in] dev Device node of interest
202+ *
203+ * @retval true Device is partition
204+ * @retval false Device is not a partition
205+ */
206+bool util_sys_dev_is_partition(dev_t dev)
207+{
208+ bool is_part;
209+ char *path;
210+
211+ path = util_path_sysfs("dev/block/%u:%u/partition",
212+ major(dev), minor(dev));
213+ is_part = util_path_exists(path);
214+ free(path);
215+
216+ return is_part;
217+}
218+
219+/**
220+ * Determine base device
221+ *
222+ * This function determines the base device \p base_dev of a given
223+ * device \p dev. If \p dev is a base device, \p base_dev becomes \p dev.
224+ *
225+ * @param[in] dev Device node of interest
226+ * @param[out] base_dev Identified base device
227+ *
228+ * @retval 0 Success
229+ * @retval -1 Error while reading device information or
230+ * constructed path
231+ */
232+int util_sys_get_base_dev(dev_t dev, dev_t *base_dev)
233+{
234+ int base_major, base_minor;
235+ char buf[PAGE_SIZE];
236+ char *path;
237+
238+ /* check if the device already is a base device */
239+ if (!util_sys_dev_is_partition(dev)) {
240+ *base_dev = makedev(major(dev), minor(dev));
241+ return 0;
242+ }
243+ path = util_path_sysfs("dev/block/%d:%d/../dev",
244+ major(dev), minor(dev));
245+ if (util_file_read_line(buf, sizeof(buf), path)) {
246+ warnx("Could not read from path '%s'", path);
247+ free(path);
248+ return -1;
249+ }
250+ free(path);
251+ if (sscanf(buf, "%i:%i", &base_major, &base_minor) != 2) {
252+ warn("Could not parse major:minor from string '%s'", buf);
253+ return -1;
254+ }
255+ *base_dev = makedev(base_major, base_minor);
256+
257+ return 0;
258+}
259
260 /**
261 * Identify device address
262@@ -44,13 +141,17 @@
263 unsigned int maj, min;
264 struct stat s;
265 ssize_t len;
266+ dev_t base;
267 char *path;
268
269 if (stat(dev, &s) != 0)
270 return -1;
271
272- maj = major(s.st_rdev);
273- min = minor(s.st_rdev);
274+ if (util_sys_get_base_dev(s.st_rdev, &base))
275+ return -1;
276+
277+ maj = major(base);
278+ min = minor(base);
279
280 if (S_ISBLK(s.st_mode))
281 path = util_path_sysfs("dev/block/%u:%u/device", maj, min);
282--- a/zipl/src/disk.c
283+++ b/zipl/src/disk.c
284@@ -25,6 +25,7 @@
285 #include <linux/fiemap.h>
286
287 #include "lib/util_proc.h"
288+#include "lib/util_sys.h"
289
290 #include "disk.h"
291 #include "error.h"
292@@ -89,88 +90,6 @@
293 return 0;
294 }
295
296-static int blkext_get_partnum(dev_t dev)
297-{
298- char path[PATH_MAX], *buf;
299- int dev_major, dev_minor, partnum = -1;
300-
301- dev_major = major(dev);
302- dev_minor = minor(dev);
303- snprintf(path, PATH_MAX, "/sys/dev/block/%d:%d/partition",
304- dev_major, dev_minor);
305-
306- if (misc_read_special_file(path, &buf, NULL, 1)) {
307- error_text("Could not read from path '%s'", path);
308- return -1;
309- }
310-
311- partnum = atoi(buf);
312- free(buf);
313- if (partnum < 0) {
314- error_text("Bad partition number in '%s'", path);
315- return -1;
316- }
317-
318- return partnum;
319-}
320-
321-static int blkext_is_base_device(dev_t dev)
322-{
323- int dev_major, dev_minor;
324- char path[PATH_MAX];
325- struct stat stats;
326-
327- dev_major = major(dev);
328- dev_minor = minor(dev);
329-
330- snprintf(path, PATH_MAX, "/sys/dev/block/%d:%d/partition",
331- dev_major, dev_minor);
332- return (stat(path, &stats));
333-}
334-
335-static int blkext_get_base_dev(dev_t dev, dev_t *base_dev)
336-{
337- int base_major, base_minor;
338- char dev_path[PATH_MAX], base_path[PATH_MAX];
339- char *temp_path, *buf;
340-
341- misc_asprintf(&temp_path, "/sys/dev/block/%d:%d", major(dev), minor(dev));
342- if (!realpath(temp_path, dev_path)) {
343- error_reason(strerror(errno));
344- error_text("Could not resolve link %s", temp_path);
345- free(temp_path);
346- return -1;
347- }
348- free(temp_path);
349-
350- misc_asprintf(&temp_path, "%s/..", dev_path);
351- if (!realpath(temp_path, base_path)) {
352- error_reason(strerror(errno));
353- error_text("Could not resolve path %s", temp_path);
354- free(temp_path);
355- return -1;
356- }
357- free(temp_path);
358-
359- misc_asprintf(&temp_path, "%s/dev", base_path);
360- if (misc_read_special_file(temp_path, &buf, NULL, 1)) {
361- error_text("Could not read from path '%s'", temp_path);
362- free(temp_path);
363- return -1;
364- }
365- free(temp_path);
366-
367- if (sscanf(buf, "%i:%i", &base_major, &base_minor) != 2) {
368- error_text("Could not parse major:minor from string '%s'", buf);
369- free(buf);
370- return -1;
371- }
372-
373- free(buf);
374- *base_dev = makedev(base_major, base_minor);
375- return 0;
376-}
377-
378 /* Return non-zero for ECKD type. */
379 int
380 disk_is_eckd(disk_type_t type)
381@@ -492,15 +411,15 @@
382 data->devno = -1;
383 data->type = disk_type_scsi;
384
385- if (blkext_is_base_device(stats.st_rdev)) {
386- data->device = stats.st_rdev;
387- data->partnum = 0;
388- } else {
389- if (blkext_get_base_dev(stats.st_rdev, &data->device))
390+ if (util_sys_dev_is_partition(stats.st_rdev)) {
391+ if (util_sys_get_base_dev(stats.st_rdev, &data->device))
392 goto out_close;
393- data->partnum = blkext_get_partnum(stats.st_rdev);
394+ data->partnum = util_sys_get_partnum(stats.st_rdev);
395 if (data->partnum == -1)
396 goto out_close;
397+ } else {
398+ data->device = stats.st_rdev;
399+ data->partnum = 0;
400 }
401 } else {
402 /* Driver name is unknown */
diff --git a/debian/patches/series b/debian/patches/series
index e779db8..894d113 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -110,3 +110,6 @@ f742ed73e1db99dc04b821a1f9aa4a852584e4d8.patch
1100110-zipl-stage3-correctly-handle-diag308-response-code.patch1100110-zipl-stage3-correctly-handle-diag308-response-code.patch
1110111-zipl-fix-incorrect-setup-of-stage3-flags.patch1110111-zipl-fix-incorrect-setup-of-stage3-flags.patch
1120112-cpumf-lscpumf.pl-displays-raw-event-number-incorrect.patch1120112-cpumf-lscpumf.pl-displays-raw-event-number-incorrect.patch
113s390-tools-sru-lp1903984-focal.patch
114s390-tools-sru-lp1908371-focal.patch
115s390-tools-sru-lp1902179-focal.patch

Subscribers

People subscribed via source and target branches