aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_mbx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mbx.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c396
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 */
44static int 44static int
45qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) 45qla2x00_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 */
890int 894int
891qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, 895qla2x00_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
2305atarget_done: 2324atarget_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 */
2647int
2648qla24xx_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
2685int
2686qla24xx_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
2723void
2724qla24xx_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 */
2791int
2792qla24xx_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 */
2859int
2860qla24xx_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
2950int
2951qla2x00_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}