Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/nvme/nvme_ns.c
Show First 20 Lines • Show All 504 Lines • ▼ Show 20 Lines | |||||
nvme_ns_ioctl_process(struct nvme_namespace *ns, u_long cmd, caddr_t arg, | nvme_ns_ioctl_process(struct nvme_namespace *ns, u_long cmd, caddr_t arg, | ||||
int flag, struct thread *td) | int flag, struct thread *td) | ||||
{ | { | ||||
return (nvme_ns_ioctl(ns->cdev, cmd, arg, flag, td)); | return (nvme_ns_ioctl(ns->cdev, cmd, arg, flag, td)); | ||||
} | } | ||||
int | int | ||||
nvme_ns_construct(struct nvme_namespace *ns, uint32_t id, | nvme_ns_construct(struct nvme_namespace *ns, uint32_t id, | ||||
struct nvme_controller *ctrlr) | struct nvme_controller *ctrlr, enum nvme_ctor_reason why) | ||||
{ | { | ||||
struct make_dev_args md_args; | struct make_dev_args md_args; | ||||
struct nvme_completion_poll_status status; | struct nvme_completion_poll_status status; | ||||
int res; | int res; | ||||
int unit; | int unit; | ||||
uint8_t flbas_fmt; | uint8_t flbas_fmt; | ||||
uint8_t vwc_present; | uint8_t vwc_present; | ||||
Show All 22 Lines | nvme_ns_construct(struct nvme_namespace *ns, uint32_t id, | ||||
/* Convert data to host endian */ | /* Convert data to host endian */ | ||||
nvme_namespace_data_swapbytes(&ns->data); | nvme_namespace_data_swapbytes(&ns->data); | ||||
/* | /* | ||||
* If the size of is zero, chances are this isn't a valid | * If the size of is zero, chances are this isn't a valid | ||||
* namespace (eg one that's not been configured yet). The | * namespace (eg one that's not been configured yet). The | ||||
* standard says the entire id will be zeros, so this is a | * standard says the entire id will be zeros, so this is a | ||||
* cheap way to test for that. | * cheap way to test for that. If we previously added this | ||||
* device, then it's now gone. | |||||
*/ | */ | ||||
if (ns->data.nsze == 0) | if (ns->data.nsze == 0) { | ||||
return (ENXIO); | ns->flags |= NVME_NS_FLAG_GONE; | ||||
return ((ns->flags & NVME_NS_FLAG_ADDED) ? 0 : ENXIO); | |||||
} | |||||
flbas_fmt = (ns->data.flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) & | flbas_fmt = (ns->data.flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) & | ||||
NVME_NS_DATA_FLBAS_FORMAT_MASK; | NVME_NS_DATA_FLBAS_FORMAT_MASK; | ||||
/* | /* | ||||
* Note: format is a 0-based value, so > is appropriate here, | * Note: format is a 0-based value, so > is appropriate here, | ||||
* not >=. | * not >=. | ||||
*/ | */ | ||||
if (flbas_fmt > ns->data.nlbaf) { | if (flbas_fmt > ns->data.nlbaf) { | ||||
Show All 28 Lines | nvme_ns_construct(struct nvme_namespace *ns, uint32_t id, | ||||
vwc_present = (ctrlr->cdata.vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) & | vwc_present = (ctrlr->cdata.vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) & | ||||
NVME_CTRLR_DATA_VWC_PRESENT_MASK; | NVME_CTRLR_DATA_VWC_PRESENT_MASK; | ||||
if (vwc_present) | if (vwc_present) | ||||
ns->flags |= NVME_NS_FLUSH_SUPPORTED; | ns->flags |= NVME_NS_FLUSH_SUPPORTED; | ||||
/* | /* | ||||
* cdev may have already been created, if we are reconstructing the | * cdev may have already been created, if we are reconstructing the | ||||
* namespace after a controller-level reset. | * namespace after a controller-level reset. If not, then flag this | ||||
* ns as changed for notification. | |||||
*/ | */ | ||||
if (ns->cdev != NULL) | if (ns->cdev != NULL) { | ||||
if (why != NVME_REASON_RESET) | |||||
ns->flags |= NVME_NS_FLAG_CHANGED; | |||||
return (0); | return (0); | ||||
} | |||||
/* | /* | ||||
* Namespace IDs start at 1, so we need to subtract 1 to create a | * Namespace IDs start at 1, so we need to subtract 1 to create a | ||||
* correct unit number. | * correct unit number. | ||||
*/ | */ | ||||
unit = device_get_unit(ctrlr->dev) * NVME_MAX_NAMESPACES + ns->id - 1; | unit = device_get_unit(ctrlr->dev) * NVME_MAX_NAMESPACES + ns->id - 1; | ||||
make_dev_args_init(&md_args); | make_dev_args_init(&md_args); | ||||
md_args.mda_devsw = &nvme_ns_cdevsw; | md_args.mda_devsw = &nvme_ns_cdevsw; | ||||
md_args.mda_unit = unit; | md_args.mda_unit = unit; | ||||
md_args.mda_mode = 0600; | md_args.mda_mode = 0600; | ||||
md_args.mda_si_drv1 = ns; | md_args.mda_si_drv1 = ns; | ||||
res = make_dev_s(&md_args, &ns->cdev, "nvme%dns%d", | res = make_dev_s(&md_args, &ns->cdev, "nvme%dns%d", | ||||
device_get_unit(ctrlr->dev), ns->id); | device_get_unit(ctrlr->dev), ns->id); | ||||
if (res != 0) | if (res != 0) | ||||
return (ENXIO); | return (ENXIO); | ||||
ns->cdev->si_flags |= SI_UNMAPPED; | ns->cdev->si_flags |= SI_UNMAPPED; | ||||
ns->flags |= NVME_NS_FLAG_ADDED; | |||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
nvme_ns_destruct(struct nvme_namespace *ns) | nvme_ns_destruct(struct nvme_namespace *ns) | ||||
{ | { | ||||
if (ns->cdev != NULL) | if (ns->cdev != NULL) | ||||
destroy_dev(ns->cdev); | destroy_dev(ns->cdev); | ||||
} | } |