]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/nvme/host/core.c
2 * NVM Express device driver
3 * Copyright (c) 2011-2014, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 #include <linux/blkdev.h>
16 #include <linux/blk-mq.h>
17 #include <linux/errno.h>
18 #include <linux/kernel.h>
19 #include <linux/slab.h>
20 #include <linux/types.h>
24 struct request
*nvme_alloc_request(struct request_queue
*q
,
25 struct nvme_command
*cmd
, unsigned int flags
)
27 bool write
= cmd
->common
.opcode
& 1;
30 req
= blk_mq_alloc_request(q
, write
, flags
);
34 req
->cmd_type
= REQ_TYPE_DRV_PRIV
;
35 req
->cmd_flags
|= REQ_FAILFAST_DRIVER
;
37 req
->__sector
= (sector_t
) -1;
38 req
->bio
= req
->biotail
= NULL
;
40 req
->cmd
= (unsigned char *)cmd
;
41 req
->cmd_len
= sizeof(struct nvme_command
);
42 req
->special
= (void *)0;
48 * Returns 0 on success. If the result is negative, it's a Linux error code;
49 * if the result is positive, it's an NVM Express status code
51 int __nvme_submit_sync_cmd(struct request_queue
*q
, struct nvme_command
*cmd
,
52 void *buffer
, unsigned bufflen
, u32
*result
, unsigned timeout
)
57 req
= nvme_alloc_request(q
, cmd
, 0);
61 req
->timeout
= timeout
? timeout
: ADMIN_TIMEOUT
;
63 if (buffer
&& bufflen
) {
64 ret
= blk_rq_map_kern(q
, req
, buffer
, bufflen
, GFP_KERNEL
);
69 blk_execute_rq(req
->q
, NULL
, req
, 0);
71 *result
= (u32
)(uintptr_t)req
->special
;
74 blk_mq_free_request(req
);
78 int nvme_submit_sync_cmd(struct request_queue
*q
, struct nvme_command
*cmd
,
79 void *buffer
, unsigned bufflen
)
81 return __nvme_submit_sync_cmd(q
, cmd
, buffer
, bufflen
, NULL
, 0);
84 int nvme_submit_user_cmd(struct request_queue
*q
, struct nvme_command
*cmd
,
85 void __user
*ubuffer
, unsigned bufflen
, u32
*result
,
88 struct bio
*bio
= NULL
;
92 req
= nvme_alloc_request(q
, cmd
, 0);
96 req
->timeout
= timeout
? timeout
: ADMIN_TIMEOUT
;
98 if (ubuffer
&& bufflen
) {
99 ret
= blk_rq_map_user(q
, req
, NULL
, ubuffer
, bufflen
,
106 blk_execute_rq(req
->q
, NULL
, req
, 0);
108 blk_rq_unmap_user(bio
);
110 *result
= (u32
)(uintptr_t)req
->special
;
113 blk_mq_free_request(req
);
117 int nvme_identify_ctrl(struct nvme_ctrl
*dev
, struct nvme_id_ctrl
**id
)
119 struct nvme_command c
= { };
122 /* gcc-4.4.4 (at least) has issues with initializers and anon unions */
123 c
.identify
.opcode
= nvme_admin_identify
;
124 c
.identify
.cns
= cpu_to_le32(1);
126 *id
= kmalloc(sizeof(struct nvme_id_ctrl
), GFP_KERNEL
);
130 error
= nvme_submit_sync_cmd(dev
->admin_q
, &c
, *id
,
131 sizeof(struct nvme_id_ctrl
));
137 int nvme_identify_ns(struct nvme_ctrl
*dev
, unsigned nsid
,
138 struct nvme_id_ns
**id
)
140 struct nvme_command c
= { };
143 /* gcc-4.4.4 (at least) has issues with initializers and anon unions */
144 c
.identify
.opcode
= nvme_admin_identify
,
145 c
.identify
.nsid
= cpu_to_le32(nsid
),
147 *id
= kmalloc(sizeof(struct nvme_id_ns
), GFP_KERNEL
);
151 error
= nvme_submit_sync_cmd(dev
->admin_q
, &c
, *id
,
152 sizeof(struct nvme_id_ns
));
158 int nvme_get_features(struct nvme_ctrl
*dev
, unsigned fid
, unsigned nsid
,
159 dma_addr_t dma_addr
, u32
*result
)
161 struct nvme_command c
;
163 memset(&c
, 0, sizeof(c
));
164 c
.features
.opcode
= nvme_admin_get_features
;
165 c
.features
.nsid
= cpu_to_le32(nsid
);
166 c
.features
.prp1
= cpu_to_le64(dma_addr
);
167 c
.features
.fid
= cpu_to_le32(fid
);
169 return __nvme_submit_sync_cmd(dev
->admin_q
, &c
, NULL
, 0, result
, 0);
172 int nvme_set_features(struct nvme_ctrl
*dev
, unsigned fid
, unsigned dword11
,
173 dma_addr_t dma_addr
, u32
*result
)
175 struct nvme_command c
;
177 memset(&c
, 0, sizeof(c
));
178 c
.features
.opcode
= nvme_admin_set_features
;
179 c
.features
.prp1
= cpu_to_le64(dma_addr
);
180 c
.features
.fid
= cpu_to_le32(fid
);
181 c
.features
.dword11
= cpu_to_le32(dword11
);
183 return __nvme_submit_sync_cmd(dev
->admin_q
, &c
, NULL
, 0, result
, 0);
186 int nvme_get_log_page(struct nvme_ctrl
*dev
, struct nvme_smart_log
**log
)
188 struct nvme_command c
= { };
191 c
.common
.opcode
= nvme_admin_get_log_page
,
192 c
.common
.nsid
= cpu_to_le32(0xFFFFFFFF),
193 c
.common
.cdw10
[0] = cpu_to_le32(
194 (((sizeof(struct nvme_smart_log
) / 4) - 1) << 16) |
197 *log
= kmalloc(sizeof(struct nvme_smart_log
), GFP_KERNEL
);
201 error
= nvme_submit_sync_cmd(dev
->admin_q
, &c
, *log
,
202 sizeof(struct nvme_smart_log
));