Mon May 29 02:24:00 2017 UTC ()
nvme(4): Do not use bus_space_{read,write}_8() even on LP64 archs.

> some (broken) controllers require ordered split transfers.
> From linux a310acd7a7ea53533886c11bb7edd11ffd61a036

from OpenBSD nvme.c r1.53.


(nonaka)
diff -r1.27 -r1.28 src/sys/dev/ic/nvme.c

cvs diff -r1.27 -r1.28 src/sys/dev/ic/nvme.c (expand / switch to unified diff)

--- src/sys/dev/ic/nvme.c 2017/05/29 02:20:34 1.27
+++ src/sys/dev/ic/nvme.c 2017/05/29 02:24:00 1.28
@@ -1,34 +1,34 @@ @@ -1,34 +1,34 @@
1/* $NetBSD: nvme.c,v 1.27 2017/05/29 02:20:34 nonaka Exp $ */ 1/* $NetBSD: nvme.c,v 1.28 2017/05/29 02:24:00 nonaka Exp $ */
2/* $OpenBSD: nvme.c,v 1.49 2016/04/18 05:59:50 dlg Exp $ */ 2/* $OpenBSD: nvme.c,v 1.49 2016/04/18 05:59:50 dlg Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2014 David Gwynne <dlg@openbsd.org> 5 * Copyright (c) 2014 David Gwynne <dlg@openbsd.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */ 18 */
19 19
20#include <sys/cdefs.h> 20#include <sys/cdefs.h>
21__KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.27 2017/05/29 02:20:34 nonaka Exp $"); 21__KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.28 2017/05/29 02:24:00 nonaka Exp $");
22 22
23#include <sys/param.h> 23#include <sys/param.h>
24#include <sys/systm.h> 24#include <sys/systm.h>
25#include <sys/kernel.h> 25#include <sys/kernel.h>
26#include <sys/atomic.h> 26#include <sys/atomic.h>
27#include <sys/bus.h> 27#include <sys/bus.h>
28#include <sys/buf.h> 28#include <sys/buf.h>
29#include <sys/conf.h> 29#include <sys/conf.h>
30#include <sys/device.h> 30#include <sys/device.h>
31#include <sys/kmem.h> 31#include <sys/kmem.h>
32#include <sys/once.h> 32#include <sys/once.h>
33#include <sys/proc.h> 33#include <sys/proc.h>
34#include <sys/queue.h> 34#include <sys/queue.h>
@@ -111,32 +111,30 @@ static int nvme_command_passthrough(stru @@ -111,32 +111,30 @@ static int nvme_command_passthrough(stru
111 struct nvme_pt_command *, uint16_t, struct lwp *, bool); 111 struct nvme_pt_command *, uint16_t, struct lwp *, bool);
112 112
113static int nvme_get_number_of_queues(struct nvme_softc *, u_int *); 113static int nvme_get_number_of_queues(struct nvme_softc *, u_int *);
114 114
115#define NVME_TIMO_QOP 5 /* queue create and delete timeout */ 115#define NVME_TIMO_QOP 5 /* queue create and delete timeout */
116#define NVME_TIMO_IDENT 10 /* probe identify timeout */ 116#define NVME_TIMO_IDENT 10 /* probe identify timeout */
117#define NVME_TIMO_PT -1 /* passthrough cmd timeout */ 117#define NVME_TIMO_PT -1 /* passthrough cmd timeout */
118#define NVME_TIMO_SY 60 /* sync cache timeout */ 118#define NVME_TIMO_SY 60 /* sync cache timeout */
119 119
120#define nvme_read4(_s, _r) \ 120#define nvme_read4(_s, _r) \
121 bus_space_read_4((_s)->sc_iot, (_s)->sc_ioh, (_r)) 121 bus_space_read_4((_s)->sc_iot, (_s)->sc_ioh, (_r))
122#define nvme_write4(_s, _r, _v) \ 122#define nvme_write4(_s, _r, _v) \
123 bus_space_write_4((_s)->sc_iot, (_s)->sc_ioh, (_r), (_v)) 123 bus_space_write_4((_s)->sc_iot, (_s)->sc_ioh, (_r), (_v))
124#ifdef __LP64__ 124/*
125#define nvme_read8(_s, _r) \ 125 * Some controllers, at least Apple NVMe, always require split
126 bus_space_read_8((_s)->sc_iot, (_s)->sc_ioh, (_r)) 126 * transfers, so don't use bus_space_{read,write}_8() on LP64.
127#define nvme_write8(_s, _r, _v) \ 127 */
128 bus_space_write_8((_s)->sc_iot, (_s)->sc_ioh, (_r), (_v)) 
129#else /* __LP64__ */ 
130static inline uint64_t 128static inline uint64_t
131nvme_read8(struct nvme_softc *sc, bus_size_t r) 129nvme_read8(struct nvme_softc *sc, bus_size_t r)
132{ 130{
133 uint64_t v; 131 uint64_t v;
134 uint32_t *a = (uint32_t *)&v; 132 uint32_t *a = (uint32_t *)&v;
135 133
136#if _BYTE_ORDER == _LITTLE_ENDIAN 134#if _BYTE_ORDER == _LITTLE_ENDIAN
137 a[0] = nvme_read4(sc, r); 135 a[0] = nvme_read4(sc, r);
138 a[1] = nvme_read4(sc, r + 4); 136 a[1] = nvme_read4(sc, r + 4);
139#else /* _BYTE_ORDER == _LITTLE_ENDIAN */ 137#else /* _BYTE_ORDER == _LITTLE_ENDIAN */
140 a[1] = nvme_read4(sc, r); 138 a[1] = nvme_read4(sc, r);
141 a[0] = nvme_read4(sc, r + 4); 139 a[0] = nvme_read4(sc, r + 4);
142#endif 140#endif
@@ -147,27 +145,26 @@ nvme_read8(struct nvme_softc *sc, bus_si @@ -147,27 +145,26 @@ nvme_read8(struct nvme_softc *sc, bus_si
147static inline void 145static inline void
148nvme_write8(struct nvme_softc *sc, bus_size_t r, uint64_t v) 146nvme_write8(struct nvme_softc *sc, bus_size_t r, uint64_t v)
149{ 147{
150 uint32_t *a = (uint32_t *)&v; 148 uint32_t *a = (uint32_t *)&v;
151 149
152#if _BYTE_ORDER == _LITTLE_ENDIAN 150#if _BYTE_ORDER == _LITTLE_ENDIAN
153 nvme_write4(sc, r, a[0]); 151 nvme_write4(sc, r, a[0]);
154 nvme_write4(sc, r + 4, a[1]); 152 nvme_write4(sc, r + 4, a[1]);
155#else /* _BYTE_ORDER == _LITTLE_ENDIAN */ 153#else /* _BYTE_ORDER == _LITTLE_ENDIAN */
156 nvme_write4(sc, r, a[1]); 154 nvme_write4(sc, r, a[1]);
157 nvme_write4(sc, r + 4, a[0]); 155 nvme_write4(sc, r + 4, a[0]);
158#endif 156#endif
159} 157}
160#endif /* __LP64__ */ 
161#define nvme_barrier(_s, _r, _l, _f) \ 158#define nvme_barrier(_s, _r, _l, _f) \
162 bus_space_barrier((_s)->sc_iot, (_s)->sc_ioh, (_r), (_l), (_f)) 159 bus_space_barrier((_s)->sc_iot, (_s)->sc_ioh, (_r), (_l), (_f))
163 160
164#ifdef NVME_DEBUG 161#ifdef NVME_DEBUG
165static __used void 162static __used void
166nvme_dumpregs(struct nvme_softc *sc) 163nvme_dumpregs(struct nvme_softc *sc)
167{ 164{
168 uint64_t r8; 165 uint64_t r8;
169 uint32_t r4; 166 uint32_t r4;
170 167
171#define DEVNAME(_sc) device_xname((_sc)->sc_dev) 168#define DEVNAME(_sc) device_xname((_sc)->sc_dev)
172 r8 = nvme_read8(sc, NVME_CAP); 169 r8 = nvme_read8(sc, NVME_CAP);
173 printf("%s: cap 0x%016"PRIx64"\n", DEVNAME(sc), nvme_read8(sc, NVME_CAP)); 170 printf("%s: cap 0x%016"PRIx64"\n", DEVNAME(sc), nvme_read8(sc, NVME_CAP));