Commit | Line | Data |
---|---|---|
f11bb3e2 CH |
1 | /* |
2 | * Copyright (c) 2011-2014, Intel Corporation. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms and conditions of the GNU General Public License, | |
6 | * version 2, as published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope it will be useful, but WITHOUT | |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
11 | * more details. | |
12 | */ | |
13 | ||
14 | #ifndef _NVME_H | |
15 | #define _NVME_H | |
16 | ||
17 | #include <linux/nvme.h> | |
18 | #include <linux/pci.h> | |
19 | #include <linux/kref.h> | |
20 | #include <linux/blk-mq.h> | |
21 | ||
1673f1f0 CH |
22 | struct nvme_passthru_cmd; |
23 | ||
f11bb3e2 CH |
24 | extern unsigned char nvme_io_timeout; |
25 | #define NVME_IO_TIMEOUT (nvme_io_timeout * HZ) | |
26 | ||
21d34711 CH |
27 | extern unsigned char admin_timeout; |
28 | #define ADMIN_TIMEOUT (admin_timeout * HZ) | |
29 | ||
5fd4ce1b CH |
30 | extern unsigned char shutdown_timeout; |
31 | #define SHUTDOWN_TIMEOUT (shutdown_timeout * HZ) | |
32 | ||
ca064085 MB |
33 | enum { |
34 | NVME_NS_LBA = 0, | |
35 | NVME_NS_LIGHTNVM = 1, | |
36 | }; | |
37 | ||
106198ed CH |
38 | /* |
39 | * List of workarounds for devices that required behavior not specified in | |
40 | * the standard. | |
41 | */ | |
42 | enum nvme_quirks { | |
43 | /* | |
44 | * Prefers I/O aligned to a stripe size specified in a vendor | |
45 | * specific Identify field. | |
46 | */ | |
47 | NVME_QUIRK_STRIPE_SIZE = (1 << 0), | |
48 | }; | |
49 | ||
1c63dc66 CH |
50 | struct nvme_ctrl { |
51 | const struct nvme_ctrl_ops *ops; | |
f11bb3e2 | 52 | struct request_queue *admin_q; |
f11bb3e2 | 53 | struct device *dev; |
1673f1f0 | 54 | struct kref kref; |
f11bb3e2 | 55 | int instance; |
5bae7f73 CH |
56 | struct blk_mq_tag_set *tagset; |
57 | struct list_head namespaces; | |
58 | struct device *device; /* char device */ | |
1c63dc66 | 59 | |
f11bb3e2 CH |
60 | char name[12]; |
61 | char serial[20]; | |
62 | char model[40]; | |
63 | char firmware_rev[8]; | |
5fd4ce1b CH |
64 | |
65 | u32 ctrl_config; | |
66 | ||
67 | u32 page_size; | |
7fd8930f CH |
68 | u32 max_hw_sectors; |
69 | u32 stripe_size; | |
f11bb3e2 CH |
70 | u16 oncs; |
71 | u16 abort_limit; | |
72 | u8 event_limit; | |
73 | u8 vwc; | |
106198ed | 74 | unsigned long quirks; |
f11bb3e2 CH |
75 | }; |
76 | ||
77 | /* | |
78 | * An NVM Express namespace is equivalent to a SCSI LUN | |
79 | */ | |
80 | struct nvme_ns { | |
81 | struct list_head list; | |
82 | ||
1c63dc66 | 83 | struct nvme_ctrl *ctrl; |
f11bb3e2 CH |
84 | struct request_queue *queue; |
85 | struct gendisk *disk; | |
86 | struct kref kref; | |
87 | ||
88 | unsigned ns_id; | |
89 | int lba_shift; | |
90 | u16 ms; | |
91 | bool ext; | |
92 | u8 pi_type; | |
ca064085 | 93 | int type; |
f11bb3e2 CH |
94 | u64 mode_select_num_blocks; |
95 | u32 mode_select_block_len; | |
96 | }; | |
97 | ||
1c63dc66 CH |
98 | struct nvme_ctrl_ops { |
99 | int (*reg_read32)(struct nvme_ctrl *ctrl, u32 off, u32 *val); | |
5fd4ce1b | 100 | int (*reg_write32)(struct nvme_ctrl *ctrl, u32 off, u32 val); |
7fd8930f | 101 | int (*reg_read64)(struct nvme_ctrl *ctrl, u32 off, u64 *val); |
5bae7f73 | 102 | bool (*io_incapable)(struct nvme_ctrl *ctrl); |
1673f1f0 | 103 | void (*free_ctrl)(struct nvme_ctrl *ctrl); |
1c63dc66 CH |
104 | }; |
105 | ||
106 | static inline bool nvme_ctrl_ready(struct nvme_ctrl *ctrl) | |
107 | { | |
108 | u32 val = 0; | |
109 | ||
110 | if (ctrl->ops->reg_read32(ctrl, NVME_REG_CSTS, &val)) | |
111 | return false; | |
112 | return val & NVME_CSTS_RDY; | |
113 | } | |
114 | ||
5bae7f73 CH |
115 | static inline bool nvme_io_incapable(struct nvme_ctrl *ctrl) |
116 | { | |
117 | u32 val = 0; | |
118 | ||
119 | if (ctrl->ops->io_incapable(ctrl)) | |
120 | return false; | |
121 | if (ctrl->ops->reg_read32(ctrl, NVME_REG_CSTS, &val)) | |
122 | return false; | |
123 | return val & NVME_CSTS_CFS; | |
124 | } | |
125 | ||
f11bb3e2 CH |
126 | static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector) |
127 | { | |
128 | return (sector >> (ns->lba_shift - 9)); | |
129 | } | |
130 | ||
22944e99 CH |
131 | static inline void nvme_setup_flush(struct nvme_ns *ns, |
132 | struct nvme_command *cmnd) | |
133 | { | |
134 | memset(cmnd, 0, sizeof(*cmnd)); | |
135 | cmnd->common.opcode = nvme_cmd_flush; | |
136 | cmnd->common.nsid = cpu_to_le32(ns->ns_id); | |
137 | } | |
138 | ||
139 | static inline void nvme_setup_rw(struct nvme_ns *ns, struct request *req, | |
140 | struct nvme_command *cmnd) | |
141 | { | |
142 | u16 control = 0; | |
143 | u32 dsmgmt = 0; | |
144 | ||
145 | if (req->cmd_flags & REQ_FUA) | |
146 | control |= NVME_RW_FUA; | |
147 | if (req->cmd_flags & (REQ_FAILFAST_DEV | REQ_RAHEAD)) | |
148 | control |= NVME_RW_LR; | |
149 | ||
150 | if (req->cmd_flags & REQ_RAHEAD) | |
151 | dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH; | |
152 | ||
153 | memset(cmnd, 0, sizeof(*cmnd)); | |
154 | cmnd->rw.opcode = (rq_data_dir(req) ? nvme_cmd_write : nvme_cmd_read); | |
155 | cmnd->rw.command_id = req->tag; | |
156 | cmnd->rw.nsid = cpu_to_le32(ns->ns_id); | |
157 | cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req))); | |
158 | cmnd->rw.length = cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1); | |
159 | ||
160 | if (ns->ms) { | |
161 | switch (ns->pi_type) { | |
162 | case NVME_NS_DPS_PI_TYPE3: | |
163 | control |= NVME_RW_PRINFO_PRCHK_GUARD; | |
164 | break; | |
165 | case NVME_NS_DPS_PI_TYPE1: | |
166 | case NVME_NS_DPS_PI_TYPE2: | |
167 | control |= NVME_RW_PRINFO_PRCHK_GUARD | | |
168 | NVME_RW_PRINFO_PRCHK_REF; | |
169 | cmnd->rw.reftag = cpu_to_le32( | |
170 | nvme_block_nr(ns, blk_rq_pos(req))); | |
171 | break; | |
172 | } | |
173 | if (!blk_integrity_rq(req)) | |
174 | control |= NVME_RW_PRINFO_PRACT; | |
175 | } | |
176 | ||
177 | cmnd->rw.control = cpu_to_le16(control); | |
178 | cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt); | |
179 | } | |
180 | ||
181 | ||
15a190f7 CH |
182 | static inline int nvme_error_status(u16 status) |
183 | { | |
184 | switch (status & 0x7ff) { | |
185 | case NVME_SC_SUCCESS: | |
186 | return 0; | |
187 | case NVME_SC_CAP_EXCEEDED: | |
188 | return -ENOSPC; | |
189 | default: | |
190 | return -EIO; | |
191 | } | |
192 | } | |
193 | ||
5fd4ce1b CH |
194 | int nvme_disable_ctrl(struct nvme_ctrl *ctrl, u64 cap); |
195 | int nvme_enable_ctrl(struct nvme_ctrl *ctrl, u64 cap); | |
196 | int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl); | |
1673f1f0 | 197 | void nvme_put_ctrl(struct nvme_ctrl *ctrl); |
7fd8930f | 198 | int nvme_init_identify(struct nvme_ctrl *ctrl); |
5bae7f73 CH |
199 | |
200 | void nvme_scan_namespaces(struct nvme_ctrl *ctrl); | |
201 | void nvme_remove_namespaces(struct nvme_ctrl *ctrl); | |
1673f1f0 | 202 | |
4160982e CH |
203 | struct request *nvme_alloc_request(struct request_queue *q, |
204 | struct nvme_command *cmd, unsigned int flags); | |
f11bb3e2 CH |
205 | int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, |
206 | void *buf, unsigned bufflen); | |
207 | int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, | |
4160982e CH |
208 | void *buffer, unsigned bufflen, u32 *result, unsigned timeout); |
209 | int nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd, | |
210 | void __user *ubuffer, unsigned bufflen, u32 *result, | |
211 | unsigned timeout); | |
0b7f1f26 KB |
212 | int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd, |
213 | void __user *ubuffer, unsigned bufflen, | |
214 | void __user *meta_buffer, unsigned meta_len, u32 meta_seed, | |
215 | u32 *result, unsigned timeout); | |
1c63dc66 CH |
216 | int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id); |
217 | int nvme_identify_ns(struct nvme_ctrl *dev, unsigned nsid, | |
f11bb3e2 | 218 | struct nvme_id_ns **id); |
1c63dc66 CH |
219 | int nvme_get_log_page(struct nvme_ctrl *dev, struct nvme_smart_log **log); |
220 | int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid, | |
f11bb3e2 | 221 | dma_addr_t dma_addr, u32 *result); |
1c63dc66 | 222 | int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11, |
f11bb3e2 CH |
223 | dma_addr_t dma_addr, u32 *result); |
224 | ||
1673f1f0 CH |
225 | extern spinlock_t dev_list_lock; |
226 | ||
1673f1f0 CH |
227 | int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, |
228 | struct nvme_passthru_cmd __user *ucmd); | |
229 | ||
f11bb3e2 CH |
230 | struct sg_io_hdr; |
231 | ||
232 | int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr); | |
233 | int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg); | |
234 | int nvme_sg_get_version_num(int __user *ip); | |
235 | ||
ca064085 MB |
236 | int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id); |
237 | int nvme_nvm_register(struct request_queue *q, char *disk_name); | |
238 | void nvme_nvm_unregister(struct request_queue *q, char *disk_name); | |
239 | ||
5bae7f73 CH |
240 | int __init nvme_core_init(void); |
241 | void nvme_core_exit(void); | |
242 | ||
f11bb3e2 | 243 | #endif /* _NVME_H */ |