| @@ -1,34 +1,34 @@ | | | @@ -1,34 +1,34 @@ |
1 | /* $NetBSD: nvme.c,v 1.14 2016/09/27 03:33:32 pgoyette Exp $ */ | | 1 | /* $NetBSD: nvme.c,v 1.15 2016/10/05 03:46:38 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.14 2016/09/27 03:33:32 pgoyette Exp $"); | | 21 | __KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.15 2016/10/05 03:46:38 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> |
| @@ -347,26 +347,28 @@ nvme_attach(struct nvme_softc *sc) | | | @@ -347,26 +347,28 @@ nvme_attach(struct nvme_softc *sc) |
347 | | | 347 | |
348 | nvme_version(sc, reg); | | 348 | nvme_version(sc, reg); |
349 | | | 349 | |
350 | cap = nvme_read8(sc, NVME_CAP); | | 350 | cap = nvme_read8(sc, NVME_CAP); |
351 | dstrd = NVME_CAP_DSTRD(cap); | | 351 | dstrd = NVME_CAP_DSTRD(cap); |
352 | if (NVME_CAP_MPSMIN(cap) > PAGE_SHIFT) { | | 352 | if (NVME_CAP_MPSMIN(cap) > PAGE_SHIFT) { |
353 | aprint_error_dev(sc->sc_dev, "NVMe minimum page size %u " | | 353 | aprint_error_dev(sc->sc_dev, "NVMe minimum page size %u " |
354 | "is greater than CPU page size %u\n", | | 354 | "is greater than CPU page size %u\n", |
355 | 1 << NVME_CAP_MPSMIN(cap), 1 << PAGE_SHIFT); | | 355 | 1 << NVME_CAP_MPSMIN(cap), 1 << PAGE_SHIFT); |
356 | return 1; | | 356 | return 1; |
357 | } | | 357 | } |
358 | if (NVME_CAP_MPSMAX(cap) < mps) | | 358 | if (NVME_CAP_MPSMAX(cap) < mps) |
359 | mps = NVME_CAP_MPSMAX(cap); | | 359 | mps = NVME_CAP_MPSMAX(cap); |
| | | 360 | if (ioq_entries > NVME_CAP_MQES(cap)) |
| | | 361 | ioq_entries = NVME_CAP_MQES(cap); |
360 | | | 362 | |
361 | /* set initial values to be used for admin queue during probe */ | | 363 | /* set initial values to be used for admin queue during probe */ |
362 | sc->sc_rdy_to = NVME_CAP_TO(cap); | | 364 | sc->sc_rdy_to = NVME_CAP_TO(cap); |
363 | sc->sc_mps = 1 << mps; | | 365 | sc->sc_mps = 1 << mps; |
364 | sc->sc_mdts = MAXPHYS; | | 366 | sc->sc_mdts = MAXPHYS; |
365 | sc->sc_max_sgl = 2; | | 367 | sc->sc_max_sgl = 2; |
366 | | | 368 | |
367 | if (nvme_disable(sc) != 0) { | | 369 | if (nvme_disable(sc) != 0) { |
368 | aprint_error_dev(sc->sc_dev, "unable to disable controller\n"); | | 370 | aprint_error_dev(sc->sc_dev, "unable to disable controller\n"); |
369 | return 1; | | 371 | return 1; |
370 | } | | 372 | } |
371 | | | 373 | |
372 | sc->sc_admin_q = nvme_q_alloc(sc, NVME_ADMIN_Q, adminq_entries, dstrd); | | 374 | sc->sc_admin_q = nvme_q_alloc(sc, NVME_ADMIN_Q, adminq_entries, dstrd); |
| @@ -435,36 +437,42 @@ free_q: | | | @@ -435,36 +437,42 @@ free_q: |
435 | disable: | | 437 | disable: |
436 | nvme_disable(sc); | | 438 | nvme_disable(sc); |
437 | disestablish_admin_q: | | 439 | disestablish_admin_q: |
438 | sc->sc_intr_disestablish(sc, NVME_ADMIN_Q); | | 440 | sc->sc_intr_disestablish(sc, NVME_ADMIN_Q); |
439 | free_admin_q: | | 441 | free_admin_q: |
440 | nvme_q_free(sc, sc->sc_admin_q); | | 442 | nvme_q_free(sc, sc->sc_admin_q); |
441 | | | 443 | |
442 | return 1; | | 444 | return 1; |
443 | } | | 445 | } |
444 | | | 446 | |
445 | int | | 447 | int |
446 | nvme_rescan(device_t self, const char *attr, const int *flags) | | 448 | nvme_rescan(device_t self, const char *attr, const int *flags) |
447 | { | | 449 | { |
448 | int i; | | | |
449 | struct nvme_softc *sc = device_private(self); | | 450 | struct nvme_softc *sc = device_private(self); |
450 | struct nvme_attach_args naa; | | 451 | struct nvme_attach_args naa; |
| | | 452 | uint64_t cap; |
| | | 453 | int ioq_entries = nvme_ioq_size; |
| | | 454 | int i; |
| | | 455 | |
| | | 456 | cap = nvme_read8(sc, NVME_CAP); |
| | | 457 | if (ioq_entries > NVME_CAP_MQES(cap)) |
| | | 458 | ioq_entries = NVME_CAP_MQES(cap); |
451 | | | 459 | |
452 | for (i = 0; i < sc->sc_nn; i++) { | | 460 | for (i = 0; i < sc->sc_nn; i++) { |
453 | if (sc->sc_namespaces[i].dev) | | 461 | if (sc->sc_namespaces[i].dev) |
454 | continue; | | 462 | continue; |
455 | memset(&naa, 0, sizeof(naa)); | | 463 | memset(&naa, 0, sizeof(naa)); |
456 | naa.naa_nsid = i + 1; | | 464 | naa.naa_nsid = i + 1; |
457 | naa.naa_qentries = nvme_ioq_size; | | 465 | naa.naa_qentries = ioq_entries; |
458 | sc->sc_namespaces[i].dev = config_found(sc->sc_dev, &naa, | | 466 | sc->sc_namespaces[i].dev = config_found(sc->sc_dev, &naa, |
459 | nvme_print); | | 467 | nvme_print); |
460 | } | | 468 | } |
461 | return 0; | | 469 | return 0; |
462 | } | | 470 | } |
463 | | | 471 | |
464 | static int | | 472 | static int |
465 | nvme_print(void *aux, const char *pnp) | | 473 | nvme_print(void *aux, const char *pnp) |
466 | { | | 474 | { |
467 | struct nvme_attach_args *naa = aux; | | 475 | struct nvme_attach_args *naa = aux; |
468 | | | 476 | |
469 | if (pnp) | | 477 | if (pnp) |
470 | aprint_normal("at %s", pnp); | | 478 | aprint_normal("at %s", pnp); |