diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/percpu_ida.h | 60 | ||||
-rw-r--r-- | include/scsi/scsi.h | 1 | ||||
-rw-r--r-- | include/target/iscsi/iscsi_transport.h | 8 | ||||
-rw-r--r-- | include/target/target_core_backend.h | 7 | ||||
-rw-r--r-- | include/target/target_core_base.h | 26 | ||||
-rw-r--r-- | include/target/target_core_fabric.h | 30 |
6 files changed, 128 insertions, 4 deletions
diff --git a/include/linux/percpu_ida.h b/include/linux/percpu_ida.h new file mode 100644 index 000000000000..0b23edbee309 --- /dev/null +++ b/include/linux/percpu_ida.h | |||
@@ -0,0 +1,60 @@ | |||
1 | #ifndef __PERCPU_IDA_H__ | ||
2 | #define __PERCPU_IDA_H__ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | #include <linux/bitops.h> | ||
6 | #include <linux/init.h> | ||
7 | #include <linux/spinlock_types.h> | ||
8 | #include <linux/wait.h> | ||
9 | #include <linux/cpumask.h> | ||
10 | |||
11 | struct percpu_ida_cpu; | ||
12 | |||
13 | struct percpu_ida { | ||
14 | /* | ||
15 | * number of tags available to be allocated, as passed to | ||
16 | * percpu_ida_init() | ||
17 | */ | ||
18 | unsigned nr_tags; | ||
19 | |||
20 | struct percpu_ida_cpu __percpu *tag_cpu; | ||
21 | |||
22 | /* | ||
23 | * Bitmap of cpus that (may) have tags on their percpu freelists: | ||
24 | * steal_tags() uses this to decide when to steal tags, and which cpus | ||
25 | * to try stealing from. | ||
26 | * | ||
27 | * It's ok for a freelist to be empty when its bit is set - steal_tags() | ||
28 | * will just keep looking - but the bitmap _must_ be set whenever a | ||
29 | * percpu freelist does have tags. | ||
30 | */ | ||
31 | cpumask_t cpus_have_tags; | ||
32 | |||
33 | struct { | ||
34 | spinlock_t lock; | ||
35 | /* | ||
36 | * When we go to steal tags from another cpu (see steal_tags()), | ||
37 | * we want to pick a cpu at random. Cycling through them every | ||
38 | * time we steal is a bit easier and more or less equivalent: | ||
39 | */ | ||
40 | unsigned cpu_last_stolen; | ||
41 | |||
42 | /* For sleeping on allocation failure */ | ||
43 | wait_queue_head_t wait; | ||
44 | |||
45 | /* | ||
46 | * Global freelist - it's a stack where nr_free points to the | ||
47 | * top | ||
48 | */ | ||
49 | unsigned nr_free; | ||
50 | unsigned *freelist; | ||
51 | } ____cacheline_aligned_in_smp; | ||
52 | }; | ||
53 | |||
54 | int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp); | ||
55 | void percpu_ida_free(struct percpu_ida *pool, unsigned tag); | ||
56 | |||
57 | void percpu_ida_destroy(struct percpu_ida *pool); | ||
58 | int percpu_ida_init(struct percpu_ida *pool, unsigned long nr_tags); | ||
59 | |||
60 | #endif /* __PERCPU_IDA_H__ */ | ||
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index d477bfb73fb9..66d42edfb3fc 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h | |||
@@ -144,6 +144,7 @@ enum scsi_timeouts { | |||
144 | #define ACCESS_CONTROL_IN 0x86 | 144 | #define ACCESS_CONTROL_IN 0x86 |
145 | #define ACCESS_CONTROL_OUT 0x87 | 145 | #define ACCESS_CONTROL_OUT 0x87 |
146 | #define READ_16 0x88 | 146 | #define READ_16 0x88 |
147 | #define COMPARE_AND_WRITE 0x89 | ||
147 | #define WRITE_16 0x8a | 148 | #define WRITE_16 0x8a |
148 | #define READ_ATTRIBUTE 0x8c | 149 | #define READ_ATTRIBUTE 0x8c |
149 | #define WRITE_ATTRIBUTE 0x8d | 150 | #define WRITE_ATTRIBUTE 0x8d |
diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index e5d09d242ba3..a12589c4ee92 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h | |||
@@ -6,13 +6,13 @@ struct iscsit_transport { | |||
6 | #define ISCSIT_TRANSPORT_NAME 16 | 6 | #define ISCSIT_TRANSPORT_NAME 16 |
7 | char name[ISCSIT_TRANSPORT_NAME]; | 7 | char name[ISCSIT_TRANSPORT_NAME]; |
8 | int transport_type; | 8 | int transport_type; |
9 | int priv_size; | ||
9 | struct module *owner; | 10 | struct module *owner; |
10 | struct list_head t_node; | 11 | struct list_head t_node; |
11 | int (*iscsit_setup_np)(struct iscsi_np *, struct __kernel_sockaddr_storage *); | 12 | int (*iscsit_setup_np)(struct iscsi_np *, struct __kernel_sockaddr_storage *); |
12 | int (*iscsit_accept_np)(struct iscsi_np *, struct iscsi_conn *); | 13 | int (*iscsit_accept_np)(struct iscsi_np *, struct iscsi_conn *); |
13 | void (*iscsit_free_np)(struct iscsi_np *); | 14 | void (*iscsit_free_np)(struct iscsi_np *); |
14 | void (*iscsit_free_conn)(struct iscsi_conn *); | 15 | void (*iscsit_free_conn)(struct iscsi_conn *); |
15 | struct iscsi_cmd *(*iscsit_alloc_cmd)(struct iscsi_conn *, gfp_t); | ||
16 | int (*iscsit_get_login_rx)(struct iscsi_conn *, struct iscsi_login *); | 16 | int (*iscsit_get_login_rx)(struct iscsi_conn *, struct iscsi_login *); |
17 | int (*iscsit_put_login_tx)(struct iscsi_conn *, struct iscsi_login *, u32); | 17 | int (*iscsit_put_login_tx)(struct iscsi_conn *, struct iscsi_login *, u32); |
18 | int (*iscsit_immediate_queue)(struct iscsi_conn *, struct iscsi_cmd *, int); | 18 | int (*iscsit_immediate_queue)(struct iscsi_conn *, struct iscsi_cmd *, int); |
@@ -22,6 +22,11 @@ struct iscsit_transport { | |||
22 | int (*iscsit_queue_status)(struct iscsi_conn *, struct iscsi_cmd *); | 22 | int (*iscsit_queue_status)(struct iscsi_conn *, struct iscsi_cmd *); |
23 | }; | 23 | }; |
24 | 24 | ||
25 | static inline void *iscsit_priv_cmd(struct iscsi_cmd *cmd) | ||
26 | { | ||
27 | return (void *)(cmd + 1); | ||
28 | } | ||
29 | |||
25 | /* | 30 | /* |
26 | * From iscsi_target_transport.c | 31 | * From iscsi_target_transport.c |
27 | */ | 32 | */ |
@@ -92,3 +97,4 @@ extern int iscsit_tmr_post_handler(struct iscsi_cmd *, struct iscsi_conn *); | |||
92 | extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t); | 97 | extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t); |
93 | extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, | 98 | extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, |
94 | unsigned char *, __be32); | 99 | unsigned char *, __be32); |
100 | extern void iscsit_release_cmd(struct iscsi_cmd *); | ||
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index ffa2696d64dc..5ebe21cd5d1c 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h | |||
@@ -39,7 +39,8 @@ struct se_subsystem_api { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | struct sbc_ops { | 41 | struct sbc_ops { |
42 | sense_reason_t (*execute_rw)(struct se_cmd *cmd); | 42 | sense_reason_t (*execute_rw)(struct se_cmd *cmd, struct scatterlist *, |
43 | u32, enum dma_data_direction); | ||
43 | sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd); | 44 | sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd); |
44 | sense_reason_t (*execute_write_same)(struct se_cmd *cmd); | 45 | sense_reason_t (*execute_write_same)(struct se_cmd *cmd); |
45 | sense_reason_t (*execute_write_same_unmap)(struct se_cmd *cmd); | 46 | sense_reason_t (*execute_write_same_unmap)(struct se_cmd *cmd); |
@@ -73,6 +74,10 @@ int transport_set_vpd_ident(struct t10_vpd *, unsigned char *); | |||
73 | /* core helpers also used by command snooping in pscsi */ | 74 | /* core helpers also used by command snooping in pscsi */ |
74 | void *transport_kmap_data_sg(struct se_cmd *); | 75 | void *transport_kmap_data_sg(struct se_cmd *); |
75 | void transport_kunmap_data_sg(struct se_cmd *); | 76 | void transport_kunmap_data_sg(struct se_cmd *); |
77 | /* core helpers also used by xcopy during internal command setup */ | ||
78 | int target_alloc_sgl(struct scatterlist **, unsigned int *, u32, bool); | ||
79 | sense_reason_t transport_generic_map_mem_to_cmd(struct se_cmd *, | ||
80 | struct scatterlist *, u32, struct scatterlist *, u32); | ||
76 | 81 | ||
77 | void array_free(void *array, int n); | 82 | void array_free(void *array, int n); |
78 | 83 | ||
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index e34fc904f2e1..5bdb8b7d2a69 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
@@ -5,11 +5,12 @@ | |||
5 | #include <linux/configfs.h> | 5 | #include <linux/configfs.h> |
6 | #include <linux/dma-mapping.h> | 6 | #include <linux/dma-mapping.h> |
7 | #include <linux/blkdev.h> | 7 | #include <linux/blkdev.h> |
8 | #include <linux/percpu_ida.h> | ||
8 | #include <scsi/scsi_cmnd.h> | 9 | #include <scsi/scsi_cmnd.h> |
9 | #include <net/sock.h> | 10 | #include <net/sock.h> |
10 | #include <net/tcp.h> | 11 | #include <net/tcp.h> |
11 | 12 | ||
12 | #define TARGET_CORE_MOD_VERSION "v4.1.0-rc2-ml" | 13 | #define TARGET_CORE_MOD_VERSION "v4.1.0" |
13 | #define TARGET_CORE_VERSION TARGET_CORE_MOD_VERSION | 14 | #define TARGET_CORE_VERSION TARGET_CORE_MOD_VERSION |
14 | 15 | ||
15 | /* Maximum Number of LUNs per Target Portal Group */ | 16 | /* Maximum Number of LUNs per Target Portal Group */ |
@@ -96,6 +97,10 @@ | |||
96 | * block/blk-lib.c:blkdev_issue_discard() | 97 | * block/blk-lib.c:blkdev_issue_discard() |
97 | */ | 98 | */ |
98 | #define DA_EMULATE_TPWS 0 | 99 | #define DA_EMULATE_TPWS 0 |
100 | /* Emulation for CompareAndWrite (AtomicTestandSet) by default */ | ||
101 | #define DA_EMULATE_CAW 1 | ||
102 | /* Emulation for 3rd Party Copy (ExtendedCopy) by default */ | ||
103 | #define DA_EMULATE_3PC 1 | ||
99 | /* No Emulation for PSCSI by default */ | 104 | /* No Emulation for PSCSI by default */ |
100 | #define DA_EMULATE_ALUA 0 | 105 | #define DA_EMULATE_ALUA 0 |
101 | /* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */ | 106 | /* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */ |
@@ -158,6 +163,9 @@ enum se_cmd_flags_table { | |||
158 | SCF_ALUA_NON_OPTIMIZED = 0x00008000, | 163 | SCF_ALUA_NON_OPTIMIZED = 0x00008000, |
159 | SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000, | 164 | SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000, |
160 | SCF_ACK_KREF = 0x00040000, | 165 | SCF_ACK_KREF = 0x00040000, |
166 | SCF_COMPARE_AND_WRITE = 0x00080000, | ||
167 | SCF_COMPARE_AND_WRITE_POST = 0x00100000, | ||
168 | SCF_CMD_XCOPY_PASSTHROUGH = 0x00200000, | ||
161 | }; | 169 | }; |
162 | 170 | ||
163 | /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */ | 171 | /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */ |
@@ -196,6 +204,7 @@ enum tcm_sense_reason_table { | |||
196 | TCM_ADDRESS_OUT_OF_RANGE = R(0x11), | 204 | TCM_ADDRESS_OUT_OF_RANGE = R(0x11), |
197 | TCM_OUT_OF_RESOURCES = R(0x12), | 205 | TCM_OUT_OF_RESOURCES = R(0x12), |
198 | TCM_PARAMETER_LIST_LENGTH_ERROR = R(0x13), | 206 | TCM_PARAMETER_LIST_LENGTH_ERROR = R(0x13), |
207 | TCM_MISCOMPARE_VERIFY = R(0x14), | ||
199 | #undef R | 208 | #undef R |
200 | }; | 209 | }; |
201 | 210 | ||
@@ -415,6 +424,8 @@ struct se_cmd { | |||
415 | enum dma_data_direction data_direction; | 424 | enum dma_data_direction data_direction; |
416 | /* For SAM Task Attribute */ | 425 | /* For SAM Task Attribute */ |
417 | int sam_task_attr; | 426 | int sam_task_attr; |
427 | /* Used for se_sess->sess_tag_pool */ | ||
428 | unsigned int map_tag; | ||
418 | /* Transport protocol dependent state, see transport_state_table */ | 429 | /* Transport protocol dependent state, see transport_state_table */ |
419 | enum transport_state_table t_state; | 430 | enum transport_state_table t_state; |
420 | unsigned cmd_wait_set:1; | 431 | unsigned cmd_wait_set:1; |
@@ -444,11 +455,14 @@ struct se_cmd { | |||
444 | struct kref cmd_kref; | 455 | struct kref cmd_kref; |
445 | struct target_core_fabric_ops *se_tfo; | 456 | struct target_core_fabric_ops *se_tfo; |
446 | sense_reason_t (*execute_cmd)(struct se_cmd *); | 457 | sense_reason_t (*execute_cmd)(struct se_cmd *); |
447 | void (*transport_complete_callback)(struct se_cmd *); | 458 | sense_reason_t (*execute_rw)(struct se_cmd *, struct scatterlist *, |
459 | u32, enum dma_data_direction); | ||
460 | sense_reason_t (*transport_complete_callback)(struct se_cmd *); | ||
448 | 461 | ||
449 | unsigned char *t_task_cdb; | 462 | unsigned char *t_task_cdb; |
450 | unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; | 463 | unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; |
451 | unsigned long long t_task_lba; | 464 | unsigned long long t_task_lba; |
465 | unsigned int t_task_nolb; | ||
452 | unsigned int transport_state; | 466 | unsigned int transport_state; |
453 | #define CMD_T_ABORTED (1 << 0) | 467 | #define CMD_T_ABORTED (1 << 0) |
454 | #define CMD_T_ACTIVE (1 << 1) | 468 | #define CMD_T_ACTIVE (1 << 1) |
@@ -469,7 +483,9 @@ struct se_cmd { | |||
469 | struct work_struct work; | 483 | struct work_struct work; |
470 | 484 | ||
471 | struct scatterlist *t_data_sg; | 485 | struct scatterlist *t_data_sg; |
486 | struct scatterlist *t_data_sg_orig; | ||
472 | unsigned int t_data_nents; | 487 | unsigned int t_data_nents; |
488 | unsigned int t_data_nents_orig; | ||
473 | void *t_data_vmap; | 489 | void *t_data_vmap; |
474 | struct scatterlist *t_bidi_data_sg; | 490 | struct scatterlist *t_bidi_data_sg; |
475 | unsigned int t_bidi_data_nents; | 491 | unsigned int t_bidi_data_nents; |
@@ -536,6 +552,8 @@ struct se_session { | |||
536 | struct list_head sess_wait_list; | 552 | struct list_head sess_wait_list; |
537 | spinlock_t sess_cmd_lock; | 553 | spinlock_t sess_cmd_lock; |
538 | struct kref sess_kref; | 554 | struct kref sess_kref; |
555 | void *sess_cmd_map; | ||
556 | struct percpu_ida sess_tag_pool; | ||
539 | }; | 557 | }; |
540 | 558 | ||
541 | struct se_device; | 559 | struct se_device; |
@@ -589,6 +607,8 @@ struct se_dev_attrib { | |||
589 | int emulate_tas; | 607 | int emulate_tas; |
590 | int emulate_tpu; | 608 | int emulate_tpu; |
591 | int emulate_tpws; | 609 | int emulate_tpws; |
610 | int emulate_caw; | ||
611 | int emulate_3pc; | ||
592 | int enforce_pr_isids; | 612 | int enforce_pr_isids; |
593 | int is_nonrot; | 613 | int is_nonrot; |
594 | int emulate_rest_reord; | 614 | int emulate_rest_reord; |
@@ -656,6 +676,7 @@ struct se_device { | |||
656 | spinlock_t se_port_lock; | 676 | spinlock_t se_port_lock; |
657 | spinlock_t se_tmr_lock; | 677 | spinlock_t se_tmr_lock; |
658 | spinlock_t qf_cmd_lock; | 678 | spinlock_t qf_cmd_lock; |
679 | struct semaphore caw_sem; | ||
659 | /* Used for legacy SPC-2 reservationsa */ | 680 | /* Used for legacy SPC-2 reservationsa */ |
660 | struct se_node_acl *dev_reserved_node_acl; | 681 | struct se_node_acl *dev_reserved_node_acl; |
661 | /* Used for ALUA Logical Unit Group membership */ | 682 | /* Used for ALUA Logical Unit Group membership */ |
@@ -669,6 +690,7 @@ struct se_device { | |||
669 | struct list_head delayed_cmd_list; | 690 | struct list_head delayed_cmd_list; |
670 | struct list_head state_list; | 691 | struct list_head state_list; |
671 | struct list_head qf_cmd_list; | 692 | struct list_head qf_cmd_list; |
693 | struct list_head g_dev_node; | ||
672 | /* Pointer to associated SE HBA */ | 694 | /* Pointer to associated SE HBA */ |
673 | struct se_hba *se_hba; | 695 | struct se_hba *se_hba; |
674 | /* T10 Inquiry and VPD WWN Information */ | 696 | /* T10 Inquiry and VPD WWN Information */ |
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 7a16178424f9..882b650e32be 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h | |||
@@ -84,6 +84,9 @@ struct target_core_fabric_ops { | |||
84 | }; | 84 | }; |
85 | 85 | ||
86 | struct se_session *transport_init_session(void); | 86 | struct se_session *transport_init_session(void); |
87 | int transport_alloc_session_tags(struct se_session *, unsigned int, | ||
88 | unsigned int); | ||
89 | struct se_session *transport_init_session_tags(unsigned int, unsigned int); | ||
87 | void __transport_register_session(struct se_portal_group *, | 90 | void __transport_register_session(struct se_portal_group *, |
88 | struct se_node_acl *, struct se_session *, void *); | 91 | struct se_node_acl *, struct se_session *, void *); |
89 | void transport_register_session(struct se_portal_group *, | 92 | void transport_register_session(struct se_portal_group *, |
@@ -131,6 +134,7 @@ int core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t); | |||
131 | void core_tmr_release_req(struct se_tmr_req *); | 134 | void core_tmr_release_req(struct se_tmr_req *); |
132 | int transport_generic_handle_tmr(struct se_cmd *); | 135 | int transport_generic_handle_tmr(struct se_cmd *); |
133 | void transport_generic_request_failure(struct se_cmd *, sense_reason_t); | 136 | void transport_generic_request_failure(struct se_cmd *, sense_reason_t); |
137 | void __target_execute_cmd(struct se_cmd *); | ||
134 | int transport_lookup_tmr_lun(struct se_cmd *, u32); | 138 | int transport_lookup_tmr_lun(struct se_cmd *, u32); |
135 | 139 | ||
136 | struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *, | 140 | struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *, |
@@ -175,4 +179,30 @@ u32 iscsi_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl * | |||
175 | char *iscsi_parse_pr_out_transport_id(struct se_portal_group *, const char *, | 179 | char *iscsi_parse_pr_out_transport_id(struct se_portal_group *, const char *, |
176 | u32 *, char **); | 180 | u32 *, char **); |
177 | 181 | ||
182 | /* | ||
183 | * The LIO target core uses DMA_TO_DEVICE to mean that data is going | ||
184 | * to the target (eg handling a WRITE) and DMA_FROM_DEVICE to mean | ||
185 | * that data is coming from the target (eg handling a READ). However, | ||
186 | * this is just the opposite of what we have to tell the DMA mapping | ||
187 | * layer -- eg when handling a READ, the HBA will have to DMA the data | ||
188 | * out of memory so it can send it to the initiator, which means we | ||
189 | * need to use DMA_TO_DEVICE when we map the data. | ||
190 | */ | ||
191 | static inline enum dma_data_direction | ||
192 | target_reverse_dma_direction(struct se_cmd *se_cmd) | ||
193 | { | ||
194 | if (se_cmd->se_cmd_flags & SCF_BIDI) | ||
195 | return DMA_BIDIRECTIONAL; | ||
196 | |||
197 | switch (se_cmd->data_direction) { | ||
198 | case DMA_TO_DEVICE: | ||
199 | return DMA_FROM_DEVICE; | ||
200 | case DMA_FROM_DEVICE: | ||
201 | return DMA_TO_DEVICE; | ||
202 | case DMA_NONE: | ||
203 | default: | ||
204 | return DMA_NONE; | ||
205 | } | ||
206 | } | ||
207 | |||
178 | #endif /* TARGET_CORE_FABRICH */ | 208 | #endif /* TARGET_CORE_FABRICH */ |