diff options
author | Seokmann Ju <seokmann.ju@qlogic.com> | 2007-07-05 16:16:51 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-07-14 20:08:05 -0400 |
commit | 2c3dfe3f6ad8daff5acdb01713e4f2b116e78136 (patch) | |
tree | 8d95e2356c0f5121ceab48ab564d2796b6530d29 /drivers/scsi/qla2xxx/qla_mbx.c | |
parent | 968a5763fb7247feb0e69573a2975a7a0c094267 (diff) |
[SCSI] qla2xxx: add support for NPIV
Following patch adds support for NPIV (N-Port ID Virtualization) to the
qla2xxx.
- supported within switched-fabric topologies only.
- supports up to 63 virtual ports on each physical port.
Signed-off-by: Seokmann Ju <seokmann.ju@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mbx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 396 |
1 files changed, 383 insertions, 13 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 71e32a248528..2cd0cff25928 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -42,25 +42,29 @@ qla2x00_mbx_sem_timeout(unsigned long data) | |||
42 | * Kernel context. | 42 | * Kernel context. |
43 | */ | 43 | */ |
44 | static int | 44 | static int |
45 | qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | 45 | qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) |
46 | { | 46 | { |
47 | int rval; | 47 | int rval; |
48 | unsigned long flags = 0; | 48 | unsigned long flags = 0; |
49 | device_reg_t __iomem *reg = ha->iobase; | 49 | device_reg_t __iomem *reg; |
50 | struct timer_list tmp_intr_timer; | 50 | struct timer_list tmp_intr_timer; |
51 | uint8_t abort_active; | 51 | uint8_t abort_active; |
52 | uint8_t io_lock_on = ha->flags.init_done; | 52 | uint8_t io_lock_on; |
53 | uint16_t command; | 53 | uint16_t command; |
54 | uint16_t *iptr; | 54 | uint16_t *iptr; |
55 | uint16_t __iomem *optr; | 55 | uint16_t __iomem *optr; |
56 | uint32_t cnt; | 56 | uint32_t cnt; |
57 | uint32_t mboxes; | 57 | uint32_t mboxes; |
58 | unsigned long wait_time; | 58 | unsigned long wait_time; |
59 | scsi_qla_host_t *ha = to_qla_parent(pvha); | ||
60 | |||
61 | reg = ha->iobase; | ||
62 | io_lock_on = ha->flags.init_done; | ||
59 | 63 | ||
60 | rval = QLA_SUCCESS; | 64 | rval = QLA_SUCCESS; |
61 | abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 65 | abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); |
62 | 66 | ||
63 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 67 | DEBUG11(printk("%s(%ld): entered.\n", __func__, pvha->host_no)); |
64 | 68 | ||
65 | /* | 69 | /* |
66 | * Wait for active mailbox commands to finish by waiting at most tov | 70 | * Wait for active mailbox commands to finish by waiting at most tov |
@@ -889,7 +893,7 @@ qla2x00_abort_target(fc_port_t *fcport) | |||
889 | */ | 893 | */ |
890 | int | 894 | int |
891 | qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, | 895 | qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, |
892 | uint8_t *area, uint8_t *domain, uint16_t *top) | 896 | uint8_t *area, uint8_t *domain, uint16_t *top, uint16_t *sw_cap) |
893 | { | 897 | { |
894 | int rval; | 898 | int rval; |
895 | mbx_cmd_t mc; | 899 | mbx_cmd_t mc; |
@@ -899,8 +903,9 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, | |||
899 | ha->host_no)); | 903 | ha->host_no)); |
900 | 904 | ||
901 | mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; | 905 | mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; |
906 | mcp->mb[9] = ha->vp_idx; | ||
902 | mcp->out_mb = MBX_0; | 907 | mcp->out_mb = MBX_0; |
903 | mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; | 908 | mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; |
904 | mcp->tov = 30; | 909 | mcp->tov = 30; |
905 | mcp->flags = 0; | 910 | mcp->flags = 0; |
906 | rval = qla2x00_mailbox_command(ha, mcp); | 911 | rval = qla2x00_mailbox_command(ha, mcp); |
@@ -913,6 +918,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, | |||
913 | *area = MSB(mcp->mb[2]); | 918 | *area = MSB(mcp->mb[2]); |
914 | *domain = LSB(mcp->mb[3]); | 919 | *domain = LSB(mcp->mb[3]); |
915 | *top = mcp->mb[6]; | 920 | *top = mcp->mb[6]; |
921 | *sw_cap = mcp->mb[7]; | ||
916 | 922 | ||
917 | if (rval != QLA_SUCCESS) { | 923 | if (rval != QLA_SUCCESS) { |
918 | /*EMPTY*/ | 924 | /*EMPTY*/ |
@@ -1009,7 +1015,11 @@ qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size) | |||
1009 | DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", | 1015 | DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", |
1010 | ha->host_no)); | 1016 | ha->host_no)); |
1011 | 1017 | ||
1012 | mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; | 1018 | if (ha->flags.npiv_supported) |
1019 | mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE; | ||
1020 | else | ||
1021 | mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; | ||
1022 | |||
1013 | mcp->mb[2] = MSW(ha->init_cb_dma); | 1023 | mcp->mb[2] = MSW(ha->init_cb_dma); |
1014 | mcp->mb[3] = LSW(ha->init_cb_dma); | 1024 | mcp->mb[3] = LSW(ha->init_cb_dma); |
1015 | mcp->mb[4] = 0; | 1025 | mcp->mb[4] = 0; |
@@ -1081,7 +1091,8 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) | |||
1081 | mcp->mb[3] = LSW(pd_dma); | 1091 | mcp->mb[3] = LSW(pd_dma); |
1082 | mcp->mb[6] = MSW(MSD(pd_dma)); | 1092 | mcp->mb[6] = MSW(MSD(pd_dma)); |
1083 | mcp->mb[7] = LSW(MSD(pd_dma)); | 1093 | mcp->mb[7] = LSW(MSD(pd_dma)); |
1084 | mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | 1094 | mcp->mb[9] = ha->vp_idx; |
1095 | mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | ||
1085 | mcp->in_mb = MBX_0; | 1096 | mcp->in_mb = MBX_0; |
1086 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1097 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { |
1087 | mcp->mb[1] = fcport->loop_id; | 1098 | mcp->mb[1] = fcport->loop_id; |
@@ -1259,7 +1270,8 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name, | |||
1259 | ha->host_no)); | 1270 | ha->host_no)); |
1260 | 1271 | ||
1261 | mcp->mb[0] = MBC_GET_PORT_NAME; | 1272 | mcp->mb[0] = MBC_GET_PORT_NAME; |
1262 | mcp->out_mb = MBX_1|MBX_0; | 1273 | mcp->mb[9] = ha->vp_idx; |
1274 | mcp->out_mb = MBX_9|MBX_1|MBX_0; | ||
1263 | if (HAS_EXTENDED_IDS(ha)) { | 1275 | if (HAS_EXTENDED_IDS(ha)) { |
1264 | mcp->mb[1] = loop_id; | 1276 | mcp->mb[1] = loop_id; |
1265 | mcp->mb[10] = opt; | 1277 | mcp->mb[10] = opt; |
@@ -1447,6 +1459,7 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | |||
1447 | lg->port_id[0] = al_pa; | 1459 | lg->port_id[0] = al_pa; |
1448 | lg->port_id[1] = area; | 1460 | lg->port_id[1] = area; |
1449 | lg->port_id[2] = domain; | 1461 | lg->port_id[2] = domain; |
1462 | lg->vp_index = cpu_to_le16(ha->vp_idx); | ||
1450 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); | 1463 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); |
1451 | if (rval != QLA_SUCCESS) { | 1464 | if (rval != QLA_SUCCESS) { |
1452 | DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB " | 1465 | DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB " |
@@ -1701,6 +1714,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | |||
1701 | lg->port_id[0] = al_pa; | 1714 | lg->port_id[0] = al_pa; |
1702 | lg->port_id[1] = area; | 1715 | lg->port_id[1] = area; |
1703 | lg->port_id[2] = domain; | 1716 | lg->port_id[2] = domain; |
1717 | lg->vp_index = cpu_to_le16(ha->vp_idx); | ||
1704 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); | 1718 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); |
1705 | if (rval != QLA_SUCCESS) { | 1719 | if (rval != QLA_SUCCESS) { |
1706 | DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB " | 1720 | DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB " |
@@ -1863,7 +1877,8 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, | |||
1863 | mcp->mb[6] = MSW(MSD(id_list_dma)); | 1877 | mcp->mb[6] = MSW(MSD(id_list_dma)); |
1864 | mcp->mb[7] = LSW(MSD(id_list_dma)); | 1878 | mcp->mb[7] = LSW(MSD(id_list_dma)); |
1865 | mcp->mb[8] = 0; | 1879 | mcp->mb[8] = 0; |
1866 | mcp->out_mb |= MBX_8|MBX_7|MBX_6|MBX_3|MBX_2; | 1880 | mcp->mb[9] = ha->vp_idx; |
1881 | mcp->out_mb |= MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2; | ||
1867 | } else { | 1882 | } else { |
1868 | mcp->mb[1] = MSW(id_list_dma); | 1883 | mcp->mb[1] = MSW(id_list_dma); |
1869 | mcp->mb[2] = LSW(id_list_dma); | 1884 | mcp->mb[2] = LSW(id_list_dma); |
@@ -2212,6 +2227,7 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp) | |||
2212 | abt->port_id[0] = fcport->d_id.b.al_pa; | 2227 | abt->port_id[0] = fcport->d_id.b.al_pa; |
2213 | abt->port_id[1] = fcport->d_id.b.area; | 2228 | abt->port_id[1] = fcport->d_id.b.area; |
2214 | abt->port_id[2] = fcport->d_id.b.domain; | 2229 | abt->port_id[2] = fcport->d_id.b.domain; |
2230 | abt->vp_index = fcport->vp_idx; | ||
2215 | rval = qla2x00_issue_iocb(ha, abt, abt_dma, 0); | 2231 | rval = qla2x00_issue_iocb(ha, abt, abt_dma, 0); |
2216 | if (rval != QLA_SUCCESS) { | 2232 | if (rval != QLA_SUCCESS) { |
2217 | DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n", | 2233 | DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n", |
@@ -2249,7 +2265,7 @@ qla24xx_abort_target(fc_port_t *fcport) | |||
2249 | int rval; | 2265 | int rval; |
2250 | struct tsk_mgmt_cmd *tsk; | 2266 | struct tsk_mgmt_cmd *tsk; |
2251 | dma_addr_t tsk_dma; | 2267 | dma_addr_t tsk_dma; |
2252 | scsi_qla_host_t *ha; | 2268 | scsi_qla_host_t *ha, *pha; |
2253 | 2269 | ||
2254 | if (fcport == NULL) | 2270 | if (fcport == NULL) |
2255 | return 0; | 2271 | return 0; |
@@ -2257,7 +2273,8 @@ qla24xx_abort_target(fc_port_t *fcport) | |||
2257 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no)); | 2273 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no)); |
2258 | 2274 | ||
2259 | ha = fcport->ha; | 2275 | ha = fcport->ha; |
2260 | tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma); | 2276 | pha = to_qla_parent(ha); |
2277 | tsk = dma_pool_alloc(pha->s_dma_pool, GFP_KERNEL, &tsk_dma); | ||
2261 | if (tsk == NULL) { | 2278 | if (tsk == NULL) { |
2262 | DEBUG2_3(printk("%s(%ld): failed to allocate Task Management " | 2279 | DEBUG2_3(printk("%s(%ld): failed to allocate Task Management " |
2263 | "IOCB.\n", __func__, ha->host_no)); | 2280 | "IOCB.\n", __func__, ha->host_no)); |
@@ -2273,6 +2290,8 @@ qla24xx_abort_target(fc_port_t *fcport) | |||
2273 | tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; | 2290 | tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; |
2274 | tsk->p.tsk.port_id[1] = fcport->d_id.b.area; | 2291 | tsk->p.tsk.port_id[1] = fcport->d_id.b.area; |
2275 | tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; | 2292 | tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; |
2293 | tsk->p.tsk.vp_index = fcport->vp_idx; | ||
2294 | |||
2276 | rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0); | 2295 | rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0); |
2277 | if (rval != QLA_SUCCESS) { | 2296 | if (rval != QLA_SUCCESS) { |
2278 | DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB " | 2297 | DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB " |
@@ -2303,7 +2322,7 @@ qla24xx_abort_target(fc_port_t *fcport) | |||
2303 | } | 2322 | } |
2304 | 2323 | ||
2305 | atarget_done: | 2324 | atarget_done: |
2306 | dma_pool_free(ha->s_dma_pool, tsk, tsk_dma); | 2325 | dma_pool_free(pha->s_dma_pool, tsk, tsk_dma); |
2307 | 2326 | ||
2308 | return rval; | 2327 | return rval; |
2309 | } | 2328 | } |
@@ -2610,3 +2629,354 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, | |||
2610 | 2629 | ||
2611 | return rval; | 2630 | return rval; |
2612 | } | 2631 | } |
2632 | |||
2633 | /* | ||
2634 | * qla24xx_get_vp_database | ||
2635 | * Get the VP's database for all configured ports. | ||
2636 | * | ||
2637 | * Input: | ||
2638 | * ha = adapter block pointer. | ||
2639 | * size = size of initialization control block. | ||
2640 | * | ||
2641 | * Returns: | ||
2642 | * qla2x00 local function return status code. | ||
2643 | * | ||
2644 | * Context: | ||
2645 | * Kernel context. | ||
2646 | */ | ||
2647 | int | ||
2648 | qla24xx_get_vp_database(scsi_qla_host_t *ha, uint16_t size) | ||
2649 | { | ||
2650 | int rval; | ||
2651 | mbx_cmd_t mc; | ||
2652 | mbx_cmd_t *mcp = &mc; | ||
2653 | |||
2654 | DEBUG11(printk("scsi(%ld):%s - entered.\n", | ||
2655 | ha->host_no, __func__)); | ||
2656 | |||
2657 | mcp->mb[0] = MBC_MID_GET_VP_DATABASE; | ||
2658 | mcp->mb[2] = MSW(ha->init_cb_dma); | ||
2659 | mcp->mb[3] = LSW(ha->init_cb_dma); | ||
2660 | mcp->mb[4] = 0; | ||
2661 | mcp->mb[5] = 0; | ||
2662 | mcp->mb[6] = MSW(MSD(ha->init_cb_dma)); | ||
2663 | mcp->mb[7] = LSW(MSD(ha->init_cb_dma)); | ||
2664 | mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | ||
2665 | mcp->in_mb = MBX_1|MBX_0; | ||
2666 | mcp->buf_size = size; | ||
2667 | mcp->flags = MBX_DMA_OUT; | ||
2668 | mcp->tov = MBX_TOV_SECONDS; | ||
2669 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2670 | |||
2671 | if (rval != QLA_SUCCESS) { | ||
2672 | /*EMPTY*/ | ||
2673 | DEBUG2_3_11(printk("%s(%ld): failed=%x " | ||
2674 | "mb0=%x.\n", | ||
2675 | __func__, ha->host_no, rval, mcp->mb[0])); | ||
2676 | } else { | ||
2677 | /*EMPTY*/ | ||
2678 | DEBUG11(printk("%s(%ld): done.\n", | ||
2679 | __func__, ha->host_no)); | ||
2680 | } | ||
2681 | |||
2682 | return rval; | ||
2683 | } | ||
2684 | |||
2685 | int | ||
2686 | qla24xx_get_vp_entry(scsi_qla_host_t *ha, uint16_t size, int vp_id) | ||
2687 | { | ||
2688 | int rval; | ||
2689 | mbx_cmd_t mc; | ||
2690 | mbx_cmd_t *mcp = &mc; | ||
2691 | |||
2692 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2693 | |||
2694 | mcp->mb[0] = MBC_MID_GET_VP_ENTRY; | ||
2695 | mcp->mb[2] = MSW(ha->init_cb_dma); | ||
2696 | mcp->mb[3] = LSW(ha->init_cb_dma); | ||
2697 | mcp->mb[4] = 0; | ||
2698 | mcp->mb[5] = 0; | ||
2699 | mcp->mb[6] = MSW(MSD(ha->init_cb_dma)); | ||
2700 | mcp->mb[7] = LSW(MSD(ha->init_cb_dma)); | ||
2701 | mcp->mb[9] = vp_id; | ||
2702 | mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | ||
2703 | mcp->in_mb = MBX_0; | ||
2704 | mcp->buf_size = size; | ||
2705 | mcp->flags = MBX_DMA_OUT; | ||
2706 | mcp->tov = 30; | ||
2707 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2708 | |||
2709 | if (rval != QLA_SUCCESS) { | ||
2710 | /*EMPTY*/ | ||
2711 | DEBUG2_3_11(printk("qla24xx_get_vp_entry(%ld): failed=%x " | ||
2712 | "mb0=%x.\n", | ||
2713 | ha->host_no, rval, mcp->mb[0])); | ||
2714 | } else { | ||
2715 | /*EMPTY*/ | ||
2716 | DEBUG11(printk("qla24xx_get_vp_entry(%ld): done.\n", | ||
2717 | ha->host_no)); | ||
2718 | } | ||
2719 | |||
2720 | return rval; | ||
2721 | } | ||
2722 | |||
2723 | void | ||
2724 | qla24xx_report_id_acquisition(scsi_qla_host_t *ha, | ||
2725 | struct vp_rpt_id_entry_24xx *rptid_entry) | ||
2726 | { | ||
2727 | uint8_t vp_idx; | ||
2728 | scsi_qla_host_t *vha; | ||
2729 | |||
2730 | if (rptid_entry->entry_status != 0) | ||
2731 | return; | ||
2732 | if (rptid_entry->entry_status != __constant_cpu_to_le16(CS_COMPLETE)) | ||
2733 | return; | ||
2734 | |||
2735 | if (rptid_entry->format == 0) { | ||
2736 | DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d," | ||
2737 | " number of VPs acquired %d\n", __func__, ha->host_no, | ||
2738 | MSB(rptid_entry->vp_count), LSB(rptid_entry->vp_count))); | ||
2739 | DEBUG15(printk("%s primary port id %02x%02x%02x\n", __func__, | ||
2740 | rptid_entry->port_id[2], rptid_entry->port_id[1], | ||
2741 | rptid_entry->port_id[0])); | ||
2742 | } else if (rptid_entry->format == 1) { | ||
2743 | vp_idx = LSB(rptid_entry->vp_idx); | ||
2744 | DEBUG15(printk("%s:format 1: scsi(%ld): VP[%d] enabled " | ||
2745 | "- status %d - " | ||
2746 | "with port id %02x%02x%02x\n",__func__,ha->host_no, | ||
2747 | vp_idx, MSB(rptid_entry->vp_idx), | ||
2748 | rptid_entry->port_id[2], rptid_entry->port_id[1], | ||
2749 | rptid_entry->port_id[0])); | ||
2750 | if (vp_idx == 0) | ||
2751 | return; | ||
2752 | |||
2753 | if (MSB(rptid_entry->vp_idx) == 1) | ||
2754 | return; | ||
2755 | |||
2756 | list_for_each_entry(vha, &ha->vp_list, vp_list) | ||
2757 | if (vp_idx == vha->vp_idx) | ||
2758 | break; | ||
2759 | |||
2760 | if (!vha) | ||
2761 | return; | ||
2762 | |||
2763 | vha->d_id.b.domain = rptid_entry->port_id[2]; | ||
2764 | vha->d_id.b.area = rptid_entry->port_id[1]; | ||
2765 | vha->d_id.b.al_pa = rptid_entry->port_id[0]; | ||
2766 | |||
2767 | /* | ||
2768 | * Cannot configure here as we are still sitting on the | ||
2769 | * response queue. Handle it in dpc context. | ||
2770 | */ | ||
2771 | set_bit(VP_IDX_ACQUIRED, &vha->vp_flags); | ||
2772 | set_bit(VP_DPC_NEEDED, &ha->dpc_flags); | ||
2773 | |||
2774 | wake_up_process(ha->dpc_thread); | ||
2775 | } | ||
2776 | } | ||
2777 | |||
2778 | /* | ||
2779 | * qla24xx_modify_vp_config | ||
2780 | * Change VP configuration for vha | ||
2781 | * | ||
2782 | * Input: | ||
2783 | * vha = adapter block pointer. | ||
2784 | * | ||
2785 | * Returns: | ||
2786 | * qla2xxx local function return status code. | ||
2787 | * | ||
2788 | * Context: | ||
2789 | * Kernel context. | ||
2790 | */ | ||
2791 | int | ||
2792 | qla24xx_modify_vp_config(scsi_qla_host_t *vha) | ||
2793 | { | ||
2794 | int rval; | ||
2795 | struct vp_config_entry_24xx *vpmod; | ||
2796 | dma_addr_t vpmod_dma; | ||
2797 | scsi_qla_host_t *pha; | ||
2798 | |||
2799 | /* This can be called by the parent */ | ||
2800 | pha = to_qla_parent(vha); | ||
2801 | |||
2802 | vpmod = dma_pool_alloc(pha->s_dma_pool, GFP_KERNEL, &vpmod_dma); | ||
2803 | if (!vpmod) { | ||
2804 | DEBUG2_3(printk("%s(%ld): failed to allocate Modify VP " | ||
2805 | "IOCB.\n", __func__, pha->host_no)); | ||
2806 | return QLA_MEMORY_ALLOC_FAILED; | ||
2807 | } | ||
2808 | |||
2809 | memset(vpmod, 0, sizeof(struct vp_config_entry_24xx)); | ||
2810 | vpmod->entry_type = VP_CONFIG_IOCB_TYPE; | ||
2811 | vpmod->entry_count = 1; | ||
2812 | vpmod->command = VCT_COMMAND_MOD_ENABLE_VPS; | ||
2813 | vpmod->vp_count = 1; | ||
2814 | vpmod->vp_index1 = vha->vp_idx; | ||
2815 | vpmod->options_idx1 = BIT_3|BIT_4|BIT_5; | ||
2816 | memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE); | ||
2817 | memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE); | ||
2818 | vpmod->entry_count = 1; | ||
2819 | |||
2820 | rval = qla2x00_issue_iocb(pha, vpmod, vpmod_dma, 0); | ||
2821 | if (rval != QLA_SUCCESS) { | ||
2822 | DEBUG2_3_11(printk("%s(%ld): failed to issue VP config IOCB" | ||
2823 | "(%x).\n", __func__, pha->host_no, rval)); | ||
2824 | } else if (vpmod->comp_status != 0) { | ||
2825 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2826 | "-- error status (%x).\n", __func__, pha->host_no, | ||
2827 | vpmod->comp_status)); | ||
2828 | rval = QLA_FUNCTION_FAILED; | ||
2829 | } else if (vpmod->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { | ||
2830 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2831 | "-- completion status (%x).\n", __func__, pha->host_no, | ||
2832 | le16_to_cpu(vpmod->comp_status))); | ||
2833 | rval = QLA_FUNCTION_FAILED; | ||
2834 | } else { | ||
2835 | /* EMPTY */ | ||
2836 | DEBUG11(printk("%s(%ld): done.\n", __func__, pha->host_no)); | ||
2837 | fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING); | ||
2838 | } | ||
2839 | dma_pool_free(pha->s_dma_pool, vpmod, vpmod_dma); | ||
2840 | |||
2841 | return rval; | ||
2842 | } | ||
2843 | |||
2844 | /* | ||
2845 | * qla24xx_control_vp | ||
2846 | * Enable a virtual port for given host | ||
2847 | * | ||
2848 | * Input: | ||
2849 | * ha = adapter block pointer. | ||
2850 | * vhba = virtual adapter (unused) | ||
2851 | * index = index number for enabled VP | ||
2852 | * | ||
2853 | * Returns: | ||
2854 | * qla2xxx local function return status code. | ||
2855 | * | ||
2856 | * Context: | ||
2857 | * Kernel context. | ||
2858 | */ | ||
2859 | int | ||
2860 | qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) | ||
2861 | { | ||
2862 | int rval; | ||
2863 | int map, pos; | ||
2864 | struct vp_ctrl_entry_24xx *vce; | ||
2865 | dma_addr_t vce_dma; | ||
2866 | scsi_qla_host_t *ha = vha->parent; | ||
2867 | int vp_index = vha->vp_idx; | ||
2868 | |||
2869 | DEBUG11(printk("%s(%ld): entered. Enabling index %d\n", __func__, | ||
2870 | ha->host_no, vp_index)); | ||
2871 | |||
2872 | if (vp_index == 0 || vp_index >= MAX_MULTI_ID_LOOP) | ||
2873 | return QLA_PARAMETER_ERROR; | ||
2874 | |||
2875 | vce = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma); | ||
2876 | if (!vce) { | ||
2877 | DEBUG2_3(printk("%s(%ld): " | ||
2878 | "failed to allocate VP Control IOCB.\n", __func__, | ||
2879 | ha->host_no)); | ||
2880 | return QLA_MEMORY_ALLOC_FAILED; | ||
2881 | } | ||
2882 | memset(vce, 0, sizeof(struct vp_ctrl_entry_24xx)); | ||
2883 | |||
2884 | vce->entry_type = VP_CTRL_IOCB_TYPE; | ||
2885 | vce->entry_count = 1; | ||
2886 | vce->command = cpu_to_le16(cmd); | ||
2887 | vce->vp_count = __constant_cpu_to_le16(1); | ||
2888 | |||
2889 | /* index map in firmware starts with 1; decrement index | ||
2890 | * this is ok as we never use index 0 | ||
2891 | */ | ||
2892 | map = (vp_index - 1) / 8; | ||
2893 | pos = (vp_index - 1) & 7; | ||
2894 | down(&ha->vport_sem); | ||
2895 | vce->vp_idx_map[map] |= 1 << pos; | ||
2896 | up(&ha->vport_sem); | ||
2897 | |||
2898 | rval = qla2x00_issue_iocb(ha, vce, vce_dma, 0); | ||
2899 | if (rval != QLA_SUCCESS) { | ||
2900 | DEBUG2_3_11(printk("%s(%ld): failed to issue VP control IOCB" | ||
2901 | "(%x).\n", __func__, ha->host_no, rval)); | ||
2902 | printk("%s(%ld): failed to issue VP control IOCB" | ||
2903 | "(%x).\n", __func__, ha->host_no, rval); | ||
2904 | } else if (vce->entry_status != 0) { | ||
2905 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2906 | "-- error status (%x).\n", __func__, ha->host_no, | ||
2907 | vce->entry_status)); | ||
2908 | printk("%s(%ld): failed to complete IOCB " | ||
2909 | "-- error status (%x).\n", __func__, ha->host_no, | ||
2910 | vce->entry_status); | ||
2911 | rval = QLA_FUNCTION_FAILED; | ||
2912 | } else if (vce->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { | ||
2913 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2914 | "-- completion status (%x).\n", __func__, ha->host_no, | ||
2915 | le16_to_cpu(vce->comp_status))); | ||
2916 | printk("%s(%ld): failed to complete IOCB " | ||
2917 | "-- completion status (%x).\n", __func__, ha->host_no, | ||
2918 | le16_to_cpu(vce->comp_status)); | ||
2919 | rval = QLA_FUNCTION_FAILED; | ||
2920 | } else { | ||
2921 | DEBUG2(printk("%s(%ld): done.\n", __func__, ha->host_no)); | ||
2922 | } | ||
2923 | |||
2924 | dma_pool_free(ha->s_dma_pool, vce, vce_dma); | ||
2925 | |||
2926 | return rval; | ||
2927 | } | ||
2928 | |||
2929 | /* | ||
2930 | * qla2x00_send_change_request | ||
2931 | * Receive or disable RSCN request from fabric controller | ||
2932 | * | ||
2933 | * Input: | ||
2934 | * ha = adapter block pointer | ||
2935 | * format = registration format: | ||
2936 | * 0 - Reserved | ||
2937 | * 1 - Fabric detected registration | ||
2938 | * 2 - N_port detected registration | ||
2939 | * 3 - Full registration | ||
2940 | * FF - clear registration | ||
2941 | * vp_idx = Virtual port index | ||
2942 | * | ||
2943 | * Returns: | ||
2944 | * qla2x00 local function return status code. | ||
2945 | * | ||
2946 | * Context: | ||
2947 | * Kernel Context | ||
2948 | */ | ||
2949 | |||
2950 | int | ||
2951 | qla2x00_send_change_request(scsi_qla_host_t *ha, uint16_t format, | ||
2952 | uint16_t vp_idx) | ||
2953 | { | ||
2954 | int rval; | ||
2955 | mbx_cmd_t mc; | ||
2956 | mbx_cmd_t *mcp = &mc; | ||
2957 | |||
2958 | /* | ||
2959 | * This command is implicitly executed by firmware during login for the | ||
2960 | * physical hosts | ||
2961 | */ | ||
2962 | if (vp_idx == 0) | ||
2963 | return QLA_FUNCTION_FAILED; | ||
2964 | |||
2965 | mcp->mb[0] = MBC_SEND_CHANGE_REQUEST; | ||
2966 | mcp->mb[1] = format; | ||
2967 | mcp->mb[9] = vp_idx; | ||
2968 | mcp->out_mb = MBX_9|MBX_1|MBX_0; | ||
2969 | mcp->in_mb = MBX_0|MBX_1; | ||
2970 | mcp->tov = MBX_TOV_SECONDS; | ||
2971 | mcp->flags = 0; | ||
2972 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2973 | |||
2974 | if (rval == QLA_SUCCESS) { | ||
2975 | if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { | ||
2976 | rval = BIT_1; | ||
2977 | } | ||
2978 | } else | ||
2979 | rval = BIT_1; | ||
2980 | |||
2981 | return rval; | ||
2982 | } | ||