Skip to content

Commit be93e87

Browse files
Keith BuschChristoph Hellwig
authored andcommitted
nvme: support for multiple Command Sets Supported and Effects log pages
The Commands Supported and Effects log page was extended with a CSI field that enables the host to query the log page for each command set supported. Retrieve this log page for each command set that an attached namespace supports, and save a pointer to that log in the namespace head. Reviewed-by: Matias Bjørling <matias.bjorling@wdc.com> Reviewed-by: Javier González <javier.gonz@samsung.com> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Daniel Wagner <dwagner@suse.de> Signed-off-by: Keith Busch <keith.busch@wdc.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent 71010c3 commit be93e87

File tree

6 files changed

+76
-25
lines changed

6 files changed

+76
-25
lines changed

drivers/nvme/host/core.c

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,8 +1370,8 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
13701370
u32 effects = 0;
13711371

13721372
if (ns) {
1373-
if (ctrl->effects)
1374-
effects = le32_to_cpu(ctrl->effects->iocs[opcode]);
1373+
if (ns->head->effects)
1374+
effects = le32_to_cpu(ns->head->effects->iocs[opcode]);
13751375
if (effects & ~(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC))
13761376
dev_warn(ctrl->device,
13771377
"IO command:%02x has unhandled effects:%08x\n",
@@ -2851,7 +2851,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
28512851
return ret;
28522852
}
28532853

2854-
int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp,
2854+
int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi,
28552855
void *log, size_t size, u64 offset)
28562856
{
28572857
struct nvme_command c = { };
@@ -2865,27 +2865,55 @@ int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp,
28652865
c.get_log_page.numdu = cpu_to_le16(dwlen >> 16);
28662866
c.get_log_page.lpol = cpu_to_le32(lower_32_bits(offset));
28672867
c.get_log_page.lpou = cpu_to_le32(upper_32_bits(offset));
2868+
c.get_log_page.csi = csi;
28682869

28692870
return nvme_submit_sync_cmd(ctrl->admin_q, &c, log, size);
28702871
}
28712872

2872-
static int nvme_get_effects_log(struct nvme_ctrl *ctrl)
2873+
static struct nvme_cel *nvme_find_cel(struct nvme_ctrl *ctrl, u8 csi)
28732874
{
2875+
struct nvme_cel *cel, *ret = NULL;
2876+
2877+
spin_lock(&ctrl->lock);
2878+
list_for_each_entry(cel, &ctrl->cels, entry) {
2879+
if (cel->csi == csi) {
2880+
ret = cel;
2881+
break;
2882+
}
2883+
}
2884+
spin_unlock(&ctrl->lock);
2885+
2886+
return ret;
2887+
}
2888+
2889+
static int nvme_get_effects_log(struct nvme_ctrl *ctrl, u8 csi,
2890+
struct nvme_effects_log **log)
2891+
{
2892+
struct nvme_cel *cel = nvme_find_cel(ctrl, csi);
28742893
int ret;
28752894

2876-
if (!ctrl->effects)
2877-
ctrl->effects = kzalloc(sizeof(*ctrl->effects), GFP_KERNEL);
2895+
if (cel)
2896+
goto out;
28782897

2879-
if (!ctrl->effects)
2880-
return 0;
2898+
cel = kzalloc(sizeof(*cel), GFP_KERNEL);
2899+
if (!cel)
2900+
return -ENOMEM;
28812901

2882-
ret = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_CMD_EFFECTS, 0,
2883-
ctrl->effects, sizeof(*ctrl->effects), 0);
2902+
ret = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_CMD_EFFECTS, 0, csi,
2903+
&cel->log, sizeof(cel->log), 0);
28842904
if (ret) {
2885-
kfree(ctrl->effects);
2886-
ctrl->effects = NULL;
2905+
kfree(cel);
2906+
return ret;
28872907
}
2888-
return ret;
2908+
2909+
cel->csi = csi;
2910+
2911+
spin_lock(&ctrl->lock);
2912+
list_add_tail(&cel->entry, &ctrl->cels);
2913+
spin_unlock(&ctrl->lock);
2914+
out:
2915+
*log = &cel->log;
2916+
return 0;
28892917
}
28902918

28912919
/*
@@ -2918,7 +2946,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
29182946
}
29192947

29202948
if (id->lpa & NVME_CTRL_LPA_CMD_EFFECTS_LOG) {
2921-
ret = nvme_get_effects_log(ctrl);
2949+
ret = nvme_get_effects_log(ctrl, NVME_CSI_NVM, &ctrl->effects);
29222950
if (ret < 0)
29232951
goto out_free;
29242952
}
@@ -3551,6 +3579,13 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
35513579
goto out_cleanup_srcu;
35523580
}
35533581

3582+
if (head->ids.csi) {
3583+
ret = nvme_get_effects_log(ctrl, head->ids.csi, &head->effects);
3584+
if (ret)
3585+
goto out_cleanup_srcu;
3586+
} else
3587+
head->effects = ctrl->effects;
3588+
35543589
ret = nvme_mpath_alloc_disk(ctrl, head);
35553590
if (ret)
35563591
goto out_cleanup_srcu;
@@ -3891,8 +3926,8 @@ static void nvme_clear_changed_ns_log(struct nvme_ctrl *ctrl)
38913926
* raced with us in reading the log page, which could cause us to miss
38923927
* updates.
38933928
*/
3894-
error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_CHANGED_NS, 0, log,
3895-
log_size, 0);
3929+
error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_CHANGED_NS, 0,
3930+
NVME_CSI_NVM, log, log_size, 0);
38963931
if (error)
38973932
dev_warn(ctrl->device,
38983933
"reading changed ns log failed: %d\n", error);
@@ -4036,8 +4071,8 @@ static void nvme_get_fw_slot_info(struct nvme_ctrl *ctrl)
40364071
if (!log)
40374072
return;
40384073

4039-
if (nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_FW_SLOT, 0, log,
4040-
sizeof(*log), 0))
4074+
if (nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_FW_SLOT, 0, NVME_CSI_NVM,
4075+
log, sizeof(*log), 0))
40414076
dev_warn(ctrl->device, "Get FW SLOT INFO log error\n");
40424077
kfree(log);
40434078
}
@@ -4174,11 +4209,16 @@ static void nvme_free_ctrl(struct device *dev)
41744209
struct nvme_ctrl *ctrl =
41754210
container_of(dev, struct nvme_ctrl, ctrl_device);
41764211
struct nvme_subsystem *subsys = ctrl->subsys;
4212+
struct nvme_cel *cel, *next;
41774213

41784214
if (subsys && ctrl->instance != subsys->instance)
41794215
ida_simple_remove(&nvme_instance_ida, ctrl->instance);
41804216

4181-
kfree(ctrl->effects);
4217+
list_for_each_entry_safe(cel, next, &ctrl->cels, entry) {
4218+
list_del(&cel->entry);
4219+
kfree(cel);
4220+
}
4221+
41824222
nvme_mpath_uninit(ctrl);
41834223
__free_page(ctrl->discard_page);
41844224

@@ -4209,6 +4249,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
42094249
spin_lock_init(&ctrl->lock);
42104250
mutex_init(&ctrl->scan_lock);
42114251
INIT_LIST_HEAD(&ctrl->namespaces);
4252+
INIT_LIST_HEAD(&ctrl->cels);
42124253
init_rwsem(&ctrl->namespaces_rwsem);
42134254
ctrl->dev = dev;
42144255
ctrl->ops = ops;

drivers/nvme/host/hwmon.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ static int nvme_hwmon_get_smart_log(struct nvme_hwmon_data *data)
6262
int ret;
6363

6464
ret = nvme_get_log(data->ctrl, NVME_NSID_ALL, NVME_LOG_SMART, 0,
65-
&data->log, sizeof(data->log), 0);
65+
NVME_CSI_NVM, &data->log, sizeof(data->log), 0);
6666

6767
return ret <= 0 ? ret : -EIO;
6868
}

drivers/nvme/host/lightnvm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,8 @@ static int nvme_nvm_get_chk_meta(struct nvm_dev *ndev,
593593
dev_meta_off = dev_meta;
594594

595595
ret = nvme_get_log(ctrl, ns->head->ns_id,
596-
NVME_NVM_LOG_REPORT_CHUNK, 0, dev_meta, len,
597-
offset);
596+
NVME_NVM_LOG_REPORT_CHUNK, 0, NVME_CSI_NVM,
597+
dev_meta, len, offset);
598598
if (ret) {
599599
dev_err(ctrl->device, "Get REPORT CHUNK log error\n");
600600
break;

drivers/nvme/host/multipath.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ static int nvme_read_ana_log(struct nvme_ctrl *ctrl)
527527
int error;
528528

529529
mutex_lock(&ctrl->ana_lock);
530-
error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_ANA, 0,
530+
error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_ANA, 0, NVME_CSI_NVM,
531531
ctrl->ana_log_buf, ctrl->ana_log_size, 0);
532532
if (error) {
533533
dev_warn(ctrl->device, "Failed to get ANA log: %d\n", error);

drivers/nvme/host/nvme.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ struct nvme_fault_inject {
191191
#endif
192192
};
193193

194+
struct nvme_cel {
195+
struct list_head entry;
196+
struct nvme_effects_log log;
197+
u8 csi;
198+
};
199+
194200
struct nvme_ctrl {
195201
bool comp_seen;
196202
enum nvme_ctrl_state state;
@@ -257,6 +263,7 @@ struct nvme_ctrl {
257263
unsigned long quirks;
258264
struct nvme_id_power_state psd[32];
259265
struct nvme_effects_log *effects;
266+
struct list_head cels;
260267
struct work_struct scan_work;
261268
struct work_struct async_event_work;
262269
struct delayed_work ka_work;
@@ -359,6 +366,7 @@ struct nvme_ns_head {
359366
struct kref ref;
360367
bool shared;
361368
int instance;
369+
struct nvme_effects_log *effects;
362370
#ifdef CONFIG_NVME_MULTIPATH
363371
struct gendisk *disk;
364372
struct bio_list requeue_list;
@@ -561,7 +569,7 @@ int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl);
561569
int nvme_try_sched_reset(struct nvme_ctrl *ctrl);
562570
int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
563571

564-
int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp,
572+
int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi,
565573
void *log, size_t size, u64 offset);
566574

567575
extern const struct attribute_group *nvme_ns_id_attr_groups[];

include/linux/nvme.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,9 @@ struct nvme_get_log_page_command {
11011101
};
11021102
__le64 lpo;
11031103
};
1104-
__u32 rsvd14[2];
1104+
__u8 rsvd14[3];
1105+
__u8 csi;
1106+
__u32 rsvd15;
11051107
};
11061108

11071109
struct nvme_directive_cmd {

0 commit comments

Comments
 (0)