diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-13 17:22:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-13 17:22:26 -0500 |
commit | 9ea18f8cab5f1c36cdd0f09717e35ceb48c36a87 (patch) | |
tree | 0c8da7ac47cb59fe39f177ab0407f554aff77194 /drivers/block/nvme-scsi.c | |
parent | caf292ae5bb9d57198ce001d8b762f7abae3a94d (diff) | |
parent | 849c6e7746e4f6317ace6aa7d2fcdcd844e99ddb (diff) |
Merge branch 'for-3.19/drivers' of git://git.kernel.dk/linux-block
Pull block layer driver updates from Jens Axboe:
- NVMe updates:
- The blk-mq conversion from Matias (and others)
- A stack of NVMe bug fixes from the nvme tree, mostly from Keith.
- Various bug fixes from me, fixing issues in both the blk-mq
conversion and generic bugs.
- Abort and CPU online fix from Sam.
- Hot add/remove fix from Indraneel.
- A couple of drbd fixes from the drbd team (Andreas, Lars, Philipp)
- With the generic IO stat accounting from 3.19/core, converting md,
bcache, and rsxx to use those. From Gu Zheng.
- Boundary check for queue/irq mode for null_blk from Matias. Fixes
cases where invalid values could be given, causing the device to hang.
- The xen blkfront pull request, with two bug fixes from Vitaly.
* 'for-3.19/drivers' of git://git.kernel.dk/linux-block: (56 commits)
NVMe: fix race condition in nvme_submit_sync_cmd()
NVMe: fix retry/error logic in nvme_queue_rq()
NVMe: Fix FS mount issue (hot-remove followed by hot-add)
NVMe: fix error return checking from blk_mq_alloc_request()
NVMe: fix freeing of wrong request in abort path
xen/blkfront: remove redundant flush_op
xen/blkfront: improve protection against issuing unsupported REQ_FUA
NVMe: Fix command setup on IO retry
null_blk: boundary check queue_mode and irqmode
block/rsxx: use generic io stats accounting functions to simplify io stat accounting
md: use generic io stats accounting functions to simplify io stat accounting
drbd: use generic io stats accounting functions to simplify io stat accounting
md/bcache: use generic io stats accounting functions to simplify io stat accounting
NVMe: Update module version major number
NVMe: fail pci initialization if the device doesn't have any BARs
NVMe: add ->exit_hctx() hook
NVMe: make setup work for devices that don't do INTx
NVMe: enable IO stats by default
NVMe: nvme_submit_async_admin_req() must use atomic rq allocation
NVMe: replace blk_put_request() with blk_mq_free_request()
...
Diffstat (limited to 'drivers/block/nvme-scsi.c')
-rw-r--r-- | drivers/block/nvme-scsi.c | 162 |
1 files changed, 12 insertions, 150 deletions
diff --git a/drivers/block/nvme-scsi.c b/drivers/block/nvme-scsi.c index 0b4b2775600e..5e78568026c3 100644 --- a/drivers/block/nvme-scsi.c +++ b/drivers/block/nvme-scsi.c | |||
@@ -2105,7 +2105,7 @@ static int nvme_trans_do_nvme_io(struct nvme_ns *ns, struct sg_io_hdr *hdr, | |||
2105 | 2105 | ||
2106 | nvme_offset += unit_num_blocks; | 2106 | nvme_offset += unit_num_blocks; |
2107 | 2107 | ||
2108 | nvme_sc = nvme_submit_io_cmd(dev, &c, NULL); | 2108 | nvme_sc = nvme_submit_io_cmd(dev, ns, &c, NULL); |
2109 | if (nvme_sc != NVME_SC_SUCCESS) { | 2109 | if (nvme_sc != NVME_SC_SUCCESS) { |
2110 | nvme_unmap_user_pages(dev, | 2110 | nvme_unmap_user_pages(dev, |
2111 | (is_write) ? DMA_TO_DEVICE : DMA_FROM_DEVICE, | 2111 | (is_write) ? DMA_TO_DEVICE : DMA_FROM_DEVICE, |
@@ -2658,7 +2658,7 @@ static int nvme_trans_start_stop(struct nvme_ns *ns, struct sg_io_hdr *hdr, | |||
2658 | c.common.opcode = nvme_cmd_flush; | 2658 | c.common.opcode = nvme_cmd_flush; |
2659 | c.common.nsid = cpu_to_le32(ns->ns_id); | 2659 | c.common.nsid = cpu_to_le32(ns->ns_id); |
2660 | 2660 | ||
2661 | nvme_sc = nvme_submit_io_cmd(ns->dev, &c, NULL); | 2661 | nvme_sc = nvme_submit_io_cmd(ns->dev, ns, &c, NULL); |
2662 | res = nvme_trans_status_code(hdr, nvme_sc); | 2662 | res = nvme_trans_status_code(hdr, nvme_sc); |
2663 | if (res) | 2663 | if (res) |
2664 | goto out; | 2664 | goto out; |
@@ -2686,7 +2686,7 @@ static int nvme_trans_synchronize_cache(struct nvme_ns *ns, | |||
2686 | c.common.opcode = nvme_cmd_flush; | 2686 | c.common.opcode = nvme_cmd_flush; |
2687 | c.common.nsid = cpu_to_le32(ns->ns_id); | 2687 | c.common.nsid = cpu_to_le32(ns->ns_id); |
2688 | 2688 | ||
2689 | nvme_sc = nvme_submit_io_cmd(ns->dev, &c, NULL); | 2689 | nvme_sc = nvme_submit_io_cmd(ns->dev, ns, &c, NULL); |
2690 | 2690 | ||
2691 | res = nvme_trans_status_code(hdr, nvme_sc); | 2691 | res = nvme_trans_status_code(hdr, nvme_sc); |
2692 | if (res) | 2692 | if (res) |
@@ -2894,7 +2894,7 @@ static int nvme_trans_unmap(struct nvme_ns *ns, struct sg_io_hdr *hdr, | |||
2894 | c.dsm.nr = cpu_to_le32(ndesc - 1); | 2894 | c.dsm.nr = cpu_to_le32(ndesc - 1); |
2895 | c.dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD); | 2895 | c.dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD); |
2896 | 2896 | ||
2897 | nvme_sc = nvme_submit_io_cmd(dev, &c, NULL); | 2897 | nvme_sc = nvme_submit_io_cmd(dev, ns, &c, NULL); |
2898 | res = nvme_trans_status_code(hdr, nvme_sc); | 2898 | res = nvme_trans_status_code(hdr, nvme_sc); |
2899 | 2899 | ||
2900 | dma_free_coherent(&dev->pci_dev->dev, ndesc * sizeof(*range), | 2900 | dma_free_coherent(&dev->pci_dev->dev, ndesc * sizeof(*range), |
@@ -2915,6 +2915,14 @@ static int nvme_scsi_translate(struct nvme_ns *ns, struct sg_io_hdr *hdr) | |||
2915 | if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len)) | 2915 | if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len)) |
2916 | return -EFAULT; | 2916 | return -EFAULT; |
2917 | 2917 | ||
2918 | /* | ||
2919 | * Prime the hdr with good status for scsi commands that don't require | ||
2920 | * an nvme command for translation. | ||
2921 | */ | ||
2922 | retcode = nvme_trans_status_code(hdr, NVME_SC_SUCCESS); | ||
2923 | if (retcode) | ||
2924 | return retcode; | ||
2925 | |||
2918 | opcode = cmd[0]; | 2926 | opcode = cmd[0]; |
2919 | 2927 | ||
2920 | switch (opcode) { | 2928 | switch (opcode) { |
@@ -3016,152 +3024,6 @@ int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr) | |||
3016 | return retcode; | 3024 | return retcode; |
3017 | } | 3025 | } |
3018 | 3026 | ||
3019 | #ifdef CONFIG_COMPAT | ||
3020 | typedef struct sg_io_hdr32 { | ||
3021 | compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ | ||
3022 | compat_int_t dxfer_direction; /* [i] data transfer direction */ | ||
3023 | unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ | ||
3024 | unsigned char mx_sb_len; /* [i] max length to write to sbp */ | ||
3025 | unsigned short iovec_count; /* [i] 0 implies no scatter gather */ | ||
3026 | compat_uint_t dxfer_len; /* [i] byte count of data transfer */ | ||
3027 | compat_uint_t dxferp; /* [i], [*io] points to data transfer memory | ||
3028 | or scatter gather list */ | ||
3029 | compat_uptr_t cmdp; /* [i], [*i] points to command to perform */ | ||
3030 | compat_uptr_t sbp; /* [i], [*o] points to sense_buffer memory */ | ||
3031 | compat_uint_t timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ | ||
3032 | compat_uint_t flags; /* [i] 0 -> default, see SG_FLAG... */ | ||
3033 | compat_int_t pack_id; /* [i->o] unused internally (normally) */ | ||
3034 | compat_uptr_t usr_ptr; /* [i->o] unused internally */ | ||
3035 | unsigned char status; /* [o] scsi status */ | ||
3036 | unsigned char masked_status; /* [o] shifted, masked scsi status */ | ||
3037 | unsigned char msg_status; /* [o] messaging level data (optional) */ | ||
3038 | unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ | ||
3039 | unsigned short host_status; /* [o] errors from host adapter */ | ||
3040 | unsigned short driver_status; /* [o] errors from software driver */ | ||
3041 | compat_int_t resid; /* [o] dxfer_len - actual_transferred */ | ||
3042 | compat_uint_t duration; /* [o] time taken by cmd (unit: millisec) */ | ||
3043 | compat_uint_t info; /* [o] auxiliary information */ | ||
3044 | } sg_io_hdr32_t; /* 64 bytes long (on sparc32) */ | ||
3045 | |||
3046 | typedef struct sg_iovec32 { | ||
3047 | compat_uint_t iov_base; | ||
3048 | compat_uint_t iov_len; | ||
3049 | } sg_iovec32_t; | ||
3050 | |||
3051 | static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iovec_count) | ||
3052 | { | ||
3053 | sg_iovec_t __user *iov = (sg_iovec_t __user *) (sgio + 1); | ||
3054 | sg_iovec32_t __user *iov32 = dxferp; | ||
3055 | int i; | ||
3056 | |||
3057 | for (i = 0; i < iovec_count; i++) { | ||
3058 | u32 base, len; | ||
3059 | |||
3060 | if (get_user(base, &iov32[i].iov_base) || | ||
3061 | get_user(len, &iov32[i].iov_len) || | ||
3062 | put_user(compat_ptr(base), &iov[i].iov_base) || | ||
3063 | put_user(len, &iov[i].iov_len)) | ||
3064 | return -EFAULT; | ||
3065 | } | ||
3066 | |||
3067 | if (put_user(iov, &sgio->dxferp)) | ||
3068 | return -EFAULT; | ||
3069 | return 0; | ||
3070 | } | ||
3071 | |||
3072 | int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg) | ||
3073 | { | ||
3074 | sg_io_hdr32_t __user *sgio32 = (sg_io_hdr32_t __user *)arg; | ||
3075 | sg_io_hdr_t __user *sgio; | ||
3076 | u16 iovec_count; | ||
3077 | u32 data; | ||
3078 | void __user *dxferp; | ||
3079 | int err; | ||
3080 | int interface_id; | ||
3081 | |||
3082 | if (get_user(interface_id, &sgio32->interface_id)) | ||
3083 | return -EFAULT; | ||
3084 | if (interface_id != 'S') | ||
3085 | return -EINVAL; | ||
3086 | |||
3087 | if (get_user(iovec_count, &sgio32->iovec_count)) | ||
3088 | return -EFAULT; | ||
3089 | |||
3090 | { | ||
3091 | void __user *top = compat_alloc_user_space(0); | ||
3092 | void __user *new = compat_alloc_user_space(sizeof(sg_io_hdr_t) + | ||
3093 | (iovec_count * sizeof(sg_iovec_t))); | ||
3094 | if (new > top) | ||
3095 | return -EINVAL; | ||
3096 | |||
3097 | sgio = new; | ||
3098 | } | ||
3099 | |||
3100 | /* Ok, now construct. */ | ||
3101 | if (copy_in_user(&sgio->interface_id, &sgio32->interface_id, | ||
3102 | (2 * sizeof(int)) + | ||
3103 | (2 * sizeof(unsigned char)) + | ||
3104 | (1 * sizeof(unsigned short)) + | ||
3105 | (1 * sizeof(unsigned int)))) | ||
3106 | return -EFAULT; | ||
3107 | |||
3108 | if (get_user(data, &sgio32->dxferp)) | ||
3109 | return -EFAULT; | ||
3110 | dxferp = compat_ptr(data); | ||
3111 | if (iovec_count) { | ||
3112 | if (sg_build_iovec(sgio, dxferp, iovec_count)) | ||
3113 | return -EFAULT; | ||
3114 | } else { | ||
3115 | if (put_user(dxferp, &sgio->dxferp)) | ||
3116 | return -EFAULT; | ||
3117 | } | ||
3118 | |||
3119 | { | ||
3120 | unsigned char __user *cmdp; | ||
3121 | unsigned char __user *sbp; | ||
3122 | |||
3123 | if (get_user(data, &sgio32->cmdp)) | ||
3124 | return -EFAULT; | ||
3125 | cmdp = compat_ptr(data); | ||
3126 | |||
3127 | if (get_user(data, &sgio32->sbp)) | ||
3128 | return -EFAULT; | ||
3129 | sbp = compat_ptr(data); | ||
3130 | |||
3131 | if (put_user(cmdp, &sgio->cmdp) || | ||
3132 | put_user(sbp, &sgio->sbp)) | ||
3133 | return -EFAULT; | ||
3134 | } | ||
3135 | |||
3136 | if (copy_in_user(&sgio->timeout, &sgio32->timeout, | ||
3137 | 3 * sizeof(int))) | ||
3138 | return -EFAULT; | ||
3139 | |||
3140 | if (get_user(data, &sgio32->usr_ptr)) | ||
3141 | return -EFAULT; | ||
3142 | if (put_user(compat_ptr(data), &sgio->usr_ptr)) | ||
3143 | return -EFAULT; | ||
3144 | |||
3145 | err = nvme_sg_io(ns, sgio); | ||
3146 | if (err >= 0) { | ||
3147 | void __user *datap; | ||
3148 | |||
3149 | if (copy_in_user(&sgio32->pack_id, &sgio->pack_id, | ||
3150 | sizeof(int)) || | ||
3151 | get_user(datap, &sgio->usr_ptr) || | ||
3152 | put_user((u32)(unsigned long)datap, | ||
3153 | &sgio32->usr_ptr) || | ||
3154 | copy_in_user(&sgio32->status, &sgio->status, | ||
3155 | (4 * sizeof(unsigned char)) + | ||
3156 | (2 * sizeof(unsigned short)) + | ||
3157 | (3 * sizeof(int)))) | ||
3158 | err = -EFAULT; | ||
3159 | } | ||
3160 | |||
3161 | return err; | ||
3162 | } | ||
3163 | #endif | ||
3164 | |||
3165 | int nvme_sg_get_version_num(int __user *ip) | 3027 | int nvme_sg_get_version_num(int __user *ip) |
3166 | { | 3028 | { |
3167 | return put_user(sg_version_num, ip); | 3029 | return put_user(sg_version_num, ip); |