diff options
43 files changed, 2300 insertions, 505 deletions
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index d64a02fb1f73..5d70edc9855f 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c | |||
@@ -36,7 +36,8 @@ static unsigned int __blk_mq_get_tag(struct blk_mq_tags *tags, gfp_t gfp) | |||
36 | { | 36 | { |
37 | int tag; | 37 | int tag; |
38 | 38 | ||
39 | tag = percpu_ida_alloc(&tags->free_tags, gfp); | 39 | tag = percpu_ida_alloc(&tags->free_tags, (gfp & __GFP_WAIT) ? |
40 | TASK_UNINTERRUPTIBLE : TASK_RUNNING); | ||
40 | if (tag < 0) | 41 | if (tag < 0) |
41 | return BLK_MQ_TAG_FAIL; | 42 | return BLK_MQ_TAG_FAIL; |
42 | return tag + tags->nr_reserved_tags; | 43 | return tag + tags->nr_reserved_tags; |
@@ -52,7 +53,8 @@ static unsigned int __blk_mq_get_reserved_tag(struct blk_mq_tags *tags, | |||
52 | return BLK_MQ_TAG_FAIL; | 53 | return BLK_MQ_TAG_FAIL; |
53 | } | 54 | } |
54 | 55 | ||
55 | tag = percpu_ida_alloc(&tags->reserved_tags, gfp); | 56 | tag = percpu_ida_alloc(&tags->reserved_tags, (gfp & __GFP_WAIT) ? |
57 | TASK_UNINTERRUPTIBLE : TASK_RUNNING); | ||
56 | if (tag < 0) | 58 | if (tag < 0) |
57 | return BLK_MQ_TAG_FAIL; | 59 | return BLK_MQ_TAG_FAIL; |
58 | return tag; | 60 | return tag; |
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 9804fca6bf06..2b161be3c1a3 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c | |||
@@ -47,10 +47,10 @@ static int | |||
47 | isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 47 | isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, |
48 | struct isert_rdma_wr *wr); | 48 | struct isert_rdma_wr *wr); |
49 | static void | 49 | static void |
50 | isert_unreg_rdma_frwr(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); | 50 | isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); |
51 | static int | 51 | static int |
52 | isert_reg_rdma_frwr(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 52 | isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, |
53 | struct isert_rdma_wr *wr); | 53 | struct isert_rdma_wr *wr); |
54 | 54 | ||
55 | static void | 55 | static void |
56 | isert_qp_event_callback(struct ib_event *e, void *context) | 56 | isert_qp_event_callback(struct ib_event *e, void *context) |
@@ -227,11 +227,11 @@ isert_create_device_ib_res(struct isert_device *device) | |||
227 | 227 | ||
228 | /* asign function handlers */ | 228 | /* asign function handlers */ |
229 | if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) { | 229 | if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) { |
230 | device->use_frwr = 1; | 230 | device->use_fastreg = 1; |
231 | device->reg_rdma_mem = isert_reg_rdma_frwr; | 231 | device->reg_rdma_mem = isert_reg_rdma; |
232 | device->unreg_rdma_mem = isert_unreg_rdma_frwr; | 232 | device->unreg_rdma_mem = isert_unreg_rdma; |
233 | } else { | 233 | } else { |
234 | device->use_frwr = 0; | 234 | device->use_fastreg = 0; |
235 | device->reg_rdma_mem = isert_map_rdma; | 235 | device->reg_rdma_mem = isert_map_rdma; |
236 | device->unreg_rdma_mem = isert_unmap_cmd; | 236 | device->unreg_rdma_mem = isert_unmap_cmd; |
237 | } | 237 | } |
@@ -239,9 +239,10 @@ isert_create_device_ib_res(struct isert_device *device) | |||
239 | device->cqs_used = min_t(int, num_online_cpus(), | 239 | device->cqs_used = min_t(int, num_online_cpus(), |
240 | device->ib_device->num_comp_vectors); | 240 | device->ib_device->num_comp_vectors); |
241 | device->cqs_used = min(ISERT_MAX_CQ, device->cqs_used); | 241 | device->cqs_used = min(ISERT_MAX_CQ, device->cqs_used); |
242 | pr_debug("Using %d CQs, device %s supports %d vectors support FRWR %d\n", | 242 | pr_debug("Using %d CQs, device %s supports %d vectors support " |
243 | "Fast registration %d\n", | ||
243 | device->cqs_used, device->ib_device->name, | 244 | device->cqs_used, device->ib_device->name, |
244 | device->ib_device->num_comp_vectors, device->use_frwr); | 245 | device->ib_device->num_comp_vectors, device->use_fastreg); |
245 | device->cq_desc = kzalloc(sizeof(struct isert_cq_desc) * | 246 | device->cq_desc = kzalloc(sizeof(struct isert_cq_desc) * |
246 | device->cqs_used, GFP_KERNEL); | 247 | device->cqs_used, GFP_KERNEL); |
247 | if (!device->cq_desc) { | 248 | if (!device->cq_desc) { |
@@ -250,13 +251,6 @@ isert_create_device_ib_res(struct isert_device *device) | |||
250 | } | 251 | } |
251 | cq_desc = device->cq_desc; | 252 | cq_desc = device->cq_desc; |
252 | 253 | ||
253 | device->dev_pd = ib_alloc_pd(ib_dev); | ||
254 | if (IS_ERR(device->dev_pd)) { | ||
255 | ret = PTR_ERR(device->dev_pd); | ||
256 | pr_err("ib_alloc_pd failed for dev_pd: %d\n", ret); | ||
257 | goto out_cq_desc; | ||
258 | } | ||
259 | |||
260 | for (i = 0; i < device->cqs_used; i++) { | 254 | for (i = 0; i < device->cqs_used; i++) { |
261 | cq_desc[i].device = device; | 255 | cq_desc[i].device = device; |
262 | cq_desc[i].cq_index = i; | 256 | cq_desc[i].cq_index = i; |
@@ -294,13 +288,6 @@ isert_create_device_ib_res(struct isert_device *device) | |||
294 | goto out_cq; | 288 | goto out_cq; |
295 | } | 289 | } |
296 | 290 | ||
297 | device->dev_mr = ib_get_dma_mr(device->dev_pd, IB_ACCESS_LOCAL_WRITE); | ||
298 | if (IS_ERR(device->dev_mr)) { | ||
299 | ret = PTR_ERR(device->dev_mr); | ||
300 | pr_err("ib_get_dma_mr failed for dev_mr: %d\n", ret); | ||
301 | goto out_cq; | ||
302 | } | ||
303 | |||
304 | return 0; | 291 | return 0; |
305 | 292 | ||
306 | out_cq: | 293 | out_cq: |
@@ -316,9 +303,6 @@ out_cq: | |||
316 | ib_destroy_cq(device->dev_tx_cq[j]); | 303 | ib_destroy_cq(device->dev_tx_cq[j]); |
317 | } | 304 | } |
318 | } | 305 | } |
319 | ib_dealloc_pd(device->dev_pd); | ||
320 | |||
321 | out_cq_desc: | ||
322 | kfree(device->cq_desc); | 306 | kfree(device->cq_desc); |
323 | 307 | ||
324 | return ret; | 308 | return ret; |
@@ -341,8 +325,6 @@ isert_free_device_ib_res(struct isert_device *device) | |||
341 | device->dev_tx_cq[i] = NULL; | 325 | device->dev_tx_cq[i] = NULL; |
342 | } | 326 | } |
343 | 327 | ||
344 | ib_dereg_mr(device->dev_mr); | ||
345 | ib_dealloc_pd(device->dev_pd); | ||
346 | kfree(device->cq_desc); | 328 | kfree(device->cq_desc); |
347 | } | 329 | } |
348 | 330 | ||
@@ -398,18 +380,18 @@ isert_device_find_by_ib_dev(struct rdma_cm_id *cma_id) | |||
398 | } | 380 | } |
399 | 381 | ||
400 | static void | 382 | static void |
401 | isert_conn_free_frwr_pool(struct isert_conn *isert_conn) | 383 | isert_conn_free_fastreg_pool(struct isert_conn *isert_conn) |
402 | { | 384 | { |
403 | struct fast_reg_descriptor *fr_desc, *tmp; | 385 | struct fast_reg_descriptor *fr_desc, *tmp; |
404 | int i = 0; | 386 | int i = 0; |
405 | 387 | ||
406 | if (list_empty(&isert_conn->conn_frwr_pool)) | 388 | if (list_empty(&isert_conn->conn_fr_pool)) |
407 | return; | 389 | return; |
408 | 390 | ||
409 | pr_debug("Freeing conn %p frwr pool", isert_conn); | 391 | pr_debug("Freeing conn %p fastreg pool", isert_conn); |
410 | 392 | ||
411 | list_for_each_entry_safe(fr_desc, tmp, | 393 | list_for_each_entry_safe(fr_desc, tmp, |
412 | &isert_conn->conn_frwr_pool, list) { | 394 | &isert_conn->conn_fr_pool, list) { |
413 | list_del(&fr_desc->list); | 395 | list_del(&fr_desc->list); |
414 | ib_free_fast_reg_page_list(fr_desc->data_frpl); | 396 | ib_free_fast_reg_page_list(fr_desc->data_frpl); |
415 | ib_dereg_mr(fr_desc->data_mr); | 397 | ib_dereg_mr(fr_desc->data_mr); |
@@ -417,20 +399,47 @@ isert_conn_free_frwr_pool(struct isert_conn *isert_conn) | |||
417 | ++i; | 399 | ++i; |
418 | } | 400 | } |
419 | 401 | ||
420 | if (i < isert_conn->conn_frwr_pool_size) | 402 | if (i < isert_conn->conn_fr_pool_size) |
421 | pr_warn("Pool still has %d regions registered\n", | 403 | pr_warn("Pool still has %d regions registered\n", |
422 | isert_conn->conn_frwr_pool_size - i); | 404 | isert_conn->conn_fr_pool_size - i); |
405 | } | ||
406 | |||
407 | static int | ||
408 | isert_create_fr_desc(struct ib_device *ib_device, struct ib_pd *pd, | ||
409 | struct fast_reg_descriptor *fr_desc) | ||
410 | { | ||
411 | fr_desc->data_frpl = ib_alloc_fast_reg_page_list(ib_device, | ||
412 | ISCSI_ISER_SG_TABLESIZE); | ||
413 | if (IS_ERR(fr_desc->data_frpl)) { | ||
414 | pr_err("Failed to allocate data frpl err=%ld\n", | ||
415 | PTR_ERR(fr_desc->data_frpl)); | ||
416 | return PTR_ERR(fr_desc->data_frpl); | ||
417 | } | ||
418 | |||
419 | fr_desc->data_mr = ib_alloc_fast_reg_mr(pd, ISCSI_ISER_SG_TABLESIZE); | ||
420 | if (IS_ERR(fr_desc->data_mr)) { | ||
421 | pr_err("Failed to allocate data frmr err=%ld\n", | ||
422 | PTR_ERR(fr_desc->data_mr)); | ||
423 | ib_free_fast_reg_page_list(fr_desc->data_frpl); | ||
424 | return PTR_ERR(fr_desc->data_mr); | ||
425 | } | ||
426 | pr_debug("Create fr_desc %p page_list %p\n", | ||
427 | fr_desc, fr_desc->data_frpl->page_list); | ||
428 | |||
429 | fr_desc->valid = true; | ||
430 | |||
431 | return 0; | ||
423 | } | 432 | } |
424 | 433 | ||
425 | static int | 434 | static int |
426 | isert_conn_create_frwr_pool(struct isert_conn *isert_conn) | 435 | isert_conn_create_fastreg_pool(struct isert_conn *isert_conn) |
427 | { | 436 | { |
428 | struct fast_reg_descriptor *fr_desc; | 437 | struct fast_reg_descriptor *fr_desc; |
429 | struct isert_device *device = isert_conn->conn_device; | 438 | struct isert_device *device = isert_conn->conn_device; |
430 | int i, ret; | 439 | int i, ret; |
431 | 440 | ||
432 | INIT_LIST_HEAD(&isert_conn->conn_frwr_pool); | 441 | INIT_LIST_HEAD(&isert_conn->conn_fr_pool); |
433 | isert_conn->conn_frwr_pool_size = 0; | 442 | isert_conn->conn_fr_pool_size = 0; |
434 | for (i = 0; i < ISCSI_DEF_XMIT_CMDS_MAX; i++) { | 443 | for (i = 0; i < ISCSI_DEF_XMIT_CMDS_MAX; i++) { |
435 | fr_desc = kzalloc(sizeof(*fr_desc), GFP_KERNEL); | 444 | fr_desc = kzalloc(sizeof(*fr_desc), GFP_KERNEL); |
436 | if (!fr_desc) { | 445 | if (!fr_desc) { |
@@ -439,40 +448,25 @@ isert_conn_create_frwr_pool(struct isert_conn *isert_conn) | |||
439 | goto err; | 448 | goto err; |
440 | } | 449 | } |
441 | 450 | ||
442 | fr_desc->data_frpl = | 451 | ret = isert_create_fr_desc(device->ib_device, |
443 | ib_alloc_fast_reg_page_list(device->ib_device, | 452 | isert_conn->conn_pd, fr_desc); |
444 | ISCSI_ISER_SG_TABLESIZE); | 453 | if (ret) { |
445 | if (IS_ERR(fr_desc->data_frpl)) { | 454 | pr_err("Failed to create fastreg descriptor err=%d\n", |
446 | pr_err("Failed to allocate fr_pg_list err=%ld\n", | 455 | ret); |
447 | PTR_ERR(fr_desc->data_frpl)); | ||
448 | ret = PTR_ERR(fr_desc->data_frpl); | ||
449 | goto err; | ||
450 | } | ||
451 | |||
452 | fr_desc->data_mr = ib_alloc_fast_reg_mr(device->dev_pd, | ||
453 | ISCSI_ISER_SG_TABLESIZE); | ||
454 | if (IS_ERR(fr_desc->data_mr)) { | ||
455 | pr_err("Failed to allocate frmr err=%ld\n", | ||
456 | PTR_ERR(fr_desc->data_mr)); | ||
457 | ret = PTR_ERR(fr_desc->data_mr); | ||
458 | ib_free_fast_reg_page_list(fr_desc->data_frpl); | ||
459 | goto err; | 456 | goto err; |
460 | } | 457 | } |
461 | pr_debug("Create fr_desc %p page_list %p\n", | ||
462 | fr_desc, fr_desc->data_frpl->page_list); | ||
463 | 458 | ||
464 | fr_desc->valid = true; | 459 | list_add_tail(&fr_desc->list, &isert_conn->conn_fr_pool); |
465 | list_add_tail(&fr_desc->list, &isert_conn->conn_frwr_pool); | 460 | isert_conn->conn_fr_pool_size++; |
466 | isert_conn->conn_frwr_pool_size++; | ||
467 | } | 461 | } |
468 | 462 | ||
469 | pr_debug("Creating conn %p frwr pool size=%d", | 463 | pr_debug("Creating conn %p fastreg pool size=%d", |
470 | isert_conn, isert_conn->conn_frwr_pool_size); | 464 | isert_conn, isert_conn->conn_fr_pool_size); |
471 | 465 | ||
472 | return 0; | 466 | return 0; |
473 | 467 | ||
474 | err: | 468 | err: |
475 | isert_conn_free_frwr_pool(isert_conn); | 469 | isert_conn_free_fastreg_pool(isert_conn); |
476 | return ret; | 470 | return ret; |
477 | } | 471 | } |
478 | 472 | ||
@@ -558,14 +552,29 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) | |||
558 | } | 552 | } |
559 | 553 | ||
560 | isert_conn->conn_device = device; | 554 | isert_conn->conn_device = device; |
561 | isert_conn->conn_pd = device->dev_pd; | 555 | isert_conn->conn_pd = ib_alloc_pd(isert_conn->conn_device->ib_device); |
562 | isert_conn->conn_mr = device->dev_mr; | 556 | if (IS_ERR(isert_conn->conn_pd)) { |
557 | ret = PTR_ERR(isert_conn->conn_pd); | ||
558 | pr_err("ib_alloc_pd failed for conn %p: ret=%d\n", | ||
559 | isert_conn, ret); | ||
560 | goto out_pd; | ||
561 | } | ||
563 | 562 | ||
564 | if (device->use_frwr) { | 563 | isert_conn->conn_mr = ib_get_dma_mr(isert_conn->conn_pd, |
565 | ret = isert_conn_create_frwr_pool(isert_conn); | 564 | IB_ACCESS_LOCAL_WRITE); |
565 | if (IS_ERR(isert_conn->conn_mr)) { | ||
566 | ret = PTR_ERR(isert_conn->conn_mr); | ||
567 | pr_err("ib_get_dma_mr failed for conn %p: ret=%d\n", | ||
568 | isert_conn, ret); | ||
569 | goto out_mr; | ||
570 | } | ||
571 | |||
572 | if (device->use_fastreg) { | ||
573 | ret = isert_conn_create_fastreg_pool(isert_conn); | ||
566 | if (ret) { | 574 | if (ret) { |
567 | pr_err("Conn: %p failed to create frwr_pool\n", isert_conn); | 575 | pr_err("Conn: %p failed to create fastreg pool\n", |
568 | goto out_frwr; | 576 | isert_conn); |
577 | goto out_fastreg; | ||
569 | } | 578 | } |
570 | } | 579 | } |
571 | 580 | ||
@@ -582,9 +591,13 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) | |||
582 | return 0; | 591 | return 0; |
583 | 592 | ||
584 | out_conn_dev: | 593 | out_conn_dev: |
585 | if (device->use_frwr) | 594 | if (device->use_fastreg) |
586 | isert_conn_free_frwr_pool(isert_conn); | 595 | isert_conn_free_fastreg_pool(isert_conn); |
587 | out_frwr: | 596 | out_fastreg: |
597 | ib_dereg_mr(isert_conn->conn_mr); | ||
598 | out_mr: | ||
599 | ib_dealloc_pd(isert_conn->conn_pd); | ||
600 | out_pd: | ||
588 | isert_device_try_release(device); | 601 | isert_device_try_release(device); |
589 | out_rsp_dma_map: | 602 | out_rsp_dma_map: |
590 | ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma, | 603 | ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma, |
@@ -608,8 +621,8 @@ isert_connect_release(struct isert_conn *isert_conn) | |||
608 | 621 | ||
609 | pr_debug("Entering isert_connect_release(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); | 622 | pr_debug("Entering isert_connect_release(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); |
610 | 623 | ||
611 | if (device && device->use_frwr) | 624 | if (device && device->use_fastreg) |
612 | isert_conn_free_frwr_pool(isert_conn); | 625 | isert_conn_free_fastreg_pool(isert_conn); |
613 | 626 | ||
614 | if (isert_conn->conn_qp) { | 627 | if (isert_conn->conn_qp) { |
615 | cq_index = ((struct isert_cq_desc *) | 628 | cq_index = ((struct isert_cq_desc *) |
@@ -623,6 +636,9 @@ isert_connect_release(struct isert_conn *isert_conn) | |||
623 | isert_free_rx_descriptors(isert_conn); | 636 | isert_free_rx_descriptors(isert_conn); |
624 | rdma_destroy_id(isert_conn->conn_cm_id); | 637 | rdma_destroy_id(isert_conn->conn_cm_id); |
625 | 638 | ||
639 | ib_dereg_mr(isert_conn->conn_mr); | ||
640 | ib_dealloc_pd(isert_conn->conn_pd); | ||
641 | |||
626 | if (isert_conn->login_buf) { | 642 | if (isert_conn->login_buf) { |
627 | ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma, | 643 | ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma, |
628 | ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE); | 644 | ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE); |
@@ -1024,13 +1040,13 @@ isert_rx_login_req(struct iser_rx_desc *rx_desc, int rx_buflen, | |||
1024 | } | 1040 | } |
1025 | 1041 | ||
1026 | static struct iscsi_cmd | 1042 | static struct iscsi_cmd |
1027 | *isert_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp) | 1043 | *isert_allocate_cmd(struct iscsi_conn *conn) |
1028 | { | 1044 | { |
1029 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 1045 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; |
1030 | struct isert_cmd *isert_cmd; | 1046 | struct isert_cmd *isert_cmd; |
1031 | struct iscsi_cmd *cmd; | 1047 | struct iscsi_cmd *cmd; |
1032 | 1048 | ||
1033 | cmd = iscsit_allocate_cmd(conn, gfp); | 1049 | cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); |
1034 | if (!cmd) { | 1050 | if (!cmd) { |
1035 | pr_err("Unable to allocate iscsi_cmd + isert_cmd\n"); | 1051 | pr_err("Unable to allocate iscsi_cmd + isert_cmd\n"); |
1036 | return NULL; | 1052 | return NULL; |
@@ -1219,7 +1235,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | |||
1219 | 1235 | ||
1220 | switch (opcode) { | 1236 | switch (opcode) { |
1221 | case ISCSI_OP_SCSI_CMD: | 1237 | case ISCSI_OP_SCSI_CMD: |
1222 | cmd = isert_allocate_cmd(conn, GFP_KERNEL); | 1238 | cmd = isert_allocate_cmd(conn); |
1223 | if (!cmd) | 1239 | if (!cmd) |
1224 | break; | 1240 | break; |
1225 | 1241 | ||
@@ -1233,7 +1249,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | |||
1233 | rx_desc, (unsigned char *)hdr); | 1249 | rx_desc, (unsigned char *)hdr); |
1234 | break; | 1250 | break; |
1235 | case ISCSI_OP_NOOP_OUT: | 1251 | case ISCSI_OP_NOOP_OUT: |
1236 | cmd = isert_allocate_cmd(conn, GFP_KERNEL); | 1252 | cmd = isert_allocate_cmd(conn); |
1237 | if (!cmd) | 1253 | if (!cmd) |
1238 | break; | 1254 | break; |
1239 | 1255 | ||
@@ -1246,7 +1262,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | |||
1246 | (unsigned char *)hdr); | 1262 | (unsigned char *)hdr); |
1247 | break; | 1263 | break; |
1248 | case ISCSI_OP_SCSI_TMFUNC: | 1264 | case ISCSI_OP_SCSI_TMFUNC: |
1249 | cmd = isert_allocate_cmd(conn, GFP_KERNEL); | 1265 | cmd = isert_allocate_cmd(conn); |
1250 | if (!cmd) | 1266 | if (!cmd) |
1251 | break; | 1267 | break; |
1252 | 1268 | ||
@@ -1254,7 +1270,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | |||
1254 | (unsigned char *)hdr); | 1270 | (unsigned char *)hdr); |
1255 | break; | 1271 | break; |
1256 | case ISCSI_OP_LOGOUT: | 1272 | case ISCSI_OP_LOGOUT: |
1257 | cmd = isert_allocate_cmd(conn, GFP_KERNEL); | 1273 | cmd = isert_allocate_cmd(conn); |
1258 | if (!cmd) | 1274 | if (!cmd) |
1259 | break; | 1275 | break; |
1260 | 1276 | ||
@@ -1265,7 +1281,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | |||
1265 | HZ); | 1281 | HZ); |
1266 | break; | 1282 | break; |
1267 | case ISCSI_OP_TEXT: | 1283 | case ISCSI_OP_TEXT: |
1268 | cmd = isert_allocate_cmd(conn, GFP_KERNEL); | 1284 | cmd = isert_allocate_cmd(conn); |
1269 | if (!cmd) | 1285 | if (!cmd) |
1270 | break; | 1286 | break; |
1271 | 1287 | ||
@@ -1404,25 +1420,25 @@ isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn) | |||
1404 | } | 1420 | } |
1405 | 1421 | ||
1406 | static void | 1422 | static void |
1407 | isert_unreg_rdma_frwr(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn) | 1423 | isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn) |
1408 | { | 1424 | { |
1409 | struct isert_rdma_wr *wr = &isert_cmd->rdma_wr; | 1425 | struct isert_rdma_wr *wr = &isert_cmd->rdma_wr; |
1410 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 1426 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; |
1411 | LIST_HEAD(unmap_list); | 1427 | LIST_HEAD(unmap_list); |
1412 | 1428 | ||
1413 | pr_debug("unreg_frwr_cmd: %p\n", isert_cmd); | 1429 | pr_debug("unreg_fastreg_cmd: %p\n", isert_cmd); |
1414 | 1430 | ||
1415 | if (wr->fr_desc) { | 1431 | if (wr->fr_desc) { |
1416 | pr_debug("unreg_frwr_cmd: %p free fr_desc %p\n", | 1432 | pr_debug("unreg_fastreg_cmd: %p free fr_desc %p\n", |
1417 | isert_cmd, wr->fr_desc); | 1433 | isert_cmd, wr->fr_desc); |
1418 | spin_lock_bh(&isert_conn->conn_lock); | 1434 | spin_lock_bh(&isert_conn->conn_lock); |
1419 | list_add_tail(&wr->fr_desc->list, &isert_conn->conn_frwr_pool); | 1435 | list_add_tail(&wr->fr_desc->list, &isert_conn->conn_fr_pool); |
1420 | spin_unlock_bh(&isert_conn->conn_lock); | 1436 | spin_unlock_bh(&isert_conn->conn_lock); |
1421 | wr->fr_desc = NULL; | 1437 | wr->fr_desc = NULL; |
1422 | } | 1438 | } |
1423 | 1439 | ||
1424 | if (wr->sge) { | 1440 | if (wr->sge) { |
1425 | pr_debug("unreg_frwr_cmd: %p unmap_sg op\n", isert_cmd); | 1441 | pr_debug("unreg_fastreg_cmd: %p unmap_sg op\n", isert_cmd); |
1426 | ib_dma_unmap_sg(ib_dev, wr->sge, wr->num_sge, | 1442 | ib_dma_unmap_sg(ib_dev, wr->sge, wr->num_sge, |
1427 | (wr->iser_ib_op == ISER_IB_RDMA_WRITE) ? | 1443 | (wr->iser_ib_op == ISER_IB_RDMA_WRITE) ? |
1428 | DMA_TO_DEVICE : DMA_FROM_DEVICE); | 1444 | DMA_TO_DEVICE : DMA_FROM_DEVICE); |
@@ -2163,26 +2179,22 @@ isert_map_fr_pagelist(struct ib_device *ib_dev, | |||
2163 | 2179 | ||
2164 | static int | 2180 | static int |
2165 | isert_fast_reg_mr(struct fast_reg_descriptor *fr_desc, | 2181 | isert_fast_reg_mr(struct fast_reg_descriptor *fr_desc, |
2166 | struct isert_cmd *isert_cmd, struct isert_conn *isert_conn, | 2182 | struct isert_conn *isert_conn, struct scatterlist *sg_start, |
2167 | struct ib_sge *ib_sge, u32 offset, unsigned int data_len) | 2183 | struct ib_sge *ib_sge, u32 sg_nents, u32 offset, |
2184 | unsigned int data_len) | ||
2168 | { | 2185 | { |
2169 | struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd; | ||
2170 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 2186 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; |
2171 | struct scatterlist *sg_start; | ||
2172 | u32 sg_off, page_off; | ||
2173 | struct ib_send_wr fr_wr, inv_wr; | 2187 | struct ib_send_wr fr_wr, inv_wr; |
2174 | struct ib_send_wr *bad_wr, *wr = NULL; | 2188 | struct ib_send_wr *bad_wr, *wr = NULL; |
2189 | int ret, pagelist_len; | ||
2190 | u32 page_off; | ||
2175 | u8 key; | 2191 | u8 key; |
2176 | int ret, sg_nents, pagelist_len; | ||
2177 | 2192 | ||
2178 | sg_off = offset / PAGE_SIZE; | 2193 | sg_nents = min_t(unsigned int, sg_nents, ISCSI_ISER_SG_TABLESIZE); |
2179 | sg_start = &cmd->se_cmd.t_data_sg[sg_off]; | ||
2180 | sg_nents = min_t(unsigned int, cmd->se_cmd.t_data_nents - sg_off, | ||
2181 | ISCSI_ISER_SG_TABLESIZE); | ||
2182 | page_off = offset % PAGE_SIZE; | 2194 | page_off = offset % PAGE_SIZE; |
2183 | 2195 | ||
2184 | pr_debug("Cmd: %p use fr_desc %p sg_nents %d sg_off %d offset %u\n", | 2196 | pr_debug("Use fr_desc %p sg_nents %d offset %u\n", |
2185 | isert_cmd, fr_desc, sg_nents, sg_off, offset); | 2197 | fr_desc, sg_nents, offset); |
2186 | 2198 | ||
2187 | pagelist_len = isert_map_fr_pagelist(ib_dev, sg_start, sg_nents, | 2199 | pagelist_len = isert_map_fr_pagelist(ib_dev, sg_start, sg_nents, |
2188 | &fr_desc->data_frpl->page_list[0]); | 2200 | &fr_desc->data_frpl->page_list[0]); |
@@ -2232,8 +2244,8 @@ isert_fast_reg_mr(struct fast_reg_descriptor *fr_desc, | |||
2232 | } | 2244 | } |
2233 | 2245 | ||
2234 | static int | 2246 | static int |
2235 | isert_reg_rdma_frwr(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 2247 | isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, |
2236 | struct isert_rdma_wr *wr) | 2248 | struct isert_rdma_wr *wr) |
2237 | { | 2249 | { |
2238 | struct se_cmd *se_cmd = &cmd->se_cmd; | 2250 | struct se_cmd *se_cmd = &cmd->se_cmd; |
2239 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 2251 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); |
@@ -2251,9 +2263,9 @@ isert_reg_rdma_frwr(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
2251 | if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) { | 2263 | if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) { |
2252 | data_left = se_cmd->data_length; | 2264 | data_left = se_cmd->data_length; |
2253 | } else { | 2265 | } else { |
2254 | sg_off = cmd->write_data_done / PAGE_SIZE; | ||
2255 | data_left = se_cmd->data_length - cmd->write_data_done; | ||
2256 | offset = cmd->write_data_done; | 2266 | offset = cmd->write_data_done; |
2267 | sg_off = offset / PAGE_SIZE; | ||
2268 | data_left = se_cmd->data_length - cmd->write_data_done; | ||
2257 | isert_cmd->tx_desc.isert_cmd = isert_cmd; | 2269 | isert_cmd->tx_desc.isert_cmd = isert_cmd; |
2258 | } | 2270 | } |
2259 | 2271 | ||
@@ -2311,16 +2323,16 @@ isert_reg_rdma_frwr(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
2311 | wr->fr_desc = NULL; | 2323 | wr->fr_desc = NULL; |
2312 | } else { | 2324 | } else { |
2313 | spin_lock_irqsave(&isert_conn->conn_lock, flags); | 2325 | spin_lock_irqsave(&isert_conn->conn_lock, flags); |
2314 | fr_desc = list_first_entry(&isert_conn->conn_frwr_pool, | 2326 | fr_desc = list_first_entry(&isert_conn->conn_fr_pool, |
2315 | struct fast_reg_descriptor, list); | 2327 | struct fast_reg_descriptor, list); |
2316 | list_del(&fr_desc->list); | 2328 | list_del(&fr_desc->list); |
2317 | spin_unlock_irqrestore(&isert_conn->conn_lock, flags); | 2329 | spin_unlock_irqrestore(&isert_conn->conn_lock, flags); |
2318 | wr->fr_desc = fr_desc; | 2330 | wr->fr_desc = fr_desc; |
2319 | 2331 | ||
2320 | ret = isert_fast_reg_mr(fr_desc, isert_cmd, isert_conn, | 2332 | ret = isert_fast_reg_mr(fr_desc, isert_conn, sg_start, |
2321 | ib_sge, offset, data_len); | 2333 | ib_sge, sg_nents, offset, data_len); |
2322 | if (ret) { | 2334 | if (ret) { |
2323 | list_add_tail(&fr_desc->list, &isert_conn->conn_frwr_pool); | 2335 | list_add_tail(&fr_desc->list, &isert_conn->conn_fr_pool); |
2324 | goto unmap_sg; | 2336 | goto unmap_sg; |
2325 | } | 2337 | } |
2326 | } | 2338 | } |
diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 691f90ff2d83..708a069002f3 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h | |||
@@ -119,9 +119,9 @@ struct isert_conn { | |||
119 | wait_queue_head_t conn_wait; | 119 | wait_queue_head_t conn_wait; |
120 | wait_queue_head_t conn_wait_comp_err; | 120 | wait_queue_head_t conn_wait_comp_err; |
121 | struct kref conn_kref; | 121 | struct kref conn_kref; |
122 | struct list_head conn_frwr_pool; | 122 | struct list_head conn_fr_pool; |
123 | int conn_frwr_pool_size; | 123 | int conn_fr_pool_size; |
124 | /* lock to protect frwr_pool */ | 124 | /* lock to protect fastreg pool */ |
125 | spinlock_t conn_lock; | 125 | spinlock_t conn_lock; |
126 | #define ISERT_COMP_BATCH_COUNT 8 | 126 | #define ISERT_COMP_BATCH_COUNT 8 |
127 | int conn_comp_batch; | 127 | int conn_comp_batch; |
@@ -139,13 +139,11 @@ struct isert_cq_desc { | |||
139 | }; | 139 | }; |
140 | 140 | ||
141 | struct isert_device { | 141 | struct isert_device { |
142 | int use_frwr; | 142 | int use_fastreg; |
143 | int cqs_used; | 143 | int cqs_used; |
144 | int refcount; | 144 | int refcount; |
145 | int cq_active_qps[ISERT_MAX_CQ]; | 145 | int cq_active_qps[ISERT_MAX_CQ]; |
146 | struct ib_device *ib_device; | 146 | struct ib_device *ib_device; |
147 | struct ib_pd *dev_pd; | ||
148 | struct ib_mr *dev_mr; | ||
149 | struct ib_cq *dev_rx_cq[ISERT_MAX_CQ]; | 147 | struct ib_cq *dev_rx_cq[ISERT_MAX_CQ]; |
150 | struct ib_cq *dev_tx_cq[ISERT_MAX_CQ]; | 148 | struct ib_cq *dev_tx_cq[ISERT_MAX_CQ]; |
151 | struct isert_cq_desc *cq_desc; | 149 | struct isert_cq_desc *cq_desc; |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 570c7fcc0c4d..4a0d7c92181f 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -1990,6 +1990,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) | |||
1990 | 1990 | ||
1991 | vha->flags.delete_progress = 1; | 1991 | vha->flags.delete_progress = 1; |
1992 | 1992 | ||
1993 | qlt_remove_target(ha, vha); | ||
1994 | |||
1993 | fc_remove_host(vha->host); | 1995 | fc_remove_host(vha->host); |
1994 | 1996 | ||
1995 | scsi_remove_host(vha->host); | 1997 | scsi_remove_host(vha->host); |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 41d6491d7bd9..e1fe95ef23e1 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -2750,6 +2750,13 @@ struct qlfc_fw { | |||
2750 | uint32_t len; | 2750 | uint32_t len; |
2751 | }; | 2751 | }; |
2752 | 2752 | ||
2753 | struct scsi_qlt_host { | ||
2754 | void *target_lport_ptr; | ||
2755 | struct mutex tgt_mutex; | ||
2756 | struct mutex tgt_host_action_mutex; | ||
2757 | struct qla_tgt *qla_tgt; | ||
2758 | }; | ||
2759 | |||
2753 | struct qlt_hw_data { | 2760 | struct qlt_hw_data { |
2754 | /* Protected by hw lock */ | 2761 | /* Protected by hw lock */ |
2755 | uint32_t enable_class_2:1; | 2762 | uint32_t enable_class_2:1; |
@@ -2765,15 +2772,11 @@ struct qlt_hw_data { | |||
2765 | uint32_t __iomem *atio_q_in; | 2772 | uint32_t __iomem *atio_q_in; |
2766 | uint32_t __iomem *atio_q_out; | 2773 | uint32_t __iomem *atio_q_out; |
2767 | 2774 | ||
2768 | void *target_lport_ptr; | ||
2769 | struct qla_tgt_func_tmpl *tgt_ops; | 2775 | struct qla_tgt_func_tmpl *tgt_ops; |
2770 | struct qla_tgt *qla_tgt; | ||
2771 | struct qla_tgt_cmd *cmds[DEFAULT_OUTSTANDING_COMMANDS]; | 2776 | struct qla_tgt_cmd *cmds[DEFAULT_OUTSTANDING_COMMANDS]; |
2772 | uint16_t current_handle; | 2777 | uint16_t current_handle; |
2773 | 2778 | ||
2774 | struct qla_tgt_vp_map *tgt_vp_map; | 2779 | struct qla_tgt_vp_map *tgt_vp_map; |
2775 | struct mutex tgt_mutex; | ||
2776 | struct mutex tgt_host_action_mutex; | ||
2777 | 2780 | ||
2778 | int saved_set; | 2781 | int saved_set; |
2779 | uint16_t saved_exchange_count; | 2782 | uint16_t saved_exchange_count; |
@@ -3435,6 +3438,7 @@ typedef struct scsi_qla_host { | |||
3435 | #define VP_ERR_FAB_LOGOUT 4 | 3438 | #define VP_ERR_FAB_LOGOUT 4 |
3436 | #define VP_ERR_ADAP_NORESOURCES 5 | 3439 | #define VP_ERR_ADAP_NORESOURCES 5 |
3437 | struct qla_hw_data *hw; | 3440 | struct qla_hw_data *hw; |
3441 | struct scsi_qlt_host vha_tgt; | ||
3438 | struct req_que *req; | 3442 | struct req_que *req; |
3439 | int fw_heartbeat_counter; | 3443 | int fw_heartbeat_counter; |
3440 | int seconds_since_last_heartbeat; | 3444 | int seconds_since_last_heartbeat; |
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 38a1257e76e1..9e80d61e5a3a 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c | |||
@@ -590,7 +590,7 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
590 | 590 | ||
591 | /* Check to avoid double sessions */ | 591 | /* Check to avoid double sessions */ |
592 | spin_lock_irqsave(&ha->hardware_lock, flags); | 592 | spin_lock_irqsave(&ha->hardware_lock, flags); |
593 | list_for_each_entry(sess, &ha->tgt.qla_tgt->sess_list, | 593 | list_for_each_entry(sess, &vha->vha_tgt.qla_tgt->sess_list, |
594 | sess_list_entry) { | 594 | sess_list_entry) { |
595 | if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) { | 595 | if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) { |
596 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005, | 596 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005, |
@@ -627,7 +627,7 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
627 | 627 | ||
628 | return NULL; | 628 | return NULL; |
629 | } | 629 | } |
630 | sess->tgt = ha->tgt.qla_tgt; | 630 | sess->tgt = vha->vha_tgt.qla_tgt; |
631 | sess->vha = vha; | 631 | sess->vha = vha; |
632 | sess->s_id = fcport->d_id; | 632 | sess->s_id = fcport->d_id; |
633 | sess->loop_id = fcport->loop_id; | 633 | sess->loop_id = fcport->loop_id; |
@@ -635,7 +635,7 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
635 | 635 | ||
636 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006, | 636 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006, |
637 | "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n", | 637 | "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n", |
638 | sess, ha->tgt.qla_tgt); | 638 | sess, vha->vha_tgt.qla_tgt); |
639 | 639 | ||
640 | be_sid[0] = sess->s_id.b.domain; | 640 | be_sid[0] = sess->s_id.b.domain; |
641 | be_sid[1] = sess->s_id.b.area; | 641 | be_sid[1] = sess->s_id.b.area; |
@@ -662,8 +662,8 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
662 | memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); | 662 | memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); |
663 | 663 | ||
664 | spin_lock_irqsave(&ha->hardware_lock, flags); | 664 | spin_lock_irqsave(&ha->hardware_lock, flags); |
665 | list_add_tail(&sess->sess_list_entry, &ha->tgt.qla_tgt->sess_list); | 665 | list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list); |
666 | ha->tgt.qla_tgt->sess_count++; | 666 | vha->vha_tgt.qla_tgt->sess_count++; |
667 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 667 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
668 | 668 | ||
669 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, | 669 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, |
@@ -682,7 +682,7 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
682 | void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) | 682 | void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) |
683 | { | 683 | { |
684 | struct qla_hw_data *ha = vha->hw; | 684 | struct qla_hw_data *ha = vha->hw; |
685 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 685 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
686 | struct qla_tgt_sess *sess; | 686 | struct qla_tgt_sess *sess; |
687 | unsigned long flags; | 687 | unsigned long flags; |
688 | 688 | ||
@@ -692,6 +692,9 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) | |||
692 | if (!tgt || (fcport->port_type != FCT_INITIATOR)) | 692 | if (!tgt || (fcport->port_type != FCT_INITIATOR)) |
693 | return; | 693 | return; |
694 | 694 | ||
695 | if (qla_ini_mode_enabled(vha)) | ||
696 | return; | ||
697 | |||
695 | spin_lock_irqsave(&ha->hardware_lock, flags); | 698 | spin_lock_irqsave(&ha->hardware_lock, flags); |
696 | if (tgt->tgt_stop) { | 699 | if (tgt->tgt_stop) { |
697 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 700 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
@@ -701,9 +704,9 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) | |||
701 | if (!sess) { | 704 | if (!sess) { |
702 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 705 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
703 | 706 | ||
704 | mutex_lock(&ha->tgt.tgt_mutex); | 707 | mutex_lock(&vha->vha_tgt.tgt_mutex); |
705 | sess = qlt_create_sess(vha, fcport, false); | 708 | sess = qlt_create_sess(vha, fcport, false); |
706 | mutex_unlock(&ha->tgt.tgt_mutex); | 709 | mutex_unlock(&vha->vha_tgt.tgt_mutex); |
707 | 710 | ||
708 | spin_lock_irqsave(&ha->hardware_lock, flags); | 711 | spin_lock_irqsave(&ha->hardware_lock, flags); |
709 | } else { | 712 | } else { |
@@ -739,7 +742,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) | |||
739 | void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) | 742 | void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) |
740 | { | 743 | { |
741 | struct qla_hw_data *ha = vha->hw; | 744 | struct qla_hw_data *ha = vha->hw; |
742 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 745 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
743 | struct qla_tgt_sess *sess; | 746 | struct qla_tgt_sess *sess; |
744 | unsigned long flags; | 747 | unsigned long flags; |
745 | 748 | ||
@@ -806,12 +809,12 @@ void qlt_stop_phase1(struct qla_tgt *tgt) | |||
806 | * Mutex needed to sync with qla_tgt_fc_port_[added,deleted]. | 809 | * Mutex needed to sync with qla_tgt_fc_port_[added,deleted]. |
807 | * Lock is needed, because we still can get an incoming packet. | 810 | * Lock is needed, because we still can get an incoming packet. |
808 | */ | 811 | */ |
809 | mutex_lock(&ha->tgt.tgt_mutex); | 812 | mutex_lock(&vha->vha_tgt.tgt_mutex); |
810 | spin_lock_irqsave(&ha->hardware_lock, flags); | 813 | spin_lock_irqsave(&ha->hardware_lock, flags); |
811 | tgt->tgt_stop = 1; | 814 | tgt->tgt_stop = 1; |
812 | qlt_clear_tgt_db(tgt, true); | 815 | qlt_clear_tgt_db(tgt, true); |
813 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 816 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
814 | mutex_unlock(&ha->tgt.tgt_mutex); | 817 | mutex_unlock(&vha->vha_tgt.tgt_mutex); |
815 | 818 | ||
816 | flush_delayed_work(&tgt->sess_del_work); | 819 | flush_delayed_work(&tgt->sess_del_work); |
817 | 820 | ||
@@ -845,20 +848,21 @@ EXPORT_SYMBOL(qlt_stop_phase1); | |||
845 | void qlt_stop_phase2(struct qla_tgt *tgt) | 848 | void qlt_stop_phase2(struct qla_tgt *tgt) |
846 | { | 849 | { |
847 | struct qla_hw_data *ha = tgt->ha; | 850 | struct qla_hw_data *ha = tgt->ha; |
851 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); | ||
848 | unsigned long flags; | 852 | unsigned long flags; |
849 | 853 | ||
850 | if (tgt->tgt_stopped) { | 854 | if (tgt->tgt_stopped) { |
851 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf04f, | 855 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04f, |
852 | "Already in tgt->tgt_stopped state\n"); | 856 | "Already in tgt->tgt_stopped state\n"); |
853 | dump_stack(); | 857 | dump_stack(); |
854 | return; | 858 | return; |
855 | } | 859 | } |
856 | 860 | ||
857 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00b, | 861 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00b, |
858 | "Waiting for %d IRQ commands to complete (tgt %p)", | 862 | "Waiting for %d IRQ commands to complete (tgt %p)", |
859 | tgt->irq_cmd_count, tgt); | 863 | tgt->irq_cmd_count, tgt); |
860 | 864 | ||
861 | mutex_lock(&ha->tgt.tgt_mutex); | 865 | mutex_lock(&vha->vha_tgt.tgt_mutex); |
862 | spin_lock_irqsave(&ha->hardware_lock, flags); | 866 | spin_lock_irqsave(&ha->hardware_lock, flags); |
863 | while (tgt->irq_cmd_count != 0) { | 867 | while (tgt->irq_cmd_count != 0) { |
864 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 868 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
@@ -868,9 +872,9 @@ void qlt_stop_phase2(struct qla_tgt *tgt) | |||
868 | tgt->tgt_stop = 0; | 872 | tgt->tgt_stop = 0; |
869 | tgt->tgt_stopped = 1; | 873 | tgt->tgt_stopped = 1; |
870 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 874 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
871 | mutex_unlock(&ha->tgt.tgt_mutex); | 875 | mutex_unlock(&vha->vha_tgt.tgt_mutex); |
872 | 876 | ||
873 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00c, "Stop of tgt %p finished", | 877 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00c, "Stop of tgt %p finished", |
874 | tgt); | 878 | tgt); |
875 | } | 879 | } |
876 | EXPORT_SYMBOL(qlt_stop_phase2); | 880 | EXPORT_SYMBOL(qlt_stop_phase2); |
@@ -878,14 +882,14 @@ EXPORT_SYMBOL(qlt_stop_phase2); | |||
878 | /* Called from qlt_remove_target() -> qla2x00_remove_one() */ | 882 | /* Called from qlt_remove_target() -> qla2x00_remove_one() */ |
879 | static void qlt_release(struct qla_tgt *tgt) | 883 | static void qlt_release(struct qla_tgt *tgt) |
880 | { | 884 | { |
881 | struct qla_hw_data *ha = tgt->ha; | 885 | scsi_qla_host_t *vha = tgt->vha; |
882 | 886 | ||
883 | if ((ha->tgt.qla_tgt != NULL) && !tgt->tgt_stopped) | 887 | if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stopped) |
884 | qlt_stop_phase2(tgt); | 888 | qlt_stop_phase2(tgt); |
885 | 889 | ||
886 | ha->tgt.qla_tgt = NULL; | 890 | vha->vha_tgt.qla_tgt = NULL; |
887 | 891 | ||
888 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00d, | 892 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00d, |
889 | "Release of tgt %p finished\n", tgt); | 893 | "Release of tgt %p finished\n", tgt); |
890 | 894 | ||
891 | kfree(tgt); | 895 | kfree(tgt); |
@@ -949,8 +953,8 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha, | |||
949 | return; | 953 | return; |
950 | } | 954 | } |
951 | 955 | ||
952 | if (ha->tgt.qla_tgt != NULL) | 956 | if (vha->vha_tgt.qla_tgt != NULL) |
953 | ha->tgt.qla_tgt->notify_ack_expected++; | 957 | vha->vha_tgt.qla_tgt->notify_ack_expected++; |
954 | 958 | ||
955 | pkt->entry_type = NOTIFY_ACK_TYPE; | 959 | pkt->entry_type = NOTIFY_ACK_TYPE; |
956 | pkt->entry_count = 1; | 960 | pkt->entry_count = 1; |
@@ -1054,7 +1058,7 @@ static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha, | |||
1054 | /* Other bytes are zero */ | 1058 | /* Other bytes are zero */ |
1055 | } | 1059 | } |
1056 | 1060 | ||
1057 | ha->tgt.qla_tgt->abts_resp_expected++; | 1061 | vha->vha_tgt.qla_tgt->abts_resp_expected++; |
1058 | 1062 | ||
1059 | qla2x00_start_iocbs(vha, vha->req); | 1063 | qla2x00_start_iocbs(vha, vha->req); |
1060 | } | 1064 | } |
@@ -1206,7 +1210,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, | |||
1206 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012, | 1210 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012, |
1207 | "qla_target(%d): task abort for non-existant session\n", | 1211 | "qla_target(%d): task abort for non-existant session\n", |
1208 | vha->vp_idx); | 1212 | vha->vp_idx); |
1209 | rc = qlt_sched_sess_work(ha->tgt.qla_tgt, | 1213 | rc = qlt_sched_sess_work(vha->vha_tgt.qla_tgt, |
1210 | QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts)); | 1214 | QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts)); |
1211 | if (rc != 0) { | 1215 | if (rc != 0) { |
1212 | qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, | 1216 | qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, |
@@ -2157,8 +2161,7 @@ static int qlt_prepare_srr_ctio(struct scsi_qla_host *vha, | |||
2157 | struct qla_tgt_cmd *cmd, void *ctio) | 2161 | struct qla_tgt_cmd *cmd, void *ctio) |
2158 | { | 2162 | { |
2159 | struct qla_tgt_srr_ctio *sc; | 2163 | struct qla_tgt_srr_ctio *sc; |
2160 | struct qla_hw_data *ha = vha->hw; | 2164 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
2161 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
2162 | struct qla_tgt_srr_imm *imm; | 2165 | struct qla_tgt_srr_imm *imm; |
2163 | 2166 | ||
2164 | tgt->ctio_srr_id++; | 2167 | tgt->ctio_srr_id++; |
@@ -2474,7 +2477,7 @@ static void qlt_do_work(struct work_struct *work) | |||
2474 | struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); | 2477 | struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); |
2475 | scsi_qla_host_t *vha = cmd->vha; | 2478 | scsi_qla_host_t *vha = cmd->vha; |
2476 | struct qla_hw_data *ha = vha->hw; | 2479 | struct qla_hw_data *ha = vha->hw; |
2477 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 2480 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
2478 | struct qla_tgt_sess *sess = NULL; | 2481 | struct qla_tgt_sess *sess = NULL; |
2479 | struct atio_from_isp *atio = &cmd->atio; | 2482 | struct atio_from_isp *atio = &cmd->atio; |
2480 | unsigned char *cdb; | 2483 | unsigned char *cdb; |
@@ -2507,10 +2510,10 @@ static void qlt_do_work(struct work_struct *work) | |||
2507 | goto out_term; | 2510 | goto out_term; |
2508 | } | 2511 | } |
2509 | 2512 | ||
2510 | mutex_lock(&ha->tgt.tgt_mutex); | 2513 | mutex_lock(&vha->vha_tgt.tgt_mutex); |
2511 | sess = qlt_make_local_sess(vha, s_id); | 2514 | sess = qlt_make_local_sess(vha, s_id); |
2512 | /* sess has an extra creation ref. */ | 2515 | /* sess has an extra creation ref. */ |
2513 | mutex_unlock(&ha->tgt.tgt_mutex); | 2516 | mutex_unlock(&vha->vha_tgt.tgt_mutex); |
2514 | 2517 | ||
2515 | if (!sess) | 2518 | if (!sess) |
2516 | goto out_term; | 2519 | goto out_term; |
@@ -2576,8 +2579,7 @@ out_term: | |||
2576 | static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, | 2579 | static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, |
2577 | struct atio_from_isp *atio) | 2580 | struct atio_from_isp *atio) |
2578 | { | 2581 | { |
2579 | struct qla_hw_data *ha = vha->hw; | 2582 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
2580 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
2581 | struct qla_tgt_cmd *cmd; | 2583 | struct qla_tgt_cmd *cmd; |
2582 | 2584 | ||
2583 | if (unlikely(tgt->tgt_stop)) { | 2585 | if (unlikely(tgt->tgt_stop)) { |
@@ -2597,7 +2599,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, | |||
2597 | 2599 | ||
2598 | memcpy(&cmd->atio, atio, sizeof(*atio)); | 2600 | memcpy(&cmd->atio, atio, sizeof(*atio)); |
2599 | cmd->state = QLA_TGT_STATE_NEW; | 2601 | cmd->state = QLA_TGT_STATE_NEW; |
2600 | cmd->tgt = ha->tgt.qla_tgt; | 2602 | cmd->tgt = vha->vha_tgt.qla_tgt; |
2601 | cmd->vha = vha; | 2603 | cmd->vha = vha; |
2602 | 2604 | ||
2603 | INIT_WORK(&cmd->work, qlt_do_work); | 2605 | INIT_WORK(&cmd->work, qlt_do_work); |
@@ -2723,7 +2725,7 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb) | |||
2723 | uint32_t lun, unpacked_lun; | 2725 | uint32_t lun, unpacked_lun; |
2724 | int lun_size, fn; | 2726 | int lun_size, fn; |
2725 | 2727 | ||
2726 | tgt = ha->tgt.qla_tgt; | 2728 | tgt = vha->vha_tgt.qla_tgt; |
2727 | 2729 | ||
2728 | lun = a->u.isp24.fcp_cmnd.lun; | 2730 | lun = a->u.isp24.fcp_cmnd.lun; |
2729 | lun_size = sizeof(a->u.isp24.fcp_cmnd.lun); | 2731 | lun_size = sizeof(a->u.isp24.fcp_cmnd.lun); |
@@ -2797,7 +2799,7 @@ static int qlt_abort_task(struct scsi_qla_host *vha, | |||
2797 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf025, | 2799 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf025, |
2798 | "qla_target(%d): task abort for unexisting " | 2800 | "qla_target(%d): task abort for unexisting " |
2799 | "session\n", vha->vp_idx); | 2801 | "session\n", vha->vp_idx); |
2800 | return qlt_sched_sess_work(ha->tgt.qla_tgt, | 2802 | return qlt_sched_sess_work(vha->vha_tgt.qla_tgt, |
2801 | QLA_TGT_SESS_WORK_ABORT, iocb, sizeof(*iocb)); | 2803 | QLA_TGT_SESS_WORK_ABORT, iocb, sizeof(*iocb)); |
2802 | } | 2804 | } |
2803 | 2805 | ||
@@ -2810,7 +2812,6 @@ static int qlt_abort_task(struct scsi_qla_host *vha, | |||
2810 | static int qlt_24xx_handle_els(struct scsi_qla_host *vha, | 2812 | static int qlt_24xx_handle_els(struct scsi_qla_host *vha, |
2811 | struct imm_ntfy_from_isp *iocb) | 2813 | struct imm_ntfy_from_isp *iocb) |
2812 | { | 2814 | { |
2813 | struct qla_hw_data *ha = vha->hw; | ||
2814 | int res = 0; | 2815 | int res = 0; |
2815 | 2816 | ||
2816 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026, | 2817 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026, |
@@ -2828,7 +2829,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, | |||
2828 | case ELS_PDISC: | 2829 | case ELS_PDISC: |
2829 | case ELS_ADISC: | 2830 | case ELS_ADISC: |
2830 | { | 2831 | { |
2831 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 2832 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
2832 | if (tgt->link_reinit_iocb_pending) { | 2833 | if (tgt->link_reinit_iocb_pending) { |
2833 | qlt_send_notify_ack(vha, &tgt->link_reinit_iocb, | 2834 | qlt_send_notify_ack(vha, &tgt->link_reinit_iocb, |
2834 | 0, 0, 0, 0, 0, 0); | 2835 | 0, 0, 0, 0, 0, 0); |
@@ -3202,8 +3203,7 @@ static void qlt_prepare_srr_imm(struct scsi_qla_host *vha, | |||
3202 | struct imm_ntfy_from_isp *iocb) | 3203 | struct imm_ntfy_from_isp *iocb) |
3203 | { | 3204 | { |
3204 | struct qla_tgt_srr_imm *imm; | 3205 | struct qla_tgt_srr_imm *imm; |
3205 | struct qla_hw_data *ha = vha->hw; | 3206 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
3206 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
3207 | struct qla_tgt_srr_ctio *sctio; | 3207 | struct qla_tgt_srr_ctio *sctio; |
3208 | 3208 | ||
3209 | tgt->imm_srr_id++; | 3209 | tgt->imm_srr_id++; |
@@ -3313,7 +3313,7 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha, | |||
3313 | 3313 | ||
3314 | case IMM_NTFY_LIP_LINK_REINIT: | 3314 | case IMM_NTFY_LIP_LINK_REINIT: |
3315 | { | 3315 | { |
3316 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 3316 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
3317 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf033, | 3317 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf033, |
3318 | "qla_target(%d): LINK REINIT (loop %#x, " | 3318 | "qla_target(%d): LINK REINIT (loop %#x, " |
3319 | "subcode %x)\n", vha->vp_idx, | 3319 | "subcode %x)\n", vha->vp_idx, |
@@ -3489,7 +3489,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
3489 | struct atio_from_isp *atio) | 3489 | struct atio_from_isp *atio) |
3490 | { | 3490 | { |
3491 | struct qla_hw_data *ha = vha->hw; | 3491 | struct qla_hw_data *ha = vha->hw; |
3492 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 3492 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
3493 | int rc; | 3493 | int rc; |
3494 | 3494 | ||
3495 | if (unlikely(tgt == NULL)) { | 3495 | if (unlikely(tgt == NULL)) { |
@@ -3591,7 +3591,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
3591 | static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) | 3591 | static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) |
3592 | { | 3592 | { |
3593 | struct qla_hw_data *ha = vha->hw; | 3593 | struct qla_hw_data *ha = vha->hw; |
3594 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 3594 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
3595 | 3595 | ||
3596 | if (unlikely(tgt == NULL)) { | 3596 | if (unlikely(tgt == NULL)) { |
3597 | ql_dbg(ql_dbg_tgt, vha, 0xe05d, | 3597 | ql_dbg(ql_dbg_tgt, vha, 0xe05d, |
@@ -3794,7 +3794,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha, | |||
3794 | uint16_t *mailbox) | 3794 | uint16_t *mailbox) |
3795 | { | 3795 | { |
3796 | struct qla_hw_data *ha = vha->hw; | 3796 | struct qla_hw_data *ha = vha->hw; |
3797 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 3797 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
3798 | int login_code; | 3798 | int login_code; |
3799 | 3799 | ||
3800 | ql_dbg(ql_dbg_tgt, vha, 0xe039, | 3800 | ql_dbg(ql_dbg_tgt, vha, 0xe039, |
@@ -3924,14 +3924,14 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha, | |||
3924 | static struct qla_tgt_sess *qlt_make_local_sess(struct scsi_qla_host *vha, | 3924 | static struct qla_tgt_sess *qlt_make_local_sess(struct scsi_qla_host *vha, |
3925 | uint8_t *s_id) | 3925 | uint8_t *s_id) |
3926 | { | 3926 | { |
3927 | struct qla_hw_data *ha = vha->hw; | ||
3928 | struct qla_tgt_sess *sess = NULL; | 3927 | struct qla_tgt_sess *sess = NULL; |
3929 | fc_port_t *fcport = NULL; | 3928 | fc_port_t *fcport = NULL; |
3930 | int rc, global_resets; | 3929 | int rc, global_resets; |
3931 | uint16_t loop_id = 0; | 3930 | uint16_t loop_id = 0; |
3932 | 3931 | ||
3933 | retry: | 3932 | retry: |
3934 | global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); | 3933 | global_resets = |
3934 | atomic_read(&vha->vha_tgt.qla_tgt->tgt_global_resets_count); | ||
3935 | 3935 | ||
3936 | rc = qla24xx_get_loop_id(vha, s_id, &loop_id); | 3936 | rc = qla24xx_get_loop_id(vha, s_id, &loop_id); |
3937 | if (rc != 0) { | 3937 | if (rc != 0) { |
@@ -3958,12 +3958,13 @@ retry: | |||
3958 | return NULL; | 3958 | return NULL; |
3959 | 3959 | ||
3960 | if (global_resets != | 3960 | if (global_resets != |
3961 | atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)) { | 3961 | atomic_read(&vha->vha_tgt.qla_tgt->tgt_global_resets_count)) { |
3962 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf043, | 3962 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf043, |
3963 | "qla_target(%d): global reset during session discovery " | 3963 | "qla_target(%d): global reset during session discovery " |
3964 | "(counter was %d, new %d), retrying", vha->vp_idx, | 3964 | "(counter was %d, new %d), retrying", vha->vp_idx, |
3965 | global_resets, | 3965 | global_resets, |
3966 | atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)); | 3966 | atomic_read(&vha->vha_tgt. |
3967 | qla_tgt->tgt_global_resets_count)); | ||
3967 | goto retry; | 3968 | goto retry; |
3968 | } | 3969 | } |
3969 | 3970 | ||
@@ -3998,10 +3999,10 @@ static void qlt_abort_work(struct qla_tgt *tgt, | |||
3998 | if (!sess) { | 3999 | if (!sess) { |
3999 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 4000 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
4000 | 4001 | ||
4001 | mutex_lock(&ha->tgt.tgt_mutex); | 4002 | mutex_lock(&vha->vha_tgt.tgt_mutex); |
4002 | sess = qlt_make_local_sess(vha, s_id); | 4003 | sess = qlt_make_local_sess(vha, s_id); |
4003 | /* sess has got an extra creation ref */ | 4004 | /* sess has got an extra creation ref */ |
4004 | mutex_unlock(&ha->tgt.tgt_mutex); | 4005 | mutex_unlock(&vha->vha_tgt.tgt_mutex); |
4005 | 4006 | ||
4006 | spin_lock_irqsave(&ha->hardware_lock, flags); | 4007 | spin_lock_irqsave(&ha->hardware_lock, flags); |
4007 | if (!sess) | 4008 | if (!sess) |
@@ -4052,10 +4053,10 @@ static void qlt_tmr_work(struct qla_tgt *tgt, | |||
4052 | if (!sess) { | 4053 | if (!sess) { |
4053 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 4054 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
4054 | 4055 | ||
4055 | mutex_lock(&ha->tgt.tgt_mutex); | 4056 | mutex_lock(&vha->vha_tgt.tgt_mutex); |
4056 | sess = qlt_make_local_sess(vha, s_id); | 4057 | sess = qlt_make_local_sess(vha, s_id); |
4057 | /* sess has got an extra creation ref */ | 4058 | /* sess has got an extra creation ref */ |
4058 | mutex_unlock(&ha->tgt.tgt_mutex); | 4059 | mutex_unlock(&vha->vha_tgt.tgt_mutex); |
4059 | 4060 | ||
4060 | spin_lock_irqsave(&ha->hardware_lock, flags); | 4061 | spin_lock_irqsave(&ha->hardware_lock, flags); |
4061 | if (!sess) | 4062 | if (!sess) |
@@ -4141,9 +4142,9 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) | |||
4141 | } | 4142 | } |
4142 | 4143 | ||
4143 | ql_dbg(ql_dbg_tgt, base_vha, 0xe03b, | 4144 | ql_dbg(ql_dbg_tgt, base_vha, 0xe03b, |
4144 | "Registering target for host %ld(%p)", base_vha->host_no, ha); | 4145 | "Registering target for host %ld(%p).\n", base_vha->host_no, ha); |
4145 | 4146 | ||
4146 | BUG_ON((ha->tgt.qla_tgt != NULL) || (ha->tgt.tgt_ops != NULL)); | 4147 | BUG_ON(base_vha->vha_tgt.qla_tgt != NULL); |
4147 | 4148 | ||
4148 | tgt = kzalloc(sizeof(struct qla_tgt), GFP_KERNEL); | 4149 | tgt = kzalloc(sizeof(struct qla_tgt), GFP_KERNEL); |
4149 | if (!tgt) { | 4150 | if (!tgt) { |
@@ -4171,7 +4172,7 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) | |||
4171 | INIT_WORK(&tgt->srr_work, qlt_handle_srr_work); | 4172 | INIT_WORK(&tgt->srr_work, qlt_handle_srr_work); |
4172 | atomic_set(&tgt->tgt_global_resets_count, 0); | 4173 | atomic_set(&tgt->tgt_global_resets_count, 0); |
4173 | 4174 | ||
4174 | ha->tgt.qla_tgt = tgt; | 4175 | base_vha->vha_tgt.qla_tgt = tgt; |
4175 | 4176 | ||
4176 | ql_dbg(ql_dbg_tgt, base_vha, 0xe067, | 4177 | ql_dbg(ql_dbg_tgt, base_vha, 0xe067, |
4177 | "qla_target(%d): using 64 Bit PCI addressing", | 4178 | "qla_target(%d): using 64 Bit PCI addressing", |
@@ -4192,16 +4193,16 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) | |||
4192 | /* Must be called under tgt_host_action_mutex */ | 4193 | /* Must be called under tgt_host_action_mutex */ |
4193 | int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha) | 4194 | int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha) |
4194 | { | 4195 | { |
4195 | if (!ha->tgt.qla_tgt) | 4196 | if (!vha->vha_tgt.qla_tgt) |
4196 | return 0; | 4197 | return 0; |
4197 | 4198 | ||
4198 | mutex_lock(&qla_tgt_mutex); | 4199 | mutex_lock(&qla_tgt_mutex); |
4199 | list_del(&ha->tgt.qla_tgt->tgt_list_entry); | 4200 | list_del(&vha->vha_tgt.qla_tgt->tgt_list_entry); |
4200 | mutex_unlock(&qla_tgt_mutex); | 4201 | mutex_unlock(&qla_tgt_mutex); |
4201 | 4202 | ||
4202 | ql_dbg(ql_dbg_tgt, vha, 0xe03c, "Unregistering target for host %ld(%p)", | 4203 | ql_dbg(ql_dbg_tgt, vha, 0xe03c, "Unregistering target for host %ld(%p)", |
4203 | vha->host_no, ha); | 4204 | vha->host_no, ha); |
4204 | qlt_release(ha->tgt.qla_tgt); | 4205 | qlt_release(vha->vha_tgt.qla_tgt); |
4205 | 4206 | ||
4206 | return 0; | 4207 | return 0; |
4207 | } | 4208 | } |
@@ -4235,8 +4236,9 @@ static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn, | |||
4235 | * @callback: lport initialization callback for tcm_qla2xxx code | 4236 | * @callback: lport initialization callback for tcm_qla2xxx code |
4236 | * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data | 4237 | * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data |
4237 | */ | 4238 | */ |
4238 | int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, | 4239 | int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn, |
4239 | int (*callback)(struct scsi_qla_host *), void *target_lport_ptr) | 4240 | u64 npiv_wwpn, u64 npiv_wwnn, |
4241 | int (*callback)(struct scsi_qla_host *, void *, u64, u64)) | ||
4240 | { | 4242 | { |
4241 | struct qla_tgt *tgt; | 4243 | struct qla_tgt *tgt; |
4242 | struct scsi_qla_host *vha; | 4244 | struct scsi_qla_host *vha; |
@@ -4255,14 +4257,11 @@ int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, | |||
4255 | if (!host) | 4257 | if (!host) |
4256 | continue; | 4258 | continue; |
4257 | 4259 | ||
4258 | if (ha->tgt.tgt_ops != NULL) | ||
4259 | continue; | ||
4260 | |||
4261 | if (!(host->hostt->supported_mode & MODE_TARGET)) | 4260 | if (!(host->hostt->supported_mode & MODE_TARGET)) |
4262 | continue; | 4261 | continue; |
4263 | 4262 | ||
4264 | spin_lock_irqsave(&ha->hardware_lock, flags); | 4263 | spin_lock_irqsave(&ha->hardware_lock, flags); |
4265 | if (host->active_mode & MODE_TARGET) { | 4264 | if ((!npiv_wwpn || !npiv_wwnn) && host->active_mode & MODE_TARGET) { |
4266 | pr_debug("MODE_TARGET already active on qla2xxx(%d)\n", | 4265 | pr_debug("MODE_TARGET already active on qla2xxx(%d)\n", |
4267 | host->host_no); | 4266 | host->host_no); |
4268 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 4267 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
@@ -4276,24 +4275,18 @@ int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, | |||
4276 | " qla2xxx scsi_host\n"); | 4275 | " qla2xxx scsi_host\n"); |
4277 | continue; | 4276 | continue; |
4278 | } | 4277 | } |
4279 | qlt_lport_dump(vha, wwpn, b); | 4278 | qlt_lport_dump(vha, phys_wwpn, b); |
4280 | 4279 | ||
4281 | if (memcmp(vha->port_name, b, WWN_SIZE)) { | 4280 | if (memcmp(vha->port_name, b, WWN_SIZE)) { |
4282 | scsi_host_put(host); | 4281 | scsi_host_put(host); |
4283 | continue; | 4282 | continue; |
4284 | } | 4283 | } |
4285 | /* | ||
4286 | * Setup passed parameters ahead of invoking callback | ||
4287 | */ | ||
4288 | ha->tgt.tgt_ops = qla_tgt_ops; | ||
4289 | ha->tgt.target_lport_ptr = target_lport_ptr; | ||
4290 | rc = (*callback)(vha); | ||
4291 | if (rc != 0) { | ||
4292 | ha->tgt.tgt_ops = NULL; | ||
4293 | ha->tgt.target_lport_ptr = NULL; | ||
4294 | scsi_host_put(host); | ||
4295 | } | ||
4296 | mutex_unlock(&qla_tgt_mutex); | 4284 | mutex_unlock(&qla_tgt_mutex); |
4285 | |||
4286 | rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn); | ||
4287 | if (rc != 0) | ||
4288 | scsi_host_put(host); | ||
4289 | |||
4297 | return rc; | 4290 | return rc; |
4298 | } | 4291 | } |
4299 | mutex_unlock(&qla_tgt_mutex); | 4292 | mutex_unlock(&qla_tgt_mutex); |
@@ -4314,7 +4307,7 @@ void qlt_lport_deregister(struct scsi_qla_host *vha) | |||
4314 | /* | 4307 | /* |
4315 | * Clear the target_lport_ptr qla_target_template pointer in qla_hw_data | 4308 | * Clear the target_lport_ptr qla_target_template pointer in qla_hw_data |
4316 | */ | 4309 | */ |
4317 | ha->tgt.target_lport_ptr = NULL; | 4310 | vha->vha_tgt.target_lport_ptr = NULL; |
4318 | ha->tgt.tgt_ops = NULL; | 4311 | ha->tgt.tgt_ops = NULL; |
4319 | /* | 4312 | /* |
4320 | * Release the Scsi_Host reference for the underlying qla2xxx host | 4313 | * Release the Scsi_Host reference for the underlying qla2xxx host |
@@ -4376,8 +4369,9 @@ void | |||
4376 | qlt_enable_vha(struct scsi_qla_host *vha) | 4369 | qlt_enable_vha(struct scsi_qla_host *vha) |
4377 | { | 4370 | { |
4378 | struct qla_hw_data *ha = vha->hw; | 4371 | struct qla_hw_data *ha = vha->hw; |
4379 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 4372 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
4380 | unsigned long flags; | 4373 | unsigned long flags; |
4374 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | ||
4381 | 4375 | ||
4382 | if (!tgt) { | 4376 | if (!tgt) { |
4383 | ql_dbg(ql_dbg_tgt, vha, 0xe069, | 4377 | ql_dbg(ql_dbg_tgt, vha, 0xe069, |
@@ -4392,9 +4386,14 @@ qlt_enable_vha(struct scsi_qla_host *vha) | |||
4392 | qlt_set_mode(vha); | 4386 | qlt_set_mode(vha); |
4393 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 4387 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
4394 | 4388 | ||
4395 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 4389 | if (vha->vp_idx) { |
4396 | qla2xxx_wake_dpc(vha); | 4390 | qla24xx_disable_vp(vha); |
4397 | qla2x00_wait_for_hba_online(vha); | 4391 | qla24xx_enable_vp(vha); |
4392 | } else { | ||
4393 | set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); | ||
4394 | qla2xxx_wake_dpc(base_vha); | ||
4395 | qla2x00_wait_for_hba_online(base_vha); | ||
4396 | } | ||
4398 | } | 4397 | } |
4399 | EXPORT_SYMBOL(qlt_enable_vha); | 4398 | EXPORT_SYMBOL(qlt_enable_vha); |
4400 | 4399 | ||
@@ -4407,7 +4406,7 @@ void | |||
4407 | qlt_disable_vha(struct scsi_qla_host *vha) | 4406 | qlt_disable_vha(struct scsi_qla_host *vha) |
4408 | { | 4407 | { |
4409 | struct qla_hw_data *ha = vha->hw; | 4408 | struct qla_hw_data *ha = vha->hw; |
4410 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | 4409 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
4411 | unsigned long flags; | 4410 | unsigned long flags; |
4412 | 4411 | ||
4413 | if (!tgt) { | 4412 | if (!tgt) { |
@@ -4438,8 +4437,10 @@ qlt_vport_create(struct scsi_qla_host *vha, struct qla_hw_data *ha) | |||
4438 | if (!qla_tgt_mode_enabled(vha)) | 4437 | if (!qla_tgt_mode_enabled(vha)) |
4439 | return; | 4438 | return; |
4440 | 4439 | ||
4441 | mutex_init(&ha->tgt.tgt_mutex); | 4440 | vha->vha_tgt.qla_tgt = NULL; |
4442 | mutex_init(&ha->tgt.tgt_host_action_mutex); | 4441 | |
4442 | mutex_init(&vha->vha_tgt.tgt_mutex); | ||
4443 | mutex_init(&vha->vha_tgt.tgt_host_action_mutex); | ||
4443 | 4444 | ||
4444 | qlt_clear_mode(vha); | 4445 | qlt_clear_mode(vha); |
4445 | 4446 | ||
@@ -4450,6 +4451,8 @@ qlt_vport_create(struct scsi_qla_host *vha, struct qla_hw_data *ha) | |||
4450 | * assigning the value appropriately. | 4451 | * assigning the value appropriately. |
4451 | */ | 4452 | */ |
4452 | ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; | 4453 | ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; |
4454 | |||
4455 | qlt_add_target(ha, vha); | ||
4453 | } | 4456 | } |
4454 | 4457 | ||
4455 | void | 4458 | void |
@@ -4768,8 +4771,8 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha) | |||
4768 | ISP_ATIO_Q_OUT(base_vha) = &ha->iobase->isp24.atio_q_out; | 4771 | ISP_ATIO_Q_OUT(base_vha) = &ha->iobase->isp24.atio_q_out; |
4769 | } | 4772 | } |
4770 | 4773 | ||
4771 | mutex_init(&ha->tgt.tgt_mutex); | 4774 | mutex_init(&base_vha->vha_tgt.tgt_mutex); |
4772 | mutex_init(&ha->tgt.tgt_host_action_mutex); | 4775 | mutex_init(&base_vha->vha_tgt.tgt_host_action_mutex); |
4773 | qlt_clear_mode(base_vha); | 4776 | qlt_clear_mode(base_vha); |
4774 | } | 4777 | } |
4775 | 4778 | ||
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index b33e411f28a0..1d10eecad499 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h | |||
@@ -932,8 +932,8 @@ void qlt_disable_vha(struct scsi_qla_host *); | |||
932 | */ | 932 | */ |
933 | extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *); | 933 | extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *); |
934 | extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); | 934 | extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); |
935 | extern int qlt_lport_register(struct qla_tgt_func_tmpl *, u64, | 935 | extern int qlt_lport_register(void *, u64, u64, u64, |
936 | int (*callback)(struct scsi_qla_host *), void *); | 936 | int (*callback)(struct scsi_qla_host *, void *, u64, u64)); |
937 | extern void qlt_lport_deregister(struct scsi_qla_host *); | 937 | extern void qlt_lport_deregister(struct scsi_qla_host *); |
938 | extern void qlt_unreg_sess(struct qla_tgt_sess *); | 938 | extern void qlt_unreg_sess(struct qla_tgt_sess *); |
939 | extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); | 939 | extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); |
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 7eb19be35d46..75a141bbe74d 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | |||
@@ -53,16 +53,6 @@ | |||
53 | struct workqueue_struct *tcm_qla2xxx_free_wq; | 53 | struct workqueue_struct *tcm_qla2xxx_free_wq; |
54 | struct workqueue_struct *tcm_qla2xxx_cmd_wq; | 54 | struct workqueue_struct *tcm_qla2xxx_cmd_wq; |
55 | 55 | ||
56 | static int tcm_qla2xxx_check_true(struct se_portal_group *se_tpg) | ||
57 | { | ||
58 | return 1; | ||
59 | } | ||
60 | |||
61 | static int tcm_qla2xxx_check_false(struct se_portal_group *se_tpg) | ||
62 | { | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /* | 56 | /* |
67 | * Parse WWN. | 57 | * Parse WWN. |
68 | * If strict, we require lower-case hex and colon separators to be sure | 58 | * If strict, we require lower-case hex and colon separators to be sure |
@@ -174,7 +164,7 @@ static int tcm_qla2xxx_npiv_parse_wwn( | |||
174 | *wwnn = 0; | 164 | *wwnn = 0; |
175 | 165 | ||
176 | /* count may include a LF at end of string */ | 166 | /* count may include a LF at end of string */ |
177 | if (name[cnt-1] == '\n') | 167 | if (name[cnt-1] == '\n' || name[cnt-1] == 0) |
178 | cnt--; | 168 | cnt--; |
179 | 169 | ||
180 | /* validate we have enough characters for WWPN */ | 170 | /* validate we have enough characters for WWPN */ |
@@ -777,6 +767,9 @@ static void tcm_qla2xxx_put_session(struct se_session *se_sess) | |||
777 | 767 | ||
778 | static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) | 768 | static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) |
779 | { | 769 | { |
770 | if (!sess) | ||
771 | return; | ||
772 | |||
780 | assert_spin_locked(&sess->vha->hw->hardware_lock); | 773 | assert_spin_locked(&sess->vha->hw->hardware_lock); |
781 | kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session); | 774 | kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session); |
782 | } | 775 | } |
@@ -957,7 +950,6 @@ static ssize_t tcm_qla2xxx_tpg_store_enable( | |||
957 | struct tcm_qla2xxx_lport *lport = container_of(se_wwn, | 950 | struct tcm_qla2xxx_lport *lport = container_of(se_wwn, |
958 | struct tcm_qla2xxx_lport, lport_wwn); | 951 | struct tcm_qla2xxx_lport, lport_wwn); |
959 | struct scsi_qla_host *vha = lport->qla_vha; | 952 | struct scsi_qla_host *vha = lport->qla_vha; |
960 | struct qla_hw_data *ha = vha->hw; | ||
961 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | 953 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, |
962 | struct tcm_qla2xxx_tpg, se_tpg); | 954 | struct tcm_qla2xxx_tpg, se_tpg); |
963 | unsigned long op; | 955 | unsigned long op; |
@@ -977,12 +969,12 @@ static ssize_t tcm_qla2xxx_tpg_store_enable( | |||
977 | atomic_set(&tpg->lport_tpg_enabled, 1); | 969 | atomic_set(&tpg->lport_tpg_enabled, 1); |
978 | qlt_enable_vha(vha); | 970 | qlt_enable_vha(vha); |
979 | } else { | 971 | } else { |
980 | if (!ha->tgt.qla_tgt) { | 972 | if (!vha->vha_tgt.qla_tgt) { |
981 | pr_err("truct qla_hw_data *ha->tgt.qla_tgt is NULL\n"); | 973 | pr_err("struct qla_hw_data *vha->vha_tgt.qla_tgt is NULL\n"); |
982 | return -ENODEV; | 974 | return -ENODEV; |
983 | } | 975 | } |
984 | atomic_set(&tpg->lport_tpg_enabled, 0); | 976 | atomic_set(&tpg->lport_tpg_enabled, 0); |
985 | qlt_stop_phase1(ha->tgt.qla_tgt); | 977 | qlt_stop_phase1(vha->vha_tgt.qla_tgt); |
986 | } | 978 | } |
987 | 979 | ||
988 | return count; | 980 | return count; |
@@ -1011,7 +1003,7 @@ static struct se_portal_group *tcm_qla2xxx_make_tpg( | |||
1011 | if (kstrtoul(name + 5, 10, &tpgt) || tpgt > USHRT_MAX) | 1003 | if (kstrtoul(name + 5, 10, &tpgt) || tpgt > USHRT_MAX) |
1012 | return ERR_PTR(-EINVAL); | 1004 | return ERR_PTR(-EINVAL); |
1013 | 1005 | ||
1014 | if (!lport->qla_npiv_vp && (tpgt != 1)) { | 1006 | if ((tpgt != 1)) { |
1015 | pr_err("In non NPIV mode, a single TPG=1 is used for HW port mappings\n"); | 1007 | pr_err("In non NPIV mode, a single TPG=1 is used for HW port mappings\n"); |
1016 | return ERR_PTR(-ENOSYS); | 1008 | return ERR_PTR(-ENOSYS); |
1017 | } | 1009 | } |
@@ -1038,11 +1030,8 @@ static struct se_portal_group *tcm_qla2xxx_make_tpg( | |||
1038 | kfree(tpg); | 1030 | kfree(tpg); |
1039 | return NULL; | 1031 | return NULL; |
1040 | } | 1032 | } |
1041 | /* | 1033 | |
1042 | * Setup local TPG=1 pointer for non NPIV mode. | 1034 | lport->tpg_1 = tpg; |
1043 | */ | ||
1044 | if (lport->qla_npiv_vp == NULL) | ||
1045 | lport->tpg_1 = tpg; | ||
1046 | 1035 | ||
1047 | return &tpg->se_tpg; | 1036 | return &tpg->se_tpg; |
1048 | } | 1037 | } |
@@ -1053,19 +1042,17 @@ static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg) | |||
1053 | struct tcm_qla2xxx_tpg, se_tpg); | 1042 | struct tcm_qla2xxx_tpg, se_tpg); |
1054 | struct tcm_qla2xxx_lport *lport = tpg->lport; | 1043 | struct tcm_qla2xxx_lport *lport = tpg->lport; |
1055 | struct scsi_qla_host *vha = lport->qla_vha; | 1044 | struct scsi_qla_host *vha = lport->qla_vha; |
1056 | struct qla_hw_data *ha = vha->hw; | ||
1057 | /* | 1045 | /* |
1058 | * Call into qla2x_target.c LLD logic to shutdown the active | 1046 | * Call into qla2x_target.c LLD logic to shutdown the active |
1059 | * FC Nexuses and disable target mode operation for this qla_hw_data | 1047 | * FC Nexuses and disable target mode operation for this qla_hw_data |
1060 | */ | 1048 | */ |
1061 | if (ha->tgt.qla_tgt && !ha->tgt.qla_tgt->tgt_stop) | 1049 | if (vha->vha_tgt.qla_tgt && !vha->vha_tgt.qla_tgt->tgt_stop) |
1062 | qlt_stop_phase1(ha->tgt.qla_tgt); | 1050 | qlt_stop_phase1(vha->vha_tgt.qla_tgt); |
1063 | 1051 | ||
1064 | core_tpg_deregister(se_tpg); | 1052 | core_tpg_deregister(se_tpg); |
1065 | /* | 1053 | /* |
1066 | * Clear local TPG=1 pointer for non NPIV mode. | 1054 | * Clear local TPG=1 pointer for non NPIV mode. |
1067 | */ | 1055 | */ |
1068 | if (lport->qla_npiv_vp == NULL) | ||
1069 | lport->tpg_1 = NULL; | 1056 | lport->tpg_1 = NULL; |
1070 | 1057 | ||
1071 | kfree(tpg); | 1058 | kfree(tpg); |
@@ -1095,12 +1082,22 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg( | |||
1095 | tpg->lport = lport; | 1082 | tpg->lport = lport; |
1096 | tpg->lport_tpgt = tpgt; | 1083 | tpg->lport_tpgt = tpgt; |
1097 | 1084 | ||
1085 | /* | ||
1086 | * By default allow READ-ONLY TPG demo-mode access w/ cached dynamic | ||
1087 | * NodeACLs | ||
1088 | */ | ||
1089 | tpg->tpg_attrib.generate_node_acls = 1; | ||
1090 | tpg->tpg_attrib.demo_mode_write_protect = 1; | ||
1091 | tpg->tpg_attrib.cache_dynamic_acls = 1; | ||
1092 | tpg->tpg_attrib.demo_mode_login_only = 1; | ||
1093 | |||
1098 | ret = core_tpg_register(&tcm_qla2xxx_npiv_fabric_configfs->tf_ops, wwn, | 1094 | ret = core_tpg_register(&tcm_qla2xxx_npiv_fabric_configfs->tf_ops, wwn, |
1099 | &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); | 1095 | &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); |
1100 | if (ret < 0) { | 1096 | if (ret < 0) { |
1101 | kfree(tpg); | 1097 | kfree(tpg); |
1102 | return NULL; | 1098 | return NULL; |
1103 | } | 1099 | } |
1100 | lport->tpg_1 = tpg; | ||
1104 | return &tpg->se_tpg; | 1101 | return &tpg->se_tpg; |
1105 | } | 1102 | } |
1106 | 1103 | ||
@@ -1111,13 +1108,12 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id( | |||
1111 | scsi_qla_host_t *vha, | 1108 | scsi_qla_host_t *vha, |
1112 | const uint8_t *s_id) | 1109 | const uint8_t *s_id) |
1113 | { | 1110 | { |
1114 | struct qla_hw_data *ha = vha->hw; | ||
1115 | struct tcm_qla2xxx_lport *lport; | 1111 | struct tcm_qla2xxx_lport *lport; |
1116 | struct se_node_acl *se_nacl; | 1112 | struct se_node_acl *se_nacl; |
1117 | struct tcm_qla2xxx_nacl *nacl; | 1113 | struct tcm_qla2xxx_nacl *nacl; |
1118 | u32 key; | 1114 | u32 key; |
1119 | 1115 | ||
1120 | lport = ha->tgt.target_lport_ptr; | 1116 | lport = vha->vha_tgt.target_lport_ptr; |
1121 | if (!lport) { | 1117 | if (!lport) { |
1122 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | 1118 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); |
1123 | dump_stack(); | 1119 | dump_stack(); |
@@ -1221,13 +1217,12 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id( | |||
1221 | scsi_qla_host_t *vha, | 1217 | scsi_qla_host_t *vha, |
1222 | const uint16_t loop_id) | 1218 | const uint16_t loop_id) |
1223 | { | 1219 | { |
1224 | struct qla_hw_data *ha = vha->hw; | ||
1225 | struct tcm_qla2xxx_lport *lport; | 1220 | struct tcm_qla2xxx_lport *lport; |
1226 | struct se_node_acl *se_nacl; | 1221 | struct se_node_acl *se_nacl; |
1227 | struct tcm_qla2xxx_nacl *nacl; | 1222 | struct tcm_qla2xxx_nacl *nacl; |
1228 | struct tcm_qla2xxx_fc_loopid *fc_loopid; | 1223 | struct tcm_qla2xxx_fc_loopid *fc_loopid; |
1229 | 1224 | ||
1230 | lport = ha->tgt.target_lport_ptr; | 1225 | lport = vha->vha_tgt.target_lport_ptr; |
1231 | if (!lport) { | 1226 | if (!lport) { |
1232 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | 1227 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); |
1233 | dump_stack(); | 1228 | dump_stack(); |
@@ -1341,6 +1336,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) | |||
1341 | { | 1336 | { |
1342 | struct qla_tgt *tgt = sess->tgt; | 1337 | struct qla_tgt *tgt = sess->tgt; |
1343 | struct qla_hw_data *ha = tgt->ha; | 1338 | struct qla_hw_data *ha = tgt->ha; |
1339 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); | ||
1344 | struct se_session *se_sess; | 1340 | struct se_session *se_sess; |
1345 | struct se_node_acl *se_nacl; | 1341 | struct se_node_acl *se_nacl; |
1346 | struct tcm_qla2xxx_lport *lport; | 1342 | struct tcm_qla2xxx_lport *lport; |
@@ -1357,7 +1353,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) | |||
1357 | se_nacl = se_sess->se_node_acl; | 1353 | se_nacl = se_sess->se_node_acl; |
1358 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); | 1354 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); |
1359 | 1355 | ||
1360 | lport = ha->tgt.target_lport_ptr; | 1356 | lport = vha->vha_tgt.target_lport_ptr; |
1361 | if (!lport) { | 1357 | if (!lport) { |
1362 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | 1358 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); |
1363 | dump_stack(); | 1359 | dump_stack(); |
@@ -1391,7 +1387,7 @@ static int tcm_qla2xxx_check_initiator_node_acl( | |||
1391 | unsigned char port_name[36]; | 1387 | unsigned char port_name[36]; |
1392 | unsigned long flags; | 1388 | unsigned long flags; |
1393 | 1389 | ||
1394 | lport = ha->tgt.target_lport_ptr; | 1390 | lport = vha->vha_tgt.target_lport_ptr; |
1395 | if (!lport) { | 1391 | if (!lport) { |
1396 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | 1392 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); |
1397 | dump_stack(); | 1393 | dump_stack(); |
@@ -1455,7 +1451,8 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, | |||
1455 | { | 1451 | { |
1456 | struct qla_tgt *tgt = sess->tgt; | 1452 | struct qla_tgt *tgt = sess->tgt; |
1457 | struct qla_hw_data *ha = tgt->ha; | 1453 | struct qla_hw_data *ha = tgt->ha; |
1458 | struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr; | 1454 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); |
1455 | struct tcm_qla2xxx_lport *lport = vha->vha_tgt.target_lport_ptr; | ||
1459 | struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; | 1456 | struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; |
1460 | struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, | 1457 | struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, |
1461 | struct tcm_qla2xxx_nacl, se_node_acl); | 1458 | struct tcm_qla2xxx_nacl, se_node_acl); |
@@ -1562,15 +1559,18 @@ static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) | |||
1562 | return 0; | 1559 | return 0; |
1563 | } | 1560 | } |
1564 | 1561 | ||
1565 | static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha) | 1562 | static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha, |
1563 | void *target_lport_ptr, | ||
1564 | u64 npiv_wwpn, u64 npiv_wwnn) | ||
1566 | { | 1565 | { |
1567 | struct qla_hw_data *ha = vha->hw; | 1566 | struct qla_hw_data *ha = vha->hw; |
1568 | struct tcm_qla2xxx_lport *lport; | 1567 | struct tcm_qla2xxx_lport *lport = |
1568 | (struct tcm_qla2xxx_lport *)target_lport_ptr; | ||
1569 | /* | 1569 | /* |
1570 | * Setup local pointer to vha, NPIV VP pointer (if present) and | 1570 | * Setup tgt_ops, local pointer to vha and target_lport_ptr |
1571 | * vha->tcm_lport pointer | ||
1572 | */ | 1571 | */ |
1573 | lport = (struct tcm_qla2xxx_lport *)ha->tgt.target_lport_ptr; | 1572 | ha->tgt.tgt_ops = &tcm_qla2xxx_template; |
1573 | vha->vha_tgt.target_lport_ptr = target_lport_ptr; | ||
1574 | lport->qla_vha = vha; | 1574 | lport->qla_vha = vha; |
1575 | 1575 | ||
1576 | return 0; | 1576 | return 0; |
@@ -1602,8 +1602,8 @@ static struct se_wwn *tcm_qla2xxx_make_lport( | |||
1602 | if (ret != 0) | 1602 | if (ret != 0) |
1603 | goto out; | 1603 | goto out; |
1604 | 1604 | ||
1605 | ret = qlt_lport_register(&tcm_qla2xxx_template, wwpn, | 1605 | ret = qlt_lport_register(lport, wwpn, 0, 0, |
1606 | tcm_qla2xxx_lport_register_cb, lport); | 1606 | tcm_qla2xxx_lport_register_cb); |
1607 | if (ret != 0) | 1607 | if (ret != 0) |
1608 | goto out_lport; | 1608 | goto out_lport; |
1609 | 1609 | ||
@@ -1621,7 +1621,6 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) | |||
1621 | struct tcm_qla2xxx_lport *lport = container_of(wwn, | 1621 | struct tcm_qla2xxx_lport *lport = container_of(wwn, |
1622 | struct tcm_qla2xxx_lport, lport_wwn); | 1622 | struct tcm_qla2xxx_lport, lport_wwn); |
1623 | struct scsi_qla_host *vha = lport->qla_vha; | 1623 | struct scsi_qla_host *vha = lport->qla_vha; |
1624 | struct qla_hw_data *ha = vha->hw; | ||
1625 | struct se_node_acl *node; | 1624 | struct se_node_acl *node; |
1626 | u32 key = 0; | 1625 | u32 key = 0; |
1627 | 1626 | ||
@@ -1630,8 +1629,8 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) | |||
1630 | * shutdown of struct qla_tgt after the call to | 1629 | * shutdown of struct qla_tgt after the call to |
1631 | * qlt_stop_phase1() from tcm_qla2xxx_drop_tpg() above.. | 1630 | * qlt_stop_phase1() from tcm_qla2xxx_drop_tpg() above.. |
1632 | */ | 1631 | */ |
1633 | if (ha->tgt.qla_tgt && !ha->tgt.qla_tgt->tgt_stopped) | 1632 | if (vha->vha_tgt.qla_tgt && !vha->vha_tgt.qla_tgt->tgt_stopped) |
1634 | qlt_stop_phase2(ha->tgt.qla_tgt); | 1633 | qlt_stop_phase2(vha->vha_tgt.qla_tgt); |
1635 | 1634 | ||
1636 | qlt_lport_deregister(vha); | 1635 | qlt_lport_deregister(vha); |
1637 | 1636 | ||
@@ -1642,17 +1641,70 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) | |||
1642 | kfree(lport); | 1641 | kfree(lport); |
1643 | } | 1642 | } |
1644 | 1643 | ||
1644 | static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, | ||
1645 | void *target_lport_ptr, | ||
1646 | u64 npiv_wwpn, u64 npiv_wwnn) | ||
1647 | { | ||
1648 | struct fc_vport *vport; | ||
1649 | struct Scsi_Host *sh = base_vha->host; | ||
1650 | struct scsi_qla_host *npiv_vha; | ||
1651 | struct tcm_qla2xxx_lport *lport = | ||
1652 | (struct tcm_qla2xxx_lport *)target_lport_ptr; | ||
1653 | struct fc_vport_identifiers vport_id; | ||
1654 | |||
1655 | if (!qla_tgt_mode_enabled(base_vha)) { | ||
1656 | pr_err("qla2xxx base_vha not enabled for target mode\n"); | ||
1657 | return -EPERM; | ||
1658 | } | ||
1659 | |||
1660 | memset(&vport_id, 0, sizeof(vport_id)); | ||
1661 | vport_id.port_name = npiv_wwpn; | ||
1662 | vport_id.node_name = npiv_wwnn; | ||
1663 | vport_id.roles = FC_PORT_ROLE_FCP_INITIATOR; | ||
1664 | vport_id.vport_type = FC_PORTTYPE_NPIV; | ||
1665 | vport_id.disable = false; | ||
1666 | |||
1667 | vport = fc_vport_create(sh, 0, &vport_id); | ||
1668 | if (!vport) { | ||
1669 | pr_err("fc_vport_create failed for qla2xxx_npiv\n"); | ||
1670 | return -ENODEV; | ||
1671 | } | ||
1672 | /* | ||
1673 | * Setup local pointer to NPIV vhba + target_lport_ptr | ||
1674 | */ | ||
1675 | npiv_vha = (struct scsi_qla_host *)vport->dd_data; | ||
1676 | npiv_vha->vha_tgt.target_lport_ptr = target_lport_ptr; | ||
1677 | lport->qla_vha = npiv_vha; | ||
1678 | |||
1679 | scsi_host_get(npiv_vha->host); | ||
1680 | return 0; | ||
1681 | } | ||
1682 | |||
1683 | |||
1645 | static struct se_wwn *tcm_qla2xxx_npiv_make_lport( | 1684 | static struct se_wwn *tcm_qla2xxx_npiv_make_lport( |
1646 | struct target_fabric_configfs *tf, | 1685 | struct target_fabric_configfs *tf, |
1647 | struct config_group *group, | 1686 | struct config_group *group, |
1648 | const char *name) | 1687 | const char *name) |
1649 | { | 1688 | { |
1650 | struct tcm_qla2xxx_lport *lport; | 1689 | struct tcm_qla2xxx_lport *lport; |
1651 | u64 npiv_wwpn, npiv_wwnn; | 1690 | u64 phys_wwpn, npiv_wwpn, npiv_wwnn; |
1691 | char *p, tmp[128]; | ||
1652 | int ret; | 1692 | int ret; |
1653 | 1693 | ||
1654 | if (tcm_qla2xxx_npiv_parse_wwn(name, strlen(name)+1, | 1694 | snprintf(tmp, 128, "%s", name); |
1655 | &npiv_wwpn, &npiv_wwnn) < 0) | 1695 | |
1696 | p = strchr(tmp, '@'); | ||
1697 | if (!p) { | ||
1698 | pr_err("Unable to locate NPIV '@' seperator\n"); | ||
1699 | return ERR_PTR(-EINVAL); | ||
1700 | } | ||
1701 | *p++ = '\0'; | ||
1702 | |||
1703 | if (tcm_qla2xxx_parse_wwn(tmp, &phys_wwpn, 1) < 0) | ||
1704 | return ERR_PTR(-EINVAL); | ||
1705 | |||
1706 | if (tcm_qla2xxx_npiv_parse_wwn(p, strlen(p)+1, | ||
1707 | &npiv_wwpn, &npiv_wwnn) < 0) | ||
1656 | return ERR_PTR(-EINVAL); | 1708 | return ERR_PTR(-EINVAL); |
1657 | 1709 | ||
1658 | lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL); | 1710 | lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL); |
@@ -1666,12 +1718,19 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport( | |||
1666 | TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); | 1718 | TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); |
1667 | sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn); | 1719 | sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn); |
1668 | 1720 | ||
1669 | /* FIXME: tcm_qla2xxx_npiv_make_lport */ | 1721 | ret = tcm_qla2xxx_init_lport(lport); |
1670 | ret = -ENOSYS; | ||
1671 | if (ret != 0) | 1722 | if (ret != 0) |
1672 | goto out; | 1723 | goto out; |
1673 | 1724 | ||
1725 | ret = qlt_lport_register(lport, phys_wwpn, npiv_wwpn, npiv_wwnn, | ||
1726 | tcm_qla2xxx_lport_register_npiv_cb); | ||
1727 | if (ret != 0) | ||
1728 | goto out_lport; | ||
1729 | |||
1674 | return &lport->lport_wwn; | 1730 | return &lport->lport_wwn; |
1731 | out_lport: | ||
1732 | vfree(lport->lport_loopid_map); | ||
1733 | btree_destroy32(&lport->lport_fcport_map); | ||
1675 | out: | 1734 | out: |
1676 | kfree(lport); | 1735 | kfree(lport); |
1677 | return ERR_PTR(ret); | 1736 | return ERR_PTR(ret); |
@@ -1681,14 +1740,16 @@ static void tcm_qla2xxx_npiv_drop_lport(struct se_wwn *wwn) | |||
1681 | { | 1740 | { |
1682 | struct tcm_qla2xxx_lport *lport = container_of(wwn, | 1741 | struct tcm_qla2xxx_lport *lport = container_of(wwn, |
1683 | struct tcm_qla2xxx_lport, lport_wwn); | 1742 | struct tcm_qla2xxx_lport, lport_wwn); |
1684 | struct scsi_qla_host *vha = lport->qla_vha; | 1743 | struct scsi_qla_host *npiv_vha = lport->qla_vha; |
1685 | struct Scsi_Host *sh = vha->host; | 1744 | struct qla_hw_data *ha = npiv_vha->hw; |
1745 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | ||
1746 | |||
1747 | scsi_host_put(npiv_vha->host); | ||
1686 | /* | 1748 | /* |
1687 | * Notify libfc that we want to release the lport->npiv_vport | 1749 | * Notify libfc that we want to release the vha->fc_vport |
1688 | */ | 1750 | */ |
1689 | fc_vport_terminate(lport->npiv_vport); | 1751 | fc_vport_terminate(npiv_vha->fc_vport); |
1690 | 1752 | scsi_host_put(base_vha->host); | |
1691 | scsi_host_put(sh); | ||
1692 | kfree(lport); | 1753 | kfree(lport); |
1693 | } | 1754 | } |
1694 | 1755 | ||
@@ -1769,14 +1830,16 @@ static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { | |||
1769 | .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, | 1830 | .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, |
1770 | .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, | 1831 | .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, |
1771 | .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, | 1832 | .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, |
1772 | .tpg_check_demo_mode = tcm_qla2xxx_check_false, | 1833 | .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, |
1773 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_true, | 1834 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, |
1774 | .tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_true, | 1835 | .tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_demo_mode, |
1775 | .tpg_check_prod_mode_write_protect = tcm_qla2xxx_check_false, | 1836 | .tpg_check_prod_mode_write_protect = |
1837 | tcm_qla2xxx_check_prod_write_protect, | ||
1776 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, | 1838 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, |
1777 | .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, | 1839 | .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, |
1778 | .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, | 1840 | .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, |
1779 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, | 1841 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, |
1842 | .check_stop_free = tcm_qla2xxx_check_stop_free, | ||
1780 | .release_cmd = tcm_qla2xxx_release_cmd, | 1843 | .release_cmd = tcm_qla2xxx_release_cmd, |
1781 | .put_session = tcm_qla2xxx_put_session, | 1844 | .put_session = tcm_qla2xxx_put_session, |
1782 | .shutdown_session = tcm_qla2xxx_shutdown_session, | 1845 | .shutdown_session = tcm_qla2xxx_shutdown_session, |
@@ -1871,7 +1934,8 @@ static int tcm_qla2xxx_register_configfs(void) | |||
1871 | * Setup default attribute lists for various npiv_fabric->tf_cit_tmpl | 1934 | * Setup default attribute lists for various npiv_fabric->tf_cit_tmpl |
1872 | */ | 1935 | */ |
1873 | npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs; | 1936 | npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs; |
1874 | npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = NULL; | 1937 | npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = |
1938 | tcm_qla2xxx_tpg_attrs; | ||
1875 | npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL; | 1939 | npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL; |
1876 | npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL; | 1940 | npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL; |
1877 | npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL; | 1941 | npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL; |
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h index 771f7b816443..275d8b9a7a34 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h | |||
@@ -70,12 +70,8 @@ struct tcm_qla2xxx_lport { | |||
70 | struct tcm_qla2xxx_fc_loopid *lport_loopid_map; | 70 | struct tcm_qla2xxx_fc_loopid *lport_loopid_map; |
71 | /* Pointer to struct scsi_qla_host from qla2xxx LLD */ | 71 | /* Pointer to struct scsi_qla_host from qla2xxx LLD */ |
72 | struct scsi_qla_host *qla_vha; | 72 | struct scsi_qla_host *qla_vha; |
73 | /* Pointer to struct scsi_qla_host for NPIV VP from qla2xxx LLD */ | ||
74 | struct scsi_qla_host *qla_npiv_vp; | ||
75 | /* Pointer to struct qla_tgt pointer */ | 73 | /* Pointer to struct qla_tgt pointer */ |
76 | struct qla_tgt lport_qla_tgt; | 74 | struct qla_tgt lport_qla_tgt; |
77 | /* Pointer to struct fc_vport for NPIV vport from libfc */ | ||
78 | struct fc_vport *npiv_vport; | ||
79 | /* Pointer to TPG=1 for non NPIV mode */ | 75 | /* Pointer to TPG=1 for non NPIV mode */ |
80 | struct tcm_qla2xxx_tpg *tpg_1; | 76 | struct tcm_qla2xxx_tpg *tpg_1; |
81 | /* Returned by tcm_qla2xxx_make_lport() */ | 77 | /* Returned by tcm_qla2xxx_make_lport() */ |
diff --git a/drivers/target/Kconfig b/drivers/target/Kconfig index 18303686eb58..dc2d84ac5a0e 100644 --- a/drivers/target/Kconfig +++ b/drivers/target/Kconfig | |||
@@ -3,6 +3,7 @@ menuconfig TARGET_CORE | |||
3 | tristate "Generic Target Core Mod (TCM) and ConfigFS Infrastructure" | 3 | tristate "Generic Target Core Mod (TCM) and ConfigFS Infrastructure" |
4 | depends on SCSI && BLOCK | 4 | depends on SCSI && BLOCK |
5 | select CONFIGFS_FS | 5 | select CONFIGFS_FS |
6 | select CRC_T10DIF | ||
6 | default n | 7 | default n |
7 | help | 8 | help |
8 | Say Y or M here to enable the TCM Storage Engine and ConfigFS enabled | 9 | Say Y or M here to enable the TCM Storage Engine and ConfigFS enabled |
@@ -13,6 +14,7 @@ if TARGET_CORE | |||
13 | 14 | ||
14 | config TCM_IBLOCK | 15 | config TCM_IBLOCK |
15 | tristate "TCM/IBLOCK Subsystem Plugin for Linux/BLOCK" | 16 | tristate "TCM/IBLOCK Subsystem Plugin for Linux/BLOCK" |
17 | select BLK_DEV_INTEGRITY | ||
16 | help | 18 | help |
17 | Say Y here to enable the TCM/IBLOCK subsystem plugin for non-buffered | 19 | Say Y here to enable the TCM/IBLOCK subsystem plugin for non-buffered |
18 | access to Linux/Block devices using BIO | 20 | access to Linux/Block devices using BIO |
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 00867190413c..7f1a7ce4b771 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -52,7 +52,7 @@ | |||
52 | static LIST_HEAD(g_tiqn_list); | 52 | static LIST_HEAD(g_tiqn_list); |
53 | static LIST_HEAD(g_np_list); | 53 | static LIST_HEAD(g_np_list); |
54 | static DEFINE_SPINLOCK(tiqn_lock); | 54 | static DEFINE_SPINLOCK(tiqn_lock); |
55 | static DEFINE_SPINLOCK(np_lock); | 55 | static DEFINE_MUTEX(np_lock); |
56 | 56 | ||
57 | static struct idr tiqn_idr; | 57 | static struct idr tiqn_idr; |
58 | struct idr sess_idr; | 58 | struct idr sess_idr; |
@@ -307,6 +307,9 @@ bool iscsit_check_np_match( | |||
307 | return false; | 307 | return false; |
308 | } | 308 | } |
309 | 309 | ||
310 | /* | ||
311 | * Called with mutex np_lock held | ||
312 | */ | ||
310 | static struct iscsi_np *iscsit_get_np( | 313 | static struct iscsi_np *iscsit_get_np( |
311 | struct __kernel_sockaddr_storage *sockaddr, | 314 | struct __kernel_sockaddr_storage *sockaddr, |
312 | int network_transport) | 315 | int network_transport) |
@@ -314,11 +317,10 @@ static struct iscsi_np *iscsit_get_np( | |||
314 | struct iscsi_np *np; | 317 | struct iscsi_np *np; |
315 | bool match; | 318 | bool match; |
316 | 319 | ||
317 | spin_lock_bh(&np_lock); | ||
318 | list_for_each_entry(np, &g_np_list, np_list) { | 320 | list_for_each_entry(np, &g_np_list, np_list) { |
319 | spin_lock(&np->np_thread_lock); | 321 | spin_lock_bh(&np->np_thread_lock); |
320 | if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) { | 322 | if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) { |
321 | spin_unlock(&np->np_thread_lock); | 323 | spin_unlock_bh(&np->np_thread_lock); |
322 | continue; | 324 | continue; |
323 | } | 325 | } |
324 | 326 | ||
@@ -330,13 +332,11 @@ static struct iscsi_np *iscsit_get_np( | |||
330 | * while iscsi_tpg_add_network_portal() is called. | 332 | * while iscsi_tpg_add_network_portal() is called. |
331 | */ | 333 | */ |
332 | np->np_exports++; | 334 | np->np_exports++; |
333 | spin_unlock(&np->np_thread_lock); | 335 | spin_unlock_bh(&np->np_thread_lock); |
334 | spin_unlock_bh(&np_lock); | ||
335 | return np; | 336 | return np; |
336 | } | 337 | } |
337 | spin_unlock(&np->np_thread_lock); | 338 | spin_unlock_bh(&np->np_thread_lock); |
338 | } | 339 | } |
339 | spin_unlock_bh(&np_lock); | ||
340 | 340 | ||
341 | return NULL; | 341 | return NULL; |
342 | } | 342 | } |
@@ -350,16 +350,22 @@ struct iscsi_np *iscsit_add_np( | |||
350 | struct sockaddr_in6 *sock_in6; | 350 | struct sockaddr_in6 *sock_in6; |
351 | struct iscsi_np *np; | 351 | struct iscsi_np *np; |
352 | int ret; | 352 | int ret; |
353 | |||
354 | mutex_lock(&np_lock); | ||
355 | |||
353 | /* | 356 | /* |
354 | * Locate the existing struct iscsi_np if already active.. | 357 | * Locate the existing struct iscsi_np if already active.. |
355 | */ | 358 | */ |
356 | np = iscsit_get_np(sockaddr, network_transport); | 359 | np = iscsit_get_np(sockaddr, network_transport); |
357 | if (np) | 360 | if (np) { |
361 | mutex_unlock(&np_lock); | ||
358 | return np; | 362 | return np; |
363 | } | ||
359 | 364 | ||
360 | np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL); | 365 | np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL); |
361 | if (!np) { | 366 | if (!np) { |
362 | pr_err("Unable to allocate memory for struct iscsi_np\n"); | 367 | pr_err("Unable to allocate memory for struct iscsi_np\n"); |
368 | mutex_unlock(&np_lock); | ||
363 | return ERR_PTR(-ENOMEM); | 369 | return ERR_PTR(-ENOMEM); |
364 | } | 370 | } |
365 | 371 | ||
@@ -382,6 +388,7 @@ struct iscsi_np *iscsit_add_np( | |||
382 | ret = iscsi_target_setup_login_socket(np, sockaddr); | 388 | ret = iscsi_target_setup_login_socket(np, sockaddr); |
383 | if (ret != 0) { | 389 | if (ret != 0) { |
384 | kfree(np); | 390 | kfree(np); |
391 | mutex_unlock(&np_lock); | ||
385 | return ERR_PTR(ret); | 392 | return ERR_PTR(ret); |
386 | } | 393 | } |
387 | 394 | ||
@@ -390,6 +397,7 @@ struct iscsi_np *iscsit_add_np( | |||
390 | pr_err("Unable to create kthread: iscsi_np\n"); | 397 | pr_err("Unable to create kthread: iscsi_np\n"); |
391 | ret = PTR_ERR(np->np_thread); | 398 | ret = PTR_ERR(np->np_thread); |
392 | kfree(np); | 399 | kfree(np); |
400 | mutex_unlock(&np_lock); | ||
393 | return ERR_PTR(ret); | 401 | return ERR_PTR(ret); |
394 | } | 402 | } |
395 | /* | 403 | /* |
@@ -400,10 +408,10 @@ struct iscsi_np *iscsit_add_np( | |||
400 | * point because iscsi_np has not been added to g_np_list yet. | 408 | * point because iscsi_np has not been added to g_np_list yet. |
401 | */ | 409 | */ |
402 | np->np_exports = 1; | 410 | np->np_exports = 1; |
411 | np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; | ||
403 | 412 | ||
404 | spin_lock_bh(&np_lock); | ||
405 | list_add_tail(&np->np_list, &g_np_list); | 413 | list_add_tail(&np->np_list, &g_np_list); |
406 | spin_unlock_bh(&np_lock); | 414 | mutex_unlock(&np_lock); |
407 | 415 | ||
408 | pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n", | 416 | pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n", |
409 | np->np_ip, np->np_port, np->np_transport->name); | 417 | np->np_ip, np->np_port, np->np_transport->name); |
@@ -470,9 +478,9 @@ int iscsit_del_np(struct iscsi_np *np) | |||
470 | 478 | ||
471 | np->np_transport->iscsit_free_np(np); | 479 | np->np_transport->iscsit_free_np(np); |
472 | 480 | ||
473 | spin_lock_bh(&np_lock); | 481 | mutex_lock(&np_lock); |
474 | list_del(&np->np_list); | 482 | list_del(&np->np_list); |
475 | spin_unlock_bh(&np_lock); | 483 | mutex_unlock(&np_lock); |
476 | 484 | ||
477 | pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n", | 485 | pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n", |
478 | np->np_ip, np->np_port, np->np_transport->name); | 486 | np->np_ip, np->np_port, np->np_transport->name); |
@@ -622,7 +630,7 @@ static int iscsit_add_reject( | |||
622 | { | 630 | { |
623 | struct iscsi_cmd *cmd; | 631 | struct iscsi_cmd *cmd; |
624 | 632 | ||
625 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 633 | cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); |
626 | if (!cmd) | 634 | if (!cmd) |
627 | return -1; | 635 | return -1; |
628 | 636 | ||
@@ -2475,7 +2483,7 @@ static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn) | |||
2475 | if (!conn_p) | 2483 | if (!conn_p) |
2476 | return; | 2484 | return; |
2477 | 2485 | ||
2478 | cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC); | 2486 | cmd = iscsit_allocate_cmd(conn_p, TASK_RUNNING); |
2479 | if (!cmd) { | 2487 | if (!cmd) { |
2480 | iscsit_dec_conn_usage_count(conn_p); | 2488 | iscsit_dec_conn_usage_count(conn_p); |
2481 | return; | 2489 | return; |
@@ -3951,7 +3959,7 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) | |||
3951 | 3959 | ||
3952 | switch (hdr->opcode & ISCSI_OPCODE_MASK) { | 3960 | switch (hdr->opcode & ISCSI_OPCODE_MASK) { |
3953 | case ISCSI_OP_SCSI_CMD: | 3961 | case ISCSI_OP_SCSI_CMD: |
3954 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3962 | cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); |
3955 | if (!cmd) | 3963 | if (!cmd) |
3956 | goto reject; | 3964 | goto reject; |
3957 | 3965 | ||
@@ -3963,28 +3971,28 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) | |||
3963 | case ISCSI_OP_NOOP_OUT: | 3971 | case ISCSI_OP_NOOP_OUT: |
3964 | cmd = NULL; | 3972 | cmd = NULL; |
3965 | if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { | 3973 | if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { |
3966 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3974 | cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); |
3967 | if (!cmd) | 3975 | if (!cmd) |
3968 | goto reject; | 3976 | goto reject; |
3969 | } | 3977 | } |
3970 | ret = iscsit_handle_nop_out(conn, cmd, buf); | 3978 | ret = iscsit_handle_nop_out(conn, cmd, buf); |
3971 | break; | 3979 | break; |
3972 | case ISCSI_OP_SCSI_TMFUNC: | 3980 | case ISCSI_OP_SCSI_TMFUNC: |
3973 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3981 | cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); |
3974 | if (!cmd) | 3982 | if (!cmd) |
3975 | goto reject; | 3983 | goto reject; |
3976 | 3984 | ||
3977 | ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); | 3985 | ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); |
3978 | break; | 3986 | break; |
3979 | case ISCSI_OP_TEXT: | 3987 | case ISCSI_OP_TEXT: |
3980 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3988 | cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); |
3981 | if (!cmd) | 3989 | if (!cmd) |
3982 | goto reject; | 3990 | goto reject; |
3983 | 3991 | ||
3984 | ret = iscsit_handle_text_cmd(conn, cmd, buf); | 3992 | ret = iscsit_handle_text_cmd(conn, cmd, buf); |
3985 | break; | 3993 | break; |
3986 | case ISCSI_OP_LOGOUT: | 3994 | case ISCSI_OP_LOGOUT: |
3987 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3995 | cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); |
3988 | if (!cmd) | 3996 | if (!cmd) |
3989 | goto reject; | 3997 | goto reject; |
3990 | 3998 | ||
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 83c965c65386..582ba84075ec 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c | |||
@@ -1192,7 +1192,7 @@ get_target: | |||
1192 | */ | 1192 | */ |
1193 | alloc_tags: | 1193 | alloc_tags: |
1194 | tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth); | 1194 | tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth); |
1195 | tag_num += (tag_num / 2) + ISCSIT_EXTRA_TAGS; | 1195 | tag_num = (tag_num * 2) + ISCSIT_EXTRA_TAGS; |
1196 | tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; | 1196 | tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; |
1197 | 1197 | ||
1198 | ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size); | 1198 | ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size); |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 0819e688a398..e655b042ed18 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -152,13 +152,16 @@ void iscsit_free_r2ts_from_list(struct iscsi_cmd *cmd) | |||
152 | * May be called from software interrupt (timer) context for allocating | 152 | * May be called from software interrupt (timer) context for allocating |
153 | * iSCSI NopINs. | 153 | * iSCSI NopINs. |
154 | */ | 154 | */ |
155 | struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask) | 155 | struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state) |
156 | { | 156 | { |
157 | struct iscsi_cmd *cmd; | 157 | struct iscsi_cmd *cmd; |
158 | struct se_session *se_sess = conn->sess->se_sess; | 158 | struct se_session *se_sess = conn->sess->se_sess; |
159 | int size, tag; | 159 | int size, tag; |
160 | 160 | ||
161 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, gfp_mask); | 161 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, state); |
162 | if (tag < 0) | ||
163 | return NULL; | ||
164 | |||
162 | size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; | 165 | size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; |
163 | cmd = (struct iscsi_cmd *)(se_sess->sess_cmd_map + (tag * size)); | 166 | cmd = (struct iscsi_cmd *)(se_sess->sess_cmd_map + (tag * size)); |
164 | memset(cmd, 0, size); | 167 | memset(cmd, 0, size); |
@@ -926,7 +929,7 @@ static int iscsit_add_nopin(struct iscsi_conn *conn, int want_response) | |||
926 | u8 state; | 929 | u8 state; |
927 | struct iscsi_cmd *cmd; | 930 | struct iscsi_cmd *cmd; |
928 | 931 | ||
929 | cmd = iscsit_allocate_cmd(conn, GFP_ATOMIC); | 932 | cmd = iscsit_allocate_cmd(conn, TASK_RUNNING); |
930 | if (!cmd) | 933 | if (!cmd) |
931 | return -1; | 934 | return -1; |
932 | 935 | ||
diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index e4fc34a02f57..561a424d1980 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h | |||
@@ -9,7 +9,7 @@ extern struct iscsi_r2t *iscsit_get_r2t_from_list(struct iscsi_cmd *); | |||
9 | extern void iscsit_free_r2t(struct iscsi_r2t *, struct iscsi_cmd *); | 9 | extern void iscsit_free_r2t(struct iscsi_r2t *, struct iscsi_cmd *); |
10 | extern void iscsit_free_r2ts_from_list(struct iscsi_cmd *); | 10 | extern void iscsit_free_r2ts_from_list(struct iscsi_cmd *); |
11 | extern struct iscsi_cmd *iscsit_alloc_cmd(struct iscsi_conn *, gfp_t); | 11 | extern struct iscsi_cmd *iscsit_alloc_cmd(struct iscsi_conn *, gfp_t); |
12 | extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t); | 12 | extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, int); |
13 | extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32); | 13 | extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32); |
14 | extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *); | 14 | extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *); |
15 | extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32); | 15 | extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32); |
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 1b41e6776152..fadad7c5f635 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c | |||
@@ -217,7 +217,8 @@ static void tcm_loop_submission_work(struct work_struct *work) | |||
217 | scsi_bufflen(sc), tcm_loop_sam_attr(sc), | 217 | scsi_bufflen(sc), tcm_loop_sam_attr(sc), |
218 | sc->sc_data_direction, 0, | 218 | sc->sc_data_direction, 0, |
219 | scsi_sglist(sc), scsi_sg_count(sc), | 219 | scsi_sglist(sc), scsi_sg_count(sc), |
220 | sgl_bidi, sgl_bidi_count); | 220 | sgl_bidi, sgl_bidi_count, |
221 | scsi_prot_sglist(sc), scsi_prot_sg_count(sc)); | ||
221 | if (rc < 0) { | 222 | if (rc < 0) { |
222 | set_host_byte(sc, DID_NO_CONNECT); | 223 | set_host_byte(sc, DID_NO_CONNECT); |
223 | goto out_done; | 224 | goto out_done; |
@@ -462,7 +463,7 @@ static int tcm_loop_driver_probe(struct device *dev) | |||
462 | { | 463 | { |
463 | struct tcm_loop_hba *tl_hba; | 464 | struct tcm_loop_hba *tl_hba; |
464 | struct Scsi_Host *sh; | 465 | struct Scsi_Host *sh; |
465 | int error; | 466 | int error, host_prot; |
466 | 467 | ||
467 | tl_hba = to_tcm_loop_hba(dev); | 468 | tl_hba = to_tcm_loop_hba(dev); |
468 | 469 | ||
@@ -486,6 +487,13 @@ static int tcm_loop_driver_probe(struct device *dev) | |||
486 | sh->max_channel = 0; | 487 | sh->max_channel = 0; |
487 | sh->max_cmd_len = TL_SCSI_MAX_CMD_LEN; | 488 | sh->max_cmd_len = TL_SCSI_MAX_CMD_LEN; |
488 | 489 | ||
490 | host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | | ||
491 | SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | | ||
492 | SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION; | ||
493 | |||
494 | scsi_host_set_prot(sh, host_prot); | ||
495 | scsi_host_set_guard(sh, SHOST_DIX_GUARD_CRC); | ||
496 | |||
489 | error = scsi_add_host(sh, &tl_hba->dev); | 497 | error = scsi_add_host(sh, &tl_hba->dev); |
490 | if (error) { | 498 | if (error) { |
491 | pr_err("%s: scsi_add_host failed\n", __func__); | 499 | pr_err("%s: scsi_add_host failed\n", __func__); |
@@ -1228,7 +1236,7 @@ static struct configfs_attribute *tcm_loop_tpg_attrs[] = { | |||
1228 | 1236 | ||
1229 | /* Start items for tcm_loop_naa_cit */ | 1237 | /* Start items for tcm_loop_naa_cit */ |
1230 | 1238 | ||
1231 | struct se_portal_group *tcm_loop_make_naa_tpg( | 1239 | static struct se_portal_group *tcm_loop_make_naa_tpg( |
1232 | struct se_wwn *wwn, | 1240 | struct se_wwn *wwn, |
1233 | struct config_group *group, | 1241 | struct config_group *group, |
1234 | const char *name) | 1242 | const char *name) |
@@ -1273,7 +1281,7 @@ struct se_portal_group *tcm_loop_make_naa_tpg( | |||
1273 | return &tl_tpg->tl_se_tpg; | 1281 | return &tl_tpg->tl_se_tpg; |
1274 | } | 1282 | } |
1275 | 1283 | ||
1276 | void tcm_loop_drop_naa_tpg( | 1284 | static void tcm_loop_drop_naa_tpg( |
1277 | struct se_portal_group *se_tpg) | 1285 | struct se_portal_group *se_tpg) |
1278 | { | 1286 | { |
1279 | struct se_wwn *wwn = se_tpg->se_tpg_wwn; | 1287 | struct se_wwn *wwn = se_tpg->se_tpg_wwn; |
@@ -1305,7 +1313,7 @@ void tcm_loop_drop_naa_tpg( | |||
1305 | 1313 | ||
1306 | /* Start items for tcm_loop_cit */ | 1314 | /* Start items for tcm_loop_cit */ |
1307 | 1315 | ||
1308 | struct se_wwn *tcm_loop_make_scsi_hba( | 1316 | static struct se_wwn *tcm_loop_make_scsi_hba( |
1309 | struct target_fabric_configfs *tf, | 1317 | struct target_fabric_configfs *tf, |
1310 | struct config_group *group, | 1318 | struct config_group *group, |
1311 | const char *name) | 1319 | const char *name) |
@@ -1375,7 +1383,7 @@ out: | |||
1375 | return ERR_PTR(ret); | 1383 | return ERR_PTR(ret); |
1376 | } | 1384 | } |
1377 | 1385 | ||
1378 | void tcm_loop_drop_scsi_hba( | 1386 | static void tcm_loop_drop_scsi_hba( |
1379 | struct se_wwn *wwn) | 1387 | struct se_wwn *wwn) |
1380 | { | 1388 | { |
1381 | struct tcm_loop_hba *tl_hba = container_of(wwn, | 1389 | struct tcm_loop_hba *tl_hba = container_of(wwn, |
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index fdcee326bfbc..12da9b386169 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c | |||
@@ -41,11 +41,14 @@ | |||
41 | #include "target_core_alua.h" | 41 | #include "target_core_alua.h" |
42 | #include "target_core_ua.h" | 42 | #include "target_core_ua.h" |
43 | 43 | ||
44 | static sense_reason_t core_alua_check_transition(int state, int *primary); | 44 | static sense_reason_t core_alua_check_transition(int state, int valid, |
45 | int *primary); | ||
45 | static int core_alua_set_tg_pt_secondary_state( | 46 | static int core_alua_set_tg_pt_secondary_state( |
46 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, | 47 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, |
47 | struct se_port *port, int explicit, int offline); | 48 | struct se_port *port, int explicit, int offline); |
48 | 49 | ||
50 | static char *core_alua_dump_state(int state); | ||
51 | |||
49 | static u16 alua_lu_gps_counter; | 52 | static u16 alua_lu_gps_counter; |
50 | static u32 alua_lu_gps_count; | 53 | static u32 alua_lu_gps_count; |
51 | 54 | ||
@@ -55,6 +58,86 @@ static LIST_HEAD(lu_gps_list); | |||
55 | struct t10_alua_lu_gp *default_lu_gp; | 58 | struct t10_alua_lu_gp *default_lu_gp; |
56 | 59 | ||
57 | /* | 60 | /* |
61 | * REPORT REFERRALS | ||
62 | * | ||
63 | * See sbc3r35 section 5.23 | ||
64 | */ | ||
65 | sense_reason_t | ||
66 | target_emulate_report_referrals(struct se_cmd *cmd) | ||
67 | { | ||
68 | struct se_device *dev = cmd->se_dev; | ||
69 | struct t10_alua_lba_map *map; | ||
70 | struct t10_alua_lba_map_member *map_mem; | ||
71 | unsigned char *buf; | ||
72 | u32 rd_len = 0, off; | ||
73 | |||
74 | if (cmd->data_length < 4) { | ||
75 | pr_warn("REPORT REFERRALS allocation length %u too" | ||
76 | " small\n", cmd->data_length); | ||
77 | return TCM_INVALID_CDB_FIELD; | ||
78 | } | ||
79 | |||
80 | buf = transport_kmap_data_sg(cmd); | ||
81 | if (!buf) | ||
82 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
83 | |||
84 | off = 4; | ||
85 | spin_lock(&dev->t10_alua.lba_map_lock); | ||
86 | if (list_empty(&dev->t10_alua.lba_map_list)) { | ||
87 | spin_unlock(&dev->t10_alua.lba_map_lock); | ||
88 | transport_kunmap_data_sg(cmd); | ||
89 | |||
90 | return TCM_UNSUPPORTED_SCSI_OPCODE; | ||
91 | } | ||
92 | |||
93 | list_for_each_entry(map, &dev->t10_alua.lba_map_list, | ||
94 | lba_map_list) { | ||
95 | int desc_num = off + 3; | ||
96 | int pg_num; | ||
97 | |||
98 | off += 4; | ||
99 | if (cmd->data_length > off) | ||
100 | put_unaligned_be64(map->lba_map_first_lba, &buf[off]); | ||
101 | off += 8; | ||
102 | if (cmd->data_length > off) | ||
103 | put_unaligned_be64(map->lba_map_last_lba, &buf[off]); | ||
104 | off += 8; | ||
105 | rd_len += 20; | ||
106 | pg_num = 0; | ||
107 | list_for_each_entry(map_mem, &map->lba_map_mem_list, | ||
108 | lba_map_mem_list) { | ||
109 | int alua_state = map_mem->lba_map_mem_alua_state; | ||
110 | int alua_pg_id = map_mem->lba_map_mem_alua_pg_id; | ||
111 | |||
112 | if (cmd->data_length > off) | ||
113 | buf[off] = alua_state & 0x0f; | ||
114 | off += 2; | ||
115 | if (cmd->data_length > off) | ||
116 | buf[off] = (alua_pg_id >> 8) & 0xff; | ||
117 | off++; | ||
118 | if (cmd->data_length > off) | ||
119 | buf[off] = (alua_pg_id & 0xff); | ||
120 | off++; | ||
121 | rd_len += 4; | ||
122 | pg_num++; | ||
123 | } | ||
124 | if (cmd->data_length > desc_num) | ||
125 | buf[desc_num] = pg_num; | ||
126 | } | ||
127 | spin_unlock(&dev->t10_alua.lba_map_lock); | ||
128 | |||
129 | /* | ||
130 | * Set the RETURN DATA LENGTH set in the header of the DataIN Payload | ||
131 | */ | ||
132 | put_unaligned_be16(rd_len, &buf[2]); | ||
133 | |||
134 | transport_kunmap_data_sg(cmd); | ||
135 | |||
136 | target_complete_cmd(cmd, GOOD); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | /* | ||
58 | * REPORT_TARGET_PORT_GROUPS | 141 | * REPORT_TARGET_PORT_GROUPS |
59 | * | 142 | * |
60 | * See spc4r17 section 6.27 | 143 | * See spc4r17 section 6.27 |
@@ -210,7 +293,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
210 | unsigned char *ptr; | 293 | unsigned char *ptr; |
211 | sense_reason_t rc = TCM_NO_SENSE; | 294 | sense_reason_t rc = TCM_NO_SENSE; |
212 | u32 len = 4; /* Skip over RESERVED area in header */ | 295 | u32 len = 4; /* Skip over RESERVED area in header */ |
213 | int alua_access_state, primary = 0; | 296 | int alua_access_state, primary = 0, valid_states; |
214 | u16 tg_pt_id, rtpi; | 297 | u16 tg_pt_id, rtpi; |
215 | 298 | ||
216 | if (!l_port) | 299 | if (!l_port) |
@@ -252,6 +335,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
252 | rc = TCM_UNSUPPORTED_SCSI_OPCODE; | 335 | rc = TCM_UNSUPPORTED_SCSI_OPCODE; |
253 | goto out; | 336 | goto out; |
254 | } | 337 | } |
338 | valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states; | ||
255 | 339 | ||
256 | ptr = &buf[4]; /* Skip over RESERVED area in header */ | 340 | ptr = &buf[4]; /* Skip over RESERVED area in header */ |
257 | 341 | ||
@@ -263,7 +347,8 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
263 | * the state is a primary or secondary target port asymmetric | 347 | * the state is a primary or secondary target port asymmetric |
264 | * access state. | 348 | * access state. |
265 | */ | 349 | */ |
266 | rc = core_alua_check_transition(alua_access_state, &primary); | 350 | rc = core_alua_check_transition(alua_access_state, |
351 | valid_states, &primary); | ||
267 | if (rc) { | 352 | if (rc) { |
268 | /* | 353 | /* |
269 | * If the SET TARGET PORT GROUPS attempts to establish | 354 | * If the SET TARGET PORT GROUPS attempts to establish |
@@ -386,6 +471,81 @@ static inline int core_alua_state_nonoptimized( | |||
386 | return 0; | 471 | return 0; |
387 | } | 472 | } |
388 | 473 | ||
474 | static inline int core_alua_state_lba_dependent( | ||
475 | struct se_cmd *cmd, | ||
476 | struct t10_alua_tg_pt_gp *tg_pt_gp, | ||
477 | u8 *alua_ascq) | ||
478 | { | ||
479 | struct se_device *dev = cmd->se_dev; | ||
480 | u64 segment_size, segment_mult, sectors, lba; | ||
481 | |||
482 | /* Only need to check for cdb actually containing LBAs */ | ||
483 | if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB)) | ||
484 | return 0; | ||
485 | |||
486 | spin_lock(&dev->t10_alua.lba_map_lock); | ||
487 | segment_size = dev->t10_alua.lba_map_segment_size; | ||
488 | segment_mult = dev->t10_alua.lba_map_segment_multiplier; | ||
489 | sectors = cmd->data_length / dev->dev_attrib.block_size; | ||
490 | |||
491 | lba = cmd->t_task_lba; | ||
492 | while (lba < cmd->t_task_lba + sectors) { | ||
493 | struct t10_alua_lba_map *cur_map = NULL, *map; | ||
494 | struct t10_alua_lba_map_member *map_mem; | ||
495 | |||
496 | list_for_each_entry(map, &dev->t10_alua.lba_map_list, | ||
497 | lba_map_list) { | ||
498 | u64 start_lba, last_lba; | ||
499 | u64 first_lba = map->lba_map_first_lba; | ||
500 | |||
501 | if (segment_mult) { | ||
502 | u64 tmp = lba; | ||
503 | start_lba = sector_div(tmp, segment_size * segment_mult); | ||
504 | |||
505 | last_lba = first_lba + segment_size - 1; | ||
506 | if (start_lba >= first_lba && | ||
507 | start_lba <= last_lba) { | ||
508 | lba += segment_size; | ||
509 | cur_map = map; | ||
510 | break; | ||
511 | } | ||
512 | } else { | ||
513 | last_lba = map->lba_map_last_lba; | ||
514 | if (lba >= first_lba && lba <= last_lba) { | ||
515 | lba = last_lba + 1; | ||
516 | cur_map = map; | ||
517 | break; | ||
518 | } | ||
519 | } | ||
520 | } | ||
521 | if (!cur_map) { | ||
522 | spin_unlock(&dev->t10_alua.lba_map_lock); | ||
523 | *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; | ||
524 | return 1; | ||
525 | } | ||
526 | list_for_each_entry(map_mem, &cur_map->lba_map_mem_list, | ||
527 | lba_map_mem_list) { | ||
528 | if (map_mem->lba_map_mem_alua_pg_id != | ||
529 | tg_pt_gp->tg_pt_gp_id) | ||
530 | continue; | ||
531 | switch(map_mem->lba_map_mem_alua_state) { | ||
532 | case ALUA_ACCESS_STATE_STANDBY: | ||
533 | spin_unlock(&dev->t10_alua.lba_map_lock); | ||
534 | *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; | ||
535 | return 1; | ||
536 | case ALUA_ACCESS_STATE_UNAVAILABLE: | ||
537 | spin_unlock(&dev->t10_alua.lba_map_lock); | ||
538 | *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; | ||
539 | return 1; | ||
540 | default: | ||
541 | break; | ||
542 | } | ||
543 | } | ||
544 | } | ||
545 | spin_unlock(&dev->t10_alua.lba_map_lock); | ||
546 | return 0; | ||
547 | } | ||
548 | |||
389 | static inline int core_alua_state_standby( | 549 | static inline int core_alua_state_standby( |
390 | struct se_cmd *cmd, | 550 | struct se_cmd *cmd, |
391 | unsigned char *cdb, | 551 | unsigned char *cdb, |
@@ -583,6 +743,9 @@ target_alua_state_check(struct se_cmd *cmd) | |||
583 | case ALUA_ACCESS_STATE_TRANSITION: | 743 | case ALUA_ACCESS_STATE_TRANSITION: |
584 | ret = core_alua_state_transition(cmd, cdb, &alua_ascq); | 744 | ret = core_alua_state_transition(cmd, cdb, &alua_ascq); |
585 | break; | 745 | break; |
746 | case ALUA_ACCESS_STATE_LBA_DEPENDENT: | ||
747 | ret = core_alua_state_lba_dependent(cmd, tg_pt_gp, &alua_ascq); | ||
748 | break; | ||
586 | /* | 749 | /* |
587 | * OFFLINE is a secondary ALUA target port group access state, that is | 750 | * OFFLINE is a secondary ALUA target port group access state, that is |
588 | * handled above with struct se_port->sep_tg_pt_secondary_offline=1 | 751 | * handled above with struct se_port->sep_tg_pt_secondary_offline=1 |
@@ -618,17 +781,36 @@ out: | |||
618 | * Check implicit and explicit ALUA state change request. | 781 | * Check implicit and explicit ALUA state change request. |
619 | */ | 782 | */ |
620 | static sense_reason_t | 783 | static sense_reason_t |
621 | core_alua_check_transition(int state, int *primary) | 784 | core_alua_check_transition(int state, int valid, int *primary) |
622 | { | 785 | { |
786 | /* | ||
787 | * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are | ||
788 | * defined as primary target port asymmetric access states. | ||
789 | */ | ||
623 | switch (state) { | 790 | switch (state) { |
624 | case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED: | 791 | case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED: |
792 | if (!(valid & ALUA_AO_SUP)) | ||
793 | goto not_supported; | ||
794 | *primary = 1; | ||
795 | break; | ||
625 | case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: | 796 | case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: |
797 | if (!(valid & ALUA_AN_SUP)) | ||
798 | goto not_supported; | ||
799 | *primary = 1; | ||
800 | break; | ||
626 | case ALUA_ACCESS_STATE_STANDBY: | 801 | case ALUA_ACCESS_STATE_STANDBY: |
802 | if (!(valid & ALUA_S_SUP)) | ||
803 | goto not_supported; | ||
804 | *primary = 1; | ||
805 | break; | ||
627 | case ALUA_ACCESS_STATE_UNAVAILABLE: | 806 | case ALUA_ACCESS_STATE_UNAVAILABLE: |
628 | /* | 807 | if (!(valid & ALUA_U_SUP)) |
629 | * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are | 808 | goto not_supported; |
630 | * defined as primary target port asymmetric access states. | 809 | *primary = 1; |
631 | */ | 810 | break; |
811 | case ALUA_ACCESS_STATE_LBA_DEPENDENT: | ||
812 | if (!(valid & ALUA_LBD_SUP)) | ||
813 | goto not_supported; | ||
632 | *primary = 1; | 814 | *primary = 1; |
633 | break; | 815 | break; |
634 | case ALUA_ACCESS_STATE_OFFLINE: | 816 | case ALUA_ACCESS_STATE_OFFLINE: |
@@ -636,14 +818,27 @@ core_alua_check_transition(int state, int *primary) | |||
636 | * OFFLINE state is defined as a secondary target port | 818 | * OFFLINE state is defined as a secondary target port |
637 | * asymmetric access state. | 819 | * asymmetric access state. |
638 | */ | 820 | */ |
821 | if (!(valid & ALUA_O_SUP)) | ||
822 | goto not_supported; | ||
639 | *primary = 0; | 823 | *primary = 0; |
640 | break; | 824 | break; |
825 | case ALUA_ACCESS_STATE_TRANSITION: | ||
826 | /* | ||
827 | * Transitioning is set internally, and | ||
828 | * cannot be selected manually. | ||
829 | */ | ||
830 | goto not_supported; | ||
641 | default: | 831 | default: |
642 | pr_err("Unknown ALUA access state: 0x%02x\n", state); | 832 | pr_err("Unknown ALUA access state: 0x%02x\n", state); |
643 | return TCM_INVALID_PARAMETER_LIST; | 833 | return TCM_INVALID_PARAMETER_LIST; |
644 | } | 834 | } |
645 | 835 | ||
646 | return 0; | 836 | return 0; |
837 | |||
838 | not_supported: | ||
839 | pr_err("ALUA access state %s not supported", | ||
840 | core_alua_dump_state(state)); | ||
841 | return TCM_INVALID_PARAMETER_LIST; | ||
647 | } | 842 | } |
648 | 843 | ||
649 | static char *core_alua_dump_state(int state) | 844 | static char *core_alua_dump_state(int state) |
@@ -653,12 +848,16 @@ static char *core_alua_dump_state(int state) | |||
653 | return "Active/Optimized"; | 848 | return "Active/Optimized"; |
654 | case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: | 849 | case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: |
655 | return "Active/NonOptimized"; | 850 | return "Active/NonOptimized"; |
851 | case ALUA_ACCESS_STATE_LBA_DEPENDENT: | ||
852 | return "LBA Dependent"; | ||
656 | case ALUA_ACCESS_STATE_STANDBY: | 853 | case ALUA_ACCESS_STATE_STANDBY: |
657 | return "Standby"; | 854 | return "Standby"; |
658 | case ALUA_ACCESS_STATE_UNAVAILABLE: | 855 | case ALUA_ACCESS_STATE_UNAVAILABLE: |
659 | return "Unavailable"; | 856 | return "Unavailable"; |
660 | case ALUA_ACCESS_STATE_OFFLINE: | 857 | case ALUA_ACCESS_STATE_OFFLINE: |
661 | return "Offline"; | 858 | return "Offline"; |
859 | case ALUA_ACCESS_STATE_TRANSITION: | ||
860 | return "Transitioning"; | ||
662 | default: | 861 | default: |
663 | return "Unknown"; | 862 | return "Unknown"; |
664 | } | 863 | } |
@@ -735,58 +934,49 @@ static int core_alua_write_tpg_metadata( | |||
735 | * Called with tg_pt_gp->tg_pt_gp_md_mutex held | 934 | * Called with tg_pt_gp->tg_pt_gp_md_mutex held |
736 | */ | 935 | */ |
737 | static int core_alua_update_tpg_primary_metadata( | 936 | static int core_alua_update_tpg_primary_metadata( |
738 | struct t10_alua_tg_pt_gp *tg_pt_gp, | 937 | struct t10_alua_tg_pt_gp *tg_pt_gp) |
739 | int primary_state, | ||
740 | unsigned char *md_buf) | ||
741 | { | 938 | { |
939 | unsigned char *md_buf; | ||
742 | struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn; | 940 | struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn; |
743 | char path[ALUA_METADATA_PATH_LEN]; | 941 | char path[ALUA_METADATA_PATH_LEN]; |
744 | int len; | 942 | int len, rc; |
943 | |||
944 | md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL); | ||
945 | if (!md_buf) { | ||
946 | pr_err("Unable to allocate buf for ALUA metadata\n"); | ||
947 | return -ENOMEM; | ||
948 | } | ||
745 | 949 | ||
746 | memset(path, 0, ALUA_METADATA_PATH_LEN); | 950 | memset(path, 0, ALUA_METADATA_PATH_LEN); |
747 | 951 | ||
748 | len = snprintf(md_buf, tg_pt_gp->tg_pt_gp_md_buf_len, | 952 | len = snprintf(md_buf, ALUA_MD_BUF_LEN, |
749 | "tg_pt_gp_id=%hu\n" | 953 | "tg_pt_gp_id=%hu\n" |
750 | "alua_access_state=0x%02x\n" | 954 | "alua_access_state=0x%02x\n" |
751 | "alua_access_status=0x%02x\n", | 955 | "alua_access_status=0x%02x\n", |
752 | tg_pt_gp->tg_pt_gp_id, primary_state, | 956 | tg_pt_gp->tg_pt_gp_id, |
957 | tg_pt_gp->tg_pt_gp_alua_pending_state, | ||
753 | tg_pt_gp->tg_pt_gp_alua_access_status); | 958 | tg_pt_gp->tg_pt_gp_alua_access_status); |
754 | 959 | ||
755 | snprintf(path, ALUA_METADATA_PATH_LEN, | 960 | snprintf(path, ALUA_METADATA_PATH_LEN, |
756 | "/var/target/alua/tpgs_%s/%s", &wwn->unit_serial[0], | 961 | "/var/target/alua/tpgs_%s/%s", &wwn->unit_serial[0], |
757 | config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item)); | 962 | config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item)); |
758 | 963 | ||
759 | return core_alua_write_tpg_metadata(path, md_buf, len); | 964 | rc = core_alua_write_tpg_metadata(path, md_buf, len); |
965 | kfree(md_buf); | ||
966 | return rc; | ||
760 | } | 967 | } |
761 | 968 | ||
762 | static int core_alua_do_transition_tg_pt( | 969 | static void core_alua_do_transition_tg_pt_work(struct work_struct *work) |
763 | struct t10_alua_tg_pt_gp *tg_pt_gp, | ||
764 | struct se_port *l_port, | ||
765 | struct se_node_acl *nacl, | ||
766 | unsigned char *md_buf, | ||
767 | int new_state, | ||
768 | int explicit) | ||
769 | { | 970 | { |
971 | struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(work, | ||
972 | struct t10_alua_tg_pt_gp, tg_pt_gp_transition_work.work); | ||
973 | struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; | ||
770 | struct se_dev_entry *se_deve; | 974 | struct se_dev_entry *se_deve; |
771 | struct se_lun_acl *lacl; | 975 | struct se_lun_acl *lacl; |
772 | struct se_port *port; | 976 | struct se_port *port; |
773 | struct t10_alua_tg_pt_gp_member *mem; | 977 | struct t10_alua_tg_pt_gp_member *mem; |
774 | int old_state = 0; | 978 | bool explicit = (tg_pt_gp->tg_pt_gp_alua_access_status == |
775 | /* | 979 | ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG); |
776 | * Save the old primary ALUA access state, and set the current state | ||
777 | * to ALUA_ACCESS_STATE_TRANSITION. | ||
778 | */ | ||
779 | old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); | ||
780 | atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, | ||
781 | ALUA_ACCESS_STATE_TRANSITION); | ||
782 | tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ? | ||
783 | ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : | ||
784 | ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; | ||
785 | /* | ||
786 | * Check for the optional ALUA primary state transition delay | ||
787 | */ | ||
788 | if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0) | ||
789 | msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs); | ||
790 | 980 | ||
791 | spin_lock(&tg_pt_gp->tg_pt_gp_lock); | 981 | spin_lock(&tg_pt_gp->tg_pt_gp_lock); |
792 | list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list, | 982 | list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list, |
@@ -821,9 +1011,12 @@ static int core_alua_do_transition_tg_pt( | |||
821 | if (!lacl) | 1011 | if (!lacl) |
822 | continue; | 1012 | continue; |
823 | 1013 | ||
824 | if (explicit && | 1014 | if ((tg_pt_gp->tg_pt_gp_alua_access_status == |
825 | (nacl != NULL) && (nacl == lacl->se_lun_nacl) && | 1015 | ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) && |
826 | (l_port != NULL) && (l_port == port)) | 1016 | (tg_pt_gp->tg_pt_gp_alua_nacl != NULL) && |
1017 | (tg_pt_gp->tg_pt_gp_alua_nacl == lacl->se_lun_nacl) && | ||
1018 | (tg_pt_gp->tg_pt_gp_alua_port != NULL) && | ||
1019 | (tg_pt_gp->tg_pt_gp_alua_port == port)) | ||
827 | continue; | 1020 | continue; |
828 | 1021 | ||
829 | core_scsi3_ua_allocate(lacl->se_lun_nacl, | 1022 | core_scsi3_ua_allocate(lacl->se_lun_nacl, |
@@ -851,20 +1044,102 @@ static int core_alua_do_transition_tg_pt( | |||
851 | */ | 1044 | */ |
852 | if (tg_pt_gp->tg_pt_gp_write_metadata) { | 1045 | if (tg_pt_gp->tg_pt_gp_write_metadata) { |
853 | mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex); | 1046 | mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex); |
854 | core_alua_update_tpg_primary_metadata(tg_pt_gp, | 1047 | core_alua_update_tpg_primary_metadata(tg_pt_gp); |
855 | new_state, md_buf); | ||
856 | mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex); | 1048 | mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex); |
857 | } | 1049 | } |
858 | /* | 1050 | /* |
859 | * Set the current primary ALUA access state to the requested new state | 1051 | * Set the current primary ALUA access state to the requested new state |
860 | */ | 1052 | */ |
861 | atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state); | 1053 | atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, |
1054 | tg_pt_gp->tg_pt_gp_alua_pending_state); | ||
862 | 1055 | ||
863 | pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu" | 1056 | pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu" |
864 | " from primary access state %s to %s\n", (explicit) ? "explicit" : | 1057 | " from primary access state %s to %s\n", (explicit) ? "explicit" : |
865 | "implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), | 1058 | "implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), |
866 | tg_pt_gp->tg_pt_gp_id, core_alua_dump_state(old_state), | 1059 | tg_pt_gp->tg_pt_gp_id, |
867 | core_alua_dump_state(new_state)); | 1060 | core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_previous_state), |
1061 | core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_pending_state)); | ||
1062 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); | ||
1063 | atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); | ||
1064 | smp_mb__after_atomic_dec(); | ||
1065 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); | ||
1066 | |||
1067 | if (tg_pt_gp->tg_pt_gp_transition_complete) | ||
1068 | complete(tg_pt_gp->tg_pt_gp_transition_complete); | ||
1069 | } | ||
1070 | |||
1071 | static int core_alua_do_transition_tg_pt( | ||
1072 | struct t10_alua_tg_pt_gp *tg_pt_gp, | ||
1073 | int new_state, | ||
1074 | int explicit) | ||
1075 | { | ||
1076 | struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; | ||
1077 | DECLARE_COMPLETION_ONSTACK(wait); | ||
1078 | |||
1079 | /* Nothing to be done here */ | ||
1080 | if (atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) == new_state) | ||
1081 | return 0; | ||
1082 | |||
1083 | if (new_state == ALUA_ACCESS_STATE_TRANSITION) | ||
1084 | return -EAGAIN; | ||
1085 | |||
1086 | /* | ||
1087 | * Flush any pending transitions | ||
1088 | */ | ||
1089 | if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs && | ||
1090 | atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) == | ||
1091 | ALUA_ACCESS_STATE_TRANSITION) { | ||
1092 | /* Just in case */ | ||
1093 | tg_pt_gp->tg_pt_gp_alua_pending_state = new_state; | ||
1094 | tg_pt_gp->tg_pt_gp_transition_complete = &wait; | ||
1095 | flush_delayed_work(&tg_pt_gp->tg_pt_gp_transition_work); | ||
1096 | wait_for_completion(&wait); | ||
1097 | tg_pt_gp->tg_pt_gp_transition_complete = NULL; | ||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | /* | ||
1102 | * Save the old primary ALUA access state, and set the current state | ||
1103 | * to ALUA_ACCESS_STATE_TRANSITION. | ||
1104 | */ | ||
1105 | tg_pt_gp->tg_pt_gp_alua_previous_state = | ||
1106 | atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); | ||
1107 | tg_pt_gp->tg_pt_gp_alua_pending_state = new_state; | ||
1108 | |||
1109 | atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, | ||
1110 | ALUA_ACCESS_STATE_TRANSITION); | ||
1111 | tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ? | ||
1112 | ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : | ||
1113 | ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; | ||
1114 | |||
1115 | /* | ||
1116 | * Check for the optional ALUA primary state transition delay | ||
1117 | */ | ||
1118 | if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0) | ||
1119 | msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs); | ||
1120 | |||
1121 | /* | ||
1122 | * Take a reference for workqueue item | ||
1123 | */ | ||
1124 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); | ||
1125 | atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); | ||
1126 | smp_mb__after_atomic_inc(); | ||
1127 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); | ||
1128 | |||
1129 | if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs) { | ||
1130 | unsigned long transition_tmo; | ||
1131 | |||
1132 | transition_tmo = tg_pt_gp->tg_pt_gp_implicit_trans_secs * HZ; | ||
1133 | queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq, | ||
1134 | &tg_pt_gp->tg_pt_gp_transition_work, | ||
1135 | transition_tmo); | ||
1136 | } else { | ||
1137 | tg_pt_gp->tg_pt_gp_transition_complete = &wait; | ||
1138 | queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq, | ||
1139 | &tg_pt_gp->tg_pt_gp_transition_work, 0); | ||
1140 | wait_for_completion(&wait); | ||
1141 | tg_pt_gp->tg_pt_gp_transition_complete = NULL; | ||
1142 | } | ||
868 | 1143 | ||
869 | return 0; | 1144 | return 0; |
870 | } | 1145 | } |
@@ -878,23 +1153,15 @@ int core_alua_do_port_transition( | |||
878 | int explicit) | 1153 | int explicit) |
879 | { | 1154 | { |
880 | struct se_device *dev; | 1155 | struct se_device *dev; |
881 | struct se_port *port; | ||
882 | struct se_node_acl *nacl; | ||
883 | struct t10_alua_lu_gp *lu_gp; | 1156 | struct t10_alua_lu_gp *lu_gp; |
884 | struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; | 1157 | struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; |
885 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 1158 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
886 | unsigned char *md_buf; | 1159 | int primary, valid_states, rc = 0; |
887 | int primary; | ||
888 | 1160 | ||
889 | if (core_alua_check_transition(new_state, &primary) != 0) | 1161 | valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states; |
1162 | if (core_alua_check_transition(new_state, valid_states, &primary) != 0) | ||
890 | return -EINVAL; | 1163 | return -EINVAL; |
891 | 1164 | ||
892 | md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL); | ||
893 | if (!md_buf) { | ||
894 | pr_err("Unable to allocate buf for ALUA metadata\n"); | ||
895 | return -ENOMEM; | ||
896 | } | ||
897 | |||
898 | local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem; | 1165 | local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem; |
899 | spin_lock(&local_lu_gp_mem->lu_gp_mem_lock); | 1166 | spin_lock(&local_lu_gp_mem->lu_gp_mem_lock); |
900 | lu_gp = local_lu_gp_mem->lu_gp; | 1167 | lu_gp = local_lu_gp_mem->lu_gp; |
@@ -911,12 +1178,13 @@ int core_alua_do_port_transition( | |||
911 | * core_alua_do_transition_tg_pt() will always return | 1178 | * core_alua_do_transition_tg_pt() will always return |
912 | * success. | 1179 | * success. |
913 | */ | 1180 | */ |
914 | core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl, | 1181 | l_tg_pt_gp->tg_pt_gp_alua_port = l_port; |
915 | md_buf, new_state, explicit); | 1182 | l_tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl; |
1183 | rc = core_alua_do_transition_tg_pt(l_tg_pt_gp, | ||
1184 | new_state, explicit); | ||
916 | atomic_dec(&lu_gp->lu_gp_ref_cnt); | 1185 | atomic_dec(&lu_gp->lu_gp_ref_cnt); |
917 | smp_mb__after_atomic_dec(); | 1186 | smp_mb__after_atomic_dec(); |
918 | kfree(md_buf); | 1187 | return rc; |
919 | return 0; | ||
920 | } | 1188 | } |
921 | /* | 1189 | /* |
922 | * For all other LU groups aside from 'default_lu_gp', walk all of | 1190 | * For all other LU groups aside from 'default_lu_gp', walk all of |
@@ -951,11 +1219,11 @@ int core_alua_do_port_transition( | |||
951 | continue; | 1219 | continue; |
952 | 1220 | ||
953 | if (l_tg_pt_gp == tg_pt_gp) { | 1221 | if (l_tg_pt_gp == tg_pt_gp) { |
954 | port = l_port; | 1222 | tg_pt_gp->tg_pt_gp_alua_port = l_port; |
955 | nacl = l_nacl; | 1223 | tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl; |
956 | } else { | 1224 | } else { |
957 | port = NULL; | 1225 | tg_pt_gp->tg_pt_gp_alua_port = NULL; |
958 | nacl = NULL; | 1226 | tg_pt_gp->tg_pt_gp_alua_nacl = NULL; |
959 | } | 1227 | } |
960 | atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); | 1228 | atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); |
961 | smp_mb__after_atomic_inc(); | 1229 | smp_mb__after_atomic_inc(); |
@@ -964,12 +1232,14 @@ int core_alua_do_port_transition( | |||
964 | * core_alua_do_transition_tg_pt() will always return | 1232 | * core_alua_do_transition_tg_pt() will always return |
965 | * success. | 1233 | * success. |
966 | */ | 1234 | */ |
967 | core_alua_do_transition_tg_pt(tg_pt_gp, port, | 1235 | rc = core_alua_do_transition_tg_pt(tg_pt_gp, |
968 | nacl, md_buf, new_state, explicit); | 1236 | new_state, explicit); |
969 | 1237 | ||
970 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); | 1238 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); |
971 | atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); | 1239 | atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); |
972 | smp_mb__after_atomic_dec(); | 1240 | smp_mb__after_atomic_dec(); |
1241 | if (rc) | ||
1242 | break; | ||
973 | } | 1243 | } |
974 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); | 1244 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
975 | 1245 | ||
@@ -979,16 +1249,18 @@ int core_alua_do_port_transition( | |||
979 | } | 1249 | } |
980 | spin_unlock(&lu_gp->lu_gp_lock); | 1250 | spin_unlock(&lu_gp->lu_gp_lock); |
981 | 1251 | ||
982 | pr_debug("Successfully processed LU Group: %s all ALUA TG PT" | 1252 | if (!rc) { |
983 | " Group IDs: %hu %s transition to primary state: %s\n", | 1253 | pr_debug("Successfully processed LU Group: %s all ALUA TG PT" |
984 | config_item_name(&lu_gp->lu_gp_group.cg_item), | 1254 | " Group IDs: %hu %s transition to primary state: %s\n", |
985 | l_tg_pt_gp->tg_pt_gp_id, (explicit) ? "explicit" : "implicit", | 1255 | config_item_name(&lu_gp->lu_gp_group.cg_item), |
986 | core_alua_dump_state(new_state)); | 1256 | l_tg_pt_gp->tg_pt_gp_id, |
1257 | (explicit) ? "explicit" : "implicit", | ||
1258 | core_alua_dump_state(new_state)); | ||
1259 | } | ||
987 | 1260 | ||
988 | atomic_dec(&lu_gp->lu_gp_ref_cnt); | 1261 | atomic_dec(&lu_gp->lu_gp_ref_cnt); |
989 | smp_mb__after_atomic_dec(); | 1262 | smp_mb__after_atomic_dec(); |
990 | kfree(md_buf); | 1263 | return rc; |
991 | return 0; | ||
992 | } | 1264 | } |
993 | 1265 | ||
994 | /* | 1266 | /* |
@@ -996,13 +1268,18 @@ int core_alua_do_port_transition( | |||
996 | */ | 1268 | */ |
997 | static int core_alua_update_tpg_secondary_metadata( | 1269 | static int core_alua_update_tpg_secondary_metadata( |
998 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, | 1270 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, |
999 | struct se_port *port, | 1271 | struct se_port *port) |
1000 | unsigned char *md_buf, | ||
1001 | u32 md_buf_len) | ||
1002 | { | 1272 | { |
1273 | unsigned char *md_buf; | ||
1003 | struct se_portal_group *se_tpg = port->sep_tpg; | 1274 | struct se_portal_group *se_tpg = port->sep_tpg; |
1004 | char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN]; | 1275 | char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN]; |
1005 | int len; | 1276 | int len, rc; |
1277 | |||
1278 | md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL); | ||
1279 | if (!md_buf) { | ||
1280 | pr_err("Unable to allocate buf for ALUA metadata\n"); | ||
1281 | return -ENOMEM; | ||
1282 | } | ||
1006 | 1283 | ||
1007 | memset(path, 0, ALUA_METADATA_PATH_LEN); | 1284 | memset(path, 0, ALUA_METADATA_PATH_LEN); |
1008 | memset(wwn, 0, ALUA_SECONDARY_METADATA_WWN_LEN); | 1285 | memset(wwn, 0, ALUA_SECONDARY_METADATA_WWN_LEN); |
@@ -1014,7 +1291,7 @@ static int core_alua_update_tpg_secondary_metadata( | |||
1014 | snprintf(wwn+len, ALUA_SECONDARY_METADATA_WWN_LEN-len, "+%hu", | 1291 | snprintf(wwn+len, ALUA_SECONDARY_METADATA_WWN_LEN-len, "+%hu", |
1015 | se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); | 1292 | se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); |
1016 | 1293 | ||
1017 | len = snprintf(md_buf, md_buf_len, "alua_tg_pt_offline=%d\n" | 1294 | len = snprintf(md_buf, ALUA_MD_BUF_LEN, "alua_tg_pt_offline=%d\n" |
1018 | "alua_tg_pt_status=0x%02x\n", | 1295 | "alua_tg_pt_status=0x%02x\n", |
1019 | atomic_read(&port->sep_tg_pt_secondary_offline), | 1296 | atomic_read(&port->sep_tg_pt_secondary_offline), |
1020 | port->sep_tg_pt_secondary_stat); | 1297 | port->sep_tg_pt_secondary_stat); |
@@ -1023,7 +1300,10 @@ static int core_alua_update_tpg_secondary_metadata( | |||
1023 | se_tpg->se_tpg_tfo->get_fabric_name(), wwn, | 1300 | se_tpg->se_tpg_tfo->get_fabric_name(), wwn, |
1024 | port->sep_lun->unpacked_lun); | 1301 | port->sep_lun->unpacked_lun); |
1025 | 1302 | ||
1026 | return core_alua_write_tpg_metadata(path, md_buf, len); | 1303 | rc = core_alua_write_tpg_metadata(path, md_buf, len); |
1304 | kfree(md_buf); | ||
1305 | |||
1306 | return rc; | ||
1027 | } | 1307 | } |
1028 | 1308 | ||
1029 | static int core_alua_set_tg_pt_secondary_state( | 1309 | static int core_alua_set_tg_pt_secondary_state( |
@@ -1033,8 +1313,6 @@ static int core_alua_set_tg_pt_secondary_state( | |||
1033 | int offline) | 1313 | int offline) |
1034 | { | 1314 | { |
1035 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 1315 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
1036 | unsigned char *md_buf; | ||
1037 | u32 md_buf_len; | ||
1038 | int trans_delay_msecs; | 1316 | int trans_delay_msecs; |
1039 | 1317 | ||
1040 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | 1318 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); |
@@ -1055,7 +1333,6 @@ static int core_alua_set_tg_pt_secondary_state( | |||
1055 | else | 1333 | else |
1056 | atomic_set(&port->sep_tg_pt_secondary_offline, 0); | 1334 | atomic_set(&port->sep_tg_pt_secondary_offline, 0); |
1057 | 1335 | ||
1058 | md_buf_len = tg_pt_gp->tg_pt_gp_md_buf_len; | ||
1059 | port->sep_tg_pt_secondary_stat = (explicit) ? | 1336 | port->sep_tg_pt_secondary_stat = (explicit) ? |
1060 | ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : | 1337 | ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : |
1061 | ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; | 1338 | ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; |
@@ -1077,23 +1354,115 @@ static int core_alua_set_tg_pt_secondary_state( | |||
1077 | * secondary state and status | 1354 | * secondary state and status |
1078 | */ | 1355 | */ |
1079 | if (port->sep_tg_pt_secondary_write_md) { | 1356 | if (port->sep_tg_pt_secondary_write_md) { |
1080 | md_buf = kzalloc(md_buf_len, GFP_KERNEL); | ||
1081 | if (!md_buf) { | ||
1082 | pr_err("Unable to allocate md_buf for" | ||
1083 | " secondary ALUA access metadata\n"); | ||
1084 | return -ENOMEM; | ||
1085 | } | ||
1086 | mutex_lock(&port->sep_tg_pt_md_mutex); | 1357 | mutex_lock(&port->sep_tg_pt_md_mutex); |
1087 | core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port, | 1358 | core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port); |
1088 | md_buf, md_buf_len); | ||
1089 | mutex_unlock(&port->sep_tg_pt_md_mutex); | 1359 | mutex_unlock(&port->sep_tg_pt_md_mutex); |
1360 | } | ||
1361 | |||
1362 | return 0; | ||
1363 | } | ||
1364 | |||
1365 | struct t10_alua_lba_map * | ||
1366 | core_alua_allocate_lba_map(struct list_head *list, | ||
1367 | u64 first_lba, u64 last_lba) | ||
1368 | { | ||
1369 | struct t10_alua_lba_map *lba_map; | ||
1370 | |||
1371 | lba_map = kmem_cache_zalloc(t10_alua_lba_map_cache, GFP_KERNEL); | ||
1372 | if (!lba_map) { | ||
1373 | pr_err("Unable to allocate struct t10_alua_lba_map\n"); | ||
1374 | return ERR_PTR(-ENOMEM); | ||
1375 | } | ||
1376 | INIT_LIST_HEAD(&lba_map->lba_map_mem_list); | ||
1377 | lba_map->lba_map_first_lba = first_lba; | ||
1378 | lba_map->lba_map_last_lba = last_lba; | ||
1090 | 1379 | ||
1091 | kfree(md_buf); | 1380 | list_add_tail(&lba_map->lba_map_list, list); |
1381 | return lba_map; | ||
1382 | } | ||
1383 | |||
1384 | int | ||
1385 | core_alua_allocate_lba_map_mem(struct t10_alua_lba_map *lba_map, | ||
1386 | int pg_id, int state) | ||
1387 | { | ||
1388 | struct t10_alua_lba_map_member *lba_map_mem; | ||
1389 | |||
1390 | list_for_each_entry(lba_map_mem, &lba_map->lba_map_mem_list, | ||
1391 | lba_map_mem_list) { | ||
1392 | if (lba_map_mem->lba_map_mem_alua_pg_id == pg_id) { | ||
1393 | pr_err("Duplicate pg_id %d in lba_map\n", pg_id); | ||
1394 | return -EINVAL; | ||
1395 | } | ||
1396 | } | ||
1397 | |||
1398 | lba_map_mem = kmem_cache_zalloc(t10_alua_lba_map_mem_cache, GFP_KERNEL); | ||
1399 | if (!lba_map_mem) { | ||
1400 | pr_err("Unable to allocate struct t10_alua_lba_map_mem\n"); | ||
1401 | return -ENOMEM; | ||
1092 | } | 1402 | } |
1403 | lba_map_mem->lba_map_mem_alua_state = state; | ||
1404 | lba_map_mem->lba_map_mem_alua_pg_id = pg_id; | ||
1093 | 1405 | ||
1406 | list_add_tail(&lba_map_mem->lba_map_mem_list, | ||
1407 | &lba_map->lba_map_mem_list); | ||
1094 | return 0; | 1408 | return 0; |
1095 | } | 1409 | } |
1096 | 1410 | ||
1411 | void | ||
1412 | core_alua_free_lba_map(struct list_head *lba_list) | ||
1413 | { | ||
1414 | struct t10_alua_lba_map *lba_map, *lba_map_tmp; | ||
1415 | struct t10_alua_lba_map_member *lba_map_mem, *lba_map_mem_tmp; | ||
1416 | |||
1417 | list_for_each_entry_safe(lba_map, lba_map_tmp, lba_list, | ||
1418 | lba_map_list) { | ||
1419 | list_for_each_entry_safe(lba_map_mem, lba_map_mem_tmp, | ||
1420 | &lba_map->lba_map_mem_list, | ||
1421 | lba_map_mem_list) { | ||
1422 | list_del(&lba_map_mem->lba_map_mem_list); | ||
1423 | kmem_cache_free(t10_alua_lba_map_mem_cache, | ||
1424 | lba_map_mem); | ||
1425 | } | ||
1426 | list_del(&lba_map->lba_map_list); | ||
1427 | kmem_cache_free(t10_alua_lba_map_cache, lba_map); | ||
1428 | } | ||
1429 | } | ||
1430 | |||
1431 | void | ||
1432 | core_alua_set_lba_map(struct se_device *dev, struct list_head *lba_map_list, | ||
1433 | int segment_size, int segment_mult) | ||
1434 | { | ||
1435 | struct list_head old_lba_map_list; | ||
1436 | struct t10_alua_tg_pt_gp *tg_pt_gp; | ||
1437 | int activate = 0, supported; | ||
1438 | |||
1439 | INIT_LIST_HEAD(&old_lba_map_list); | ||
1440 | spin_lock(&dev->t10_alua.lba_map_lock); | ||
1441 | dev->t10_alua.lba_map_segment_size = segment_size; | ||
1442 | dev->t10_alua.lba_map_segment_multiplier = segment_mult; | ||
1443 | list_splice_init(&dev->t10_alua.lba_map_list, &old_lba_map_list); | ||
1444 | if (lba_map_list) { | ||
1445 | list_splice_init(lba_map_list, &dev->t10_alua.lba_map_list); | ||
1446 | activate = 1; | ||
1447 | } | ||
1448 | spin_unlock(&dev->t10_alua.lba_map_lock); | ||
1449 | spin_lock(&dev->t10_alua.tg_pt_gps_lock); | ||
1450 | list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, | ||
1451 | tg_pt_gp_list) { | ||
1452 | |||
1453 | if (!tg_pt_gp->tg_pt_gp_valid_id) | ||
1454 | continue; | ||
1455 | supported = tg_pt_gp->tg_pt_gp_alua_supported_states; | ||
1456 | if (activate) | ||
1457 | supported |= ALUA_LBD_SUP; | ||
1458 | else | ||
1459 | supported &= ~ALUA_LBD_SUP; | ||
1460 | tg_pt_gp->tg_pt_gp_alua_supported_states = supported; | ||
1461 | } | ||
1462 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); | ||
1463 | core_alua_free_lba_map(&old_lba_map_list); | ||
1464 | } | ||
1465 | |||
1097 | struct t10_alua_lu_gp * | 1466 | struct t10_alua_lu_gp * |
1098 | core_alua_allocate_lu_gp(const char *name, int def_group) | 1467 | core_alua_allocate_lu_gp(const char *name, int def_group) |
1099 | { | 1468 | { |
@@ -1346,8 +1715,9 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev, | |||
1346 | mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); | 1715 | mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); |
1347 | spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); | 1716 | spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); |
1348 | atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); | 1717 | atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); |
1718 | INIT_DELAYED_WORK(&tg_pt_gp->tg_pt_gp_transition_work, | ||
1719 | core_alua_do_transition_tg_pt_work); | ||
1349 | tg_pt_gp->tg_pt_gp_dev = dev; | 1720 | tg_pt_gp->tg_pt_gp_dev = dev; |
1350 | tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN; | ||
1351 | atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, | 1721 | atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, |
1352 | ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED); | 1722 | ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED); |
1353 | /* | 1723 | /* |
@@ -1475,6 +1845,8 @@ void core_alua_free_tg_pt_gp( | |||
1475 | dev->t10_alua.alua_tg_pt_gps_counter--; | 1845 | dev->t10_alua.alua_tg_pt_gps_counter--; |
1476 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); | 1846 | spin_unlock(&dev->t10_alua.tg_pt_gps_lock); |
1477 | 1847 | ||
1848 | flush_delayed_work(&tg_pt_gp->tg_pt_gp_transition_work); | ||
1849 | |||
1478 | /* | 1850 | /* |
1479 | * Allow a struct t10_alua_tg_pt_gp_member * referenced by | 1851 | * Allow a struct t10_alua_tg_pt_gp_member * referenced by |
1480 | * core_alua_get_tg_pt_gp_by_name() in | 1852 | * core_alua_get_tg_pt_gp_by_name() in |
diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index 88e2e835f14a..0a7d65e80404 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h | |||
@@ -13,12 +13,13 @@ | |||
13 | /* | 13 | /* |
14 | * ASYMMETRIC ACCESS STATE field | 14 | * ASYMMETRIC ACCESS STATE field |
15 | * | 15 | * |
16 | * from spc4r17 section 6.27 Table 245 | 16 | * from spc4r36j section 6.37 Table 307 |
17 | */ | 17 | */ |
18 | #define ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED 0x0 | 18 | #define ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED 0x0 |
19 | #define ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED 0x1 | 19 | #define ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED 0x1 |
20 | #define ALUA_ACCESS_STATE_STANDBY 0x2 | 20 | #define ALUA_ACCESS_STATE_STANDBY 0x2 |
21 | #define ALUA_ACCESS_STATE_UNAVAILABLE 0x3 | 21 | #define ALUA_ACCESS_STATE_UNAVAILABLE 0x3 |
22 | #define ALUA_ACCESS_STATE_LBA_DEPENDENT 0x4 | ||
22 | #define ALUA_ACCESS_STATE_OFFLINE 0xe | 23 | #define ALUA_ACCESS_STATE_OFFLINE 0xe |
23 | #define ALUA_ACCESS_STATE_TRANSITION 0xf | 24 | #define ALUA_ACCESS_STATE_TRANSITION 0xf |
24 | 25 | ||
@@ -78,18 +79,30 @@ | |||
78 | */ | 79 | */ |
79 | #define ALUA_SECONDARY_METADATA_WWN_LEN 256 | 80 | #define ALUA_SECONDARY_METADATA_WWN_LEN 256 |
80 | 81 | ||
82 | /* Used by core_alua_update_tpg_(primary,secondary)_metadata */ | ||
83 | #define ALUA_MD_BUF_LEN 1024 | ||
84 | |||
81 | extern struct kmem_cache *t10_alua_lu_gp_cache; | 85 | extern struct kmem_cache *t10_alua_lu_gp_cache; |
82 | extern struct kmem_cache *t10_alua_lu_gp_mem_cache; | 86 | extern struct kmem_cache *t10_alua_lu_gp_mem_cache; |
83 | extern struct kmem_cache *t10_alua_tg_pt_gp_cache; | 87 | extern struct kmem_cache *t10_alua_tg_pt_gp_cache; |
84 | extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; | 88 | extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; |
89 | extern struct kmem_cache *t10_alua_lba_map_cache; | ||
90 | extern struct kmem_cache *t10_alua_lba_map_mem_cache; | ||
85 | 91 | ||
86 | extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *); | 92 | extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *); |
87 | extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *); | 93 | extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *); |
94 | extern sense_reason_t target_emulate_report_referrals(struct se_cmd *); | ||
88 | extern int core_alua_check_nonop_delay(struct se_cmd *); | 95 | extern int core_alua_check_nonop_delay(struct se_cmd *); |
89 | extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *, | 96 | extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *, |
90 | struct se_device *, struct se_port *, | 97 | struct se_device *, struct se_port *, |
91 | struct se_node_acl *, int, int); | 98 | struct se_node_acl *, int, int); |
92 | extern char *core_alua_dump_status(int); | 99 | extern char *core_alua_dump_status(int); |
100 | extern struct t10_alua_lba_map *core_alua_allocate_lba_map( | ||
101 | struct list_head *, u64, u64); | ||
102 | extern int core_alua_allocate_lba_map_mem(struct t10_alua_lba_map *, int, int); | ||
103 | extern void core_alua_free_lba_map(struct list_head *); | ||
104 | extern void core_alua_set_lba_map(struct se_device *, struct list_head *, | ||
105 | int, int); | ||
93 | extern struct t10_alua_lu_gp *core_alua_allocate_lu_gp(const char *, int); | 106 | extern struct t10_alua_lu_gp *core_alua_allocate_lu_gp(const char *, int); |
94 | extern int core_alua_set_lu_gp_id(struct t10_alua_lu_gp *, u16); | 107 | extern int core_alua_set_lu_gp_id(struct t10_alua_lu_gp *, u16); |
95 | extern void core_alua_free_lu_gp(struct t10_alua_lu_gp *); | 108 | extern void core_alua_free_lu_gp(struct t10_alua_lu_gp *); |
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 272755d03e5a..f0e85b119692 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
@@ -643,6 +643,15 @@ SE_DEV_ATTR(emulate_caw, S_IRUGO | S_IWUSR); | |||
643 | DEF_DEV_ATTRIB(emulate_3pc); | 643 | DEF_DEV_ATTRIB(emulate_3pc); |
644 | SE_DEV_ATTR(emulate_3pc, S_IRUGO | S_IWUSR); | 644 | SE_DEV_ATTR(emulate_3pc, S_IRUGO | S_IWUSR); |
645 | 645 | ||
646 | DEF_DEV_ATTRIB(pi_prot_type); | ||
647 | SE_DEV_ATTR(pi_prot_type, S_IRUGO | S_IWUSR); | ||
648 | |||
649 | DEF_DEV_ATTRIB_RO(hw_pi_prot_type); | ||
650 | SE_DEV_ATTR_RO(hw_pi_prot_type); | ||
651 | |||
652 | DEF_DEV_ATTRIB(pi_prot_format); | ||
653 | SE_DEV_ATTR(pi_prot_format, S_IRUGO | S_IWUSR); | ||
654 | |||
646 | DEF_DEV_ATTRIB(enforce_pr_isids); | 655 | DEF_DEV_ATTRIB(enforce_pr_isids); |
647 | SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); | 656 | SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); |
648 | 657 | ||
@@ -702,6 +711,9 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { | |||
702 | &target_core_dev_attrib_emulate_tpws.attr, | 711 | &target_core_dev_attrib_emulate_tpws.attr, |
703 | &target_core_dev_attrib_emulate_caw.attr, | 712 | &target_core_dev_attrib_emulate_caw.attr, |
704 | &target_core_dev_attrib_emulate_3pc.attr, | 713 | &target_core_dev_attrib_emulate_3pc.attr, |
714 | &target_core_dev_attrib_pi_prot_type.attr, | ||
715 | &target_core_dev_attrib_hw_pi_prot_type.attr, | ||
716 | &target_core_dev_attrib_pi_prot_format.attr, | ||
705 | &target_core_dev_attrib_enforce_pr_isids.attr, | 717 | &target_core_dev_attrib_enforce_pr_isids.attr, |
706 | &target_core_dev_attrib_is_nonrot.attr, | 718 | &target_core_dev_attrib_is_nonrot.attr, |
707 | &target_core_dev_attrib_emulate_rest_reord.attr, | 719 | &target_core_dev_attrib_emulate_rest_reord.attr, |
@@ -1741,6 +1753,176 @@ static struct target_core_configfs_attribute target_core_attr_dev_alua_lu_gp = { | |||
1741 | .store = target_core_store_alua_lu_gp, | 1753 | .store = target_core_store_alua_lu_gp, |
1742 | }; | 1754 | }; |
1743 | 1755 | ||
1756 | static ssize_t target_core_show_dev_lba_map(void *p, char *page) | ||
1757 | { | ||
1758 | struct se_device *dev = p; | ||
1759 | struct t10_alua_lba_map *map; | ||
1760 | struct t10_alua_lba_map_member *mem; | ||
1761 | char *b = page; | ||
1762 | int bl = 0; | ||
1763 | char state; | ||
1764 | |||
1765 | spin_lock(&dev->t10_alua.lba_map_lock); | ||
1766 | if (!list_empty(&dev->t10_alua.lba_map_list)) | ||
1767 | bl += sprintf(b + bl, "%u %u\n", | ||
1768 | dev->t10_alua.lba_map_segment_size, | ||
1769 | dev->t10_alua.lba_map_segment_multiplier); | ||
1770 | list_for_each_entry(map, &dev->t10_alua.lba_map_list, lba_map_list) { | ||
1771 | bl += sprintf(b + bl, "%llu %llu", | ||
1772 | map->lba_map_first_lba, map->lba_map_last_lba); | ||
1773 | list_for_each_entry(mem, &map->lba_map_mem_list, | ||
1774 | lba_map_mem_list) { | ||
1775 | switch (mem->lba_map_mem_alua_state) { | ||
1776 | case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED: | ||
1777 | state = 'O'; | ||
1778 | break; | ||
1779 | case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: | ||
1780 | state = 'A'; | ||
1781 | break; | ||
1782 | case ALUA_ACCESS_STATE_STANDBY: | ||
1783 | state = 'S'; | ||
1784 | break; | ||
1785 | case ALUA_ACCESS_STATE_UNAVAILABLE: | ||
1786 | state = 'U'; | ||
1787 | break; | ||
1788 | default: | ||
1789 | state = '.'; | ||
1790 | break; | ||
1791 | } | ||
1792 | bl += sprintf(b + bl, " %d:%c", | ||
1793 | mem->lba_map_mem_alua_pg_id, state); | ||
1794 | } | ||
1795 | bl += sprintf(b + bl, "\n"); | ||
1796 | } | ||
1797 | spin_unlock(&dev->t10_alua.lba_map_lock); | ||
1798 | return bl; | ||
1799 | } | ||
1800 | |||
1801 | static ssize_t target_core_store_dev_lba_map( | ||
1802 | void *p, | ||
1803 | const char *page, | ||
1804 | size_t count) | ||
1805 | { | ||
1806 | struct se_device *dev = p; | ||
1807 | struct t10_alua_lba_map *lba_map = NULL; | ||
1808 | struct list_head lba_list; | ||
1809 | char *map_entries, *ptr; | ||
1810 | char state; | ||
1811 | int pg_num = -1, pg; | ||
1812 | int ret = 0, num = 0, pg_id, alua_state; | ||
1813 | unsigned long start_lba = -1, end_lba = -1; | ||
1814 | unsigned long segment_size = -1, segment_mult = -1; | ||
1815 | |||
1816 | map_entries = kstrdup(page, GFP_KERNEL); | ||
1817 | if (!map_entries) | ||
1818 | return -ENOMEM; | ||
1819 | |||
1820 | INIT_LIST_HEAD(&lba_list); | ||
1821 | while ((ptr = strsep(&map_entries, "\n")) != NULL) { | ||
1822 | if (!*ptr) | ||
1823 | continue; | ||
1824 | |||
1825 | if (num == 0) { | ||
1826 | if (sscanf(ptr, "%lu %lu\n", | ||
1827 | &segment_size, &segment_mult) != 2) { | ||
1828 | pr_err("Invalid line %d\n", num); | ||
1829 | ret = -EINVAL; | ||
1830 | break; | ||
1831 | } | ||
1832 | num++; | ||
1833 | continue; | ||
1834 | } | ||
1835 | if (sscanf(ptr, "%lu %lu", &start_lba, &end_lba) != 2) { | ||
1836 | pr_err("Invalid line %d\n", num); | ||
1837 | ret = -EINVAL; | ||
1838 | break; | ||
1839 | } | ||
1840 | ptr = strchr(ptr, ' '); | ||
1841 | if (!ptr) { | ||
1842 | pr_err("Invalid line %d, missing end lba\n", num); | ||
1843 | ret = -EINVAL; | ||
1844 | break; | ||
1845 | } | ||
1846 | ptr++; | ||
1847 | ptr = strchr(ptr, ' '); | ||
1848 | if (!ptr) { | ||
1849 | pr_err("Invalid line %d, missing state definitions\n", | ||
1850 | num); | ||
1851 | ret = -EINVAL; | ||
1852 | break; | ||
1853 | } | ||
1854 | ptr++; | ||
1855 | lba_map = core_alua_allocate_lba_map(&lba_list, | ||
1856 | start_lba, end_lba); | ||
1857 | if (IS_ERR(lba_map)) { | ||
1858 | ret = PTR_ERR(lba_map); | ||
1859 | break; | ||
1860 | } | ||
1861 | pg = 0; | ||
1862 | while (sscanf(ptr, "%d:%c", &pg_id, &state) == 2) { | ||
1863 | switch (state) { | ||
1864 | case 'O': | ||
1865 | alua_state = ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED; | ||
1866 | break; | ||
1867 | case 'A': | ||
1868 | alua_state = ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED; | ||
1869 | break; | ||
1870 | case 'S': | ||
1871 | alua_state = ALUA_ACCESS_STATE_STANDBY; | ||
1872 | break; | ||
1873 | case 'U': | ||
1874 | alua_state = ALUA_ACCESS_STATE_UNAVAILABLE; | ||
1875 | break; | ||
1876 | default: | ||
1877 | pr_err("Invalid ALUA state '%c'\n", state); | ||
1878 | ret = -EINVAL; | ||
1879 | goto out; | ||
1880 | } | ||
1881 | |||
1882 | ret = core_alua_allocate_lba_map_mem(lba_map, | ||
1883 | pg_id, alua_state); | ||
1884 | if (ret) { | ||
1885 | pr_err("Invalid target descriptor %d:%c " | ||
1886 | "at line %d\n", | ||
1887 | pg_id, state, num); | ||
1888 | break; | ||
1889 | } | ||
1890 | pg++; | ||
1891 | ptr = strchr(ptr, ' '); | ||
1892 | if (ptr) | ||
1893 | ptr++; | ||
1894 | else | ||
1895 | break; | ||
1896 | } | ||
1897 | if (pg_num == -1) | ||
1898 | pg_num = pg; | ||
1899 | else if (pg != pg_num) { | ||
1900 | pr_err("Only %d from %d port groups definitions " | ||
1901 | "at line %d\n", pg, pg_num, num); | ||
1902 | ret = -EINVAL; | ||
1903 | break; | ||
1904 | } | ||
1905 | num++; | ||
1906 | } | ||
1907 | out: | ||
1908 | if (ret) { | ||
1909 | core_alua_free_lba_map(&lba_list); | ||
1910 | count = ret; | ||
1911 | } else | ||
1912 | core_alua_set_lba_map(dev, &lba_list, | ||
1913 | segment_size, segment_mult); | ||
1914 | kfree(map_entries); | ||
1915 | return count; | ||
1916 | } | ||
1917 | |||
1918 | static struct target_core_configfs_attribute target_core_attr_dev_lba_map = { | ||
1919 | .attr = { .ca_owner = THIS_MODULE, | ||
1920 | .ca_name = "lba_map", | ||
1921 | .ca_mode = S_IRUGO | S_IWUSR }, | ||
1922 | .show = target_core_show_dev_lba_map, | ||
1923 | .store = target_core_store_dev_lba_map, | ||
1924 | }; | ||
1925 | |||
1744 | static struct configfs_attribute *lio_core_dev_attrs[] = { | 1926 | static struct configfs_attribute *lio_core_dev_attrs[] = { |
1745 | &target_core_attr_dev_info.attr, | 1927 | &target_core_attr_dev_info.attr, |
1746 | &target_core_attr_dev_control.attr, | 1928 | &target_core_attr_dev_control.attr, |
@@ -1748,6 +1930,7 @@ static struct configfs_attribute *lio_core_dev_attrs[] = { | |||
1748 | &target_core_attr_dev_udev_path.attr, | 1930 | &target_core_attr_dev_udev_path.attr, |
1749 | &target_core_attr_dev_enable.attr, | 1931 | &target_core_attr_dev_enable.attr, |
1750 | &target_core_attr_dev_alua_lu_gp.attr, | 1932 | &target_core_attr_dev_alua_lu_gp.attr, |
1933 | &target_core_attr_dev_lba_map.attr, | ||
1751 | NULL, | 1934 | NULL, |
1752 | }; | 1935 | }; |
1753 | 1936 | ||
@@ -2054,6 +2237,13 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state( | |||
2054 | " transition while TPGS_IMPLICIT_ALUA is disabled\n"); | 2237 | " transition while TPGS_IMPLICIT_ALUA is disabled\n"); |
2055 | return -EINVAL; | 2238 | return -EINVAL; |
2056 | } | 2239 | } |
2240 | if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA && | ||
2241 | new_state == ALUA_ACCESS_STATE_LBA_DEPENDENT) { | ||
2242 | /* LBA DEPENDENT is only allowed with implicit ALUA */ | ||
2243 | pr_err("Unable to process implicit configfs ALUA transition" | ||
2244 | " while explicit ALUA management is enabled\n"); | ||
2245 | return -EINVAL; | ||
2246 | } | ||
2057 | 2247 | ||
2058 | ret = core_alua_do_port_transition(tg_pt_gp, dev, | 2248 | ret = core_alua_do_port_transition(tg_pt_gp, dev, |
2059 | NULL, NULL, new_state, 0); | 2249 | NULL, NULL, new_state, 0); |
@@ -2188,7 +2378,7 @@ SE_DEV_ALUA_SUPPORT_STATE_SHOW(lba_dependent, | |||
2188 | tg_pt_gp_alua_supported_states, ALUA_LBD_SUP); | 2378 | tg_pt_gp_alua_supported_states, ALUA_LBD_SUP); |
2189 | SE_DEV_ALUA_SUPPORT_STATE_STORE(lba_dependent, | 2379 | SE_DEV_ALUA_SUPPORT_STATE_STORE(lba_dependent, |
2190 | tg_pt_gp_alua_supported_states, ALUA_LBD_SUP); | 2380 | tg_pt_gp_alua_supported_states, ALUA_LBD_SUP); |
2191 | SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO | S_IWUSR); | 2381 | SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO); |
2192 | 2382 | ||
2193 | SE_DEV_ALUA_SUPPORT_STATE_SHOW(unavailable, | 2383 | SE_DEV_ALUA_SUPPORT_STATE_SHOW(unavailable, |
2194 | tg_pt_gp_alua_supported_states, ALUA_U_SUP); | 2384 | tg_pt_gp_alua_supported_states, ALUA_U_SUP); |
@@ -2937,7 +3127,7 @@ static int __init target_core_init_configfs(void) | |||
2937 | * and ALUA Logical Unit Group and Target Port Group infrastructure. | 3127 | * and ALUA Logical Unit Group and Target Port Group infrastructure. |
2938 | */ | 3128 | */ |
2939 | target_cg = &subsys->su_group; | 3129 | target_cg = &subsys->su_group; |
2940 | target_cg->default_groups = kmalloc(sizeof(struct config_group) * 2, | 3130 | target_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
2941 | GFP_KERNEL); | 3131 | GFP_KERNEL); |
2942 | if (!target_cg->default_groups) { | 3132 | if (!target_cg->default_groups) { |
2943 | pr_err("Unable to allocate target_cg->default_groups\n"); | 3133 | pr_err("Unable to allocate target_cg->default_groups\n"); |
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index d06de84b069b..65001e133670 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
@@ -918,6 +918,90 @@ int se_dev_set_emulate_3pc(struct se_device *dev, int flag) | |||
918 | return 0; | 918 | return 0; |
919 | } | 919 | } |
920 | 920 | ||
921 | int se_dev_set_pi_prot_type(struct se_device *dev, int flag) | ||
922 | { | ||
923 | int rc, old_prot = dev->dev_attrib.pi_prot_type; | ||
924 | |||
925 | if (flag != 0 && flag != 1 && flag != 2 && flag != 3) { | ||
926 | pr_err("Illegal value %d for pi_prot_type\n", flag); | ||
927 | return -EINVAL; | ||
928 | } | ||
929 | if (flag == 2) { | ||
930 | pr_err("DIF TYPE2 protection currently not supported\n"); | ||
931 | return -ENOSYS; | ||
932 | } | ||
933 | if (dev->dev_attrib.hw_pi_prot_type) { | ||
934 | pr_warn("DIF protection enabled on underlying hardware," | ||
935 | " ignoring\n"); | ||
936 | return 0; | ||
937 | } | ||
938 | if (!dev->transport->init_prot || !dev->transport->free_prot) { | ||
939 | pr_err("DIF protection not supported by backend: %s\n", | ||
940 | dev->transport->name); | ||
941 | return -ENOSYS; | ||
942 | } | ||
943 | if (!(dev->dev_flags & DF_CONFIGURED)) { | ||
944 | pr_err("DIF protection requires device to be configured\n"); | ||
945 | return -ENODEV; | ||
946 | } | ||
947 | if (dev->export_count) { | ||
948 | pr_err("dev[%p]: Unable to change SE Device PROT type while" | ||
949 | " export_count is %d\n", dev, dev->export_count); | ||
950 | return -EINVAL; | ||
951 | } | ||
952 | |||
953 | dev->dev_attrib.pi_prot_type = flag; | ||
954 | |||
955 | if (flag && !old_prot) { | ||
956 | rc = dev->transport->init_prot(dev); | ||
957 | if (rc) { | ||
958 | dev->dev_attrib.pi_prot_type = old_prot; | ||
959 | return rc; | ||
960 | } | ||
961 | |||
962 | } else if (!flag && old_prot) { | ||
963 | dev->transport->free_prot(dev); | ||
964 | } | ||
965 | pr_debug("dev[%p]: SE Device Protection Type: %d\n", dev, flag); | ||
966 | |||
967 | return 0; | ||
968 | } | ||
969 | |||
970 | int se_dev_set_pi_prot_format(struct se_device *dev, int flag) | ||
971 | { | ||
972 | int rc; | ||
973 | |||
974 | if (!flag) | ||
975 | return 0; | ||
976 | |||
977 | if (flag != 1) { | ||
978 | pr_err("Illegal value %d for pi_prot_format\n", flag); | ||
979 | return -EINVAL; | ||
980 | } | ||
981 | if (!dev->transport->format_prot) { | ||
982 | pr_err("DIF protection format not supported by backend %s\n", | ||
983 | dev->transport->name); | ||
984 | return -ENOSYS; | ||
985 | } | ||
986 | if (!(dev->dev_flags & DF_CONFIGURED)) { | ||
987 | pr_err("DIF protection format requires device to be configured\n"); | ||
988 | return -ENODEV; | ||
989 | } | ||
990 | if (dev->export_count) { | ||
991 | pr_err("dev[%p]: Unable to format SE Device PROT type while" | ||
992 | " export_count is %d\n", dev, dev->export_count); | ||
993 | return -EINVAL; | ||
994 | } | ||
995 | |||
996 | rc = dev->transport->format_prot(dev); | ||
997 | if (rc) | ||
998 | return rc; | ||
999 | |||
1000 | pr_debug("dev[%p]: SE Device Protection Format complete\n", dev); | ||
1001 | |||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
921 | int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag) | 1005 | int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag) |
922 | { | 1006 | { |
923 | if ((flag != 0) && (flag != 1)) { | 1007 | if ((flag != 0) && (flag != 1)) { |
@@ -1117,23 +1201,23 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size) | |||
1117 | struct se_lun *core_dev_add_lun( | 1201 | struct se_lun *core_dev_add_lun( |
1118 | struct se_portal_group *tpg, | 1202 | struct se_portal_group *tpg, |
1119 | struct se_device *dev, | 1203 | struct se_device *dev, |
1120 | u32 lun) | 1204 | u32 unpacked_lun) |
1121 | { | 1205 | { |
1122 | struct se_lun *lun_p; | 1206 | struct se_lun *lun; |
1123 | int rc; | 1207 | int rc; |
1124 | 1208 | ||
1125 | lun_p = core_tpg_pre_addlun(tpg, lun); | 1209 | lun = core_tpg_alloc_lun(tpg, unpacked_lun); |
1126 | if (IS_ERR(lun_p)) | 1210 | if (IS_ERR(lun)) |
1127 | return lun_p; | 1211 | return lun; |
1128 | 1212 | ||
1129 | rc = core_tpg_post_addlun(tpg, lun_p, | 1213 | rc = core_tpg_add_lun(tpg, lun, |
1130 | TRANSPORT_LUNFLAGS_READ_WRITE, dev); | 1214 | TRANSPORT_LUNFLAGS_READ_WRITE, dev); |
1131 | if (rc < 0) | 1215 | if (rc < 0) |
1132 | return ERR_PTR(rc); | 1216 | return ERR_PTR(rc); |
1133 | 1217 | ||
1134 | pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from" | 1218 | pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from" |
1135 | " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(), | 1219 | " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(), |
1136 | tpg->se_tpg_tfo->tpg_get_tag(tpg), lun_p->unpacked_lun, | 1220 | tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, |
1137 | tpg->se_tpg_tfo->get_fabric_name(), dev->se_hba->hba_id); | 1221 | tpg->se_tpg_tfo->get_fabric_name(), dev->se_hba->hba_id); |
1138 | /* | 1222 | /* |
1139 | * Update LUN maps for dynamically added initiators when | 1223 | * Update LUN maps for dynamically added initiators when |
@@ -1154,7 +1238,7 @@ struct se_lun *core_dev_add_lun( | |||
1154 | spin_unlock_irq(&tpg->acl_node_lock); | 1238 | spin_unlock_irq(&tpg->acl_node_lock); |
1155 | } | 1239 | } |
1156 | 1240 | ||
1157 | return lun_p; | 1241 | return lun; |
1158 | } | 1242 | } |
1159 | 1243 | ||
1160 | /* core_dev_del_lun(): | 1244 | /* core_dev_del_lun(): |
@@ -1420,6 +1504,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) | |||
1420 | dev->dev_link_magic = SE_DEV_LINK_MAGIC; | 1504 | dev->dev_link_magic = SE_DEV_LINK_MAGIC; |
1421 | dev->se_hba = hba; | 1505 | dev->se_hba = hba; |
1422 | dev->transport = hba->transport; | 1506 | dev->transport = hba->transport; |
1507 | dev->prot_length = sizeof(struct se_dif_v1_tuple); | ||
1423 | 1508 | ||
1424 | INIT_LIST_HEAD(&dev->dev_list); | 1509 | INIT_LIST_HEAD(&dev->dev_list); |
1425 | INIT_LIST_HEAD(&dev->dev_sep_list); | 1510 | INIT_LIST_HEAD(&dev->dev_sep_list); |
@@ -1444,6 +1529,8 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) | |||
1444 | spin_lock_init(&dev->t10_pr.aptpl_reg_lock); | 1529 | spin_lock_init(&dev->t10_pr.aptpl_reg_lock); |
1445 | INIT_LIST_HEAD(&dev->t10_alua.tg_pt_gps_list); | 1530 | INIT_LIST_HEAD(&dev->t10_alua.tg_pt_gps_list); |
1446 | spin_lock_init(&dev->t10_alua.tg_pt_gps_lock); | 1531 | spin_lock_init(&dev->t10_alua.tg_pt_gps_lock); |
1532 | INIT_LIST_HEAD(&dev->t10_alua.lba_map_list); | ||
1533 | spin_lock_init(&dev->t10_alua.lba_map_lock); | ||
1447 | 1534 | ||
1448 | dev->t10_wwn.t10_dev = dev; | 1535 | dev->t10_wwn.t10_dev = dev; |
1449 | dev->t10_alua.t10_dev = dev; | 1536 | dev->t10_alua.t10_dev = dev; |
@@ -1460,6 +1547,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) | |||
1460 | dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; | 1547 | dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; |
1461 | dev->dev_attrib.emulate_caw = DA_EMULATE_CAW; | 1548 | dev->dev_attrib.emulate_caw = DA_EMULATE_CAW; |
1462 | dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC; | 1549 | dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC; |
1550 | dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE0_PROT; | ||
1463 | dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; | 1551 | dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; |
1464 | dev->dev_attrib.is_nonrot = DA_IS_NONROT; | 1552 | dev->dev_attrib.is_nonrot = DA_IS_NONROT; |
1465 | dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; | 1553 | dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; |
@@ -1588,9 +1676,13 @@ void target_free_device(struct se_device *dev) | |||
1588 | } | 1676 | } |
1589 | 1677 | ||
1590 | core_alua_free_lu_gp_mem(dev); | 1678 | core_alua_free_lu_gp_mem(dev); |
1679 | core_alua_set_lba_map(dev, NULL, 0, 0); | ||
1591 | core_scsi3_free_all_registrations(dev); | 1680 | core_scsi3_free_all_registrations(dev); |
1592 | se_release_vpd_for_dev(dev); | 1681 | se_release_vpd_for_dev(dev); |
1593 | 1682 | ||
1683 | if (dev->transport->free_prot) | ||
1684 | dev->transport->free_prot(dev); | ||
1685 | |||
1594 | dev->transport->free_device(dev); | 1686 | dev->transport->free_device(dev); |
1595 | } | 1687 | } |
1596 | 1688 | ||
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index dae2ad6a669e..7de9f0475d05 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c | |||
@@ -906,7 +906,7 @@ static struct config_group *target_fabric_make_lun( | |||
906 | lun_cg->default_groups[1] = NULL; | 906 | lun_cg->default_groups[1] = NULL; |
907 | 907 | ||
908 | port_stat_grp = &lun->port_stat_grps.stat_group; | 908 | port_stat_grp = &lun->port_stat_grps.stat_group; |
909 | port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3, | 909 | port_stat_grp->default_groups = kzalloc(sizeof(struct config_group *) * 4, |
910 | GFP_KERNEL); | 910 | GFP_KERNEL); |
911 | if (!port_stat_grp->default_groups) { | 911 | if (!port_stat_grp->default_groups) { |
912 | pr_err("Unable to allocate port_stat_grp->default_groups\n"); | 912 | pr_err("Unable to allocate port_stat_grp->default_groups\n"); |
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 78241a53b555..cf991a91a8a9 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
@@ -257,6 +257,72 @@ static void fd_free_device(struct se_device *dev) | |||
257 | kfree(fd_dev); | 257 | kfree(fd_dev); |
258 | } | 258 | } |
259 | 259 | ||
260 | static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot, | ||
261 | int is_write) | ||
262 | { | ||
263 | struct se_device *se_dev = cmd->se_dev; | ||
264 | struct fd_dev *dev = FD_DEV(se_dev); | ||
265 | struct file *prot_fd = dev->fd_prot_file; | ||
266 | struct scatterlist *sg; | ||
267 | loff_t pos = (cmd->t_task_lba * se_dev->prot_length); | ||
268 | unsigned char *buf; | ||
269 | u32 prot_size, len, size; | ||
270 | int rc, ret = 1, i; | ||
271 | |||
272 | prot_size = (cmd->data_length / se_dev->dev_attrib.block_size) * | ||
273 | se_dev->prot_length; | ||
274 | |||
275 | if (!is_write) { | ||
276 | fd_prot->prot_buf = vzalloc(prot_size); | ||
277 | if (!fd_prot->prot_buf) { | ||
278 | pr_err("Unable to allocate fd_prot->prot_buf\n"); | ||
279 | return -ENOMEM; | ||
280 | } | ||
281 | buf = fd_prot->prot_buf; | ||
282 | |||
283 | fd_prot->prot_sg_nents = cmd->t_prot_nents; | ||
284 | fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist) * | ||
285 | fd_prot->prot_sg_nents, GFP_KERNEL); | ||
286 | if (!fd_prot->prot_sg) { | ||
287 | pr_err("Unable to allocate fd_prot->prot_sg\n"); | ||
288 | vfree(fd_prot->prot_buf); | ||
289 | return -ENOMEM; | ||
290 | } | ||
291 | size = prot_size; | ||
292 | |||
293 | for_each_sg(fd_prot->prot_sg, sg, fd_prot->prot_sg_nents, i) { | ||
294 | |||
295 | len = min_t(u32, PAGE_SIZE, size); | ||
296 | sg_set_buf(sg, buf, len); | ||
297 | size -= len; | ||
298 | buf += len; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | if (is_write) { | ||
303 | rc = kernel_write(prot_fd, fd_prot->prot_buf, prot_size, pos); | ||
304 | if (rc < 0 || prot_size != rc) { | ||
305 | pr_err("kernel_write() for fd_do_prot_rw failed:" | ||
306 | " %d\n", rc); | ||
307 | ret = -EINVAL; | ||
308 | } | ||
309 | } else { | ||
310 | rc = kernel_read(prot_fd, pos, fd_prot->prot_buf, prot_size); | ||
311 | if (rc < 0) { | ||
312 | pr_err("kernel_read() for fd_do_prot_rw failed:" | ||
313 | " %d\n", rc); | ||
314 | ret = -EINVAL; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | if (is_write || ret < 0) { | ||
319 | kfree(fd_prot->prot_sg); | ||
320 | vfree(fd_prot->prot_buf); | ||
321 | } | ||
322 | |||
323 | return ret; | ||
324 | } | ||
325 | |||
260 | static int fd_do_rw(struct se_cmd *cmd, struct scatterlist *sgl, | 326 | static int fd_do_rw(struct se_cmd *cmd, struct scatterlist *sgl, |
261 | u32 sgl_nents, int is_write) | 327 | u32 sgl_nents, int is_write) |
262 | { | 328 | { |
@@ -551,6 +617,8 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
551 | enum dma_data_direction data_direction) | 617 | enum dma_data_direction data_direction) |
552 | { | 618 | { |
553 | struct se_device *dev = cmd->se_dev; | 619 | struct se_device *dev = cmd->se_dev; |
620 | struct fd_prot fd_prot; | ||
621 | sense_reason_t rc; | ||
554 | int ret = 0; | 622 | int ret = 0; |
555 | 623 | ||
556 | /* | 624 | /* |
@@ -558,8 +626,48 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
558 | * physical memory addresses to struct iovec virtual memory. | 626 | * physical memory addresses to struct iovec virtual memory. |
559 | */ | 627 | */ |
560 | if (data_direction == DMA_FROM_DEVICE) { | 628 | if (data_direction == DMA_FROM_DEVICE) { |
629 | memset(&fd_prot, 0, sizeof(struct fd_prot)); | ||
630 | |||
631 | if (cmd->prot_type) { | ||
632 | ret = fd_do_prot_rw(cmd, &fd_prot, false); | ||
633 | if (ret < 0) | ||
634 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
635 | } | ||
636 | |||
561 | ret = fd_do_rw(cmd, sgl, sgl_nents, 0); | 637 | ret = fd_do_rw(cmd, sgl, sgl_nents, 0); |
638 | |||
639 | if (ret > 0 && cmd->prot_type) { | ||
640 | u32 sectors = cmd->data_length / dev->dev_attrib.block_size; | ||
641 | |||
642 | rc = sbc_dif_verify_read(cmd, cmd->t_task_lba, sectors, | ||
643 | 0, fd_prot.prot_sg, 0); | ||
644 | if (rc) { | ||
645 | kfree(fd_prot.prot_sg); | ||
646 | vfree(fd_prot.prot_buf); | ||
647 | return rc; | ||
648 | } | ||
649 | kfree(fd_prot.prot_sg); | ||
650 | vfree(fd_prot.prot_buf); | ||
651 | } | ||
562 | } else { | 652 | } else { |
653 | memset(&fd_prot, 0, sizeof(struct fd_prot)); | ||
654 | |||
655 | if (cmd->prot_type) { | ||
656 | u32 sectors = cmd->data_length / dev->dev_attrib.block_size; | ||
657 | |||
658 | ret = fd_do_prot_rw(cmd, &fd_prot, false); | ||
659 | if (ret < 0) | ||
660 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
661 | |||
662 | rc = sbc_dif_verify_write(cmd, cmd->t_task_lba, sectors, | ||
663 | 0, fd_prot.prot_sg, 0); | ||
664 | if (rc) { | ||
665 | kfree(fd_prot.prot_sg); | ||
666 | vfree(fd_prot.prot_buf); | ||
667 | return rc; | ||
668 | } | ||
669 | } | ||
670 | |||
563 | ret = fd_do_rw(cmd, sgl, sgl_nents, 1); | 671 | ret = fd_do_rw(cmd, sgl, sgl_nents, 1); |
564 | /* | 672 | /* |
565 | * Perform implicit vfs_fsync_range() for fd_do_writev() ops | 673 | * Perform implicit vfs_fsync_range() for fd_do_writev() ops |
@@ -576,10 +684,19 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
576 | 684 | ||
577 | vfs_fsync_range(fd_dev->fd_file, start, end, 1); | 685 | vfs_fsync_range(fd_dev->fd_file, start, end, 1); |
578 | } | 686 | } |
687 | |||
688 | if (ret > 0 && cmd->prot_type) { | ||
689 | ret = fd_do_prot_rw(cmd, &fd_prot, true); | ||
690 | if (ret < 0) | ||
691 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
692 | } | ||
579 | } | 693 | } |
580 | 694 | ||
581 | if (ret < 0) | 695 | if (ret < 0) { |
696 | kfree(fd_prot.prot_sg); | ||
697 | vfree(fd_prot.prot_buf); | ||
582 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 698 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
699 | } | ||
583 | 700 | ||
584 | if (ret) | 701 | if (ret) |
585 | target_complete_cmd(cmd, SAM_STAT_GOOD); | 702 | target_complete_cmd(cmd, SAM_STAT_GOOD); |
@@ -700,6 +817,140 @@ static sector_t fd_get_blocks(struct se_device *dev) | |||
700 | dev->dev_attrib.block_size); | 817 | dev->dev_attrib.block_size); |
701 | } | 818 | } |
702 | 819 | ||
820 | static int fd_init_prot(struct se_device *dev) | ||
821 | { | ||
822 | struct fd_dev *fd_dev = FD_DEV(dev); | ||
823 | struct file *prot_file, *file = fd_dev->fd_file; | ||
824 | struct inode *inode; | ||
825 | int ret, flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; | ||
826 | char buf[FD_MAX_DEV_PROT_NAME]; | ||
827 | |||
828 | if (!file) { | ||
829 | pr_err("Unable to locate fd_dev->fd_file\n"); | ||
830 | return -ENODEV; | ||
831 | } | ||
832 | |||
833 | inode = file->f_mapping->host; | ||
834 | if (S_ISBLK(inode->i_mode)) { | ||
835 | pr_err("FILEIO Protection emulation only supported on" | ||
836 | " !S_ISBLK\n"); | ||
837 | return -ENOSYS; | ||
838 | } | ||
839 | |||
840 | if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) | ||
841 | flags &= ~O_DSYNC; | ||
842 | |||
843 | snprintf(buf, FD_MAX_DEV_PROT_NAME, "%s.protection", | ||
844 | fd_dev->fd_dev_name); | ||
845 | |||
846 | prot_file = filp_open(buf, flags, 0600); | ||
847 | if (IS_ERR(prot_file)) { | ||
848 | pr_err("filp_open(%s) failed\n", buf); | ||
849 | ret = PTR_ERR(prot_file); | ||
850 | return ret; | ||
851 | } | ||
852 | fd_dev->fd_prot_file = prot_file; | ||
853 | |||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | static void fd_init_format_buf(struct se_device *dev, unsigned char *buf, | ||
858 | u32 unit_size, u32 *ref_tag, u16 app_tag, | ||
859 | bool inc_reftag) | ||
860 | { | ||
861 | unsigned char *p = buf; | ||
862 | int i; | ||
863 | |||
864 | for (i = 0; i < unit_size; i += dev->prot_length) { | ||
865 | *((u16 *)&p[0]) = 0xffff; | ||
866 | *((__be16 *)&p[2]) = cpu_to_be16(app_tag); | ||
867 | *((__be32 *)&p[4]) = cpu_to_be32(*ref_tag); | ||
868 | |||
869 | if (inc_reftag) | ||
870 | (*ref_tag)++; | ||
871 | |||
872 | p += dev->prot_length; | ||
873 | } | ||
874 | } | ||
875 | |||
876 | static int fd_format_prot(struct se_device *dev) | ||
877 | { | ||
878 | struct fd_dev *fd_dev = FD_DEV(dev); | ||
879 | struct file *prot_fd = fd_dev->fd_prot_file; | ||
880 | sector_t prot_length, prot; | ||
881 | unsigned char *buf; | ||
882 | loff_t pos = 0; | ||
883 | u32 ref_tag = 0; | ||
884 | int unit_size = FDBD_FORMAT_UNIT_SIZE * dev->dev_attrib.block_size; | ||
885 | int rc, ret = 0, size, len; | ||
886 | bool inc_reftag = false; | ||
887 | |||
888 | if (!dev->dev_attrib.pi_prot_type) { | ||
889 | pr_err("Unable to format_prot while pi_prot_type == 0\n"); | ||
890 | return -ENODEV; | ||
891 | } | ||
892 | if (!prot_fd) { | ||
893 | pr_err("Unable to locate fd_dev->fd_prot_file\n"); | ||
894 | return -ENODEV; | ||
895 | } | ||
896 | |||
897 | switch (dev->dev_attrib.pi_prot_type) { | ||
898 | case TARGET_DIF_TYPE3_PROT: | ||
899 | ref_tag = 0xffffffff; | ||
900 | break; | ||
901 | case TARGET_DIF_TYPE2_PROT: | ||
902 | case TARGET_DIF_TYPE1_PROT: | ||
903 | inc_reftag = true; | ||
904 | break; | ||
905 | default: | ||
906 | break; | ||
907 | } | ||
908 | |||
909 | buf = vzalloc(unit_size); | ||
910 | if (!buf) { | ||
911 | pr_err("Unable to allocate FILEIO prot buf\n"); | ||
912 | return -ENOMEM; | ||
913 | } | ||
914 | |||
915 | prot_length = (dev->transport->get_blocks(dev) + 1) * dev->prot_length; | ||
916 | size = prot_length; | ||
917 | |||
918 | pr_debug("Using FILEIO prot_length: %llu\n", | ||
919 | (unsigned long long)prot_length); | ||
920 | |||
921 | for (prot = 0; prot < prot_length; prot += unit_size) { | ||
922 | |||
923 | fd_init_format_buf(dev, buf, unit_size, &ref_tag, 0xffff, | ||
924 | inc_reftag); | ||
925 | |||
926 | len = min(unit_size, size); | ||
927 | |||
928 | rc = kernel_write(prot_fd, buf, len, pos); | ||
929 | if (rc != len) { | ||
930 | pr_err("vfs_write to prot file failed: %d\n", rc); | ||
931 | ret = -ENODEV; | ||
932 | goto out; | ||
933 | } | ||
934 | pos += len; | ||
935 | size -= len; | ||
936 | } | ||
937 | |||
938 | out: | ||
939 | vfree(buf); | ||
940 | return ret; | ||
941 | } | ||
942 | |||
943 | static void fd_free_prot(struct se_device *dev) | ||
944 | { | ||
945 | struct fd_dev *fd_dev = FD_DEV(dev); | ||
946 | |||
947 | if (!fd_dev->fd_prot_file) | ||
948 | return; | ||
949 | |||
950 | filp_close(fd_dev->fd_prot_file, NULL); | ||
951 | fd_dev->fd_prot_file = NULL; | ||
952 | } | ||
953 | |||
703 | static struct sbc_ops fd_sbc_ops = { | 954 | static struct sbc_ops fd_sbc_ops = { |
704 | .execute_rw = fd_execute_rw, | 955 | .execute_rw = fd_execute_rw, |
705 | .execute_sync_cache = fd_execute_sync_cache, | 956 | .execute_sync_cache = fd_execute_sync_cache, |
@@ -730,6 +981,9 @@ static struct se_subsystem_api fileio_template = { | |||
730 | .show_configfs_dev_params = fd_show_configfs_dev_params, | 981 | .show_configfs_dev_params = fd_show_configfs_dev_params, |
731 | .get_device_type = sbc_get_device_type, | 982 | .get_device_type = sbc_get_device_type, |
732 | .get_blocks = fd_get_blocks, | 983 | .get_blocks = fd_get_blocks, |
984 | .init_prot = fd_init_prot, | ||
985 | .format_prot = fd_format_prot, | ||
986 | .free_prot = fd_free_prot, | ||
733 | }; | 987 | }; |
734 | 988 | ||
735 | static int __init fileio_module_init(void) | 989 | static int __init fileio_module_init(void) |
diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h index d7772c167685..182cbb295039 100644 --- a/drivers/target/target_core_file.h +++ b/drivers/target/target_core_file.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #define FD_VERSION "4.0" | 4 | #define FD_VERSION "4.0" |
5 | 5 | ||
6 | #define FD_MAX_DEV_NAME 256 | 6 | #define FD_MAX_DEV_NAME 256 |
7 | #define FD_MAX_DEV_PROT_NAME FD_MAX_DEV_NAME + 16 | ||
7 | #define FD_DEVICE_QUEUE_DEPTH 32 | 8 | #define FD_DEVICE_QUEUE_DEPTH 32 |
8 | #define FD_MAX_DEVICE_QUEUE_DEPTH 128 | 9 | #define FD_MAX_DEVICE_QUEUE_DEPTH 128 |
9 | #define FD_BLOCKSIZE 512 | 10 | #define FD_BLOCKSIZE 512 |
@@ -18,6 +19,13 @@ | |||
18 | #define FBDF_HAS_PATH 0x01 | 19 | #define FBDF_HAS_PATH 0x01 |
19 | #define FBDF_HAS_SIZE 0x02 | 20 | #define FBDF_HAS_SIZE 0x02 |
20 | #define FDBD_HAS_BUFFERED_IO_WCE 0x04 | 21 | #define FDBD_HAS_BUFFERED_IO_WCE 0x04 |
22 | #define FDBD_FORMAT_UNIT_SIZE 2048 | ||
23 | |||
24 | struct fd_prot { | ||
25 | unsigned char *prot_buf; | ||
26 | struct scatterlist *prot_sg; | ||
27 | u32 prot_sg_nents; | ||
28 | }; | ||
21 | 29 | ||
22 | struct fd_dev { | 30 | struct fd_dev { |
23 | struct se_device dev; | 31 | struct se_device dev; |
@@ -32,6 +40,7 @@ struct fd_dev { | |||
32 | u32 fd_block_size; | 40 | u32 fd_block_size; |
33 | unsigned long long fd_dev_size; | 41 | unsigned long long fd_dev_size; |
34 | struct file *fd_file; | 42 | struct file *fd_file; |
43 | struct file *fd_prot_file; | ||
35 | /* FILEIO HBA device is connected to */ | 44 | /* FILEIO HBA device is connected to */ |
36 | struct fd_host *fd_host; | 45 | struct fd_host *fd_host; |
37 | } ____cacheline_aligned; | 46 | } ____cacheline_aligned; |
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 2d29356d0c85..554d4f75a75a 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
@@ -91,6 +91,7 @@ static int iblock_configure_device(struct se_device *dev) | |||
91 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); | 91 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
92 | struct request_queue *q; | 92 | struct request_queue *q; |
93 | struct block_device *bd = NULL; | 93 | struct block_device *bd = NULL; |
94 | struct blk_integrity *bi; | ||
94 | fmode_t mode; | 95 | fmode_t mode; |
95 | int ret = -ENOMEM; | 96 | int ret = -ENOMEM; |
96 | 97 | ||
@@ -155,8 +156,40 @@ static int iblock_configure_device(struct se_device *dev) | |||
155 | if (blk_queue_nonrot(q)) | 156 | if (blk_queue_nonrot(q)) |
156 | dev->dev_attrib.is_nonrot = 1; | 157 | dev->dev_attrib.is_nonrot = 1; |
157 | 158 | ||
159 | bi = bdev_get_integrity(bd); | ||
160 | if (bi) { | ||
161 | struct bio_set *bs = ib_dev->ibd_bio_set; | ||
162 | |||
163 | if (!strcmp(bi->name, "T10-DIF-TYPE3-IP") || | ||
164 | !strcmp(bi->name, "T10-DIF-TYPE1-IP")) { | ||
165 | pr_err("IBLOCK export of blk_integrity: %s not" | ||
166 | " supported\n", bi->name); | ||
167 | ret = -ENOSYS; | ||
168 | goto out_blkdev_put; | ||
169 | } | ||
170 | |||
171 | if (!strcmp(bi->name, "T10-DIF-TYPE3-CRC")) { | ||
172 | dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT; | ||
173 | } else if (!strcmp(bi->name, "T10-DIF-TYPE1-CRC")) { | ||
174 | dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE1_PROT; | ||
175 | } | ||
176 | |||
177 | if (dev->dev_attrib.pi_prot_type) { | ||
178 | if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) { | ||
179 | pr_err("Unable to allocate bioset for PI\n"); | ||
180 | ret = -ENOMEM; | ||
181 | goto out_blkdev_put; | ||
182 | } | ||
183 | pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n", | ||
184 | bs->bio_integrity_pool); | ||
185 | } | ||
186 | dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type; | ||
187 | } | ||
188 | |||
158 | return 0; | 189 | return 0; |
159 | 190 | ||
191 | out_blkdev_put: | ||
192 | blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); | ||
160 | out_free_bioset: | 193 | out_free_bioset: |
161 | bioset_free(ib_dev->ibd_bio_set); | 194 | bioset_free(ib_dev->ibd_bio_set); |
162 | ib_dev->ibd_bio_set = NULL; | 195 | ib_dev->ibd_bio_set = NULL; |
@@ -170,8 +203,10 @@ static void iblock_free_device(struct se_device *dev) | |||
170 | 203 | ||
171 | if (ib_dev->ibd_bd != NULL) | 204 | if (ib_dev->ibd_bd != NULL) |
172 | blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); | 205 | blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); |
173 | if (ib_dev->ibd_bio_set != NULL) | 206 | if (ib_dev->ibd_bio_set != NULL) { |
207 | bioset_integrity_free(ib_dev->ibd_bio_set); | ||
174 | bioset_free(ib_dev->ibd_bio_set); | 208 | bioset_free(ib_dev->ibd_bio_set); |
209 | } | ||
175 | kfree(ib_dev); | 210 | kfree(ib_dev); |
176 | } | 211 | } |
177 | 212 | ||
@@ -586,13 +621,58 @@ static ssize_t iblock_show_configfs_dev_params(struct se_device *dev, char *b) | |||
586 | return bl; | 621 | return bl; |
587 | } | 622 | } |
588 | 623 | ||
624 | static int | ||
625 | iblock_alloc_bip(struct se_cmd *cmd, struct bio *bio) | ||
626 | { | ||
627 | struct se_device *dev = cmd->se_dev; | ||
628 | struct blk_integrity *bi; | ||
629 | struct bio_integrity_payload *bip; | ||
630 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); | ||
631 | struct scatterlist *sg; | ||
632 | int i, rc; | ||
633 | |||
634 | bi = bdev_get_integrity(ib_dev->ibd_bd); | ||
635 | if (!bi) { | ||
636 | pr_err("Unable to locate bio_integrity\n"); | ||
637 | return -ENODEV; | ||
638 | } | ||
639 | |||
640 | bip = bio_integrity_alloc(bio, GFP_NOIO, cmd->t_prot_nents); | ||
641 | if (!bip) { | ||
642 | pr_err("Unable to allocate bio_integrity_payload\n"); | ||
643 | return -ENOMEM; | ||
644 | } | ||
645 | |||
646 | bip->bip_iter.bi_size = (cmd->data_length / dev->dev_attrib.block_size) * | ||
647 | dev->prot_length; | ||
648 | bip->bip_iter.bi_sector = bio->bi_iter.bi_sector; | ||
649 | |||
650 | pr_debug("IBLOCK BIP Size: %u Sector: %llu\n", bip->bip_iter.bi_size, | ||
651 | (unsigned long long)bip->bip_iter.bi_sector); | ||
652 | |||
653 | for_each_sg(cmd->t_prot_sg, sg, cmd->t_prot_nents, i) { | ||
654 | |||
655 | rc = bio_integrity_add_page(bio, sg_page(sg), sg->length, | ||
656 | sg->offset); | ||
657 | if (rc != sg->length) { | ||
658 | pr_err("bio_integrity_add_page() failed; %d\n", rc); | ||
659 | return -ENOMEM; | ||
660 | } | ||
661 | |||
662 | pr_debug("Added bio integrity page: %p length: %d offset; %d\n", | ||
663 | sg_page(sg), sg->length, sg->offset); | ||
664 | } | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
589 | static sense_reason_t | 669 | static sense_reason_t |
590 | iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | 670 | iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, |
591 | enum dma_data_direction data_direction) | 671 | enum dma_data_direction data_direction) |
592 | { | 672 | { |
593 | struct se_device *dev = cmd->se_dev; | 673 | struct se_device *dev = cmd->se_dev; |
594 | struct iblock_req *ibr; | 674 | struct iblock_req *ibr; |
595 | struct bio *bio; | 675 | struct bio *bio, *bio_start; |
596 | struct bio_list list; | 676 | struct bio_list list; |
597 | struct scatterlist *sg; | 677 | struct scatterlist *sg; |
598 | u32 sg_num = sgl_nents; | 678 | u32 sg_num = sgl_nents; |
@@ -655,6 +735,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
655 | if (!bio) | 735 | if (!bio) |
656 | goto fail_free_ibr; | 736 | goto fail_free_ibr; |
657 | 737 | ||
738 | bio_start = bio; | ||
658 | bio_list_init(&list); | 739 | bio_list_init(&list); |
659 | bio_list_add(&list, bio); | 740 | bio_list_add(&list, bio); |
660 | 741 | ||
@@ -688,6 +769,12 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
688 | sg_num--; | 769 | sg_num--; |
689 | } | 770 | } |
690 | 771 | ||
772 | if (cmd->prot_type) { | ||
773 | int rc = iblock_alloc_bip(cmd, bio_start); | ||
774 | if (rc) | ||
775 | goto fail_put_bios; | ||
776 | } | ||
777 | |||
691 | iblock_submit_bios(&list, rw); | 778 | iblock_submit_bios(&list, rw); |
692 | iblock_complete_cmd(cmd); | 779 | iblock_complete_cmd(cmd); |
693 | return 0; | 780 | return 0; |
@@ -763,7 +850,7 @@ iblock_parse_cdb(struct se_cmd *cmd) | |||
763 | return sbc_parse_cdb(cmd, &iblock_sbc_ops); | 850 | return sbc_parse_cdb(cmd, &iblock_sbc_ops); |
764 | } | 851 | } |
765 | 852 | ||
766 | bool iblock_get_write_cache(struct se_device *dev) | 853 | static bool iblock_get_write_cache(struct se_device *dev) |
767 | { | 854 | { |
768 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); | 855 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
769 | struct block_device *bd = ib_dev->ibd_bd; | 856 | struct block_device *bd = ib_dev->ibd_bd; |
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 47b63b094cdc..de9cab708f45 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h | |||
@@ -35,6 +35,8 @@ int se_dev_set_emulate_tpu(struct se_device *, int); | |||
35 | int se_dev_set_emulate_tpws(struct se_device *, int); | 35 | int se_dev_set_emulate_tpws(struct se_device *, int); |
36 | int se_dev_set_emulate_caw(struct se_device *, int); | 36 | int se_dev_set_emulate_caw(struct se_device *, int); |
37 | int se_dev_set_emulate_3pc(struct se_device *, int); | 37 | int se_dev_set_emulate_3pc(struct se_device *, int); |
38 | int se_dev_set_pi_prot_type(struct se_device *, int); | ||
39 | int se_dev_set_pi_prot_format(struct se_device *, int); | ||
38 | int se_dev_set_enforce_pr_isids(struct se_device *, int); | 40 | int se_dev_set_enforce_pr_isids(struct se_device *, int); |
39 | int se_dev_set_is_nonrot(struct se_device *, int); | 41 | int se_dev_set_is_nonrot(struct se_device *, int); |
40 | int se_dev_set_emulate_rest_reord(struct se_device *dev, int); | 42 | int se_dev_set_emulate_rest_reord(struct se_device *dev, int); |
@@ -77,9 +79,9 @@ struct se_node_acl *__core_tpg_get_initiator_node_acl(struct se_portal_group *tp | |||
77 | const char *); | 79 | const char *); |
78 | void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *); | 80 | void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *); |
79 | void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *); | 81 | void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *); |
80 | struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32); | 82 | struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u32); |
81 | int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *, | 83 | int core_tpg_add_lun(struct se_portal_group *, struct se_lun *, |
82 | u32, void *); | 84 | u32, struct se_device *); |
83 | struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun); | 85 | struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun); |
84 | int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *); | 86 | int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *); |
85 | 87 | ||
diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h index ed75cdd32cb0..2ee2936fa0bd 100644 --- a/drivers/target/target_core_pr.h +++ b/drivers/target/target_core_pr.h | |||
@@ -43,6 +43,11 @@ | |||
43 | #define PR_APTPL_MAX_IPORT_LEN 256 | 43 | #define PR_APTPL_MAX_IPORT_LEN 256 |
44 | #define PR_APTPL_MAX_TPORT_LEN 256 | 44 | #define PR_APTPL_MAX_TPORT_LEN 256 |
45 | 45 | ||
46 | /* | ||
47 | * Function defined in target_core_spc.c | ||
48 | */ | ||
49 | void spc_parse_naa_6h_vendor_specific(struct se_device *, unsigned char *); | ||
50 | |||
46 | extern struct kmem_cache *t10_pr_reg_cache; | 51 | extern struct kmem_cache *t10_pr_reg_cache; |
47 | 52 | ||
48 | extern void core_pr_dump_initiator_port(struct t10_pr_registration *, | 53 | extern void core_pr_dump_initiator_port(struct t10_pr_registration *, |
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 4ffe5f2ec0e9..66a5aba5a0d9 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c | |||
@@ -78,23 +78,14 @@ static void rd_detach_hba(struct se_hba *hba) | |||
78 | hba->hba_ptr = NULL; | 78 | hba->hba_ptr = NULL; |
79 | } | 79 | } |
80 | 80 | ||
81 | /* rd_release_device_space(): | 81 | static u32 rd_release_sgl_table(struct rd_dev *rd_dev, struct rd_dev_sg_table *sg_table, |
82 | * | 82 | u32 sg_table_count) |
83 | * | ||
84 | */ | ||
85 | static void rd_release_device_space(struct rd_dev *rd_dev) | ||
86 | { | 83 | { |
87 | u32 i, j, page_count = 0, sg_per_table; | ||
88 | struct rd_dev_sg_table *sg_table; | ||
89 | struct page *pg; | 84 | struct page *pg; |
90 | struct scatterlist *sg; | 85 | struct scatterlist *sg; |
86 | u32 i, j, page_count = 0, sg_per_table; | ||
91 | 87 | ||
92 | if (!rd_dev->sg_table_array || !rd_dev->sg_table_count) | 88 | for (i = 0; i < sg_table_count; i++) { |
93 | return; | ||
94 | |||
95 | sg_table = rd_dev->sg_table_array; | ||
96 | |||
97 | for (i = 0; i < rd_dev->sg_table_count; i++) { | ||
98 | sg = sg_table[i].sg_table; | 89 | sg = sg_table[i].sg_table; |
99 | sg_per_table = sg_table[i].rd_sg_count; | 90 | sg_per_table = sg_table[i].rd_sg_count; |
100 | 91 | ||
@@ -105,16 +96,28 @@ static void rd_release_device_space(struct rd_dev *rd_dev) | |||
105 | page_count++; | 96 | page_count++; |
106 | } | 97 | } |
107 | } | 98 | } |
108 | |||
109 | kfree(sg); | 99 | kfree(sg); |
110 | } | 100 | } |
111 | 101 | ||
102 | kfree(sg_table); | ||
103 | return page_count; | ||
104 | } | ||
105 | |||
106 | static void rd_release_device_space(struct rd_dev *rd_dev) | ||
107 | { | ||
108 | u32 page_count; | ||
109 | |||
110 | if (!rd_dev->sg_table_array || !rd_dev->sg_table_count) | ||
111 | return; | ||
112 | |||
113 | page_count = rd_release_sgl_table(rd_dev, rd_dev->sg_table_array, | ||
114 | rd_dev->sg_table_count); | ||
115 | |||
112 | pr_debug("CORE_RD[%u] - Released device space for Ramdisk" | 116 | pr_debug("CORE_RD[%u] - Released device space for Ramdisk" |
113 | " Device ID: %u, pages %u in %u tables total bytes %lu\n", | 117 | " Device ID: %u, pages %u in %u tables total bytes %lu\n", |
114 | rd_dev->rd_host->rd_host_id, rd_dev->rd_dev_id, page_count, | 118 | rd_dev->rd_host->rd_host_id, rd_dev->rd_dev_id, page_count, |
115 | rd_dev->sg_table_count, (unsigned long)page_count * PAGE_SIZE); | 119 | rd_dev->sg_table_count, (unsigned long)page_count * PAGE_SIZE); |
116 | 120 | ||
117 | kfree(sg_table); | ||
118 | rd_dev->sg_table_array = NULL; | 121 | rd_dev->sg_table_array = NULL; |
119 | rd_dev->sg_table_count = 0; | 122 | rd_dev->sg_table_count = 0; |
120 | } | 123 | } |
@@ -124,38 +127,15 @@ static void rd_release_device_space(struct rd_dev *rd_dev) | |||
124 | * | 127 | * |
125 | * | 128 | * |
126 | */ | 129 | */ |
127 | static int rd_build_device_space(struct rd_dev *rd_dev) | 130 | static int rd_allocate_sgl_table(struct rd_dev *rd_dev, struct rd_dev_sg_table *sg_table, |
131 | u32 total_sg_needed, unsigned char init_payload) | ||
128 | { | 132 | { |
129 | u32 i = 0, j, page_offset = 0, sg_per_table, sg_tables, total_sg_needed; | 133 | u32 i = 0, j, page_offset = 0, sg_per_table; |
130 | u32 max_sg_per_table = (RD_MAX_ALLOCATION_SIZE / | 134 | u32 max_sg_per_table = (RD_MAX_ALLOCATION_SIZE / |
131 | sizeof(struct scatterlist)); | 135 | sizeof(struct scatterlist)); |
132 | struct rd_dev_sg_table *sg_table; | ||
133 | struct page *pg; | 136 | struct page *pg; |
134 | struct scatterlist *sg; | 137 | struct scatterlist *sg; |
135 | 138 | unsigned char *p; | |
136 | if (rd_dev->rd_page_count <= 0) { | ||
137 | pr_err("Illegal page count: %u for Ramdisk device\n", | ||
138 | rd_dev->rd_page_count); | ||
139 | return -EINVAL; | ||
140 | } | ||
141 | |||
142 | /* Don't need backing pages for NULLIO */ | ||
143 | if (rd_dev->rd_flags & RDF_NULLIO) | ||
144 | return 0; | ||
145 | |||
146 | total_sg_needed = rd_dev->rd_page_count; | ||
147 | |||
148 | sg_tables = (total_sg_needed / max_sg_per_table) + 1; | ||
149 | |||
150 | sg_table = kzalloc(sg_tables * sizeof(struct rd_dev_sg_table), GFP_KERNEL); | ||
151 | if (!sg_table) { | ||
152 | pr_err("Unable to allocate memory for Ramdisk" | ||
153 | " scatterlist tables\n"); | ||
154 | return -ENOMEM; | ||
155 | } | ||
156 | |||
157 | rd_dev->sg_table_array = sg_table; | ||
158 | rd_dev->sg_table_count = sg_tables; | ||
159 | 139 | ||
160 | while (total_sg_needed) { | 140 | while (total_sg_needed) { |
161 | sg_per_table = (total_sg_needed > max_sg_per_table) ? | 141 | sg_per_table = (total_sg_needed > max_sg_per_table) ? |
@@ -186,16 +166,114 @@ static int rd_build_device_space(struct rd_dev *rd_dev) | |||
186 | } | 166 | } |
187 | sg_assign_page(&sg[j], pg); | 167 | sg_assign_page(&sg[j], pg); |
188 | sg[j].length = PAGE_SIZE; | 168 | sg[j].length = PAGE_SIZE; |
169 | |||
170 | p = kmap(pg); | ||
171 | memset(p, init_payload, PAGE_SIZE); | ||
172 | kunmap(pg); | ||
189 | } | 173 | } |
190 | 174 | ||
191 | page_offset += sg_per_table; | 175 | page_offset += sg_per_table; |
192 | total_sg_needed -= sg_per_table; | 176 | total_sg_needed -= sg_per_table; |
193 | } | 177 | } |
194 | 178 | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int rd_build_device_space(struct rd_dev *rd_dev) | ||
183 | { | ||
184 | struct rd_dev_sg_table *sg_table; | ||
185 | u32 sg_tables, total_sg_needed; | ||
186 | u32 max_sg_per_table = (RD_MAX_ALLOCATION_SIZE / | ||
187 | sizeof(struct scatterlist)); | ||
188 | int rc; | ||
189 | |||
190 | if (rd_dev->rd_page_count <= 0) { | ||
191 | pr_err("Illegal page count: %u for Ramdisk device\n", | ||
192 | rd_dev->rd_page_count); | ||
193 | return -EINVAL; | ||
194 | } | ||
195 | |||
196 | /* Don't need backing pages for NULLIO */ | ||
197 | if (rd_dev->rd_flags & RDF_NULLIO) | ||
198 | return 0; | ||
199 | |||
200 | total_sg_needed = rd_dev->rd_page_count; | ||
201 | |||
202 | sg_tables = (total_sg_needed / max_sg_per_table) + 1; | ||
203 | |||
204 | sg_table = kzalloc(sg_tables * sizeof(struct rd_dev_sg_table), GFP_KERNEL); | ||
205 | if (!sg_table) { | ||
206 | pr_err("Unable to allocate memory for Ramdisk" | ||
207 | " scatterlist tables\n"); | ||
208 | return -ENOMEM; | ||
209 | } | ||
210 | |||
211 | rd_dev->sg_table_array = sg_table; | ||
212 | rd_dev->sg_table_count = sg_tables; | ||
213 | |||
214 | rc = rd_allocate_sgl_table(rd_dev, sg_table, total_sg_needed, 0x00); | ||
215 | if (rc) | ||
216 | return rc; | ||
217 | |||
195 | pr_debug("CORE_RD[%u] - Built Ramdisk Device ID: %u space of" | 218 | pr_debug("CORE_RD[%u] - Built Ramdisk Device ID: %u space of" |
196 | " %u pages in %u tables\n", rd_dev->rd_host->rd_host_id, | 219 | " %u pages in %u tables\n", rd_dev->rd_host->rd_host_id, |
197 | rd_dev->rd_dev_id, rd_dev->rd_page_count, | 220 | rd_dev->rd_dev_id, rd_dev->rd_page_count, |
198 | rd_dev->sg_table_count); | 221 | rd_dev->sg_table_count); |
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static void rd_release_prot_space(struct rd_dev *rd_dev) | ||
227 | { | ||
228 | u32 page_count; | ||
229 | |||
230 | if (!rd_dev->sg_prot_array || !rd_dev->sg_prot_count) | ||
231 | return; | ||
232 | |||
233 | page_count = rd_release_sgl_table(rd_dev, rd_dev->sg_prot_array, | ||
234 | rd_dev->sg_prot_count); | ||
235 | |||
236 | pr_debug("CORE_RD[%u] - Released protection space for Ramdisk" | ||
237 | " Device ID: %u, pages %u in %u tables total bytes %lu\n", | ||
238 | rd_dev->rd_host->rd_host_id, rd_dev->rd_dev_id, page_count, | ||
239 | rd_dev->sg_table_count, (unsigned long)page_count * PAGE_SIZE); | ||
240 | |||
241 | rd_dev->sg_prot_array = NULL; | ||
242 | rd_dev->sg_prot_count = 0; | ||
243 | } | ||
244 | |||
245 | static int rd_build_prot_space(struct rd_dev *rd_dev, int prot_length) | ||
246 | { | ||
247 | struct rd_dev_sg_table *sg_table; | ||
248 | u32 total_sg_needed, sg_tables; | ||
249 | u32 max_sg_per_table = (RD_MAX_ALLOCATION_SIZE / | ||
250 | sizeof(struct scatterlist)); | ||
251 | int rc; | ||
252 | |||
253 | if (rd_dev->rd_flags & RDF_NULLIO) | ||
254 | return 0; | ||
255 | |||
256 | total_sg_needed = rd_dev->rd_page_count / prot_length; | ||
257 | |||
258 | sg_tables = (total_sg_needed / max_sg_per_table) + 1; | ||
259 | |||
260 | sg_table = kzalloc(sg_tables * sizeof(struct rd_dev_sg_table), GFP_KERNEL); | ||
261 | if (!sg_table) { | ||
262 | pr_err("Unable to allocate memory for Ramdisk protection" | ||
263 | " scatterlist tables\n"); | ||
264 | return -ENOMEM; | ||
265 | } | ||
266 | |||
267 | rd_dev->sg_prot_array = sg_table; | ||
268 | rd_dev->sg_prot_count = sg_tables; | ||
269 | |||
270 | rc = rd_allocate_sgl_table(rd_dev, sg_table, total_sg_needed, 0xff); | ||
271 | if (rc) | ||
272 | return rc; | ||
273 | |||
274 | pr_debug("CORE_RD[%u] - Built Ramdisk Device ID: %u prot space of" | ||
275 | " %u pages in %u tables\n", rd_dev->rd_host->rd_host_id, | ||
276 | rd_dev->rd_dev_id, total_sg_needed, rd_dev->sg_prot_count); | ||
199 | 277 | ||
200 | return 0; | 278 | return 0; |
201 | } | 279 | } |
@@ -278,6 +356,26 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page) | |||
278 | return NULL; | 356 | return NULL; |
279 | } | 357 | } |
280 | 358 | ||
359 | static struct rd_dev_sg_table *rd_get_prot_table(struct rd_dev *rd_dev, u32 page) | ||
360 | { | ||
361 | struct rd_dev_sg_table *sg_table; | ||
362 | u32 i, sg_per_table = (RD_MAX_ALLOCATION_SIZE / | ||
363 | sizeof(struct scatterlist)); | ||
364 | |||
365 | i = page / sg_per_table; | ||
366 | if (i < rd_dev->sg_prot_count) { | ||
367 | sg_table = &rd_dev->sg_prot_array[i]; | ||
368 | if ((sg_table->page_start_offset <= page) && | ||
369 | (sg_table->page_end_offset >= page)) | ||
370 | return sg_table; | ||
371 | } | ||
372 | |||
373 | pr_err("Unable to locate struct prot rd_dev_sg_table for page: %u\n", | ||
374 | page); | ||
375 | |||
376 | return NULL; | ||
377 | } | ||
378 | |||
281 | static sense_reason_t | 379 | static sense_reason_t |
282 | rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | 380 | rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, |
283 | enum dma_data_direction data_direction) | 381 | enum dma_data_direction data_direction) |
@@ -292,6 +390,7 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
292 | u32 rd_page; | 390 | u32 rd_page; |
293 | u32 src_len; | 391 | u32 src_len; |
294 | u64 tmp; | 392 | u64 tmp; |
393 | sense_reason_t rc; | ||
295 | 394 | ||
296 | if (dev->rd_flags & RDF_NULLIO) { | 395 | if (dev->rd_flags & RDF_NULLIO) { |
297 | target_complete_cmd(cmd, SAM_STAT_GOOD); | 396 | target_complete_cmd(cmd, SAM_STAT_GOOD); |
@@ -314,6 +413,28 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
314 | data_direction == DMA_FROM_DEVICE ? "Read" : "Write", | 413 | data_direction == DMA_FROM_DEVICE ? "Read" : "Write", |
315 | cmd->t_task_lba, rd_size, rd_page, rd_offset); | 414 | cmd->t_task_lba, rd_size, rd_page, rd_offset); |
316 | 415 | ||
416 | if (cmd->prot_type && data_direction == DMA_TO_DEVICE) { | ||
417 | struct rd_dev_sg_table *prot_table; | ||
418 | struct scatterlist *prot_sg; | ||
419 | u32 sectors = cmd->data_length / se_dev->dev_attrib.block_size; | ||
420 | u32 prot_offset, prot_page; | ||
421 | |||
422 | tmp = cmd->t_task_lba * se_dev->prot_length; | ||
423 | prot_offset = do_div(tmp, PAGE_SIZE); | ||
424 | prot_page = tmp; | ||
425 | |||
426 | prot_table = rd_get_prot_table(dev, prot_page); | ||
427 | if (!prot_table) | ||
428 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
429 | |||
430 | prot_sg = &prot_table->sg_table[prot_page - prot_table->page_start_offset]; | ||
431 | |||
432 | rc = sbc_dif_verify_write(cmd, cmd->t_task_lba, sectors, 0, | ||
433 | prot_sg, prot_offset); | ||
434 | if (rc) | ||
435 | return rc; | ||
436 | } | ||
437 | |||
317 | src_len = PAGE_SIZE - rd_offset; | 438 | src_len = PAGE_SIZE - rd_offset; |
318 | sg_miter_start(&m, sgl, sgl_nents, | 439 | sg_miter_start(&m, sgl, sgl_nents, |
319 | data_direction == DMA_FROM_DEVICE ? | 440 | data_direction == DMA_FROM_DEVICE ? |
@@ -375,6 +496,28 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
375 | } | 496 | } |
376 | sg_miter_stop(&m); | 497 | sg_miter_stop(&m); |
377 | 498 | ||
499 | if (cmd->prot_type && data_direction == DMA_FROM_DEVICE) { | ||
500 | struct rd_dev_sg_table *prot_table; | ||
501 | struct scatterlist *prot_sg; | ||
502 | u32 sectors = cmd->data_length / se_dev->dev_attrib.block_size; | ||
503 | u32 prot_offset, prot_page; | ||
504 | |||
505 | tmp = cmd->t_task_lba * se_dev->prot_length; | ||
506 | prot_offset = do_div(tmp, PAGE_SIZE); | ||
507 | prot_page = tmp; | ||
508 | |||
509 | prot_table = rd_get_prot_table(dev, prot_page); | ||
510 | if (!prot_table) | ||
511 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
512 | |||
513 | prot_sg = &prot_table->sg_table[prot_page - prot_table->page_start_offset]; | ||
514 | |||
515 | rc = sbc_dif_verify_read(cmd, cmd->t_task_lba, sectors, 0, | ||
516 | prot_sg, prot_offset); | ||
517 | if (rc) | ||
518 | return rc; | ||
519 | } | ||
520 | |||
378 | target_complete_cmd(cmd, SAM_STAT_GOOD); | 521 | target_complete_cmd(cmd, SAM_STAT_GOOD); |
379 | return 0; | 522 | return 0; |
380 | } | 523 | } |
@@ -456,6 +599,23 @@ static sector_t rd_get_blocks(struct se_device *dev) | |||
456 | return blocks_long; | 599 | return blocks_long; |
457 | } | 600 | } |
458 | 601 | ||
602 | static int rd_init_prot(struct se_device *dev) | ||
603 | { | ||
604 | struct rd_dev *rd_dev = RD_DEV(dev); | ||
605 | |||
606 | if (!dev->dev_attrib.pi_prot_type) | ||
607 | return 0; | ||
608 | |||
609 | return rd_build_prot_space(rd_dev, dev->prot_length); | ||
610 | } | ||
611 | |||
612 | static void rd_free_prot(struct se_device *dev) | ||
613 | { | ||
614 | struct rd_dev *rd_dev = RD_DEV(dev); | ||
615 | |||
616 | rd_release_prot_space(rd_dev); | ||
617 | } | ||
618 | |||
459 | static struct sbc_ops rd_sbc_ops = { | 619 | static struct sbc_ops rd_sbc_ops = { |
460 | .execute_rw = rd_execute_rw, | 620 | .execute_rw = rd_execute_rw, |
461 | }; | 621 | }; |
@@ -481,6 +641,8 @@ static struct se_subsystem_api rd_mcp_template = { | |||
481 | .show_configfs_dev_params = rd_show_configfs_dev_params, | 641 | .show_configfs_dev_params = rd_show_configfs_dev_params, |
482 | .get_device_type = sbc_get_device_type, | 642 | .get_device_type = sbc_get_device_type, |
483 | .get_blocks = rd_get_blocks, | 643 | .get_blocks = rd_get_blocks, |
644 | .init_prot = rd_init_prot, | ||
645 | .free_prot = rd_free_prot, | ||
484 | }; | 646 | }; |
485 | 647 | ||
486 | int __init rd_module_init(void) | 648 | int __init rd_module_init(void) |
diff --git a/drivers/target/target_core_rd.h b/drivers/target/target_core_rd.h index 1789d1e14395..cc46a6a89b38 100644 --- a/drivers/target/target_core_rd.h +++ b/drivers/target/target_core_rd.h | |||
@@ -33,8 +33,12 @@ struct rd_dev { | |||
33 | u32 rd_page_count; | 33 | u32 rd_page_count; |
34 | /* Number of SG tables in sg_table_array */ | 34 | /* Number of SG tables in sg_table_array */ |
35 | u32 sg_table_count; | 35 | u32 sg_table_count; |
36 | /* Number of SG tables in sg_prot_array */ | ||
37 | u32 sg_prot_count; | ||
36 | /* Array of rd_dev_sg_table_t containing scatterlists */ | 38 | /* Array of rd_dev_sg_table_t containing scatterlists */ |
37 | struct rd_dev_sg_table *sg_table_array; | 39 | struct rd_dev_sg_table *sg_table_array; |
40 | /* Array of rd_dev_sg_table containing protection scatterlists */ | ||
41 | struct rd_dev_sg_table *sg_prot_array; | ||
38 | /* Ramdisk HBA device is connected to */ | 42 | /* Ramdisk HBA device is connected to */ |
39 | struct rd_host *rd_host; | 43 | struct rd_host *rd_host; |
40 | } ____cacheline_aligned; | 44 | } ____cacheline_aligned; |
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 52ae54e60105..fa3cae393e13 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/ratelimit.h> | 25 | #include <linux/ratelimit.h> |
26 | #include <linux/crc-t10dif.h> | ||
26 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
27 | #include <scsi/scsi.h> | 28 | #include <scsi/scsi.h> |
28 | #include <scsi/scsi_tcq.h> | 29 | #include <scsi/scsi_tcq.h> |
@@ -33,7 +34,7 @@ | |||
33 | 34 | ||
34 | #include "target_core_internal.h" | 35 | #include "target_core_internal.h" |
35 | #include "target_core_ua.h" | 36 | #include "target_core_ua.h" |
36 | 37 | #include "target_core_alua.h" | |
37 | 38 | ||
38 | static sense_reason_t | 39 | static sense_reason_t |
39 | sbc_emulate_readcapacity(struct se_cmd *cmd) | 40 | sbc_emulate_readcapacity(struct se_cmd *cmd) |
@@ -105,6 +106,11 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd) | |||
105 | buf[9] = (dev->dev_attrib.block_size >> 16) & 0xff; | 106 | buf[9] = (dev->dev_attrib.block_size >> 16) & 0xff; |
106 | buf[10] = (dev->dev_attrib.block_size >> 8) & 0xff; | 107 | buf[10] = (dev->dev_attrib.block_size >> 8) & 0xff; |
107 | buf[11] = dev->dev_attrib.block_size & 0xff; | 108 | buf[11] = dev->dev_attrib.block_size & 0xff; |
109 | /* | ||
110 | * Set P_TYPE and PROT_EN bits for DIF support | ||
111 | */ | ||
112 | if (dev->dev_attrib.pi_prot_type) | ||
113 | buf[12] = (dev->dev_attrib.pi_prot_type - 1) << 1 | 0x1; | ||
108 | 114 | ||
109 | if (dev->transport->get_lbppbe) | 115 | if (dev->transport->get_lbppbe) |
110 | buf[13] = dev->transport->get_lbppbe(dev) & 0x0f; | 116 | buf[13] = dev->transport->get_lbppbe(dev) & 0x0f; |
@@ -563,6 +569,44 @@ sbc_compare_and_write(struct se_cmd *cmd) | |||
563 | return TCM_NO_SENSE; | 569 | return TCM_NO_SENSE; |
564 | } | 570 | } |
565 | 571 | ||
572 | static bool | ||
573 | sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, | ||
574 | u32 sectors) | ||
575 | { | ||
576 | if (!cmd->t_prot_sg || !cmd->t_prot_nents) | ||
577 | return true; | ||
578 | |||
579 | switch (dev->dev_attrib.pi_prot_type) { | ||
580 | case TARGET_DIF_TYPE3_PROT: | ||
581 | if (!(cdb[1] & 0xe0)) | ||
582 | return true; | ||
583 | |||
584 | cmd->reftag_seed = 0xffffffff; | ||
585 | break; | ||
586 | case TARGET_DIF_TYPE2_PROT: | ||
587 | if (cdb[1] & 0xe0) | ||
588 | return false; | ||
589 | |||
590 | cmd->reftag_seed = cmd->t_task_lba; | ||
591 | break; | ||
592 | case TARGET_DIF_TYPE1_PROT: | ||
593 | if (!(cdb[1] & 0xe0)) | ||
594 | return true; | ||
595 | |||
596 | cmd->reftag_seed = cmd->t_task_lba; | ||
597 | break; | ||
598 | case TARGET_DIF_TYPE0_PROT: | ||
599 | default: | ||
600 | return true; | ||
601 | } | ||
602 | |||
603 | cmd->prot_type = dev->dev_attrib.pi_prot_type; | ||
604 | cmd->prot_length = dev->prot_length * sectors; | ||
605 | cmd->prot_handover = PROT_SEPERATED; | ||
606 | |||
607 | return true; | ||
608 | } | ||
609 | |||
566 | sense_reason_t | 610 | sense_reason_t |
567 | sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | 611 | sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
568 | { | 612 | { |
@@ -583,6 +627,10 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
583 | case READ_10: | 627 | case READ_10: |
584 | sectors = transport_get_sectors_10(cdb); | 628 | sectors = transport_get_sectors_10(cdb); |
585 | cmd->t_task_lba = transport_lba_32(cdb); | 629 | cmd->t_task_lba = transport_lba_32(cdb); |
630 | |||
631 | if (!sbc_check_prot(dev, cmd, cdb, sectors)) | ||
632 | return TCM_UNSUPPORTED_SCSI_OPCODE; | ||
633 | |||
586 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 634 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
587 | cmd->execute_rw = ops->execute_rw; | 635 | cmd->execute_rw = ops->execute_rw; |
588 | cmd->execute_cmd = sbc_execute_rw; | 636 | cmd->execute_cmd = sbc_execute_rw; |
@@ -590,6 +638,10 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
590 | case READ_12: | 638 | case READ_12: |
591 | sectors = transport_get_sectors_12(cdb); | 639 | sectors = transport_get_sectors_12(cdb); |
592 | cmd->t_task_lba = transport_lba_32(cdb); | 640 | cmd->t_task_lba = transport_lba_32(cdb); |
641 | |||
642 | if (!sbc_check_prot(dev, cmd, cdb, sectors)) | ||
643 | return TCM_UNSUPPORTED_SCSI_OPCODE; | ||
644 | |||
593 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 645 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
594 | cmd->execute_rw = ops->execute_rw; | 646 | cmd->execute_rw = ops->execute_rw; |
595 | cmd->execute_cmd = sbc_execute_rw; | 647 | cmd->execute_cmd = sbc_execute_rw; |
@@ -597,6 +649,10 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
597 | case READ_16: | 649 | case READ_16: |
598 | sectors = transport_get_sectors_16(cdb); | 650 | sectors = transport_get_sectors_16(cdb); |
599 | cmd->t_task_lba = transport_lba_64(cdb); | 651 | cmd->t_task_lba = transport_lba_64(cdb); |
652 | |||
653 | if (!sbc_check_prot(dev, cmd, cdb, sectors)) | ||
654 | return TCM_UNSUPPORTED_SCSI_OPCODE; | ||
655 | |||
600 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 656 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
601 | cmd->execute_rw = ops->execute_rw; | 657 | cmd->execute_rw = ops->execute_rw; |
602 | cmd->execute_cmd = sbc_execute_rw; | 658 | cmd->execute_cmd = sbc_execute_rw; |
@@ -612,6 +668,10 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
612 | case WRITE_VERIFY: | 668 | case WRITE_VERIFY: |
613 | sectors = transport_get_sectors_10(cdb); | 669 | sectors = transport_get_sectors_10(cdb); |
614 | cmd->t_task_lba = transport_lba_32(cdb); | 670 | cmd->t_task_lba = transport_lba_32(cdb); |
671 | |||
672 | if (!sbc_check_prot(dev, cmd, cdb, sectors)) | ||
673 | return TCM_UNSUPPORTED_SCSI_OPCODE; | ||
674 | |||
615 | if (cdb[1] & 0x8) | 675 | if (cdb[1] & 0x8) |
616 | cmd->se_cmd_flags |= SCF_FUA; | 676 | cmd->se_cmd_flags |= SCF_FUA; |
617 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 677 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
@@ -621,6 +681,10 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
621 | case WRITE_12: | 681 | case WRITE_12: |
622 | sectors = transport_get_sectors_12(cdb); | 682 | sectors = transport_get_sectors_12(cdb); |
623 | cmd->t_task_lba = transport_lba_32(cdb); | 683 | cmd->t_task_lba = transport_lba_32(cdb); |
684 | |||
685 | if (!sbc_check_prot(dev, cmd, cdb, sectors)) | ||
686 | return TCM_UNSUPPORTED_SCSI_OPCODE; | ||
687 | |||
624 | if (cdb[1] & 0x8) | 688 | if (cdb[1] & 0x8) |
625 | cmd->se_cmd_flags |= SCF_FUA; | 689 | cmd->se_cmd_flags |= SCF_FUA; |
626 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 690 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
@@ -630,6 +694,10 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
630 | case WRITE_16: | 694 | case WRITE_16: |
631 | sectors = transport_get_sectors_16(cdb); | 695 | sectors = transport_get_sectors_16(cdb); |
632 | cmd->t_task_lba = transport_lba_64(cdb); | 696 | cmd->t_task_lba = transport_lba_64(cdb); |
697 | |||
698 | if (!sbc_check_prot(dev, cmd, cdb, sectors)) | ||
699 | return TCM_UNSUPPORTED_SCSI_OPCODE; | ||
700 | |||
633 | if (cdb[1] & 0x8) | 701 | if (cdb[1] & 0x8) |
634 | cmd->se_cmd_flags |= SCF_FUA; | 702 | cmd->se_cmd_flags |= SCF_FUA; |
635 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 703 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
@@ -731,6 +799,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
731 | case SAI_READ_CAPACITY_16: | 799 | case SAI_READ_CAPACITY_16: |
732 | cmd->execute_cmd = sbc_emulate_readcapacity_16; | 800 | cmd->execute_cmd = sbc_emulate_readcapacity_16; |
733 | break; | 801 | break; |
802 | case SAI_REPORT_REFERRALS: | ||
803 | cmd->execute_cmd = target_emulate_report_referrals; | ||
804 | break; | ||
734 | default: | 805 | default: |
735 | pr_err("Unsupported SA: 0x%02x\n", | 806 | pr_err("Unsupported SA: 0x%02x\n", |
736 | cmd->t_task_cdb[1] & 0x1f); | 807 | cmd->t_task_cdb[1] & 0x1f); |
@@ -959,3 +1030,182 @@ err: | |||
959 | return ret; | 1030 | return ret; |
960 | } | 1031 | } |
961 | EXPORT_SYMBOL(sbc_execute_unmap); | 1032 | EXPORT_SYMBOL(sbc_execute_unmap); |
1033 | |||
1034 | static sense_reason_t | ||
1035 | sbc_dif_v1_verify(struct se_device *dev, struct se_dif_v1_tuple *sdt, | ||
1036 | const void *p, sector_t sector, unsigned int ei_lba) | ||
1037 | { | ||
1038 | int block_size = dev->dev_attrib.block_size; | ||
1039 | __be16 csum; | ||
1040 | |||
1041 | csum = cpu_to_be16(crc_t10dif(p, block_size)); | ||
1042 | |||
1043 | if (sdt->guard_tag != csum) { | ||
1044 | pr_err("DIFv1 checksum failed on sector %llu guard tag 0x%04x" | ||
1045 | " csum 0x%04x\n", (unsigned long long)sector, | ||
1046 | be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum)); | ||
1047 | return TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED; | ||
1048 | } | ||
1049 | |||
1050 | if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT && | ||
1051 | be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { | ||
1052 | pr_err("DIFv1 Type 1 reference failed on sector: %llu tag: 0x%08x" | ||
1053 | " sector MSB: 0x%08x\n", (unsigned long long)sector, | ||
1054 | be32_to_cpu(sdt->ref_tag), (u32)(sector & 0xffffffff)); | ||
1055 | return TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED; | ||
1056 | } | ||
1057 | |||
1058 | if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE2_PROT && | ||
1059 | be32_to_cpu(sdt->ref_tag) != ei_lba) { | ||
1060 | pr_err("DIFv1 Type 2 reference failed on sector: %llu tag: 0x%08x" | ||
1061 | " ei_lba: 0x%08x\n", (unsigned long long)sector, | ||
1062 | be32_to_cpu(sdt->ref_tag), ei_lba); | ||
1063 | return TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED; | ||
1064 | } | ||
1065 | |||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | static void | ||
1070 | sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, | ||
1071 | struct scatterlist *sg, int sg_off) | ||
1072 | { | ||
1073 | struct se_device *dev = cmd->se_dev; | ||
1074 | struct scatterlist *psg; | ||
1075 | void *paddr, *addr; | ||
1076 | unsigned int i, len, left; | ||
1077 | |||
1078 | left = sectors * dev->prot_length; | ||
1079 | |||
1080 | for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) { | ||
1081 | |||
1082 | len = min(psg->length, left); | ||
1083 | paddr = kmap_atomic(sg_page(psg)) + psg->offset; | ||
1084 | addr = kmap_atomic(sg_page(sg)) + sg_off; | ||
1085 | |||
1086 | if (read) | ||
1087 | memcpy(paddr, addr, len); | ||
1088 | else | ||
1089 | memcpy(addr, paddr, len); | ||
1090 | |||
1091 | left -= len; | ||
1092 | kunmap_atomic(paddr); | ||
1093 | kunmap_atomic(addr); | ||
1094 | } | ||
1095 | } | ||
1096 | |||
1097 | sense_reason_t | ||
1098 | sbc_dif_verify_write(struct se_cmd *cmd, sector_t start, unsigned int sectors, | ||
1099 | unsigned int ei_lba, struct scatterlist *sg, int sg_off) | ||
1100 | { | ||
1101 | struct se_device *dev = cmd->se_dev; | ||
1102 | struct se_dif_v1_tuple *sdt; | ||
1103 | struct scatterlist *dsg, *psg = cmd->t_prot_sg; | ||
1104 | sector_t sector = start; | ||
1105 | void *daddr, *paddr; | ||
1106 | int i, j, offset = 0; | ||
1107 | sense_reason_t rc; | ||
1108 | |||
1109 | for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) { | ||
1110 | daddr = kmap_atomic(sg_page(dsg)) + dsg->offset; | ||
1111 | paddr = kmap_atomic(sg_page(psg)) + psg->offset; | ||
1112 | |||
1113 | for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) { | ||
1114 | |||
1115 | if (offset >= psg->length) { | ||
1116 | kunmap_atomic(paddr); | ||
1117 | psg = sg_next(psg); | ||
1118 | paddr = kmap_atomic(sg_page(psg)) + psg->offset; | ||
1119 | offset = 0; | ||
1120 | } | ||
1121 | |||
1122 | sdt = paddr + offset; | ||
1123 | |||
1124 | pr_debug("DIF WRITE sector: %llu guard_tag: 0x%04x" | ||
1125 | " app_tag: 0x%04x ref_tag: %u\n", | ||
1126 | (unsigned long long)sector, sdt->guard_tag, | ||
1127 | sdt->app_tag, be32_to_cpu(sdt->ref_tag)); | ||
1128 | |||
1129 | rc = sbc_dif_v1_verify(dev, sdt, daddr + j, sector, | ||
1130 | ei_lba); | ||
1131 | if (rc) { | ||
1132 | kunmap_atomic(paddr); | ||
1133 | kunmap_atomic(daddr); | ||
1134 | cmd->bad_sector = sector; | ||
1135 | return rc; | ||
1136 | } | ||
1137 | |||
1138 | sector++; | ||
1139 | ei_lba++; | ||
1140 | offset += sizeof(struct se_dif_v1_tuple); | ||
1141 | } | ||
1142 | |||
1143 | kunmap_atomic(paddr); | ||
1144 | kunmap_atomic(daddr); | ||
1145 | } | ||
1146 | sbc_dif_copy_prot(cmd, sectors, false, sg, sg_off); | ||
1147 | |||
1148 | return 0; | ||
1149 | } | ||
1150 | EXPORT_SYMBOL(sbc_dif_verify_write); | ||
1151 | |||
1152 | sense_reason_t | ||
1153 | sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors, | ||
1154 | unsigned int ei_lba, struct scatterlist *sg, int sg_off) | ||
1155 | { | ||
1156 | struct se_device *dev = cmd->se_dev; | ||
1157 | struct se_dif_v1_tuple *sdt; | ||
1158 | struct scatterlist *dsg; | ||
1159 | sector_t sector = start; | ||
1160 | void *daddr, *paddr; | ||
1161 | int i, j, offset = sg_off; | ||
1162 | sense_reason_t rc; | ||
1163 | |||
1164 | for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) { | ||
1165 | daddr = kmap_atomic(sg_page(dsg)) + dsg->offset; | ||
1166 | paddr = kmap_atomic(sg_page(sg)) + sg->offset; | ||
1167 | |||
1168 | for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) { | ||
1169 | |||
1170 | if (offset >= sg->length) { | ||
1171 | kunmap_atomic(paddr); | ||
1172 | sg = sg_next(sg); | ||
1173 | paddr = kmap_atomic(sg_page(sg)) + sg->offset; | ||
1174 | offset = 0; | ||
1175 | } | ||
1176 | |||
1177 | sdt = paddr + offset; | ||
1178 | |||
1179 | pr_debug("DIF READ sector: %llu guard_tag: 0x%04x" | ||
1180 | " app_tag: 0x%04x ref_tag: %u\n", | ||
1181 | (unsigned long long)sector, sdt->guard_tag, | ||
1182 | sdt->app_tag, be32_to_cpu(sdt->ref_tag)); | ||
1183 | |||
1184 | if (sdt->app_tag == cpu_to_be16(0xffff)) { | ||
1185 | sector++; | ||
1186 | offset += sizeof(struct se_dif_v1_tuple); | ||
1187 | continue; | ||
1188 | } | ||
1189 | |||
1190 | rc = sbc_dif_v1_verify(dev, sdt, daddr + j, sector, | ||
1191 | ei_lba); | ||
1192 | if (rc) { | ||
1193 | kunmap_atomic(paddr); | ||
1194 | kunmap_atomic(daddr); | ||
1195 | cmd->bad_sector = sector; | ||
1196 | return rc; | ||
1197 | } | ||
1198 | |||
1199 | sector++; | ||
1200 | ei_lba++; | ||
1201 | offset += sizeof(struct se_dif_v1_tuple); | ||
1202 | } | ||
1203 | |||
1204 | kunmap_atomic(paddr); | ||
1205 | kunmap_atomic(daddr); | ||
1206 | } | ||
1207 | sbc_dif_copy_prot(cmd, sectors, true, sg, sg_off); | ||
1208 | |||
1209 | return 0; | ||
1210 | } | ||
1211 | EXPORT_SYMBOL(sbc_dif_verify_read); | ||
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 021c3f4a4f00..43c5ca9878bc 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c | |||
@@ -100,6 +100,11 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf) | |||
100 | */ | 100 | */ |
101 | if (dev->dev_attrib.emulate_3pc) | 101 | if (dev->dev_attrib.emulate_3pc) |
102 | buf[5] |= 0x8; | 102 | buf[5] |= 0x8; |
103 | /* | ||
104 | * Set Protection (PROTECT) bit when DIF has been enabled. | ||
105 | */ | ||
106 | if (dev->dev_attrib.pi_prot_type) | ||
107 | buf[5] |= 0x1; | ||
103 | 108 | ||
104 | buf[7] = 0x2; /* CmdQue=1 */ | 109 | buf[7] = 0x2; /* CmdQue=1 */ |
105 | 110 | ||
@@ -267,7 +272,7 @@ check_t10_vend_desc: | |||
267 | port = lun->lun_sep; | 272 | port = lun->lun_sep; |
268 | if (port) { | 273 | if (port) { |
269 | struct t10_alua_lu_gp *lu_gp; | 274 | struct t10_alua_lu_gp *lu_gp; |
270 | u32 padding, scsi_name_len; | 275 | u32 padding, scsi_name_len, scsi_target_len; |
271 | u16 lu_gp_id = 0; | 276 | u16 lu_gp_id = 0; |
272 | u16 tg_pt_gp_id = 0; | 277 | u16 tg_pt_gp_id = 0; |
273 | u16 tpgt; | 278 | u16 tpgt; |
@@ -365,16 +370,6 @@ check_lu_gp: | |||
365 | * section 7.5.1 Table 362 | 370 | * section 7.5.1 Table 362 |
366 | */ | 371 | */ |
367 | check_scsi_name: | 372 | check_scsi_name: |
368 | scsi_name_len = strlen(tpg->se_tpg_tfo->tpg_get_wwn(tpg)); | ||
369 | /* UTF-8 ",t,0x<16-bit TPGT>" + NULL Terminator */ | ||
370 | scsi_name_len += 10; | ||
371 | /* Check for 4-byte padding */ | ||
372 | padding = ((-scsi_name_len) & 3); | ||
373 | if (padding != 0) | ||
374 | scsi_name_len += padding; | ||
375 | /* Header size + Designation descriptor */ | ||
376 | scsi_name_len += 4; | ||
377 | |||
378 | buf[off] = | 373 | buf[off] = |
379 | (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4); | 374 | (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4); |
380 | buf[off++] |= 0x3; /* CODE SET == UTF-8 */ | 375 | buf[off++] |= 0x3; /* CODE SET == UTF-8 */ |
@@ -402,13 +397,57 @@ check_scsi_name: | |||
402 | * shall be no larger than 256 and shall be a multiple | 397 | * shall be no larger than 256 and shall be a multiple |
403 | * of four. | 398 | * of four. |
404 | */ | 399 | */ |
400 | padding = ((-scsi_name_len) & 3); | ||
405 | if (padding) | 401 | if (padding) |
406 | scsi_name_len += padding; | 402 | scsi_name_len += padding; |
403 | if (scsi_name_len > 256) | ||
404 | scsi_name_len = 256; | ||
407 | 405 | ||
408 | buf[off-1] = scsi_name_len; | 406 | buf[off-1] = scsi_name_len; |
409 | off += scsi_name_len; | 407 | off += scsi_name_len; |
410 | /* Header size + Designation descriptor */ | 408 | /* Header size + Designation descriptor */ |
411 | len += (scsi_name_len + 4); | 409 | len += (scsi_name_len + 4); |
410 | |||
411 | /* | ||
412 | * Target device designator | ||
413 | */ | ||
414 | buf[off] = | ||
415 | (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4); | ||
416 | buf[off++] |= 0x3; /* CODE SET == UTF-8 */ | ||
417 | buf[off] = 0x80; /* Set PIV=1 */ | ||
418 | /* Set ASSOCIATION == target device: 10b */ | ||
419 | buf[off] |= 0x20; | ||
420 | /* DESIGNATOR TYPE == SCSI name string */ | ||
421 | buf[off++] |= 0x8; | ||
422 | off += 2; /* Skip over Reserved and length */ | ||
423 | /* | ||
424 | * SCSI name string identifer containing, $FABRIC_MOD | ||
425 | * dependent information. For LIO-Target and iSCSI | ||
426 | * Target Port, this means "<iSCSI name>" in | ||
427 | * UTF-8 encoding. | ||
428 | */ | ||
429 | scsi_target_len = sprintf(&buf[off], "%s", | ||
430 | tpg->se_tpg_tfo->tpg_get_wwn(tpg)); | ||
431 | scsi_target_len += 1 /* Include NULL terminator */; | ||
432 | /* | ||
433 | * The null-terminated, null-padded (see 4.4.2) SCSI | ||
434 | * NAME STRING field contains a UTF-8 format string. | ||
435 | * The number of bytes in the SCSI NAME STRING field | ||
436 | * (i.e., the value in the DESIGNATOR LENGTH field) | ||
437 | * shall be no larger than 256 and shall be a multiple | ||
438 | * of four. | ||
439 | */ | ||
440 | padding = ((-scsi_target_len) & 3); | ||
441 | if (padding) | ||
442 | scsi_target_len += padding; | ||
443 | if (scsi_name_len > 256) | ||
444 | scsi_name_len = 256; | ||
445 | |||
446 | buf[off-1] = scsi_target_len; | ||
447 | off += scsi_target_len; | ||
448 | |||
449 | /* Header size + Designation descriptor */ | ||
450 | len += (scsi_target_len + 4); | ||
412 | } | 451 | } |
413 | buf[2] = ((len >> 8) & 0xff); | 452 | buf[2] = ((len >> 8) & 0xff); |
414 | buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */ | 453 | buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */ |
@@ -436,12 +475,26 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) | |||
436 | struct se_device *dev = cmd->se_dev; | 475 | struct se_device *dev = cmd->se_dev; |
437 | 476 | ||
438 | buf[3] = 0x3c; | 477 | buf[3] = 0x3c; |
478 | /* | ||
479 | * Set GRD_CHK + REF_CHK for TYPE1 protection, or GRD_CHK | ||
480 | * only for TYPE3 protection. | ||
481 | */ | ||
482 | if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT) | ||
483 | buf[4] = 0x5; | ||
484 | else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT) | ||
485 | buf[4] = 0x4; | ||
486 | |||
439 | /* Set HEADSUP, ORDSUP, SIMPSUP */ | 487 | /* Set HEADSUP, ORDSUP, SIMPSUP */ |
440 | buf[5] = 0x07; | 488 | buf[5] = 0x07; |
441 | 489 | ||
442 | /* If WriteCache emulation is enabled, set V_SUP */ | 490 | /* If WriteCache emulation is enabled, set V_SUP */ |
443 | if (spc_check_dev_wce(dev)) | 491 | if (spc_check_dev_wce(dev)) |
444 | buf[6] = 0x01; | 492 | buf[6] = 0x01; |
493 | /* If an LBA map is present set R_SUP */ | ||
494 | spin_lock(&cmd->se_dev->t10_alua.lba_map_lock); | ||
495 | if (!list_empty(&dev->t10_alua.lba_map_list)) | ||
496 | buf[8] = 0x10; | ||
497 | spin_unlock(&cmd->se_dev->t10_alua.lba_map_lock); | ||
445 | return 0; | 498 | return 0; |
446 | } | 499 | } |
447 | 500 | ||
@@ -600,6 +653,20 @@ spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) | |||
600 | return 0; | 653 | return 0; |
601 | } | 654 | } |
602 | 655 | ||
656 | /* Referrals VPD page */ | ||
657 | static sense_reason_t | ||
658 | spc_emulate_evpd_b3(struct se_cmd *cmd, unsigned char *buf) | ||
659 | { | ||
660 | struct se_device *dev = cmd->se_dev; | ||
661 | |||
662 | buf[0] = dev->transport->get_device_type(dev); | ||
663 | buf[3] = 0x0c; | ||
664 | put_unaligned_be32(dev->t10_alua.lba_map_segment_size, &buf[8]); | ||
665 | put_unaligned_be32(dev->t10_alua.lba_map_segment_size, &buf[12]); | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
603 | static sense_reason_t | 670 | static sense_reason_t |
604 | spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); | 671 | spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); |
605 | 672 | ||
@@ -614,6 +681,7 @@ static struct { | |||
614 | { .page = 0xb0, .emulate = spc_emulate_evpd_b0 }, | 681 | { .page = 0xb0, .emulate = spc_emulate_evpd_b0 }, |
615 | { .page = 0xb1, .emulate = spc_emulate_evpd_b1 }, | 682 | { .page = 0xb1, .emulate = spc_emulate_evpd_b1 }, |
616 | { .page = 0xb2, .emulate = spc_emulate_evpd_b2 }, | 683 | { .page = 0xb2, .emulate = spc_emulate_evpd_b2 }, |
684 | { .page = 0xb3, .emulate = spc_emulate_evpd_b3 }, | ||
617 | }; | 685 | }; |
618 | 686 | ||
619 | /* supported vital product data pages */ | 687 | /* supported vital product data pages */ |
@@ -643,11 +711,15 @@ spc_emulate_inquiry(struct se_cmd *cmd) | |||
643 | struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; | 711 | struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; |
644 | unsigned char *rbuf; | 712 | unsigned char *rbuf; |
645 | unsigned char *cdb = cmd->t_task_cdb; | 713 | unsigned char *cdb = cmd->t_task_cdb; |
646 | unsigned char buf[SE_INQUIRY_BUF]; | 714 | unsigned char *buf; |
647 | sense_reason_t ret; | 715 | sense_reason_t ret; |
648 | int p; | 716 | int p; |
649 | 717 | ||
650 | memset(buf, 0, SE_INQUIRY_BUF); | 718 | buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL); |
719 | if (!buf) { | ||
720 | pr_err("Unable to allocate response buffer for INQUIRY\n"); | ||
721 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
722 | } | ||
651 | 723 | ||
652 | if (dev == tpg->tpg_virt_lun0.lun_se_dev) | 724 | if (dev == tpg->tpg_virt_lun0.lun_se_dev) |
653 | buf[0] = 0x3f; /* Not connected */ | 725 | buf[0] = 0x3f; /* Not connected */ |
@@ -680,9 +752,10 @@ spc_emulate_inquiry(struct se_cmd *cmd) | |||
680 | out: | 752 | out: |
681 | rbuf = transport_kmap_data_sg(cmd); | 753 | rbuf = transport_kmap_data_sg(cmd); |
682 | if (rbuf) { | 754 | if (rbuf) { |
683 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); | 755 | memcpy(rbuf, buf, min_t(u32, SE_INQUIRY_BUF, cmd->data_length)); |
684 | transport_kunmap_data_sg(cmd); | 756 | transport_kunmap_data_sg(cmd); |
685 | } | 757 | } |
758 | kfree(buf); | ||
686 | 759 | ||
687 | if (!ret) | 760 | if (!ret) |
688 | target_complete_cmd(cmd, GOOD); | 761 | target_complete_cmd(cmd, GOOD); |
@@ -785,6 +858,19 @@ static int spc_modesense_control(struct se_device *dev, u8 pc, u8 *p) | |||
785 | * status (see SAM-4). | 858 | * status (see SAM-4). |
786 | */ | 859 | */ |
787 | p[5] = (dev->dev_attrib.emulate_tas) ? 0x40 : 0x00; | 860 | p[5] = (dev->dev_attrib.emulate_tas) ? 0x40 : 0x00; |
861 | /* | ||
862 | * From spc4r30, section 7.5.7 Control mode page | ||
863 | * | ||
864 | * Application Tag Owner (ATO) bit set to one. | ||
865 | * | ||
866 | * If the ATO bit is set to one the device server shall not modify the | ||
867 | * LOGICAL BLOCK APPLICATION TAG field and, depending on the protection | ||
868 | * type, shall not modify the contents of the LOGICAL BLOCK REFERENCE | ||
869 | * TAG field. | ||
870 | */ | ||
871 | if (dev->dev_attrib.pi_prot_type) | ||
872 | p[5] |= 0x80; | ||
873 | |||
788 | p[8] = 0xff; | 874 | p[8] = 0xff; |
789 | p[9] = 0xff; | 875 | p[9] = 0xff; |
790 | p[11] = 30; | 876 | p[11] = 30; |
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 2a573de19a9f..c036595b17cf 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c | |||
@@ -656,7 +656,7 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) | |||
656 | spin_lock_init(&lun->lun_sep_lock); | 656 | spin_lock_init(&lun->lun_sep_lock); |
657 | init_completion(&lun->lun_ref_comp); | 657 | init_completion(&lun->lun_ref_comp); |
658 | 658 | ||
659 | ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev); | 659 | ret = core_tpg_add_lun(se_tpg, lun, lun_access, dev); |
660 | if (ret < 0) | 660 | if (ret < 0) |
661 | return ret; | 661 | return ret; |
662 | 662 | ||
@@ -781,7 +781,7 @@ int core_tpg_deregister(struct se_portal_group *se_tpg) | |||
781 | } | 781 | } |
782 | EXPORT_SYMBOL(core_tpg_deregister); | 782 | EXPORT_SYMBOL(core_tpg_deregister); |
783 | 783 | ||
784 | struct se_lun *core_tpg_pre_addlun( | 784 | struct se_lun *core_tpg_alloc_lun( |
785 | struct se_portal_group *tpg, | 785 | struct se_portal_group *tpg, |
786 | u32 unpacked_lun) | 786 | u32 unpacked_lun) |
787 | { | 787 | { |
@@ -811,11 +811,11 @@ struct se_lun *core_tpg_pre_addlun( | |||
811 | return lun; | 811 | return lun; |
812 | } | 812 | } |
813 | 813 | ||
814 | int core_tpg_post_addlun( | 814 | int core_tpg_add_lun( |
815 | struct se_portal_group *tpg, | 815 | struct se_portal_group *tpg, |
816 | struct se_lun *lun, | 816 | struct se_lun *lun, |
817 | u32 lun_access, | 817 | u32 lun_access, |
818 | void *lun_ptr) | 818 | struct se_device *dev) |
819 | { | 819 | { |
820 | int ret; | 820 | int ret; |
821 | 821 | ||
@@ -823,7 +823,7 @@ int core_tpg_post_addlun( | |||
823 | if (ret < 0) | 823 | if (ret < 0) |
824 | return ret; | 824 | return ret; |
825 | 825 | ||
826 | ret = core_dev_export(lun_ptr, tpg, lun); | 826 | ret = core_dev_export(dev, tpg, lun); |
827 | if (ret < 0) { | 827 | if (ret < 0) { |
828 | percpu_ref_cancel_init(&lun->lun_ref); | 828 | percpu_ref_cancel_init(&lun->lun_ref); |
829 | return ret; | 829 | return ret; |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 91953da0f623..c50fd9f11aab 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -62,6 +62,8 @@ struct kmem_cache *t10_alua_lu_gp_cache; | |||
62 | struct kmem_cache *t10_alua_lu_gp_mem_cache; | 62 | struct kmem_cache *t10_alua_lu_gp_mem_cache; |
63 | struct kmem_cache *t10_alua_tg_pt_gp_cache; | 63 | struct kmem_cache *t10_alua_tg_pt_gp_cache; |
64 | struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; | 64 | struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; |
65 | struct kmem_cache *t10_alua_lba_map_cache; | ||
66 | struct kmem_cache *t10_alua_lba_map_mem_cache; | ||
65 | 67 | ||
66 | static void transport_complete_task_attr(struct se_cmd *cmd); | 68 | static void transport_complete_task_attr(struct se_cmd *cmd); |
67 | static void transport_handle_queue_full(struct se_cmd *cmd, | 69 | static void transport_handle_queue_full(struct se_cmd *cmd, |
@@ -128,14 +130,36 @@ int init_se_kmem_caches(void) | |||
128 | "mem_t failed\n"); | 130 | "mem_t failed\n"); |
129 | goto out_free_tg_pt_gp_cache; | 131 | goto out_free_tg_pt_gp_cache; |
130 | } | 132 | } |
133 | t10_alua_lba_map_cache = kmem_cache_create( | ||
134 | "t10_alua_lba_map_cache", | ||
135 | sizeof(struct t10_alua_lba_map), | ||
136 | __alignof__(struct t10_alua_lba_map), 0, NULL); | ||
137 | if (!t10_alua_lba_map_cache) { | ||
138 | pr_err("kmem_cache_create() for t10_alua_lba_map_" | ||
139 | "cache failed\n"); | ||
140 | goto out_free_tg_pt_gp_mem_cache; | ||
141 | } | ||
142 | t10_alua_lba_map_mem_cache = kmem_cache_create( | ||
143 | "t10_alua_lba_map_mem_cache", | ||
144 | sizeof(struct t10_alua_lba_map_member), | ||
145 | __alignof__(struct t10_alua_lba_map_member), 0, NULL); | ||
146 | if (!t10_alua_lba_map_mem_cache) { | ||
147 | pr_err("kmem_cache_create() for t10_alua_lba_map_mem_" | ||
148 | "cache failed\n"); | ||
149 | goto out_free_lba_map_cache; | ||
150 | } | ||
131 | 151 | ||
132 | target_completion_wq = alloc_workqueue("target_completion", | 152 | target_completion_wq = alloc_workqueue("target_completion", |
133 | WQ_MEM_RECLAIM, 0); | 153 | WQ_MEM_RECLAIM, 0); |
134 | if (!target_completion_wq) | 154 | if (!target_completion_wq) |
135 | goto out_free_tg_pt_gp_mem_cache; | 155 | goto out_free_lba_map_mem_cache; |
136 | 156 | ||
137 | return 0; | 157 | return 0; |
138 | 158 | ||
159 | out_free_lba_map_mem_cache: | ||
160 | kmem_cache_destroy(t10_alua_lba_map_mem_cache); | ||
161 | out_free_lba_map_cache: | ||
162 | kmem_cache_destroy(t10_alua_lba_map_cache); | ||
139 | out_free_tg_pt_gp_mem_cache: | 163 | out_free_tg_pt_gp_mem_cache: |
140 | kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache); | 164 | kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache); |
141 | out_free_tg_pt_gp_cache: | 165 | out_free_tg_pt_gp_cache: |
@@ -164,6 +188,8 @@ void release_se_kmem_caches(void) | |||
164 | kmem_cache_destroy(t10_alua_lu_gp_mem_cache); | 188 | kmem_cache_destroy(t10_alua_lu_gp_mem_cache); |
165 | kmem_cache_destroy(t10_alua_tg_pt_gp_cache); | 189 | kmem_cache_destroy(t10_alua_tg_pt_gp_cache); |
166 | kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache); | 190 | kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache); |
191 | kmem_cache_destroy(t10_alua_lba_map_cache); | ||
192 | kmem_cache_destroy(t10_alua_lba_map_mem_cache); | ||
167 | } | 193 | } |
168 | 194 | ||
169 | /* This code ensures unique mib indexes are handed out. */ | 195 | /* This code ensures unique mib indexes are handed out. */ |
@@ -568,10 +594,11 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) | |||
568 | { | 594 | { |
569 | struct se_lun *lun = cmd->se_lun; | 595 | struct se_lun *lun = cmd->se_lun; |
570 | 596 | ||
571 | if (!lun || !cmd->lun_ref_active) | 597 | if (!lun) |
572 | return; | 598 | return; |
573 | 599 | ||
574 | percpu_ref_put(&lun->lun_ref); | 600 | if (cmpxchg(&cmd->lun_ref_active, true, false)) |
601 | percpu_ref_put(&lun->lun_ref); | ||
575 | } | 602 | } |
576 | 603 | ||
577 | void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) | 604 | void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) |
@@ -1284,6 +1311,8 @@ transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl, | |||
1284 | * @sgl_count: scatterlist count for unidirectional mapping | 1311 | * @sgl_count: scatterlist count for unidirectional mapping |
1285 | * @sgl_bidi: struct scatterlist memory for bidirectional READ mapping | 1312 | * @sgl_bidi: struct scatterlist memory for bidirectional READ mapping |
1286 | * @sgl_bidi_count: scatterlist count for bidirectional READ mapping | 1313 | * @sgl_bidi_count: scatterlist count for bidirectional READ mapping |
1314 | * @sgl_prot: struct scatterlist memory protection information | ||
1315 | * @sgl_prot_count: scatterlist count for protection information | ||
1287 | * | 1316 | * |
1288 | * Returns non zero to signal active I/O shutdown failure. All other | 1317 | * Returns non zero to signal active I/O shutdown failure. All other |
1289 | * setup exceptions will be returned as a SCSI CHECK_CONDITION response, | 1318 | * setup exceptions will be returned as a SCSI CHECK_CONDITION response, |
@@ -1296,7 +1325,8 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess | |||
1296 | unsigned char *cdb, unsigned char *sense, u32 unpacked_lun, | 1325 | unsigned char *cdb, unsigned char *sense, u32 unpacked_lun, |
1297 | u32 data_length, int task_attr, int data_dir, int flags, | 1326 | u32 data_length, int task_attr, int data_dir, int flags, |
1298 | struct scatterlist *sgl, u32 sgl_count, | 1327 | struct scatterlist *sgl, u32 sgl_count, |
1299 | struct scatterlist *sgl_bidi, u32 sgl_bidi_count) | 1328 | struct scatterlist *sgl_bidi, u32 sgl_bidi_count, |
1329 | struct scatterlist *sgl_prot, u32 sgl_prot_count) | ||
1300 | { | 1330 | { |
1301 | struct se_portal_group *se_tpg; | 1331 | struct se_portal_group *se_tpg; |
1302 | sense_reason_t rc; | 1332 | sense_reason_t rc; |
@@ -1338,6 +1368,14 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess | |||
1338 | target_put_sess_cmd(se_sess, se_cmd); | 1368 | target_put_sess_cmd(se_sess, se_cmd); |
1339 | return 0; | 1369 | return 0; |
1340 | } | 1370 | } |
1371 | /* | ||
1372 | * Save pointers for SGLs containing protection information, | ||
1373 | * if present. | ||
1374 | */ | ||
1375 | if (sgl_prot_count) { | ||
1376 | se_cmd->t_prot_sg = sgl_prot; | ||
1377 | se_cmd->t_prot_nents = sgl_prot_count; | ||
1378 | } | ||
1341 | 1379 | ||
1342 | rc = target_setup_cmd_from_cdb(se_cmd, cdb); | 1380 | rc = target_setup_cmd_from_cdb(se_cmd, cdb); |
1343 | if (rc != 0) { | 1381 | if (rc != 0) { |
@@ -1380,6 +1418,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess | |||
1380 | return 0; | 1418 | return 0; |
1381 | } | 1419 | } |
1382 | } | 1420 | } |
1421 | |||
1383 | /* | 1422 | /* |
1384 | * Check if we need to delay processing because of ALUA | 1423 | * Check if we need to delay processing because of ALUA |
1385 | * Active/NonOptimized primary access state.. | 1424 | * Active/NonOptimized primary access state.. |
@@ -1419,7 +1458,7 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, | |||
1419 | { | 1458 | { |
1420 | return target_submit_cmd_map_sgls(se_cmd, se_sess, cdb, sense, | 1459 | return target_submit_cmd_map_sgls(se_cmd, se_sess, cdb, sense, |
1421 | unpacked_lun, data_length, task_attr, data_dir, | 1460 | unpacked_lun, data_length, task_attr, data_dir, |
1422 | flags, NULL, 0, NULL, 0); | 1461 | flags, NULL, 0, NULL, 0, NULL, 0); |
1423 | } | 1462 | } |
1424 | EXPORT_SYMBOL(target_submit_cmd); | 1463 | EXPORT_SYMBOL(target_submit_cmd); |
1425 | 1464 | ||
@@ -2455,6 +2494,19 @@ static int transport_get_sense_codes( | |||
2455 | return 0; | 2494 | return 0; |
2456 | } | 2495 | } |
2457 | 2496 | ||
2497 | static | ||
2498 | void transport_err_sector_info(unsigned char *buffer, sector_t bad_sector) | ||
2499 | { | ||
2500 | /* Place failed LBA in sense data information descriptor 0. */ | ||
2501 | buffer[SPC_ADD_SENSE_LEN_OFFSET] = 0xc; | ||
2502 | buffer[SPC_DESC_TYPE_OFFSET] = 0; /* Information */ | ||
2503 | buffer[SPC_ADDITIONAL_DESC_LEN_OFFSET] = 0xa; | ||
2504 | buffer[SPC_VALIDITY_OFFSET] = 0x80; | ||
2505 | |||
2506 | /* Descriptor Information: failing sector */ | ||
2507 | put_unaligned_be64(bad_sector, &buffer[12]); | ||
2508 | } | ||
2509 | |||
2458 | int | 2510 | int |
2459 | transport_send_check_condition_and_sense(struct se_cmd *cmd, | 2511 | transport_send_check_condition_and_sense(struct se_cmd *cmd, |
2460 | sense_reason_t reason, int from_transport) | 2512 | sense_reason_t reason, int from_transport) |
@@ -2648,6 +2700,39 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, | |||
2648 | buffer[SPC_ASC_KEY_OFFSET] = 0x1d; | 2700 | buffer[SPC_ASC_KEY_OFFSET] = 0x1d; |
2649 | buffer[SPC_ASCQ_KEY_OFFSET] = 0x00; | 2701 | buffer[SPC_ASCQ_KEY_OFFSET] = 0x00; |
2650 | break; | 2702 | break; |
2703 | case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED: | ||
2704 | /* CURRENT ERROR */ | ||
2705 | buffer[0] = 0x70; | ||
2706 | buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; | ||
2707 | /* ILLEGAL REQUEST */ | ||
2708 | buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; | ||
2709 | /* LOGICAL BLOCK GUARD CHECK FAILED */ | ||
2710 | buffer[SPC_ASC_KEY_OFFSET] = 0x10; | ||
2711 | buffer[SPC_ASCQ_KEY_OFFSET] = 0x01; | ||
2712 | transport_err_sector_info(buffer, cmd->bad_sector); | ||
2713 | break; | ||
2714 | case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: | ||
2715 | /* CURRENT ERROR */ | ||
2716 | buffer[0] = 0x70; | ||
2717 | buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; | ||
2718 | /* ILLEGAL REQUEST */ | ||
2719 | buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; | ||
2720 | /* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */ | ||
2721 | buffer[SPC_ASC_KEY_OFFSET] = 0x10; | ||
2722 | buffer[SPC_ASCQ_KEY_OFFSET] = 0x02; | ||
2723 | transport_err_sector_info(buffer, cmd->bad_sector); | ||
2724 | break; | ||
2725 | case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: | ||
2726 | /* CURRENT ERROR */ | ||
2727 | buffer[0] = 0x70; | ||
2728 | buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; | ||
2729 | /* ILLEGAL REQUEST */ | ||
2730 | buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; | ||
2731 | /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ | ||
2732 | buffer[SPC_ASC_KEY_OFFSET] = 0x10; | ||
2733 | buffer[SPC_ASCQ_KEY_OFFSET] = 0x03; | ||
2734 | transport_err_sector_info(buffer, cmd->bad_sector); | ||
2735 | break; | ||
2651 | case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE: | 2736 | case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE: |
2652 | default: | 2737 | default: |
2653 | /* CURRENT ERROR */ | 2738 | /* CURRENT ERROR */ |
diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index b04467e7547c..505519b10cb7 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c | |||
@@ -98,7 +98,6 @@ int core_scsi3_ua_allocate( | |||
98 | pr_err("Unable to allocate struct se_ua\n"); | 98 | pr_err("Unable to allocate struct se_ua\n"); |
99 | return -ENOMEM; | 99 | return -ENOMEM; |
100 | } | 100 | } |
101 | INIT_LIST_HEAD(&ua->ua_dev_list); | ||
102 | INIT_LIST_HEAD(&ua->ua_nacl_list); | 101 | INIT_LIST_HEAD(&ua->ua_nacl_list); |
103 | 102 | ||
104 | ua->ua_nacl = nacl; | 103 | ua->ua_nacl = nacl; |
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c index 6b88a9958f61..669c536fd959 100644 --- a/drivers/target/target_core_xcopy.c +++ b/drivers/target/target_core_xcopy.c | |||
@@ -40,10 +40,6 @@ | |||
40 | 40 | ||
41 | static struct workqueue_struct *xcopy_wq = NULL; | 41 | static struct workqueue_struct *xcopy_wq = NULL; |
42 | /* | 42 | /* |
43 | * From target_core_spc.c | ||
44 | */ | ||
45 | extern void spc_parse_naa_6h_vendor_specific(struct se_device *, unsigned char *); | ||
46 | /* | ||
47 | * From target_core_device.c | 43 | * From target_core_device.c |
48 | */ | 44 | */ |
49 | extern struct mutex g_device_mutex; | 45 | extern struct mutex g_device_mutex; |
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 479ec5621a4e..8b2c1aaf81de 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c | |||
@@ -438,7 +438,7 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp) | |||
438 | struct se_session *se_sess = sess->se_sess; | 438 | struct se_session *se_sess = sess->se_sess; |
439 | int tag; | 439 | int tag; |
440 | 440 | ||
441 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC); | 441 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); |
442 | if (tag < 0) | 442 | if (tag < 0) |
443 | goto busy; | 443 | goto busy; |
444 | 444 | ||
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c index c6932fb53a8d..e879da81ad93 100644 --- a/drivers/target/tcm_fc/tfc_conf.c +++ b/drivers/target/tcm_fc/tfc_conf.c | |||
@@ -267,7 +267,7 @@ struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata) | |||
267 | return found; | 267 | return found; |
268 | } | 268 | } |
269 | 269 | ||
270 | struct se_node_acl *ft_tpg_alloc_fabric_acl(struct se_portal_group *se_tpg) | 270 | static struct se_node_acl *ft_tpg_alloc_fabric_acl(struct se_portal_group *se_tpg) |
271 | { | 271 | { |
272 | struct ft_node_acl *acl; | 272 | struct ft_node_acl *acl; |
273 | 273 | ||
@@ -552,7 +552,7 @@ static struct target_core_fabric_ops ft_fabric_ops = { | |||
552 | .fabric_drop_nodeacl = &ft_del_acl, | 552 | .fabric_drop_nodeacl = &ft_del_acl, |
553 | }; | 553 | }; |
554 | 554 | ||
555 | int ft_register_configfs(void) | 555 | static int ft_register_configfs(void) |
556 | { | 556 | { |
557 | struct target_fabric_configfs *fabric; | 557 | struct target_fabric_configfs *fabric; |
558 | int ret; | 558 | int ret; |
@@ -599,7 +599,7 @@ int ft_register_configfs(void) | |||
599 | return 0; | 599 | return 0; |
600 | } | 600 | } |
601 | 601 | ||
602 | void ft_deregister_configfs(void) | 602 | static void ft_deregister_configfs(void) |
603 | { | 603 | { |
604 | if (!ft_configfs) | 604 | if (!ft_configfs) |
605 | return; | 605 | return; |
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 1e4c75c5b36b..0a025b8e2a12 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c | |||
@@ -728,7 +728,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, | |||
728 | } | 728 | } |
729 | se_sess = tv_nexus->tvn_se_sess; | 729 | se_sess = tv_nexus->tvn_se_sess; |
730 | 730 | ||
731 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC); | 731 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); |
732 | if (tag < 0) { | 732 | if (tag < 0) { |
733 | pr_err("Unable to obtain tag for tcm_vhost_cmd\n"); | 733 | pr_err("Unable to obtain tag for tcm_vhost_cmd\n"); |
734 | return ERR_PTR(-ENOMEM); | 734 | return ERR_PTR(-ENOMEM); |
@@ -889,7 +889,7 @@ static void tcm_vhost_submission_work(struct work_struct *work) | |||
889 | cmd->tvc_lun, cmd->tvc_exp_data_len, | 889 | cmd->tvc_lun, cmd->tvc_exp_data_len, |
890 | cmd->tvc_task_attr, cmd->tvc_data_direction, | 890 | cmd->tvc_task_attr, cmd->tvc_data_direction, |
891 | TARGET_SCF_ACK_KREF, sg_ptr, cmd->tvc_sgl_count, | 891 | TARGET_SCF_ACK_KREF, sg_ptr, cmd->tvc_sgl_count, |
892 | sg_bidi_ptr, sg_no_bidi); | 892 | sg_bidi_ptr, sg_no_bidi, NULL, 0); |
893 | if (rc < 0) { | 893 | if (rc < 0) { |
894 | transport_send_check_condition_and_sense(se_cmd, | 894 | transport_send_check_condition_and_sense(se_cmd, |
895 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); | 895 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); |
diff --git a/include/linux/percpu_ida.h b/include/linux/percpu_ida.h index 1900bd0fa639..f5cfdd6a5539 100644 --- a/include/linux/percpu_ida.h +++ b/include/linux/percpu_ida.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <linux/bitops.h> | 5 | #include <linux/bitops.h> |
6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
7 | #include <linux/sched.h> | ||
7 | #include <linux/spinlock_types.h> | 8 | #include <linux/spinlock_types.h> |
8 | #include <linux/wait.h> | 9 | #include <linux/wait.h> |
9 | #include <linux/cpumask.h> | 10 | #include <linux/cpumask.h> |
@@ -61,7 +62,7 @@ struct percpu_ida { | |||
61 | /* Max size of percpu freelist, */ | 62 | /* Max size of percpu freelist, */ |
62 | #define IDA_DEFAULT_PCPU_SIZE ((IDA_DEFAULT_PCPU_BATCH_MOVE * 3) / 2) | 63 | #define IDA_DEFAULT_PCPU_SIZE ((IDA_DEFAULT_PCPU_BATCH_MOVE * 3) / 2) |
63 | 64 | ||
64 | int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp); | 65 | int percpu_ida_alloc(struct percpu_ida *pool, int state); |
65 | void percpu_ida_free(struct percpu_ida *pool, unsigned tag); | 66 | void percpu_ida_free(struct percpu_ida *pool, unsigned tag); |
66 | 67 | ||
67 | void percpu_ida_destroy(struct percpu_ida *pool); | 68 | void percpu_ida_destroy(struct percpu_ida *pool); |
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 66d42edfb3fc..0a4edfe8af51 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h | |||
@@ -155,6 +155,7 @@ enum scsi_timeouts { | |||
155 | /* values for service action in */ | 155 | /* values for service action in */ |
156 | #define SAI_READ_CAPACITY_16 0x10 | 156 | #define SAI_READ_CAPACITY_16 0x10 |
157 | #define SAI_GET_LBA_STATUS 0x12 | 157 | #define SAI_GET_LBA_STATUS 0x12 |
158 | #define SAI_REPORT_REFERRALS 0x13 | ||
158 | /* values for VARIABLE_LENGTH_CMD service action codes | 159 | /* values for VARIABLE_LENGTH_CMD service action codes |
159 | * see spc4r17 Section D.3.5, table D.7 and D.8 */ | 160 | * see spc4r17 Section D.3.5, table D.7 and D.8 */ |
160 | #define VLC_SA_RECEIVE_CREDENTIAL 0x1800 | 161 | #define VLC_SA_RECEIVE_CREDENTIAL 0x1800 |
diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index a12589c4ee92..ae5a17111968 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h | |||
@@ -94,7 +94,7 @@ extern int iscsit_tmr_post_handler(struct iscsi_cmd *, struct iscsi_conn *); | |||
94 | /* | 94 | /* |
95 | * From iscsi_target_util.c | 95 | * From iscsi_target_util.c |
96 | */ | 96 | */ |
97 | extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t); | 97 | extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, int); |
98 | extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, | 98 | extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, |
99 | unsigned char *, __be32); | 99 | unsigned char *, __be32); |
100 | extern void iscsit_release_cmd(struct iscsi_cmd *); | 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 39e0114d70c5..7020e33e742e 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h | |||
@@ -41,6 +41,9 @@ struct se_subsystem_api { | |||
41 | unsigned int (*get_io_opt)(struct se_device *); | 41 | unsigned int (*get_io_opt)(struct se_device *); |
42 | unsigned char *(*get_sense_buffer)(struct se_cmd *); | 42 | unsigned char *(*get_sense_buffer)(struct se_cmd *); |
43 | bool (*get_write_cache)(struct se_device *); | 43 | bool (*get_write_cache)(struct se_device *); |
44 | int (*init_prot)(struct se_device *); | ||
45 | int (*format_prot)(struct se_device *); | ||
46 | void (*free_prot)(struct se_device *); | ||
44 | }; | 47 | }; |
45 | 48 | ||
46 | struct sbc_ops { | 49 | struct sbc_ops { |
@@ -70,6 +73,10 @@ sense_reason_t sbc_execute_unmap(struct se_cmd *cmd, | |||
70 | sense_reason_t (*do_unmap_fn)(struct se_cmd *cmd, void *priv, | 73 | sense_reason_t (*do_unmap_fn)(struct se_cmd *cmd, void *priv, |
71 | sector_t lba, sector_t nolb), | 74 | sector_t lba, sector_t nolb), |
72 | void *priv); | 75 | void *priv); |
76 | sense_reason_t sbc_dif_verify_write(struct se_cmd *, sector_t, unsigned int, | ||
77 | unsigned int, struct scatterlist *, int); | ||
78 | sense_reason_t sbc_dif_verify_read(struct se_cmd *, sector_t, unsigned int, | ||
79 | unsigned int, struct scatterlist *, int); | ||
73 | 80 | ||
74 | void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); | 81 | void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); |
75 | int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *); | 82 | int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *); |
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 321301c0a643..c9c791209cd1 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
@@ -37,6 +37,9 @@ | |||
37 | /* Used by transport_send_check_condition_and_sense() */ | 37 | /* Used by transport_send_check_condition_and_sense() */ |
38 | #define SPC_SENSE_KEY_OFFSET 2 | 38 | #define SPC_SENSE_KEY_OFFSET 2 |
39 | #define SPC_ADD_SENSE_LEN_OFFSET 7 | 39 | #define SPC_ADD_SENSE_LEN_OFFSET 7 |
40 | #define SPC_DESC_TYPE_OFFSET 8 | ||
41 | #define SPC_ADDITIONAL_DESC_LEN_OFFSET 9 | ||
42 | #define SPC_VALIDITY_OFFSET 10 | ||
40 | #define SPC_ASC_KEY_OFFSET 12 | 43 | #define SPC_ASC_KEY_OFFSET 12 |
41 | #define SPC_ASCQ_KEY_OFFSET 13 | 44 | #define SPC_ASCQ_KEY_OFFSET 13 |
42 | #define TRANSPORT_IQN_LEN 224 | 45 | #define TRANSPORT_IQN_LEN 224 |
@@ -112,7 +115,7 @@ | |||
112 | /* Queue Algorithm Modifier default for restricted reordering in control mode page */ | 115 | /* Queue Algorithm Modifier default for restricted reordering in control mode page */ |
113 | #define DA_EMULATE_REST_REORD 0 | 116 | #define DA_EMULATE_REST_REORD 0 |
114 | 117 | ||
115 | #define SE_INQUIRY_BUF 512 | 118 | #define SE_INQUIRY_BUF 1024 |
116 | #define SE_MODE_PAGE_BUF 512 | 119 | #define SE_MODE_PAGE_BUF 512 |
117 | #define SE_SENSE_BUF 96 | 120 | #define SE_SENSE_BUF 96 |
118 | 121 | ||
@@ -205,6 +208,9 @@ enum tcm_sense_reason_table { | |||
205 | TCM_OUT_OF_RESOURCES = R(0x12), | 208 | TCM_OUT_OF_RESOURCES = R(0x12), |
206 | TCM_PARAMETER_LIST_LENGTH_ERROR = R(0x13), | 209 | TCM_PARAMETER_LIST_LENGTH_ERROR = R(0x13), |
207 | TCM_MISCOMPARE_VERIFY = R(0x14), | 210 | TCM_MISCOMPARE_VERIFY = R(0x14), |
211 | TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED = R(0x15), | ||
212 | TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16), | ||
213 | TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17), | ||
208 | #undef R | 214 | #undef R |
209 | }; | 215 | }; |
210 | 216 | ||
@@ -247,10 +253,28 @@ typedef enum { | |||
247 | 253 | ||
248 | struct se_cmd; | 254 | struct se_cmd; |
249 | 255 | ||
256 | struct t10_alua_lba_map_member { | ||
257 | struct list_head lba_map_mem_list; | ||
258 | int lba_map_mem_alua_state; | ||
259 | int lba_map_mem_alua_pg_id; | ||
260 | }; | ||
261 | |||
262 | struct t10_alua_lba_map { | ||
263 | u64 lba_map_first_lba; | ||
264 | u64 lba_map_last_lba; | ||
265 | struct list_head lba_map_list; | ||
266 | struct list_head lba_map_mem_list; | ||
267 | }; | ||
268 | |||
250 | struct t10_alua { | 269 | struct t10_alua { |
251 | /* ALUA Target Port Group ID */ | 270 | /* ALUA Target Port Group ID */ |
252 | u16 alua_tg_pt_gps_counter; | 271 | u16 alua_tg_pt_gps_counter; |
253 | u32 alua_tg_pt_gps_count; | 272 | u32 alua_tg_pt_gps_count; |
273 | /* Referrals support */ | ||
274 | spinlock_t lba_map_lock; | ||
275 | u32 lba_map_segment_size; | ||
276 | u32 lba_map_segment_multiplier; | ||
277 | struct list_head lba_map_list; | ||
254 | spinlock_t tg_pt_gps_lock; | 278 | spinlock_t tg_pt_gps_lock; |
255 | struct se_device *t10_dev; | 279 | struct se_device *t10_dev; |
256 | /* Used for default ALUA Target Port Group */ | 280 | /* Used for default ALUA Target Port Group */ |
@@ -284,6 +308,8 @@ struct t10_alua_tg_pt_gp { | |||
284 | u16 tg_pt_gp_id; | 308 | u16 tg_pt_gp_id; |
285 | int tg_pt_gp_valid_id; | 309 | int tg_pt_gp_valid_id; |
286 | int tg_pt_gp_alua_supported_states; | 310 | int tg_pt_gp_alua_supported_states; |
311 | int tg_pt_gp_alua_pending_state; | ||
312 | int tg_pt_gp_alua_previous_state; | ||
287 | int tg_pt_gp_alua_access_status; | 313 | int tg_pt_gp_alua_access_status; |
288 | int tg_pt_gp_alua_access_type; | 314 | int tg_pt_gp_alua_access_type; |
289 | int tg_pt_gp_nonop_delay_msecs; | 315 | int tg_pt_gp_nonop_delay_msecs; |
@@ -291,9 +317,6 @@ struct t10_alua_tg_pt_gp { | |||
291 | int tg_pt_gp_implicit_trans_secs; | 317 | int tg_pt_gp_implicit_trans_secs; |
292 | int tg_pt_gp_pref; | 318 | int tg_pt_gp_pref; |
293 | int tg_pt_gp_write_metadata; | 319 | int tg_pt_gp_write_metadata; |
294 | /* Used by struct t10_alua_tg_pt_gp->tg_pt_gp_md_buf_len */ | ||
295 | #define ALUA_MD_BUF_LEN 1024 | ||
296 | u32 tg_pt_gp_md_buf_len; | ||
297 | u32 tg_pt_gp_members; | 320 | u32 tg_pt_gp_members; |
298 | atomic_t tg_pt_gp_alua_access_state; | 321 | atomic_t tg_pt_gp_alua_access_state; |
299 | atomic_t tg_pt_gp_ref_cnt; | 322 | atomic_t tg_pt_gp_ref_cnt; |
@@ -303,6 +326,10 @@ struct t10_alua_tg_pt_gp { | |||
303 | struct config_group tg_pt_gp_group; | 326 | struct config_group tg_pt_gp_group; |
304 | struct list_head tg_pt_gp_list; | 327 | struct list_head tg_pt_gp_list; |
305 | struct list_head tg_pt_gp_mem_list; | 328 | struct list_head tg_pt_gp_mem_list; |
329 | struct se_port *tg_pt_gp_alua_port; | ||
330 | struct se_node_acl *tg_pt_gp_alua_nacl; | ||
331 | struct delayed_work tg_pt_gp_transition_work; | ||
332 | struct completion *tg_pt_gp_transition_complete; | ||
306 | }; | 333 | }; |
307 | 334 | ||
308 | struct t10_alua_tg_pt_gp_member { | 335 | struct t10_alua_tg_pt_gp_member { |
@@ -414,6 +441,34 @@ struct se_tmr_req { | |||
414 | struct list_head tmr_list; | 441 | struct list_head tmr_list; |
415 | }; | 442 | }; |
416 | 443 | ||
444 | enum target_prot_op { | ||
445 | TARGET_PROT_NORMAL = 0, | ||
446 | TARGET_PROT_DIN_INSERT, | ||
447 | TARGET_PROT_DOUT_INSERT, | ||
448 | TARGET_PROT_DIN_STRIP, | ||
449 | TARGET_PROT_DOUT_STRIP, | ||
450 | TARGET_PROT_DIN_PASS, | ||
451 | TARGET_PROT_DOUT_PASS, | ||
452 | }; | ||
453 | |||
454 | enum target_prot_ho { | ||
455 | PROT_SEPERATED, | ||
456 | PROT_INTERLEAVED, | ||
457 | }; | ||
458 | |||
459 | enum target_prot_type { | ||
460 | TARGET_DIF_TYPE0_PROT, | ||
461 | TARGET_DIF_TYPE1_PROT, | ||
462 | TARGET_DIF_TYPE2_PROT, | ||
463 | TARGET_DIF_TYPE3_PROT, | ||
464 | }; | ||
465 | |||
466 | struct se_dif_v1_tuple { | ||
467 | __be16 guard_tag; | ||
468 | __be16 app_tag; | ||
469 | __be32 ref_tag; | ||
470 | }; | ||
471 | |||
417 | struct se_cmd { | 472 | struct se_cmd { |
418 | /* SAM response code being sent to initiator */ | 473 | /* SAM response code being sent to initiator */ |
419 | u8 scsi_status; | 474 | u8 scsi_status; |
@@ -497,14 +552,24 @@ struct se_cmd { | |||
497 | void *priv; | 552 | void *priv; |
498 | 553 | ||
499 | /* Used for lun->lun_ref counting */ | 554 | /* Used for lun->lun_ref counting */ |
500 | bool lun_ref_active; | 555 | int lun_ref_active; |
556 | |||
557 | /* DIF related members */ | ||
558 | enum target_prot_op prot_op; | ||
559 | enum target_prot_type prot_type; | ||
560 | u32 prot_length; | ||
561 | u32 reftag_seed; | ||
562 | struct scatterlist *t_prot_sg; | ||
563 | unsigned int t_prot_nents; | ||
564 | enum target_prot_ho prot_handover; | ||
565 | sense_reason_t pi_err; | ||
566 | sector_t bad_sector; | ||
501 | }; | 567 | }; |
502 | 568 | ||
503 | struct se_ua { | 569 | struct se_ua { |
504 | u8 ua_asc; | 570 | u8 ua_asc; |
505 | u8 ua_ascq; | 571 | u8 ua_ascq; |
506 | struct se_node_acl *ua_nacl; | 572 | struct se_node_acl *ua_nacl; |
507 | struct list_head ua_dev_list; | ||
508 | struct list_head ua_nacl_list; | 573 | struct list_head ua_nacl_list; |
509 | }; | 574 | }; |
510 | 575 | ||
@@ -605,6 +670,9 @@ struct se_dev_attrib { | |||
605 | int emulate_tpws; | 670 | int emulate_tpws; |
606 | int emulate_caw; | 671 | int emulate_caw; |
607 | int emulate_3pc; | 672 | int emulate_3pc; |
673 | int pi_prot_format; | ||
674 | enum target_prot_type pi_prot_type; | ||
675 | enum target_prot_type hw_pi_prot_type; | ||
608 | int enforce_pr_isids; | 676 | int enforce_pr_isids; |
609 | int is_nonrot; | 677 | int is_nonrot; |
610 | int emulate_rest_reord; | 678 | int emulate_rest_reord; |
@@ -736,6 +804,8 @@ struct se_device { | |||
736 | /* Linked list for struct se_hba struct se_device list */ | 804 | /* Linked list for struct se_hba struct se_device list */ |
737 | struct list_head dev_list; | 805 | struct list_head dev_list; |
738 | struct se_lun xcopy_lun; | 806 | struct se_lun xcopy_lun; |
807 | /* Protection Information */ | ||
808 | int prot_length; | ||
739 | }; | 809 | }; |
740 | 810 | ||
741 | struct se_hba { | 811 | struct se_hba { |
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 4cf4fda404a3..0218d689b3d7 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h | |||
@@ -105,7 +105,8 @@ sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u32); | |||
105 | sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); | 105 | sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); |
106 | int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *, | 106 | int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *, |
107 | unsigned char *, unsigned char *, u32, u32, int, int, int, | 107 | unsigned char *, unsigned char *, u32, u32, int, int, int, |
108 | struct scatterlist *, u32, struct scatterlist *, u32); | 108 | struct scatterlist *, u32, struct scatterlist *, u32, |
109 | struct scatterlist *, u32); | ||
109 | int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, | 110 | int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, |
110 | unsigned char *, u32, u32, int, int, int); | 111 | unsigned char *, u32, u32, int, int, int); |
111 | int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, | 112 | int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, |
diff --git a/lib/percpu_ida.c b/lib/percpu_ida.c index 9d054bf91d0f..7be235f1a70b 100644 --- a/lib/percpu_ida.c +++ b/lib/percpu_ida.c | |||
@@ -132,22 +132,22 @@ static inline unsigned alloc_local_tag(struct percpu_ida_cpu *tags) | |||
132 | /** | 132 | /** |
133 | * percpu_ida_alloc - allocate a tag | 133 | * percpu_ida_alloc - allocate a tag |
134 | * @pool: pool to allocate from | 134 | * @pool: pool to allocate from |
135 | * @gfp: gfp flags | 135 | * @state: task state for prepare_to_wait |
136 | * | 136 | * |
137 | * Returns a tag - an integer in the range [0..nr_tags) (passed to | 137 | * Returns a tag - an integer in the range [0..nr_tags) (passed to |
138 | * tag_pool_init()), or otherwise -ENOSPC on allocation failure. | 138 | * tag_pool_init()), or otherwise -ENOSPC on allocation failure. |
139 | * | 139 | * |
140 | * Safe to be called from interrupt context (assuming it isn't passed | 140 | * Safe to be called from interrupt context (assuming it isn't passed |
141 | * __GFP_WAIT, of course). | 141 | * TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, of course). |
142 | * | 142 | * |
143 | * @gfp indicates whether or not to wait until a free id is available (it's not | 143 | * @gfp indicates whether or not to wait until a free id is available (it's not |
144 | * used for internal memory allocations); thus if passed __GFP_WAIT we may sleep | 144 | * used for internal memory allocations); thus if passed __GFP_WAIT we may sleep |
145 | * however long it takes until another thread frees an id (same semantics as a | 145 | * however long it takes until another thread frees an id (same semantics as a |
146 | * mempool). | 146 | * mempool). |
147 | * | 147 | * |
148 | * Will not fail if passed __GFP_WAIT. | 148 | * Will not fail if passed TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE. |
149 | */ | 149 | */ |
150 | int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp) | 150 | int percpu_ida_alloc(struct percpu_ida *pool, int state) |
151 | { | 151 | { |
152 | DEFINE_WAIT(wait); | 152 | DEFINE_WAIT(wait); |
153 | struct percpu_ida_cpu *tags; | 153 | struct percpu_ida_cpu *tags; |
@@ -174,7 +174,8 @@ int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp) | |||
174 | * | 174 | * |
175 | * global lock held and irqs disabled, don't need percpu lock | 175 | * global lock held and irqs disabled, don't need percpu lock |
176 | */ | 176 | */ |
177 | prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE); | 177 | if (state != TASK_RUNNING) |
178 | prepare_to_wait(&pool->wait, &wait, state); | ||
178 | 179 | ||
179 | if (!tags->nr_free) | 180 | if (!tags->nr_free) |
180 | alloc_global_tags(pool, tags); | 181 | alloc_global_tags(pool, tags); |
@@ -191,16 +192,22 @@ int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp) | |||
191 | spin_unlock(&pool->lock); | 192 | spin_unlock(&pool->lock); |
192 | local_irq_restore(flags); | 193 | local_irq_restore(flags); |
193 | 194 | ||
194 | if (tag >= 0 || !(gfp & __GFP_WAIT)) | 195 | if (tag >= 0 || state == TASK_RUNNING) |
195 | break; | 196 | break; |
196 | 197 | ||
198 | if (signal_pending_state(state, current)) { | ||
199 | tag = -ERESTARTSYS; | ||
200 | break; | ||
201 | } | ||
202 | |||
197 | schedule(); | 203 | schedule(); |
198 | 204 | ||
199 | local_irq_save(flags); | 205 | local_irq_save(flags); |
200 | tags = this_cpu_ptr(pool->tag_cpu); | 206 | tags = this_cpu_ptr(pool->tag_cpu); |
201 | } | 207 | } |
208 | if (state != TASK_RUNNING) | ||
209 | finish_wait(&pool->wait, &wait); | ||
202 | 210 | ||
203 | finish_wait(&pool->wait, &wait); | ||
204 | return tag; | 211 | return tag; |
205 | } | 212 | } |
206 | EXPORT_SYMBOL_GPL(percpu_ida_alloc); | 213 | EXPORT_SYMBOL_GPL(percpu_ida_alloc); |