Skip to content

Commit 7378b00

Browse files
committed
Merge tag 'nvme-6.18-2025-09-23' of git://git.infradead.org/nvme into for-6.18/block
Pull NVMe updates from Keith: " - FC target fixes (Daniel) - Authentication fixes and updates (Martin, Chris) - Admin controller handling (Kamaljit) - Target lockdep assertions (Max) - Keep-alive updates for discovery (Alastair) - Suspend quirk (Georg)" * tag 'nvme-6.18-2025-09-23' of git://git.infradead.org/nvme: nvme: Use non zero KATO for persistent discovery connections nvmet: add safety check for subsys lock nvme-core: use nvme_is_io_ctrl() for I/O controller check nvme-core: do ioccsz/iorcsz validation only for I/O controllers nvme-core: add method to check for an I/O controller nvme-pci: Add TUXEDO IBS Gen8 to Samsung sleep quirk nvme-auth: use hkdf_expand_label() nvme-auth: add hkdf_expand_label() nvme-tcp: send only permitted commands for secure concat nvme-fc: use lock accessing port_state and rport state nvmet-fcloop: call done callback even when remote port is gone nvmet-fc: avoid scheduling association deletion twice nvmet-fc: move lsop put work to nvmet_fc_ls_req_op nvme-auth: update bi_directional flag
2 parents 5d726c4 + 2e48265 commit 7378b00

File tree

9 files changed

+126
-57
lines changed

9 files changed

+126
-57
lines changed

drivers/nvme/common/auth.c

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,59 @@ int nvme_auth_generate_digest(u8 hmac_id, u8 *psk, size_t psk_len,
683683
}
684684
EXPORT_SYMBOL_GPL(nvme_auth_generate_digest);
685685

686+
/**
687+
* hkdf_expand_label - HKDF-Expand-Label (RFC 8846 section 7.1)
688+
* @hmac_tfm: hash context keyed with pseudorandom key
689+
* @label: ASCII label without "tls13 " prefix
690+
* @labellen: length of @label
691+
* @context: context bytes
692+
* @contextlen: length of @context
693+
* @okm: output keying material
694+
* @okmlen: length of @okm
695+
*
696+
* Build the TLS 1.3 HkdfLabel structure and invoke hkdf_expand().
697+
*
698+
* Returns 0 on success with output keying material stored in @okm,
699+
* or a negative errno value otherwise.
700+
*/
701+
static int hkdf_expand_label(struct crypto_shash *hmac_tfm,
702+
const u8 *label, unsigned int labellen,
703+
const u8 *context, unsigned int contextlen,
704+
u8 *okm, unsigned int okmlen)
705+
{
706+
int err;
707+
u8 *info;
708+
unsigned int infolen;
709+
const char *tls13_prefix = "tls13 ";
710+
unsigned int prefixlen = strlen(tls13_prefix);
711+
712+
if (WARN_ON(labellen > (255 - prefixlen)))
713+
return -EINVAL;
714+
if (WARN_ON(contextlen > 255))
715+
return -EINVAL;
716+
717+
infolen = 2 + (1 + prefixlen + labellen) + (1 + contextlen);
718+
info = kzalloc(infolen, GFP_KERNEL);
719+
if (!info)
720+
return -ENOMEM;
721+
722+
/* HkdfLabel.Length */
723+
put_unaligned_be16(okmlen, info);
724+
725+
/* HkdfLabel.Label */
726+
info[2] = prefixlen + labellen;
727+
memcpy(info + 3, tls13_prefix, prefixlen);
728+
memcpy(info + 3 + prefixlen, label, labellen);
729+
730+
/* HkdfLabel.Context */
731+
info[3 + prefixlen + labellen] = contextlen;
732+
memcpy(info + 4 + prefixlen + labellen, context, contextlen);
733+
734+
err = hkdf_expand(hmac_tfm, info, infolen, okm, okmlen);
735+
kfree_sensitive(info);
736+
return err;
737+
}
738+
686739
/**
687740
* nvme_auth_derive_tls_psk - Derive TLS PSK
688741
* @hmac_id: Hash function identifier
@@ -715,10 +768,10 @@ int nvme_auth_derive_tls_psk(int hmac_id, u8 *psk, size_t psk_len,
715768
{
716769
struct crypto_shash *hmac_tfm;
717770
const char *hmac_name;
718-
const char *psk_prefix = "tls13 nvme-tls-psk";
771+
const char *label = "nvme-tls-psk";
719772
static const char default_salt[HKDF_MAX_HASHLEN];
720-
size_t info_len, prk_len;
721-
char *info;
773+
size_t prk_len;
774+
const char *ctx;
722775
unsigned char *prk, *tls_key;
723776
int ret;
724777

@@ -758,36 +811,29 @@ int nvme_auth_derive_tls_psk(int hmac_id, u8 *psk, size_t psk_len,
758811
if (ret)
759812
goto out_free_prk;
760813

761-
/*
762-
* 2 additional bytes for the length field from HDKF-Expand-Label,
763-
* 2 additional bytes for the HMAC ID, and one byte for the space
764-
* separator.
765-
*/
766-
info_len = strlen(psk_digest) + strlen(psk_prefix) + 5;
767-
info = kzalloc(info_len + 1, GFP_KERNEL);
768-
if (!info) {
814+
ctx = kasprintf(GFP_KERNEL, "%02d %s", hmac_id, psk_digest);
815+
if (!ctx) {
769816
ret = -ENOMEM;
770817
goto out_free_prk;
771818
}
772819

773-
put_unaligned_be16(psk_len, info);
774-
memcpy(info + 2, psk_prefix, strlen(psk_prefix));
775-
sprintf(info + 2 + strlen(psk_prefix), "%02d %s", hmac_id, psk_digest);
776-
777820
tls_key = kzalloc(psk_len, GFP_KERNEL);
778821
if (!tls_key) {
779822
ret = -ENOMEM;
780-
goto out_free_info;
823+
goto out_free_ctx;
781824
}
782-
ret = hkdf_expand(hmac_tfm, info, info_len, tls_key, psk_len);
825+
ret = hkdf_expand_label(hmac_tfm,
826+
label, strlen(label),
827+
ctx, strlen(ctx),
828+
tls_key, psk_len);
783829
if (ret) {
784830
kfree(tls_key);
785-
goto out_free_info;
831+
goto out_free_ctx;
786832
}
787833
*ret_psk = tls_key;
788834

789-
out_free_info:
790-
kfree(info);
835+
out_free_ctx:
836+
kfree(ctx);
791837
out_free_prk:
792838
kfree(prk);
793839
out_free_shash:

drivers/nvme/host/auth.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,10 @@ static int nvme_auth_set_dhchap_reply_data(struct nvme_ctrl *ctrl,
331331
} else {
332332
memset(chap->c2, 0, chap->hash_len);
333333
}
334-
if (ctrl->opts->concat)
334+
if (ctrl->opts->concat) {
335335
chap->s2 = 0;
336-
else
336+
chap->bi_directional = false;
337+
} else
337338
chap->s2 = nvme_auth_get_seqnum();
338339
data->seqnum = cpu_to_le32(chap->s2);
339340
if (chap->host_key_len) {

drivers/nvme/host/core.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3163,6 +3163,11 @@ static inline bool nvme_admin_ctrl(struct nvme_ctrl *ctrl)
31633163
return ctrl->cntrltype == NVME_CTRL_ADMIN;
31643164
}
31653165

3166+
static inline bool nvme_is_io_ctrl(struct nvme_ctrl *ctrl)
3167+
{
3168+
return !nvme_discovery_ctrl(ctrl) && !nvme_admin_ctrl(ctrl);
3169+
}
3170+
31663171
static bool nvme_validate_cntlid(struct nvme_subsystem *subsys,
31673172
struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
31683173
{
@@ -3365,7 +3370,7 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl)
33653370
else
33663371
ctrl->max_zeroes_sectors = 0;
33673372

3368-
if (ctrl->subsys->subtype != NVME_NQN_NVME ||
3373+
if (!nvme_is_io_ctrl(ctrl) ||
33693374
!nvme_id_cns_ok(ctrl, NVME_ID_CNS_CS_CTRL) ||
33703375
test_bit(NVME_CTRL_SKIP_ID_CNS_CS, &ctrl->flags))
33713376
return 0;
@@ -3487,14 +3492,14 @@ static int nvme_check_ctrl_fabric_info(struct nvme_ctrl *ctrl, struct nvme_id_ct
34873492
return -EINVAL;
34883493
}
34893494

3490-
if (!nvme_discovery_ctrl(ctrl) && ctrl->ioccsz < 4) {
3495+
if (nvme_is_io_ctrl(ctrl) && ctrl->ioccsz < 4) {
34913496
dev_err(ctrl->device,
34923497
"I/O queue command capsule supported size %d < 4\n",
34933498
ctrl->ioccsz);
34943499
return -EINVAL;
34953500
}
34963501

3497-
if (!nvme_discovery_ctrl(ctrl) && ctrl->iorcsz < 1) {
3502+
if (nvme_is_io_ctrl(ctrl) && ctrl->iorcsz < 1) {
34983503
dev_err(ctrl->device,
34993504
"I/O queue response capsule supported size %d < 1\n",
35003505
ctrl->iorcsz);
@@ -4986,8 +4991,14 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)
49864991
* checking that they started once before, hence are reconnecting back.
49874992
*/
49884993
if (test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags) &&
4989-
nvme_discovery_ctrl(ctrl))
4994+
nvme_discovery_ctrl(ctrl)) {
4995+
if (!ctrl->kato) {
4996+
nvme_stop_keep_alive(ctrl);
4997+
ctrl->kato = NVME_DEFAULT_KATO;
4998+
nvme_start_keep_alive(ctrl);
4999+
}
49905000
nvme_change_uevent(ctrl, "NVME_EVENT=rediscover");
5001+
}
49915002

49925003
if (ctrl->queue_count > 1) {
49935004
nvme_queue_scan(ctrl);

drivers/nvme/host/fc.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3032,11 +3032,17 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
30323032

30333033
++ctrl->ctrl.nr_reconnects;
30343034

3035-
if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE)
3035+
spin_lock_irqsave(&ctrl->rport->lock, flags);
3036+
if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE) {
3037+
spin_unlock_irqrestore(&ctrl->rport->lock, flags);
30363038
return -ENODEV;
3039+
}
30373040

3038-
if (nvme_fc_ctlr_active_on_rport(ctrl))
3041+
if (nvme_fc_ctlr_active_on_rport(ctrl)) {
3042+
spin_unlock_irqrestore(&ctrl->rport->lock, flags);
30393043
return -ENOTUNIQ;
3044+
}
3045+
spin_unlock_irqrestore(&ctrl->rport->lock, flags);
30403046

30413047
dev_info(ctrl->ctrl.device,
30423048
"NVME-FC{%d}: create association : host wwpn 0x%016llx "

drivers/nvme/host/pci.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3330,10 +3330,12 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
33303330
* Exclude Samsung 990 Evo from NVME_QUIRK_SIMPLE_SUSPEND
33313331
* because of high power consumption (> 2 Watt) in s2idle
33323332
* sleep. Only some boards with Intel CPU are affected.
3333+
* (Note for testing: Samsung 990 Evo Plus has same PCI ID)
33333334
*/
33343335
if (dmi_match(DMI_BOARD_NAME, "DN50Z-140HC-YD") ||
33353336
dmi_match(DMI_BOARD_NAME, "GMxPXxx") ||
33363337
dmi_match(DMI_BOARD_NAME, "GXxMRXx") ||
3338+
dmi_match(DMI_BOARD_NAME, "NS5X_NS7XAU") ||
33373339
dmi_match(DMI_BOARD_NAME, "PH4PG31") ||
33383340
dmi_match(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1") ||
33393341
dmi_match(DMI_BOARD_NAME, "PH6PG01_PH6PG71"))

drivers/nvme/host/tcp.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,6 +2250,9 @@ static int nvme_tcp_configure_admin_queue(struct nvme_ctrl *ctrl, bool new)
22502250
if (error)
22512251
goto out_cleanup_tagset;
22522252

2253+
if (ctrl->opts->concat && !ctrl->tls_pskid)
2254+
return 0;
2255+
22532256
error = nvme_enable_ctrl(ctrl);
22542257
if (error)
22552258
goto out_stop_queue;

drivers/nvme/target/core.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -513,16 +513,15 @@ static int nvmet_p2pmem_ns_enable(struct nvmet_ns *ns)
513513
return 0;
514514
}
515515

516-
/*
517-
* Note: ctrl->subsys->lock should be held when calling this function
518-
*/
519516
static void nvmet_p2pmem_ns_add_p2p(struct nvmet_ctrl *ctrl,
520517
struct nvmet_ns *ns)
521518
{
522519
struct device *clients[2];
523520
struct pci_dev *p2p_dev;
524521
int ret;
525522

523+
lockdep_assert_held(&ctrl->subsys->lock);
524+
526525
if (!ctrl->p2p_client || !ns->use_p2pmem)
527526
return;
528527

@@ -1539,15 +1538,14 @@ bool nvmet_host_allowed(struct nvmet_subsys *subsys, const char *hostnqn)
15391538
return false;
15401539
}
15411540

1542-
/*
1543-
* Note: ctrl->subsys->lock should be held when calling this function
1544-
*/
15451541
static void nvmet_setup_p2p_ns_map(struct nvmet_ctrl *ctrl,
15461542
struct device *p2p_client)
15471543
{
15481544
struct nvmet_ns *ns;
15491545
unsigned long idx;
15501546

1547+
lockdep_assert_held(&ctrl->subsys->lock);
1548+
15511549
if (!p2p_client)
15521550
return;
15531551

@@ -1557,14 +1555,13 @@ static void nvmet_setup_p2p_ns_map(struct nvmet_ctrl *ctrl,
15571555
nvmet_p2pmem_ns_add_p2p(ctrl, ns);
15581556
}
15591557

1560-
/*
1561-
* Note: ctrl->subsys->lock should be held when calling this function
1562-
*/
15631558
static void nvmet_release_p2p_ns_map(struct nvmet_ctrl *ctrl)
15641559
{
15651560
struct radix_tree_iter iter;
15661561
void __rcu **slot;
15671562

1563+
lockdep_assert_held(&ctrl->subsys->lock);
1564+
15681565
radix_tree_for_each_slot(slot, &ctrl->p2p_ns_map, &iter, 0)
15691566
pci_dev_put(radix_tree_deref_slot(slot));
15701567

drivers/nvme/target/fc.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ struct nvmet_fc_ls_req_op { /* for an LS RQST XMT */
5454
int ls_error;
5555
struct list_head lsreq_list; /* tgtport->ls_req_list */
5656
bool req_queued;
57+
58+
struct work_struct put_work;
5759
};
5860

5961

@@ -111,8 +113,6 @@ struct nvmet_fc_tgtport {
111113
struct nvmet_fc_port_entry *pe;
112114
struct kref ref;
113115
u32 max_sg_cnt;
114-
115-
struct work_struct put_work;
116116
};
117117

118118
struct nvmet_fc_port_entry {
@@ -235,12 +235,13 @@ static int nvmet_fc_tgt_a_get(struct nvmet_fc_tgt_assoc *assoc);
235235
static void nvmet_fc_tgt_q_put(struct nvmet_fc_tgt_queue *queue);
236236
static int nvmet_fc_tgt_q_get(struct nvmet_fc_tgt_queue *queue);
237237
static void nvmet_fc_tgtport_put(struct nvmet_fc_tgtport *tgtport);
238-
static void nvmet_fc_put_tgtport_work(struct work_struct *work)
238+
static void nvmet_fc_put_lsop_work(struct work_struct *work)
239239
{
240-
struct nvmet_fc_tgtport *tgtport =
241-
container_of(work, struct nvmet_fc_tgtport, put_work);
240+
struct nvmet_fc_ls_req_op *lsop =
241+
container_of(work, struct nvmet_fc_ls_req_op, put_work);
242242

243-
nvmet_fc_tgtport_put(tgtport);
243+
nvmet_fc_tgtport_put(lsop->tgtport);
244+
kfree(lsop);
244245
}
245246
static int nvmet_fc_tgtport_get(struct nvmet_fc_tgtport *tgtport);
246247
static void nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
@@ -367,7 +368,7 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop)
367368
DMA_BIDIRECTIONAL);
368369

369370
out_putwork:
370-
queue_work(nvmet_wq, &tgtport->put_work);
371+
queue_work(nvmet_wq, &lsop->put_work);
371372
}
372373

373374
static int
@@ -388,6 +389,7 @@ __nvmet_fc_send_ls_req(struct nvmet_fc_tgtport *tgtport,
388389
lsreq->done = done;
389390
lsop->req_queued = false;
390391
INIT_LIST_HEAD(&lsop->lsreq_list);
392+
INIT_WORK(&lsop->put_work, nvmet_fc_put_lsop_work);
391393

392394
lsreq->rqstdma = fc_dma_map_single(tgtport->dev, lsreq->rqstaddr,
393395
lsreq->rqstlen + lsreq->rsplen,
@@ -447,8 +449,6 @@ nvmet_fc_disconnect_assoc_done(struct nvmefc_ls_req *lsreq, int status)
447449
__nvmet_fc_finish_ls_req(lsop);
448450

449451
/* fc-nvme target doesn't care about success or failure of cmd */
450-
451-
kfree(lsop);
452452
}
453453

454454
/*
@@ -1075,6 +1075,14 @@ nvmet_fc_delete_assoc_work(struct work_struct *work)
10751075
static void
10761076
nvmet_fc_schedule_delete_assoc(struct nvmet_fc_tgt_assoc *assoc)
10771077
{
1078+
int terminating;
1079+
1080+
terminating = atomic_xchg(&assoc->terminating, 1);
1081+
1082+
/* if already terminating, do nothing */
1083+
if (terminating)
1084+
return;
1085+
10781086
nvmet_fc_tgtport_get(assoc->tgtport);
10791087
if (!queue_work(nvmet_wq, &assoc->del_work))
10801088
nvmet_fc_tgtport_put(assoc->tgtport);
@@ -1202,13 +1210,7 @@ nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc)
12021210
{
12031211
struct nvmet_fc_tgtport *tgtport = assoc->tgtport;
12041212
unsigned long flags;
1205-
int i, terminating;
1206-
1207-
terminating = atomic_xchg(&assoc->terminating, 1);
1208-
1209-
/* if already terminating, do nothing */
1210-
if (terminating)
1211-
return;
1213+
int i;
12121214

12131215
spin_lock_irqsave(&tgtport->lock, flags);
12141216
list_del_rcu(&assoc->a_list);
@@ -1410,7 +1412,6 @@ nvmet_fc_register_targetport(struct nvmet_fc_port_info *pinfo,
14101412
kref_init(&newrec->ref);
14111413
ida_init(&newrec->assoc_cnt);
14121414
newrec->max_sg_cnt = template->max_sgl_segments;
1413-
INIT_WORK(&newrec->put_work, nvmet_fc_put_tgtport_work);
14141415

14151416
ret = nvmet_fc_alloc_ls_iodlist(newrec);
14161417
if (ret) {

0 commit comments

Comments
 (0)