diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 39 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 20 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gs.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 239 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 206 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 309 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 7 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 27 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 141 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 2 |
12 files changed, 936 insertions, 69 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 0f8796201504..fbcb82a2f7f4 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -1670,7 +1670,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | |||
1670 | 1670 | ||
1671 | qla24xx_vport_disable(fc_vport, disable); | 1671 | qla24xx_vport_disable(fc_vport, disable); |
1672 | 1672 | ||
1673 | if (ql2xmultique_tag) { | 1673 | if (ha->flags.cpu_affinity_enabled) { |
1674 | req = ha->req_q_map[1]; | 1674 | req = ha->req_q_map[1]; |
1675 | goto vport_queue; | 1675 | goto vport_queue; |
1676 | } else if (ql2xmaxqueues == 1 || !ha->npiv_info) | 1676 | } else if (ql2xmaxqueues == 1 || !ha->npiv_info) |
@@ -1736,6 +1736,11 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) | |||
1736 | 1736 | ||
1737 | qla24xx_deallocate_vp_id(vha); | 1737 | qla24xx_deallocate_vp_id(vha); |
1738 | 1738 | ||
1739 | mutex_lock(&ha->vport_lock); | ||
1740 | ha->cur_vport_count--; | ||
1741 | clear_bit(vha->vp_idx, ha->vp_idx_map); | ||
1742 | mutex_unlock(&ha->vport_lock); | ||
1743 | |||
1739 | if (vha->timer_active) { | 1744 | if (vha->timer_active) { |
1740 | qla2x00_vp_stop_timer(vha); | 1745 | qla2x00_vp_stop_timer(vha); |
1741 | DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p " | 1746 | DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p " |
@@ -1743,7 +1748,7 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) | |||
1743 | vha->host_no, vha->vp_idx, vha)); | 1748 | vha->host_no, vha->vp_idx, vha)); |
1744 | } | 1749 | } |
1745 | 1750 | ||
1746 | if (vha->req->id && !ql2xmultique_tag) { | 1751 | if (vha->req->id && !ha->flags.cpu_affinity_enabled) { |
1747 | if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS) | 1752 | if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS) |
1748 | qla_printk(KERN_WARNING, ha, | 1753 | qla_printk(KERN_WARNING, ha, |
1749 | "Queue delete failed.\n"); | 1754 | "Queue delete failed.\n"); |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 00aa48d975a6..215061861794 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -189,6 +189,7 @@ struct req_que; | |||
189 | */ | 189 | */ |
190 | typedef struct srb { | 190 | typedef struct srb { |
191 | struct fc_port *fcport; | 191 | struct fc_port *fcport; |
192 | uint32_t handle; | ||
192 | 193 | ||
193 | struct scsi_cmnd *cmd; /* Linux SCSI command pkt */ | 194 | struct scsi_cmnd *cmd; /* Linux SCSI command pkt */ |
194 | 195 | ||
@@ -196,6 +197,8 @@ typedef struct srb { | |||
196 | 197 | ||
197 | uint32_t request_sense_length; | 198 | uint32_t request_sense_length; |
198 | uint8_t *request_sense_ptr; | 199 | uint8_t *request_sense_ptr; |
200 | |||
201 | void *ctx; | ||
199 | } srb_t; | 202 | } srb_t; |
200 | 203 | ||
201 | /* | 204 | /* |
@@ -204,6 +207,28 @@ typedef struct srb { | |||
204 | #define SRB_DMA_VALID BIT_0 /* Command sent to ISP */ | 207 | #define SRB_DMA_VALID BIT_0 /* Command sent to ISP */ |
205 | 208 | ||
206 | /* | 209 | /* |
210 | * SRB extensions. | ||
211 | */ | ||
212 | struct srb_ctx { | ||
213 | #define SRB_LOGIN_CMD 1 | ||
214 | #define SRB_LOGOUT_CMD 2 | ||
215 | uint16_t type; | ||
216 | struct timer_list timer; | ||
217 | |||
218 | void (*free)(srb_t *sp); | ||
219 | void (*timeout)(srb_t *sp); | ||
220 | }; | ||
221 | |||
222 | struct srb_logio { | ||
223 | struct srb_ctx ctx; | ||
224 | |||
225 | #define SRB_LOGIN_RETRIED BIT_0 | ||
226 | #define SRB_LOGIN_COND_PLOGI BIT_1 | ||
227 | #define SRB_LOGIN_SKIP_PRLI BIT_2 | ||
228 | uint16_t flags; | ||
229 | }; | ||
230 | |||
231 | /* | ||
207 | * ISP I/O Register Set structure definitions. | 232 | * ISP I/O Register Set structure definitions. |
208 | */ | 233 | */ |
209 | struct device_reg_2xxx { | 234 | struct device_reg_2xxx { |
@@ -1482,7 +1507,7 @@ typedef union { | |||
1482 | uint8_t domain; | 1507 | uint8_t domain; |
1483 | uint8_t area; | 1508 | uint8_t area; |
1484 | uint8_t al_pa; | 1509 | uint8_t al_pa; |
1485 | #elif __LITTLE_ENDIAN | 1510 | #elif defined(__LITTLE_ENDIAN) |
1486 | uint8_t al_pa; | 1511 | uint8_t al_pa; |
1487 | uint8_t area; | 1512 | uint8_t area; |
1488 | uint8_t domain; | 1513 | uint8_t domain; |
@@ -1565,6 +1590,7 @@ typedef struct fc_port { | |||
1565 | #define FCF_FABRIC_DEVICE BIT_0 | 1590 | #define FCF_FABRIC_DEVICE BIT_0 |
1566 | #define FCF_LOGIN_NEEDED BIT_1 | 1591 | #define FCF_LOGIN_NEEDED BIT_1 |
1567 | #define FCF_TAPE_PRESENT BIT_2 | 1592 | #define FCF_TAPE_PRESENT BIT_2 |
1593 | #define FCF_FCP2_DEVICE BIT_3 | ||
1568 | 1594 | ||
1569 | /* No loop ID flag. */ | 1595 | /* No loop ID flag. */ |
1570 | #define FC_NO_LOOP_ID 0x1000 | 1596 | #define FC_NO_LOOP_ID 0x1000 |
@@ -2093,6 +2119,10 @@ struct qla_msix_entry { | |||
2093 | enum qla_work_type { | 2119 | enum qla_work_type { |
2094 | QLA_EVT_AEN, | 2120 | QLA_EVT_AEN, |
2095 | QLA_EVT_IDC_ACK, | 2121 | QLA_EVT_IDC_ACK, |
2122 | QLA_EVT_ASYNC_LOGIN, | ||
2123 | QLA_EVT_ASYNC_LOGIN_DONE, | ||
2124 | QLA_EVT_ASYNC_LOGOUT, | ||
2125 | QLA_EVT_ASYNC_LOGOUT_DONE, | ||
2096 | }; | 2126 | }; |
2097 | 2127 | ||
2098 | 2128 | ||
@@ -2111,6 +2141,11 @@ struct qla_work_evt { | |||
2111 | #define QLA_IDC_ACK_REGS 7 | 2141 | #define QLA_IDC_ACK_REGS 7 |
2112 | uint16_t mb[QLA_IDC_ACK_REGS]; | 2142 | uint16_t mb[QLA_IDC_ACK_REGS]; |
2113 | } idc_ack; | 2143 | } idc_ack; |
2144 | struct { | ||
2145 | struct fc_port *fcport; | ||
2146 | #define QLA_LOGIO_LOGIN_RETRIED BIT_0 | ||
2147 | u16 data[2]; | ||
2148 | } logio; | ||
2114 | } u; | 2149 | } u; |
2115 | }; | 2150 | }; |
2116 | 2151 | ||
@@ -2224,6 +2259,7 @@ struct qla_hw_data { | |||
2224 | uint32_t chip_reset_done :1; | 2259 | uint32_t chip_reset_done :1; |
2225 | uint32_t port0 :1; | 2260 | uint32_t port0 :1; |
2226 | uint32_t running_gold_fw :1; | 2261 | uint32_t running_gold_fw :1; |
2262 | uint32_t cpu_affinity_enabled :1; | ||
2227 | } flags; | 2263 | } flags; |
2228 | 2264 | ||
2229 | /* This spinlock is used to protect "io transactions", you must | 2265 | /* This spinlock is used to protect "io transactions", you must |
@@ -2350,6 +2386,7 @@ struct qla_hw_data { | |||
2350 | (ha)->flags.msix_enabled) | 2386 | (ha)->flags.msix_enabled) |
2351 | #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha)) | 2387 | #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha)) |
2352 | #define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha)) | 2388 | #define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha)) |
2389 | #define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha)) | ||
2353 | 2390 | ||
2354 | #define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA) | 2391 | #define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA) |
2355 | #define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2) | 2392 | #define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2) |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index dfde2dd865cb..66a8da5d7d08 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
@@ -1126,7 +1126,7 @@ struct vp_config_entry_24xx { | |||
1126 | uint16_t id; | 1126 | uint16_t id; |
1127 | uint16_t reserved_4; | 1127 | uint16_t reserved_4; |
1128 | uint16_t hopct; | 1128 | uint16_t hopct; |
1129 | uint8_t reserved_5; | 1129 | uint8_t reserved_5[2]; |
1130 | }; | 1130 | }; |
1131 | 1131 | ||
1132 | #define VP_RPT_ID_IOCB_TYPE 0x32 /* Report ID Acquisition entry. */ | 1132 | #define VP_RPT_ID_IOCB_TYPE 0x32 /* Report ID Acquisition entry. */ |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 65b12d82867c..f3d1d1afa95b 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -52,6 +52,14 @@ extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *); | |||
52 | 52 | ||
53 | extern void qla84xx_put_chip(struct scsi_qla_host *); | 53 | extern void qla84xx_put_chip(struct scsi_qla_host *); |
54 | 54 | ||
55 | extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *, | ||
56 | uint16_t *); | ||
57 | extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); | ||
58 | extern int qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *, | ||
59 | uint16_t *); | ||
60 | extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, | ||
61 | uint16_t *); | ||
62 | |||
55 | /* | 63 | /* |
56 | * Global Data in qla_os.c source file. | 64 | * Global Data in qla_os.c source file. |
57 | */ | 65 | */ |
@@ -76,6 +84,15 @@ extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); | |||
76 | extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum | 84 | extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum |
77 | fc_host_event_code, u32); | 85 | fc_host_event_code, u32); |
78 | extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *); | 86 | extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *); |
87 | extern int qla2x00_post_async_login_work(struct scsi_qla_host *, fc_port_t *, | ||
88 | uint16_t *); | ||
89 | extern int qla2x00_post_async_login_done_work(struct scsi_qla_host *, | ||
90 | fc_port_t *, uint16_t *); | ||
91 | extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *, | ||
92 | uint16_t *); | ||
93 | extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *, | ||
94 | fc_port_t *, uint16_t *); | ||
95 | |||
79 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); | 96 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); |
80 | 97 | ||
81 | extern void qla2x00_abort_fcport_cmds(fc_port_t *); | 98 | extern void qla2x00_abort_fcport_cmds(fc_port_t *); |
@@ -83,6 +100,8 @@ extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *, | |||
83 | struct qla_hw_data *); | 100 | struct qla_hw_data *); |
84 | extern void qla2x00_free_host(struct scsi_qla_host *); | 101 | extern void qla2x00_free_host(struct scsi_qla_host *); |
85 | extern void qla2x00_relogin(struct scsi_qla_host *); | 102 | extern void qla2x00_relogin(struct scsi_qla_host *); |
103 | extern void qla2x00_do_work(struct scsi_qla_host *); | ||
104 | |||
86 | /* | 105 | /* |
87 | * Global Functions in qla_mid.c source file. | 106 | * Global Functions in qla_mid.c source file. |
88 | */ | 107 | */ |
@@ -135,6 +154,7 @@ int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, | |||
135 | uint16_t, uint16_t, uint8_t); | 154 | uint16_t, uint16_t, uint8_t); |
136 | int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, | 155 | int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, |
137 | uint16_t, uint16_t, uint8_t); | 156 | uint16_t, uint16_t, uint8_t); |
157 | extern int qla2x00_start_sp(srb_t *); | ||
138 | 158 | ||
139 | /* | 159 | /* |
140 | * Global Function Prototypes in qla_mbx.c source file. | 160 | * Global Function Prototypes in qla_mbx.c source file. |
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 917534b9f221..4647015eba63 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c | |||
@@ -1674,6 +1674,10 @@ int | |||
1674 | qla2x00_fdmi_register(scsi_qla_host_t *vha) | 1674 | qla2x00_fdmi_register(scsi_qla_host_t *vha) |
1675 | { | 1675 | { |
1676 | int rval; | 1676 | int rval; |
1677 | struct qla_hw_data *ha = vha->hw; | ||
1678 | |||
1679 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | ||
1680 | return QLA_FUNCTION_FAILED; | ||
1677 | 1681 | ||
1678 | rval = qla2x00_mgmt_svr_login(vha); | 1682 | rval = qla2x00_mgmt_svr_login(vha); |
1679 | if (rval) | 1683 | if (rval) |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f2ce8e3cc91b..9e3eaac25596 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -40,6 +40,210 @@ static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *); | |||
40 | static int qla84xx_init_chip(scsi_qla_host_t *); | 40 | static int qla84xx_init_chip(scsi_qla_host_t *); |
41 | static int qla25xx_init_queues(struct qla_hw_data *); | 41 | static int qla25xx_init_queues(struct qla_hw_data *); |
42 | 42 | ||
43 | /* SRB Extensions ---------------------------------------------------------- */ | ||
44 | |||
45 | static void | ||
46 | qla2x00_ctx_sp_timeout(unsigned long __data) | ||
47 | { | ||
48 | srb_t *sp = (srb_t *)__data; | ||
49 | struct srb_ctx *ctx; | ||
50 | fc_port_t *fcport = sp->fcport; | ||
51 | struct qla_hw_data *ha = fcport->vha->hw; | ||
52 | struct req_que *req; | ||
53 | unsigned long flags; | ||
54 | |||
55 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
56 | req = ha->req_q_map[0]; | ||
57 | req->outstanding_cmds[sp->handle] = NULL; | ||
58 | ctx = sp->ctx; | ||
59 | ctx->timeout(sp); | ||
60 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
61 | |||
62 | ctx->free(sp); | ||
63 | } | ||
64 | |||
65 | static void | ||
66 | qla2x00_ctx_sp_free(srb_t *sp) | ||
67 | { | ||
68 | struct srb_ctx *ctx = sp->ctx; | ||
69 | |||
70 | kfree(ctx); | ||
71 | mempool_free(sp, sp->fcport->vha->hw->srb_mempool); | ||
72 | } | ||
73 | |||
74 | inline srb_t * | ||
75 | qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, | ||
76 | unsigned long tmo) | ||
77 | { | ||
78 | srb_t *sp; | ||
79 | struct qla_hw_data *ha = vha->hw; | ||
80 | struct srb_ctx *ctx; | ||
81 | |||
82 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); | ||
83 | if (!sp) | ||
84 | goto done; | ||
85 | ctx = kzalloc(size, GFP_KERNEL); | ||
86 | if (!ctx) { | ||
87 | mempool_free(sp, ha->srb_mempool); | ||
88 | goto done; | ||
89 | } | ||
90 | |||
91 | memset(sp, 0, sizeof(*sp)); | ||
92 | sp->fcport = fcport; | ||
93 | sp->ctx = ctx; | ||
94 | ctx->free = qla2x00_ctx_sp_free; | ||
95 | |||
96 | init_timer(&ctx->timer); | ||
97 | if (!tmo) | ||
98 | goto done; | ||
99 | ctx->timer.expires = jiffies + tmo * HZ; | ||
100 | ctx->timer.data = (unsigned long)sp; | ||
101 | ctx->timer.function = qla2x00_ctx_sp_timeout; | ||
102 | add_timer(&ctx->timer); | ||
103 | done: | ||
104 | return sp; | ||
105 | } | ||
106 | |||
107 | /* Asynchronous Login/Logout Routines -------------------------------------- */ | ||
108 | |||
109 | #define ELS_TMO_2_RATOV(ha) ((ha)->r_a_tov / 10 * 2) | ||
110 | |||
111 | static void | ||
112 | qla2x00_async_logio_timeout(srb_t *sp) | ||
113 | { | ||
114 | fc_port_t *fcport = sp->fcport; | ||
115 | struct srb_logio *lio = sp->ctx; | ||
116 | |||
117 | DEBUG2(printk(KERN_WARNING | ||
118 | "scsi(%ld:%x): Async-%s timeout.\n", | ||
119 | fcport->vha->host_no, sp->handle, | ||
120 | lio->ctx.type == SRB_LOGIN_CMD ? "login": "logout")); | ||
121 | |||
122 | if (lio->ctx.type == SRB_LOGIN_CMD) | ||
123 | qla2x00_post_async_logout_work(fcport->vha, fcport, NULL); | ||
124 | } | ||
125 | |||
126 | int | ||
127 | qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
128 | uint16_t *data) | ||
129 | { | ||
130 | struct qla_hw_data *ha = vha->hw; | ||
131 | srb_t *sp; | ||
132 | struct srb_logio *lio; | ||
133 | int rval; | ||
134 | |||
135 | rval = QLA_FUNCTION_FAILED; | ||
136 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio), | ||
137 | ELS_TMO_2_RATOV(ha) + 2); | ||
138 | if (!sp) | ||
139 | goto done; | ||
140 | |||
141 | lio = sp->ctx; | ||
142 | lio->ctx.type = SRB_LOGIN_CMD; | ||
143 | lio->ctx.timeout = qla2x00_async_logio_timeout; | ||
144 | lio->flags |= SRB_LOGIN_COND_PLOGI; | ||
145 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | ||
146 | lio->flags |= SRB_LOGIN_RETRIED; | ||
147 | rval = qla2x00_start_sp(sp); | ||
148 | if (rval != QLA_SUCCESS) | ||
149 | goto done_free_sp; | ||
150 | |||
151 | DEBUG2(printk(KERN_DEBUG | ||
152 | "scsi(%ld:%x): Async-login - loop-id=%x portid=%02x%02x%02x " | ||
153 | "retries=%d.\n", fcport->vha->host_no, sp->handle, fcport->loop_id, | ||
154 | fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, | ||
155 | fcport->login_retry)); | ||
156 | return rval; | ||
157 | |||
158 | done_free_sp: | ||
159 | del_timer_sync(&lio->ctx.timer); | ||
160 | lio->ctx.free(sp); | ||
161 | done: | ||
162 | return rval; | ||
163 | } | ||
164 | |||
165 | int | ||
166 | qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) | ||
167 | { | ||
168 | struct qla_hw_data *ha = vha->hw; | ||
169 | srb_t *sp; | ||
170 | struct srb_logio *lio; | ||
171 | int rval; | ||
172 | |||
173 | rval = QLA_FUNCTION_FAILED; | ||
174 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio), | ||
175 | ELS_TMO_2_RATOV(ha) + 2); | ||
176 | if (!sp) | ||
177 | goto done; | ||
178 | |||
179 | lio = sp->ctx; | ||
180 | lio->ctx.type = SRB_LOGOUT_CMD; | ||
181 | lio->ctx.timeout = qla2x00_async_logio_timeout; | ||
182 | rval = qla2x00_start_sp(sp); | ||
183 | if (rval != QLA_SUCCESS) | ||
184 | goto done_free_sp; | ||
185 | |||
186 | DEBUG2(printk(KERN_DEBUG | ||
187 | "scsi(%ld:%x): Async-logout - loop-id=%x portid=%02x%02x%02x.\n", | ||
188 | fcport->vha->host_no, sp->handle, fcport->loop_id, | ||
189 | fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa)); | ||
190 | return rval; | ||
191 | |||
192 | done_free_sp: | ||
193 | del_timer_sync(&lio->ctx.timer); | ||
194 | lio->ctx.free(sp); | ||
195 | done: | ||
196 | return rval; | ||
197 | } | ||
198 | |||
199 | int | ||
200 | qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
201 | uint16_t *data) | ||
202 | { | ||
203 | int rval; | ||
204 | uint8_t opts = 0; | ||
205 | |||
206 | switch (data[0]) { | ||
207 | case MBS_COMMAND_COMPLETE: | ||
208 | if (fcport->flags & FCF_TAPE_PRESENT) | ||
209 | opts |= BIT_1; | ||
210 | rval = qla2x00_get_port_database(vha, fcport, opts); | ||
211 | if (rval != QLA_SUCCESS) | ||
212 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
213 | else | ||
214 | qla2x00_update_fcport(vha, fcport); | ||
215 | break; | ||
216 | case MBS_COMMAND_ERROR: | ||
217 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | ||
218 | set_bit(RELOGIN_NEEDED, &vha->dpc_flags); | ||
219 | else | ||
220 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
221 | break; | ||
222 | case MBS_PORT_ID_USED: | ||
223 | fcport->loop_id = data[1]; | ||
224 | qla2x00_post_async_login_work(vha, fcport, NULL); | ||
225 | break; | ||
226 | case MBS_LOOP_ID_USED: | ||
227 | fcport->loop_id++; | ||
228 | rval = qla2x00_find_new_loop_id(vha, fcport); | ||
229 | if (rval != QLA_SUCCESS) { | ||
230 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
231 | break; | ||
232 | } | ||
233 | qla2x00_post_async_login_work(vha, fcport, NULL); | ||
234 | break; | ||
235 | } | ||
236 | return QLA_SUCCESS; | ||
237 | } | ||
238 | |||
239 | int | ||
240 | qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
241 | uint16_t *data) | ||
242 | { | ||
243 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
244 | return QLA_SUCCESS; | ||
245 | } | ||
246 | |||
43 | /****************************************************************************/ | 247 | /****************************************************************************/ |
44 | /* QLogic ISP2x00 Hardware Support Functions. */ | 248 | /* QLogic ISP2x00 Hardware Support Functions. */ |
45 | /****************************************************************************/ | 249 | /****************************************************************************/ |
@@ -987,7 +1191,6 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) | |||
987 | ha->phy_version); | 1191 | ha->phy_version); |
988 | if (rval != QLA_SUCCESS) | 1192 | if (rval != QLA_SUCCESS) |
989 | goto failed; | 1193 | goto failed; |
990 | |||
991 | ha->flags.npiv_supported = 0; | 1194 | ha->flags.npiv_supported = 0; |
992 | if (IS_QLA2XXX_MIDTYPE(ha) && | 1195 | if (IS_QLA2XXX_MIDTYPE(ha) && |
993 | (ha->fw_attributes & BIT_2)) { | 1196 | (ha->fw_attributes & BIT_2)) { |
@@ -1591,7 +1794,8 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, | |||
1591 | char *st, *en; | 1794 | char *st, *en; |
1592 | uint16_t index; | 1795 | uint16_t index; |
1593 | struct qla_hw_data *ha = vha->hw; | 1796 | struct qla_hw_data *ha = vha->hw; |
1594 | int use_tbl = !IS_QLA25XX(ha) && !IS_QLA81XX(ha); | 1797 | int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && |
1798 | !IS_QLA81XX(ha); | ||
1595 | 1799 | ||
1596 | if (memcmp(model, BINZERO, len) != 0) { | 1800 | if (memcmp(model, BINZERO, len) != 0) { |
1597 | strncpy(ha->model_number, model, len); | 1801 | strncpy(ha->model_number, model, len); |
@@ -1978,7 +2182,7 @@ qla2x00_rport_del(void *data) | |||
1978 | struct fc_rport *rport; | 2182 | struct fc_rport *rport; |
1979 | 2183 | ||
1980 | spin_lock_irq(fcport->vha->host->host_lock); | 2184 | spin_lock_irq(fcport->vha->host->host_lock); |
1981 | rport = fcport->drport; | 2185 | rport = fcport->drport ? fcport->drport: fcport->rport; |
1982 | fcport->drport = NULL; | 2186 | fcport->drport = NULL; |
1983 | spin_unlock_irq(fcport->vha->host->host_lock); | 2187 | spin_unlock_irq(fcport->vha->host->host_lock); |
1984 | if (rport) | 2188 | if (rport) |
@@ -2345,8 +2549,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) | |||
2345 | struct fc_rport *rport; | 2549 | struct fc_rport *rport; |
2346 | struct qla_hw_data *ha = vha->hw; | 2550 | struct qla_hw_data *ha = vha->hw; |
2347 | 2551 | ||
2348 | if (fcport->drport) | 2552 | qla2x00_rport_del(fcport); |
2349 | qla2x00_rport_del(fcport); | ||
2350 | 2553 | ||
2351 | rport_ids.node_name = wwn_to_u64(fcport->node_name); | 2554 | rport_ids.node_name = wwn_to_u64(fcport->node_name); |
2352 | rport_ids.port_name = wwn_to_u64(fcport->port_name); | 2555 | rport_ids.port_name = wwn_to_u64(fcport->port_name); |
@@ -3039,6 +3242,12 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
3039 | rval = QLA_SUCCESS; | 3242 | rval = QLA_SUCCESS; |
3040 | retry = 0; | 3243 | retry = 0; |
3041 | 3244 | ||
3245 | if (IS_ALOGIO_CAPABLE(ha)) { | ||
3246 | rval = qla2x00_post_async_login_work(vha, fcport, NULL); | ||
3247 | if (!rval) | ||
3248 | return rval; | ||
3249 | } | ||
3250 | |||
3042 | rval = qla2x00_fabric_login(vha, fcport, next_loopid); | 3251 | rval = qla2x00_fabric_login(vha, fcport, next_loopid); |
3043 | if (rval == QLA_SUCCESS) { | 3252 | if (rval == QLA_SUCCESS) { |
3044 | /* Send an ADISC to tape devices.*/ | 3253 | /* Send an ADISC to tape devices.*/ |
@@ -3133,7 +3342,7 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
3133 | } else { | 3342 | } else { |
3134 | fcport->port_type = FCT_TARGET; | 3343 | fcport->port_type = FCT_TARGET; |
3135 | if (mb[1] & BIT_1) { | 3344 | if (mb[1] & BIT_1) { |
3136 | fcport->flags |= FCF_TAPE_PRESENT; | 3345 | fcport->flags |= FCF_FCP2_DEVICE; |
3137 | } | 3346 | } |
3138 | } | 3347 | } |
3139 | 3348 | ||
@@ -3244,7 +3453,7 @@ qla2x00_loop_resync(scsi_qla_host_t *vha) | |||
3244 | struct req_que *req; | 3453 | struct req_que *req; |
3245 | struct rsp_que *rsp; | 3454 | struct rsp_que *rsp; |
3246 | 3455 | ||
3247 | if (ql2xmultique_tag) | 3456 | if (vha->hw->flags.cpu_affinity_enabled) |
3248 | req = vha->hw->req_q_map[0]; | 3457 | req = vha->hw->req_q_map[0]; |
3249 | else | 3458 | else |
3250 | req = vha->req; | 3459 | req = vha->req; |
@@ -3286,15 +3495,17 @@ qla2x00_loop_resync(scsi_qla_host_t *vha) | |||
3286 | } | 3495 | } |
3287 | 3496 | ||
3288 | void | 3497 | void |
3289 | qla2x00_update_fcports(scsi_qla_host_t *vha) | 3498 | qla2x00_update_fcports(scsi_qla_host_t *base_vha) |
3290 | { | 3499 | { |
3291 | fc_port_t *fcport; | 3500 | fc_port_t *fcport; |
3501 | struct scsi_qla_host *tvp, *vha; | ||
3292 | 3502 | ||
3293 | /* Go with deferred removal of rport references. */ | 3503 | /* Go with deferred removal of rport references. */ |
3294 | list_for_each_entry(fcport, &vha->vp_fcports, list) | 3504 | list_for_each_entry_safe(vha, tvp, &base_vha->hw->vp_list, list) |
3295 | if (fcport && fcport->drport && | 3505 | list_for_each_entry(fcport, &vha->vp_fcports, list) |
3296 | atomic_read(&fcport->state) != FCS_UNCONFIGURED) | 3506 | if (fcport && fcport->drport && |
3297 | qla2x00_rport_del(fcport); | 3507 | atomic_read(&fcport->state) != FCS_UNCONFIGURED) |
3508 | qla2x00_rport_del(fcport); | ||
3298 | } | 3509 | } |
3299 | 3510 | ||
3300 | /* | 3511 | /* |
@@ -3331,8 +3542,6 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
3331 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | 3542 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { |
3332 | atomic_set(&vha->loop_state, LOOP_DOWN); | 3543 | atomic_set(&vha->loop_state, LOOP_DOWN); |
3333 | qla2x00_mark_all_devices_lost(vha, 0); | 3544 | qla2x00_mark_all_devices_lost(vha, 0); |
3334 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) | ||
3335 | qla2x00_mark_all_devices_lost(vp, 0); | ||
3336 | } else { | 3545 | } else { |
3337 | if (!atomic_read(&vha->loop_down_timer)) | 3546 | if (!atomic_read(&vha->loop_down_timer)) |
3338 | atomic_set(&vha->loop_down_timer, | 3547 | atomic_set(&vha->loop_down_timer, |
@@ -4264,7 +4473,7 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha) | |||
4264 | return -EINVAL; | 4473 | return -EINVAL; |
4265 | 4474 | ||
4266 | rval = qla2x00_fw_ready(base_vha); | 4475 | rval = qla2x00_fw_ready(base_vha); |
4267 | if (ql2xmultique_tag) | 4476 | if (ha->flags.cpu_affinity_enabled) |
4268 | req = ha->req_q_map[0]; | 4477 | req = ha->req_q_map[0]; |
4269 | else | 4478 | else |
4270 | req = vha->req; | 4479 | req = vha->req; |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 13396beae2ce..c5ccac0bef76 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -350,6 +350,7 @@ qla2x00_start_scsi(srb_t *sp) | |||
350 | /* Build command packet */ | 350 | /* Build command packet */ |
351 | req->current_outstanding_cmd = handle; | 351 | req->current_outstanding_cmd = handle; |
352 | req->outstanding_cmds[handle] = sp; | 352 | req->outstanding_cmds[handle] = sp; |
353 | sp->handle = handle; | ||
353 | sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; | 354 | sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; |
354 | req->cnt -= req_cnt; | 355 | req->cnt -= req_cnt; |
355 | 356 | ||
@@ -778,6 +779,7 @@ qla24xx_start_scsi(srb_t *sp) | |||
778 | /* Build command packet. */ | 779 | /* Build command packet. */ |
779 | req->current_outstanding_cmd = handle; | 780 | req->current_outstanding_cmd = handle; |
780 | req->outstanding_cmds[handle] = sp; | 781 | req->outstanding_cmds[handle] = sp; |
782 | sp->handle = handle; | ||
781 | sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; | 783 | sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; |
782 | req->cnt -= req_cnt; | 784 | req->cnt -= req_cnt; |
783 | 785 | ||
@@ -852,9 +854,211 @@ static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) | |||
852 | struct qla_hw_data *ha = sp->fcport->vha->hw; | 854 | struct qla_hw_data *ha = sp->fcport->vha->hw; |
853 | int affinity = cmd->request->cpu; | 855 | int affinity = cmd->request->cpu; |
854 | 856 | ||
855 | if (ql2xmultique_tag && affinity >= 0 && | 857 | if (ha->flags.cpu_affinity_enabled && affinity >= 0 && |
856 | affinity < ha->max_rsp_queues - 1) | 858 | affinity < ha->max_rsp_queues - 1) |
857 | *rsp = ha->rsp_q_map[affinity + 1]; | 859 | *rsp = ha->rsp_q_map[affinity + 1]; |
858 | else | 860 | else |
859 | *rsp = ha->rsp_q_map[0]; | 861 | *rsp = ha->rsp_q_map[0]; |
860 | } | 862 | } |
863 | |||
864 | /* Generic Control-SRB manipulation functions. */ | ||
865 | |||
866 | static void * | ||
867 | qla2x00_alloc_iocbs(srb_t *sp) | ||
868 | { | ||
869 | scsi_qla_host_t *vha = sp->fcport->vha; | ||
870 | struct qla_hw_data *ha = vha->hw; | ||
871 | struct req_que *req = ha->req_q_map[0]; | ||
872 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); | ||
873 | uint32_t index, handle; | ||
874 | request_t *pkt; | ||
875 | uint16_t cnt, req_cnt; | ||
876 | |||
877 | pkt = NULL; | ||
878 | req_cnt = 1; | ||
879 | |||
880 | /* Check for room in outstanding command list. */ | ||
881 | handle = req->current_outstanding_cmd; | ||
882 | for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { | ||
883 | handle++; | ||
884 | if (handle == MAX_OUTSTANDING_COMMANDS) | ||
885 | handle = 1; | ||
886 | if (!req->outstanding_cmds[handle]) | ||
887 | break; | ||
888 | } | ||
889 | if (index == MAX_OUTSTANDING_COMMANDS) | ||
890 | goto queuing_error; | ||
891 | |||
892 | /* Check for room on request queue. */ | ||
893 | if (req->cnt < req_cnt) { | ||
894 | if (ha->mqenable) | ||
895 | cnt = RD_REG_DWORD(®->isp25mq.req_q_out); | ||
896 | else if (IS_FWI2_CAPABLE(ha)) | ||
897 | cnt = RD_REG_DWORD(®->isp24.req_q_out); | ||
898 | else | ||
899 | cnt = qla2x00_debounce_register( | ||
900 | ISP_REQ_Q_OUT(ha, ®->isp)); | ||
901 | |||
902 | if (req->ring_index < cnt) | ||
903 | req->cnt = cnt - req->ring_index; | ||
904 | else | ||
905 | req->cnt = req->length - | ||
906 | (req->ring_index - cnt); | ||
907 | } | ||
908 | if (req->cnt < req_cnt) | ||
909 | goto queuing_error; | ||
910 | |||
911 | /* Prep packet */ | ||
912 | req->current_outstanding_cmd = handle; | ||
913 | req->outstanding_cmds[handle] = sp; | ||
914 | req->cnt -= req_cnt; | ||
915 | |||
916 | pkt = req->ring_ptr; | ||
917 | memset(pkt, 0, REQUEST_ENTRY_SIZE); | ||
918 | pkt->entry_count = req_cnt; | ||
919 | pkt->handle = handle; | ||
920 | sp->handle = handle; | ||
921 | |||
922 | queuing_error: | ||
923 | return pkt; | ||
924 | } | ||
925 | |||
926 | static void | ||
927 | qla2x00_start_iocbs(srb_t *sp) | ||
928 | { | ||
929 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
930 | struct req_que *req = ha->req_q_map[0]; | ||
931 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); | ||
932 | struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; | ||
933 | |||
934 | /* Adjust ring index. */ | ||
935 | req->ring_index++; | ||
936 | if (req->ring_index == req->length) { | ||
937 | req->ring_index = 0; | ||
938 | req->ring_ptr = req->ring; | ||
939 | } else | ||
940 | req->ring_ptr++; | ||
941 | |||
942 | /* Set chip new ring index. */ | ||
943 | if (ha->mqenable) { | ||
944 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); | ||
945 | RD_REG_DWORD(&ioreg->hccr); | ||
946 | } else if (IS_FWI2_CAPABLE(ha)) { | ||
947 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); | ||
948 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); | ||
949 | } else { | ||
950 | WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), req->ring_index); | ||
951 | RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); | ||
952 | } | ||
953 | } | ||
954 | |||
955 | static void | ||
956 | qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) | ||
957 | { | ||
958 | struct srb_logio *lio = sp->ctx; | ||
959 | |||
960 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
961 | logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); | ||
962 | if (lio->flags & SRB_LOGIN_COND_PLOGI) | ||
963 | logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI); | ||
964 | if (lio->flags & SRB_LOGIN_SKIP_PRLI) | ||
965 | logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); | ||
966 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
967 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
968 | logio->port_id[1] = sp->fcport->d_id.b.area; | ||
969 | logio->port_id[2] = sp->fcport->d_id.b.domain; | ||
970 | logio->vp_index = sp->fcport->vp_idx; | ||
971 | } | ||
972 | |||
973 | static void | ||
974 | qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) | ||
975 | { | ||
976 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
977 | struct srb_logio *lio = sp->ctx; | ||
978 | uint16_t opts; | ||
979 | |||
980 | mbx->entry_type = MBX_IOCB_TYPE;; | ||
981 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | ||
982 | mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT); | ||
983 | opts = lio->flags & SRB_LOGIN_COND_PLOGI ? BIT_0: 0; | ||
984 | opts |= lio->flags & SRB_LOGIN_SKIP_PRLI ? BIT_1: 0; | ||
985 | if (HAS_EXTENDED_IDS(ha)) { | ||
986 | mbx->mb1 = cpu_to_le16(sp->fcport->loop_id); | ||
987 | mbx->mb10 = cpu_to_le16(opts); | ||
988 | } else { | ||
989 | mbx->mb1 = cpu_to_le16((sp->fcport->loop_id << 8) | opts); | ||
990 | } | ||
991 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); | ||
992 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | | ||
993 | sp->fcport->d_id.b.al_pa); | ||
994 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | ||
995 | } | ||
996 | |||
997 | static void | ||
998 | qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio) | ||
999 | { | ||
1000 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
1001 | logio->control_flags = | ||
1002 | cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); | ||
1003 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
1004 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
1005 | logio->port_id[1] = sp->fcport->d_id.b.area; | ||
1006 | logio->port_id[2] = sp->fcport->d_id.b.domain; | ||
1007 | logio->vp_index = sp->fcport->vp_idx; | ||
1008 | } | ||
1009 | |||
1010 | static void | ||
1011 | qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) | ||
1012 | { | ||
1013 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
1014 | |||
1015 | mbx->entry_type = MBX_IOCB_TYPE;; | ||
1016 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | ||
1017 | mbx->mb0 = cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); | ||
1018 | mbx->mb1 = HAS_EXTENDED_IDS(ha) ? | ||
1019 | cpu_to_le16(sp->fcport->loop_id): | ||
1020 | cpu_to_le16(sp->fcport->loop_id << 8); | ||
1021 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); | ||
1022 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | | ||
1023 | sp->fcport->d_id.b.al_pa); | ||
1024 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | ||
1025 | /* Implicit: mbx->mbx10 = 0. */ | ||
1026 | } | ||
1027 | |||
1028 | int | ||
1029 | qla2x00_start_sp(srb_t *sp) | ||
1030 | { | ||
1031 | int rval; | ||
1032 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
1033 | void *pkt; | ||
1034 | struct srb_ctx *ctx = sp->ctx; | ||
1035 | unsigned long flags; | ||
1036 | |||
1037 | rval = QLA_FUNCTION_FAILED; | ||
1038 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1039 | pkt = qla2x00_alloc_iocbs(sp); | ||
1040 | if (!pkt) | ||
1041 | goto done; | ||
1042 | |||
1043 | rval = QLA_SUCCESS; | ||
1044 | switch (ctx->type) { | ||
1045 | case SRB_LOGIN_CMD: | ||
1046 | IS_FWI2_CAPABLE(ha) ? | ||
1047 | qla24xx_login_iocb(sp, pkt): | ||
1048 | qla2x00_login_iocb(sp, pkt); | ||
1049 | break; | ||
1050 | case SRB_LOGOUT_CMD: | ||
1051 | IS_FWI2_CAPABLE(ha) ? | ||
1052 | qla24xx_logout_iocb(sp, pkt): | ||
1053 | qla2x00_logout_iocb(sp, pkt); | ||
1054 | break; | ||
1055 | default: | ||
1056 | break; | ||
1057 | } | ||
1058 | |||
1059 | wmb(); | ||
1060 | qla2x00_start_iocbs(sp); | ||
1061 | done: | ||
1062 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1063 | return rval; | ||
1064 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 245e7afb4c4d..b20a7169aac2 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -598,9 +598,54 @@ skip_rio: | |||
598 | break; | 598 | break; |
599 | 599 | ||
600 | case MBA_PORT_UPDATE: /* Port database update */ | 600 | case MBA_PORT_UPDATE: /* Port database update */ |
601 | /* Only handle SCNs for our Vport index. */ | 601 | /* |
602 | if (vha->vp_idx && vha->vp_idx != (mb[3] & 0xff)) | 602 | * Handle only global and vn-port update events |
603 | * | ||
604 | * Relevant inputs: | ||
605 | * mb[1] = N_Port handle of changed port | ||
606 | * OR 0xffff for global event | ||
607 | * mb[2] = New login state | ||
608 | * 7 = Port logged out | ||
609 | * mb[3] = LSB is vp_idx, 0xff = all vps | ||
610 | * | ||
611 | * Skip processing if: | ||
612 | * Event is global, vp_idx is NOT all vps, | ||
613 | * vp_idx does not match | ||
614 | * Event is not global, vp_idx does not match | ||
615 | */ | ||
616 | if ((mb[1] == 0xffff && (mb[3] & 0xff) != 0xff) | ||
617 | || (mb[1] != 0xffff)) { | ||
618 | if (vha->vp_idx != (mb[3] & 0xff)) | ||
619 | break; | ||
620 | } | ||
621 | |||
622 | /* Global event -- port logout or port unavailable. */ | ||
623 | if (mb[1] == 0xffff && mb[2] == 0x7) { | ||
624 | DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n", | ||
625 | vha->host_no)); | ||
626 | DEBUG(printk(KERN_INFO | ||
627 | "scsi(%ld): Port unavailable %04x %04x %04x.\n", | ||
628 | vha->host_no, mb[1], mb[2], mb[3])); | ||
629 | |||
630 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | ||
631 | atomic_set(&vha->loop_state, LOOP_DOWN); | ||
632 | atomic_set(&vha->loop_down_timer, | ||
633 | LOOP_DOWN_TIME); | ||
634 | vha->device_flags |= DFLG_NO_CABLE; | ||
635 | qla2x00_mark_all_devices_lost(vha, 1); | ||
636 | } | ||
637 | |||
638 | if (vha->vp_idx) { | ||
639 | atomic_set(&vha->vp_state, VP_FAILED); | ||
640 | fc_vport_set_state(vha->fc_vport, | ||
641 | FC_VPORT_FAILED); | ||
642 | qla2x00_mark_all_devices_lost(vha, 1); | ||
643 | } | ||
644 | |||
645 | vha->flags.management_server_logged_in = 0; | ||
646 | ha->link_data_rate = PORT_SPEED_UNKNOWN; | ||
603 | break; | 647 | break; |
648 | } | ||
604 | 649 | ||
605 | /* | 650 | /* |
606 | * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET | 651 | * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET |
@@ -640,8 +685,9 @@ skip_rio: | |||
640 | if (vha->vp_idx && test_bit(VP_SCR_NEEDED, &vha->vp_flags)) | 685 | if (vha->vp_idx && test_bit(VP_SCR_NEEDED, &vha->vp_flags)) |
641 | break; | 686 | break; |
642 | /* Only handle SCNs for our Vport index. */ | 687 | /* Only handle SCNs for our Vport index. */ |
643 | if (vha->vp_idx && vha->vp_idx != (mb[3] & 0xff)) | 688 | if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff)) |
644 | break; | 689 | break; |
690 | |||
645 | DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", | 691 | DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", |
646 | vha->host_no)); | 692 | vha->host_no)); |
647 | DEBUG(printk(KERN_INFO | 693 | DEBUG(printk(KERN_INFO |
@@ -874,6 +920,249 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, | |||
874 | } | 920 | } |
875 | } | 921 | } |
876 | 922 | ||
923 | static srb_t * | ||
924 | qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, | ||
925 | struct req_que *req, void *iocb) | ||
926 | { | ||
927 | struct qla_hw_data *ha = vha->hw; | ||
928 | sts_entry_t *pkt = iocb; | ||
929 | srb_t *sp = NULL; | ||
930 | uint16_t index; | ||
931 | |||
932 | index = LSW(pkt->handle); | ||
933 | if (index >= MAX_OUTSTANDING_COMMANDS) { | ||
934 | qla_printk(KERN_WARNING, ha, | ||
935 | "%s: Invalid completion handle (%x).\n", func, index); | ||
936 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
937 | goto done; | ||
938 | } | ||
939 | sp = req->outstanding_cmds[index]; | ||
940 | if (!sp) { | ||
941 | qla_printk(KERN_WARNING, ha, | ||
942 | "%s: Invalid completion handle (%x) -- timed-out.\n", func, | ||
943 | index); | ||
944 | return sp; | ||
945 | } | ||
946 | if (sp->handle != index) { | ||
947 | qla_printk(KERN_WARNING, ha, | ||
948 | "%s: SRB handle (%x) mismatch %x.\n", func, sp->handle, | ||
949 | index); | ||
950 | return NULL; | ||
951 | } | ||
952 | req->outstanding_cmds[index] = NULL; | ||
953 | done: | ||
954 | return sp; | ||
955 | } | ||
956 | |||
957 | static void | ||
958 | qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
959 | struct mbx_entry *mbx) | ||
960 | { | ||
961 | const char func[] = "MBX-IOCB"; | ||
962 | const char *type; | ||
963 | struct qla_hw_data *ha = vha->hw; | ||
964 | fc_port_t *fcport; | ||
965 | srb_t *sp; | ||
966 | struct srb_logio *lio; | ||
967 | uint16_t data[2]; | ||
968 | |||
969 | sp = qla2x00_get_sp_from_handle(vha, func, req, mbx); | ||
970 | if (!sp) | ||
971 | return; | ||
972 | |||
973 | type = NULL; | ||
974 | lio = sp->ctx; | ||
975 | switch (lio->ctx.type) { | ||
976 | case SRB_LOGIN_CMD: | ||
977 | type = "login"; | ||
978 | break; | ||
979 | case SRB_LOGOUT_CMD: | ||
980 | type = "logout"; | ||
981 | break; | ||
982 | default: | ||
983 | qla_printk(KERN_WARNING, ha, | ||
984 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | ||
985 | lio->ctx.type); | ||
986 | return; | ||
987 | } | ||
988 | |||
989 | del_timer(&lio->ctx.timer); | ||
990 | fcport = sp->fcport; | ||
991 | |||
992 | data[0] = data[1] = 0; | ||
993 | if (mbx->entry_status) { | ||
994 | DEBUG2(printk(KERN_WARNING | ||
995 | "scsi(%ld:%x): Async-%s error entry - entry-status=%x " | ||
996 | "status=%x state-flag=%x status-flags=%x.\n", | ||
997 | fcport->vha->host_no, sp->handle, type, | ||
998 | mbx->entry_status, le16_to_cpu(mbx->status), | ||
999 | le16_to_cpu(mbx->state_flags), | ||
1000 | le16_to_cpu(mbx->status_flags))); | ||
1001 | DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx))); | ||
1002 | |||
1003 | data[0] = MBS_COMMAND_ERROR; | ||
1004 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1005 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1006 | goto done_post_logio_done_work; | ||
1007 | } | ||
1008 | |||
1009 | if (!mbx->status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) { | ||
1010 | DEBUG2(printk(KERN_DEBUG | ||
1011 | "scsi(%ld:%x): Async-%s complete - mbx1=%x.\n", | ||
1012 | fcport->vha->host_no, sp->handle, type, | ||
1013 | le16_to_cpu(mbx->mb1))); | ||
1014 | |||
1015 | data[0] = MBS_COMMAND_COMPLETE; | ||
1016 | if (lio->ctx.type == SRB_LOGIN_CMD && le16_to_cpu(mbx->mb1) & BIT_1) | ||
1017 | fcport->flags |= FCF_FCP2_DEVICE; | ||
1018 | |||
1019 | goto done_post_logio_done_work; | ||
1020 | } | ||
1021 | |||
1022 | data[0] = le16_to_cpu(mbx->mb0); | ||
1023 | switch (data[0]) { | ||
1024 | case MBS_PORT_ID_USED: | ||
1025 | data[1] = le16_to_cpu(mbx->mb1); | ||
1026 | break; | ||
1027 | case MBS_LOOP_ID_USED: | ||
1028 | break; | ||
1029 | default: | ||
1030 | data[0] = MBS_COMMAND_ERROR; | ||
1031 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1032 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1033 | break; | ||
1034 | } | ||
1035 | |||
1036 | DEBUG2(printk(KERN_WARNING | ||
1037 | "scsi(%ld:%x): Async-%s failed - status=%x mb0=%x mb1=%x mb2=%x " | ||
1038 | "mb6=%x mb7=%x.\n", | ||
1039 | fcport->vha->host_no, sp->handle, type, le16_to_cpu(mbx->status), | ||
1040 | le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1), | ||
1041 | le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6), | ||
1042 | le16_to_cpu(mbx->mb7))); | ||
1043 | |||
1044 | done_post_logio_done_work: | ||
1045 | lio->ctx.type == SRB_LOGIN_CMD ? | ||
1046 | qla2x00_post_async_login_done_work(fcport->vha, fcport, data): | ||
1047 | qla2x00_post_async_logout_done_work(fcport->vha, fcport, data); | ||
1048 | |||
1049 | lio->ctx.free(sp); | ||
1050 | } | ||
1051 | |||
1052 | static void | ||
1053 | qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
1054 | struct logio_entry_24xx *logio) | ||
1055 | { | ||
1056 | const char func[] = "LOGIO-IOCB"; | ||
1057 | const char *type; | ||
1058 | struct qla_hw_data *ha = vha->hw; | ||
1059 | fc_port_t *fcport; | ||
1060 | srb_t *sp; | ||
1061 | struct srb_logio *lio; | ||
1062 | uint16_t data[2]; | ||
1063 | uint32_t iop[2]; | ||
1064 | |||
1065 | sp = qla2x00_get_sp_from_handle(vha, func, req, logio); | ||
1066 | if (!sp) | ||
1067 | return; | ||
1068 | |||
1069 | type = NULL; | ||
1070 | lio = sp->ctx; | ||
1071 | switch (lio->ctx.type) { | ||
1072 | case SRB_LOGIN_CMD: | ||
1073 | type = "login"; | ||
1074 | break; | ||
1075 | case SRB_LOGOUT_CMD: | ||
1076 | type = "logout"; | ||
1077 | break; | ||
1078 | default: | ||
1079 | qla_printk(KERN_WARNING, ha, | ||
1080 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | ||
1081 | lio->ctx.type); | ||
1082 | return; | ||
1083 | } | ||
1084 | |||
1085 | del_timer(&lio->ctx.timer); | ||
1086 | fcport = sp->fcport; | ||
1087 | |||
1088 | data[0] = data[1] = 0; | ||
1089 | if (logio->entry_status) { | ||
1090 | DEBUG2(printk(KERN_WARNING | ||
1091 | "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n", | ||
1092 | fcport->vha->host_no, sp->handle, type, | ||
1093 | logio->entry_status)); | ||
1094 | DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio))); | ||
1095 | |||
1096 | data[0] = MBS_COMMAND_ERROR; | ||
1097 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1098 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1099 | goto done_post_logio_done_work; | ||
1100 | } | ||
1101 | |||
1102 | if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { | ||
1103 | DEBUG2(printk(KERN_DEBUG | ||
1104 | "scsi(%ld:%x): Async-%s complete - iop0=%x.\n", | ||
1105 | fcport->vha->host_no, sp->handle, type, | ||
1106 | le32_to_cpu(logio->io_parameter[0]))); | ||
1107 | |||
1108 | data[0] = MBS_COMMAND_COMPLETE; | ||
1109 | if (lio->ctx.type == SRB_LOGOUT_CMD) | ||
1110 | goto done_post_logio_done_work; | ||
1111 | |||
1112 | iop[0] = le32_to_cpu(logio->io_parameter[0]); | ||
1113 | if (iop[0] & BIT_4) { | ||
1114 | fcport->port_type = FCT_TARGET; | ||
1115 | if (iop[0] & BIT_8) | ||
1116 | fcport->flags |= FCF_FCP2_DEVICE; | ||
1117 | } | ||
1118 | if (iop[0] & BIT_5) | ||
1119 | fcport->port_type = FCT_INITIATOR; | ||
1120 | if (logio->io_parameter[7] || logio->io_parameter[8]) | ||
1121 | fcport->supported_classes |= FC_COS_CLASS2; | ||
1122 | if (logio->io_parameter[9] || logio->io_parameter[10]) | ||
1123 | fcport->supported_classes |= FC_COS_CLASS3; | ||
1124 | |||
1125 | goto done_post_logio_done_work; | ||
1126 | } | ||
1127 | |||
1128 | iop[0] = le32_to_cpu(logio->io_parameter[0]); | ||
1129 | iop[1] = le32_to_cpu(logio->io_parameter[1]); | ||
1130 | switch (iop[0]) { | ||
1131 | case LSC_SCODE_PORTID_USED: | ||
1132 | data[0] = MBS_PORT_ID_USED; | ||
1133 | data[1] = LSW(iop[1]); | ||
1134 | break; | ||
1135 | case LSC_SCODE_NPORT_USED: | ||
1136 | data[0] = MBS_LOOP_ID_USED; | ||
1137 | break; | ||
1138 | case LSC_SCODE_CMD_FAILED: | ||
1139 | if ((iop[1] & 0xff) == 0x05) { | ||
1140 | data[0] = MBS_NOT_LOGGED_IN; | ||
1141 | break; | ||
1142 | } | ||
1143 | /* Fall through. */ | ||
1144 | default: | ||
1145 | data[0] = MBS_COMMAND_ERROR; | ||
1146 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1147 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1148 | break; | ||
1149 | } | ||
1150 | |||
1151 | DEBUG2(printk(KERN_WARNING | ||
1152 | "scsi(%ld:%x): Async-%s failed - comp=%x iop0=%x iop1=%x.\n", | ||
1153 | fcport->vha->host_no, sp->handle, type, | ||
1154 | le16_to_cpu(logio->comp_status), | ||
1155 | le32_to_cpu(logio->io_parameter[0]), | ||
1156 | le32_to_cpu(logio->io_parameter[1]))); | ||
1157 | |||
1158 | done_post_logio_done_work: | ||
1159 | lio->ctx.type == SRB_LOGIN_CMD ? | ||
1160 | qla2x00_post_async_login_done_work(fcport->vha, fcport, data): | ||
1161 | qla2x00_post_async_logout_done_work(fcport->vha, fcport, data); | ||
1162 | |||
1163 | lio->ctx.free(sp); | ||
1164 | } | ||
1165 | |||
877 | /** | 1166 | /** |
878 | * qla2x00_process_response_queue() - Process response queue entries. | 1167 | * qla2x00_process_response_queue() - Process response queue entries. |
879 | * @ha: SCSI driver HA context | 1168 | * @ha: SCSI driver HA context |
@@ -935,6 +1224,9 @@ qla2x00_process_response_queue(struct rsp_que *rsp) | |||
935 | case STATUS_CONT_TYPE: | 1224 | case STATUS_CONT_TYPE: |
936 | qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); | 1225 | qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); |
937 | break; | 1226 | break; |
1227 | case MBX_IOCB_TYPE: | ||
1228 | qla2x00_mbx_iocb_entry(vha, rsp->req, | ||
1229 | (struct mbx_entry *)pkt); | ||
938 | default: | 1230 | default: |
939 | /* Type Not Supported. */ | 1231 | /* Type Not Supported. */ |
940 | DEBUG4(printk(KERN_WARNING | 1232 | DEBUG4(printk(KERN_WARNING |
@@ -1223,6 +1515,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1223 | cp->device->id, cp->device->lun, resid, | 1515 | cp->device->id, cp->device->lun, resid, |
1224 | scsi_bufflen(cp))); | 1516 | scsi_bufflen(cp))); |
1225 | 1517 | ||
1518 | scsi_set_resid(cp, resid); | ||
1226 | cp->result = DID_ERROR << 16; | 1519 | cp->result = DID_ERROR << 16; |
1227 | break; | 1520 | break; |
1228 | } | 1521 | } |
@@ -1544,6 +1837,10 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1544 | qla24xx_report_id_acquisition(vha, | 1837 | qla24xx_report_id_acquisition(vha, |
1545 | (struct vp_rpt_id_entry_24xx *)pkt); | 1838 | (struct vp_rpt_id_entry_24xx *)pkt); |
1546 | break; | 1839 | break; |
1840 | case LOGINOUT_PORT_IOCB_TYPE: | ||
1841 | qla24xx_logio_entry(vha, rsp->req, | ||
1842 | (struct logio_entry_24xx *)pkt); | ||
1843 | break; | ||
1547 | default: | 1844 | default: |
1548 | /* Type Not Supported. */ | 1845 | /* Type Not Supported. */ |
1549 | DEBUG4(printk(KERN_WARNING | 1846 | DEBUG4(printk(KERN_WARNING |
@@ -1723,8 +2020,10 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) | |||
1723 | 2020 | ||
1724 | vha = qla25xx_get_host(rsp); | 2021 | vha = qla25xx_get_host(rsp); |
1725 | qla24xx_process_response_queue(vha, rsp); | 2022 | qla24xx_process_response_queue(vha, rsp); |
1726 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | 2023 | if (!ha->mqenable) { |
1727 | 2024 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | |
2025 | RD_REG_DWORD_RELAXED(®->hccr); | ||
2026 | } | ||
1728 | spin_unlock_irq(&ha->hardware_lock); | 2027 | spin_unlock_irq(&ha->hardware_lock); |
1729 | 2028 | ||
1730 | return IRQ_HANDLED; | 2029 | return IRQ_HANDLED; |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index fe69f3057671..b6202fe118ac 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -1507,7 +1507,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1507 | 1507 | ||
1508 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 1508 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
1509 | 1509 | ||
1510 | if (ql2xmultique_tag) | 1510 | if (ha->flags.cpu_affinity_enabled) |
1511 | req = ha->req_q_map[0]; | 1511 | req = ha->req_q_map[0]; |
1512 | else | 1512 | else |
1513 | req = vha->req; | 1513 | req = vha->req; |
@@ -2324,7 +2324,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2324 | vha = fcport->vha; | 2324 | vha = fcport->vha; |
2325 | ha = vha->hw; | 2325 | ha = vha->hw; |
2326 | req = vha->req; | 2326 | req = vha->req; |
2327 | if (ql2xmultique_tag) | 2327 | if (ha->flags.cpu_affinity_enabled) |
2328 | rsp = ha->rsp_q_map[tag + 1]; | 2328 | rsp = ha->rsp_q_map[tag + 1]; |
2329 | else | 2329 | else |
2330 | rsp = req->rsp; | 2330 | rsp = req->rsp; |
@@ -2746,7 +2746,8 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, | |||
2746 | if (rptid_entry->format == 0) { | 2746 | if (rptid_entry->format == 0) { |
2747 | DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d," | 2747 | DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d," |
2748 | " number of VPs acquired %d\n", __func__, vha->host_no, | 2748 | " number of VPs acquired %d\n", __func__, vha->host_no, |
2749 | MSB(rptid_entry->vp_count), LSB(rptid_entry->vp_count))); | 2749 | MSB(le16_to_cpu(rptid_entry->vp_count)), |
2750 | LSB(le16_to_cpu(rptid_entry->vp_count)))); | ||
2750 | DEBUG15(printk("%s primary port id %02x%02x%02x\n", __func__, | 2751 | DEBUG15(printk("%s primary port id %02x%02x%02x\n", __func__, |
2751 | rptid_entry->port_id[2], rptid_entry->port_id[1], | 2752 | rptid_entry->port_id[2], rptid_entry->port_id[1], |
2752 | rptid_entry->port_id[0])); | 2753 | rptid_entry->port_id[0])); |
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index cd78c501803a..42b799abba57 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
@@ -42,7 +42,6 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) | |||
42 | 42 | ||
43 | set_bit(vp_id, ha->vp_idx_map); | 43 | set_bit(vp_id, ha->vp_idx_map); |
44 | ha->num_vhosts++; | 44 | ha->num_vhosts++; |
45 | ha->cur_vport_count++; | ||
46 | vha->vp_idx = vp_id; | 45 | vha->vp_idx = vp_id; |
47 | list_add_tail(&vha->list, &ha->vp_list); | 46 | list_add_tail(&vha->list, &ha->vp_list); |
48 | mutex_unlock(&ha->vport_lock); | 47 | mutex_unlock(&ha->vport_lock); |
@@ -58,7 +57,6 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) | |||
58 | mutex_lock(&ha->vport_lock); | 57 | mutex_lock(&ha->vport_lock); |
59 | vp_id = vha->vp_idx; | 58 | vp_id = vha->vp_idx; |
60 | ha->num_vhosts--; | 59 | ha->num_vhosts--; |
61 | ha->cur_vport_count--; | ||
62 | clear_bit(vp_id, ha->vp_idx_map); | 60 | clear_bit(vp_id, ha->vp_idx_map); |
63 | list_del(&vha->list); | 61 | list_del(&vha->list); |
64 | mutex_unlock(&ha->vport_lock); | 62 | mutex_unlock(&ha->vport_lock); |
@@ -235,7 +233,11 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha) | |||
235 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | 233 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); |
236 | } | 234 | } |
237 | 235 | ||
238 | /* To exclusively reset vport, we need to log it out first.*/ | 236 | /* |
237 | * To exclusively reset vport, we need to log it out first. Note: this | ||
238 | * control_vp can fail if ISP reset is already issued, this is | ||
239 | * expected, as the vp would be already logged out due to ISP reset. | ||
240 | */ | ||
239 | if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) | 241 | if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) |
240 | qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); | 242 | qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); |
241 | 243 | ||
@@ -247,18 +249,11 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha) | |||
247 | static int | 249 | static int |
248 | qla2x00_do_dpc_vp(scsi_qla_host_t *vha) | 250 | qla2x00_do_dpc_vp(scsi_qla_host_t *vha) |
249 | { | 251 | { |
250 | struct qla_hw_data *ha = vha->hw; | 252 | qla2x00_do_work(vha); |
251 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | ||
252 | 253 | ||
253 | if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) { | 254 | if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) { |
254 | /* VP acquired. complete port configuration */ | 255 | /* VP acquired. complete port configuration */ |
255 | if (atomic_read(&base_vha->loop_state) == LOOP_READY) { | 256 | qla24xx_configure_vp(vha); |
256 | qla24xx_configure_vp(vha); | ||
257 | } else { | ||
258 | set_bit(VP_IDX_ACQUIRED, &vha->vp_flags); | ||
259 | set_bit(VP_DPC_NEEDED, &base_vha->dpc_flags); | ||
260 | } | ||
261 | |||
262 | return 0; | 257 | return 0; |
263 | } | 258 | } |
264 | 259 | ||
@@ -309,6 +304,9 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) | |||
309 | 304 | ||
310 | clear_bit(VP_DPC_NEEDED, &vha->dpc_flags); | 305 | clear_bit(VP_DPC_NEEDED, &vha->dpc_flags); |
311 | 306 | ||
307 | if (!(ha->current_topology & ISP_CFG_F)) | ||
308 | return; | ||
309 | |||
312 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 310 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { |
313 | if (vp->vp_idx) | 311 | if (vp->vp_idx) |
314 | ret = qla2x00_do_dpc_vp(vp); | 312 | ret = qla2x00_do_dpc_vp(vp); |
@@ -413,6 +411,11 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) | |||
413 | 411 | ||
414 | vha->flags.init_done = 1; | 412 | vha->flags.init_done = 1; |
415 | 413 | ||
414 | mutex_lock(&ha->vport_lock); | ||
415 | set_bit(vha->vp_idx, ha->vp_idx_map); | ||
416 | ha->cur_vport_count++; | ||
417 | mutex_unlock(&ha->vport_lock); | ||
418 | |||
416 | return vha; | 419 | return vha; |
417 | 420 | ||
418 | create_vhost_failed: | 421 | create_vhost_failed: |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f0396e79b6fa..b79fca7d461b 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -287,9 +287,12 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha) | |||
287 | int ques, req, ret; | 287 | int ques, req, ret; |
288 | struct qla_hw_data *ha = vha->hw; | 288 | struct qla_hw_data *ha = vha->hw; |
289 | 289 | ||
290 | if (!(ha->fw_attributes & BIT_6)) { | ||
291 | qla_printk(KERN_INFO, ha, | ||
292 | "Firmware is not multi-queue capable\n"); | ||
293 | goto fail; | ||
294 | } | ||
290 | if (ql2xmultique_tag) { | 295 | if (ql2xmultique_tag) { |
291 | /* CPU affinity mode */ | ||
292 | ha->wq = create_workqueue("qla2xxx_wq"); | ||
293 | /* create a request queue for IO */ | 296 | /* create a request queue for IO */ |
294 | options |= BIT_7; | 297 | options |= BIT_7; |
295 | req = qla25xx_create_req_que(ha, options, 0, 0, -1, | 298 | req = qla25xx_create_req_que(ha, options, 0, 0, -1, |
@@ -299,6 +302,7 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha) | |||
299 | "Can't create request queue\n"); | 302 | "Can't create request queue\n"); |
300 | goto fail; | 303 | goto fail; |
301 | } | 304 | } |
305 | ha->wq = create_workqueue("qla2xxx_wq"); | ||
302 | vha->req = ha->req_q_map[req]; | 306 | vha->req = ha->req_q_map[req]; |
303 | options |= BIT_1; | 307 | options |= BIT_1; |
304 | for (ques = 1; ques < ha->max_rsp_queues; ques++) { | 308 | for (ques = 1; ques < ha->max_rsp_queues; ques++) { |
@@ -309,6 +313,8 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha) | |||
309 | goto fail2; | 313 | goto fail2; |
310 | } | 314 | } |
311 | } | 315 | } |
316 | ha->flags.cpu_affinity_enabled = 1; | ||
317 | |||
312 | DEBUG2(qla_printk(KERN_INFO, ha, | 318 | DEBUG2(qla_printk(KERN_INFO, ha, |
313 | "CPU affinity mode enabled, no. of response" | 319 | "CPU affinity mode enabled, no. of response" |
314 | " queues:%d, no. of request queues:%d\n", | 320 | " queues:%d, no. of request queues:%d\n", |
@@ -317,8 +323,13 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha) | |||
317 | return 0; | 323 | return 0; |
318 | fail2: | 324 | fail2: |
319 | qla25xx_delete_queues(vha); | 325 | qla25xx_delete_queues(vha); |
326 | destroy_workqueue(ha->wq); | ||
327 | ha->wq = NULL; | ||
320 | fail: | 328 | fail: |
321 | ha->mqenable = 0; | 329 | ha->mqenable = 0; |
330 | kfree(ha->req_q_map); | ||
331 | kfree(ha->rsp_q_map); | ||
332 | ha->max_req_queues = ha->max_rsp_queues = 1; | ||
322 | return 1; | 333 | return 1; |
323 | } | 334 | } |
324 | 335 | ||
@@ -462,6 +473,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
462 | sp->flags = 0; | 473 | sp->flags = 0; |
463 | CMD_SP(cmd) = (void *)sp; | 474 | CMD_SP(cmd) = (void *)sp; |
464 | cmd->scsi_done = done; | 475 | cmd->scsi_done = done; |
476 | sp->ctx = NULL; | ||
465 | 477 | ||
466 | return sp; | 478 | return sp; |
467 | } | 479 | } |
@@ -556,11 +568,8 @@ qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd) | |||
556 | unsigned long wait_iter = ABORT_WAIT_ITER; | 568 | unsigned long wait_iter = ABORT_WAIT_ITER; |
557 | int ret = QLA_SUCCESS; | 569 | int ret = QLA_SUCCESS; |
558 | 570 | ||
559 | while (CMD_SP(cmd)) { | 571 | while (CMD_SP(cmd) && wait_iter--) { |
560 | msleep(ABORT_POLLING_PERIOD); | 572 | msleep(ABORT_POLLING_PERIOD); |
561 | |||
562 | if (--wait_iter) | ||
563 | break; | ||
564 | } | 573 | } |
565 | if (CMD_SP(cmd)) | 574 | if (CMD_SP(cmd)) |
566 | ret = QLA_FUNCTION_FAILED; | 575 | ret = QLA_FUNCTION_FAILED; |
@@ -698,6 +707,8 @@ qla2x00_abort_fcport_cmds(fc_port_t *fcport) | |||
698 | continue; | 707 | continue; |
699 | if (sp->fcport != fcport) | 708 | if (sp->fcport != fcport) |
700 | continue; | 709 | continue; |
710 | if (sp->ctx) | ||
711 | continue; | ||
701 | 712 | ||
702 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 713 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
703 | if (ha->isp_ops->abort_command(sp)) { | 714 | if (ha->isp_ops->abort_command(sp)) { |
@@ -783,7 +794,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
783 | 794 | ||
784 | if (sp == NULL) | 795 | if (sp == NULL) |
785 | continue; | 796 | continue; |
786 | 797 | if (sp->ctx) | |
798 | continue; | ||
787 | if (sp->cmd != cmd) | 799 | if (sp->cmd != cmd) |
788 | continue; | 800 | continue; |
789 | 801 | ||
@@ -848,7 +860,8 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, | |||
848 | sp = req->outstanding_cmds[cnt]; | 860 | sp = req->outstanding_cmds[cnt]; |
849 | if (!sp) | 861 | if (!sp) |
850 | continue; | 862 | continue; |
851 | 863 | if (sp->ctx) | |
864 | continue; | ||
852 | if (vha->vp_idx != sp->fcport->vha->vp_idx) | 865 | if (vha->vp_idx != sp->fcport->vha->vp_idx) |
853 | continue; | 866 | continue; |
854 | match = 0; | 867 | match = 0; |
@@ -1106,8 +1119,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) | |||
1106 | struct fc_port *fcport; | 1119 | struct fc_port *fcport; |
1107 | struct qla_hw_data *ha = vha->hw; | 1120 | struct qla_hw_data *ha = vha->hw; |
1108 | 1121 | ||
1109 | if (ha->flags.enable_lip_full_login && !vha->vp_idx && | 1122 | if (ha->flags.enable_lip_full_login && !IS_QLA81XX(ha)) { |
1110 | !IS_QLA81XX(ha)) { | ||
1111 | ret = qla2x00_full_login_lip(vha); | 1123 | ret = qla2x00_full_login_lip(vha); |
1112 | if (ret != QLA_SUCCESS) { | 1124 | if (ret != QLA_SUCCESS) { |
1113 | DEBUG2_3(printk("%s(%ld): failed: " | 1125 | DEBUG2_3(printk("%s(%ld): failed: " |
@@ -1120,7 +1132,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) | |||
1120 | qla2x00_wait_for_loop_ready(vha); | 1132 | qla2x00_wait_for_loop_ready(vha); |
1121 | } | 1133 | } |
1122 | 1134 | ||
1123 | if (ha->flags.enable_lip_reset && !vha->vp_idx) { | 1135 | if (ha->flags.enable_lip_reset) { |
1124 | ret = qla2x00_lip_reset(vha); | 1136 | ret = qla2x00_lip_reset(vha); |
1125 | if (ret != QLA_SUCCESS) { | 1137 | if (ret != QLA_SUCCESS) { |
1126 | DEBUG2_3(printk("%s(%ld): failed: " | 1138 | DEBUG2_3(printk("%s(%ld): failed: " |
@@ -1154,6 +1166,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) | |||
1154 | int que, cnt; | 1166 | int que, cnt; |
1155 | unsigned long flags; | 1167 | unsigned long flags; |
1156 | srb_t *sp; | 1168 | srb_t *sp; |
1169 | struct srb_ctx *ctx; | ||
1157 | struct qla_hw_data *ha = vha->hw; | 1170 | struct qla_hw_data *ha = vha->hw; |
1158 | struct req_que *req; | 1171 | struct req_que *req; |
1159 | 1172 | ||
@@ -1166,8 +1179,14 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) | |||
1166 | sp = req->outstanding_cmds[cnt]; | 1179 | sp = req->outstanding_cmds[cnt]; |
1167 | if (sp) { | 1180 | if (sp) { |
1168 | req->outstanding_cmds[cnt] = NULL; | 1181 | req->outstanding_cmds[cnt] = NULL; |
1169 | sp->cmd->result = res; | 1182 | if (!sp->ctx) { |
1170 | qla2x00_sp_compl(ha, sp); | 1183 | sp->cmd->result = res; |
1184 | qla2x00_sp_compl(ha, sp); | ||
1185 | } else { | ||
1186 | ctx = sp->ctx; | ||
1187 | del_timer_sync(&ctx->timer); | ||
1188 | ctx->free(sp); | ||
1189 | } | ||
1171 | } | 1190 | } |
1172 | } | 1191 | } |
1173 | } | 1192 | } |
@@ -1193,6 +1212,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev) | |||
1193 | scsi_qla_host_t *vha = shost_priv(sdev->host); | 1212 | scsi_qla_host_t *vha = shost_priv(sdev->host); |
1194 | struct qla_hw_data *ha = vha->hw; | 1213 | struct qla_hw_data *ha = vha->hw; |
1195 | struct fc_rport *rport = starget_to_rport(sdev->sdev_target); | 1214 | struct fc_rport *rport = starget_to_rport(sdev->sdev_target); |
1215 | fc_port_t *fcport = *(fc_port_t **)rport->dd_data; | ||
1196 | struct req_que *req = vha->req; | 1216 | struct req_que *req = vha->req; |
1197 | 1217 | ||
1198 | if (sdev->tagged_supported) | 1218 | if (sdev->tagged_supported) |
@@ -1201,6 +1221,8 @@ qla2xxx_slave_configure(struct scsi_device *sdev) | |||
1201 | scsi_deactivate_tcq(sdev, req->max_q_depth); | 1221 | scsi_deactivate_tcq(sdev, req->max_q_depth); |
1202 | 1222 | ||
1203 | rport->dev_loss_tmo = ha->port_down_retry_count; | 1223 | rport->dev_loss_tmo = ha->port_down_retry_count; |
1224 | if (sdev->type == TYPE_TAPE) | ||
1225 | fcport->flags |= FCF_TAPE_PRESENT; | ||
1204 | 1226 | ||
1205 | return 0; | 1227 | return 0; |
1206 | } | 1228 | } |
@@ -1923,6 +1945,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1923 | if (ret) | 1945 | if (ret) |
1924 | goto probe_init_failed; | 1946 | goto probe_init_failed; |
1925 | /* Alloc arrays of request and response ring ptrs */ | 1947 | /* Alloc arrays of request and response ring ptrs */ |
1948 | que_init: | ||
1926 | if (!qla2x00_alloc_queues(ha)) { | 1949 | if (!qla2x00_alloc_queues(ha)) { |
1927 | qla_printk(KERN_WARNING, ha, | 1950 | qla_printk(KERN_WARNING, ha, |
1928 | "[ERROR] Failed to allocate memory for queue" | 1951 | "[ERROR] Failed to allocate memory for queue" |
@@ -1959,11 +1982,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1959 | goto probe_failed; | 1982 | goto probe_failed; |
1960 | } | 1983 | } |
1961 | 1984 | ||
1962 | if (ha->mqenable) | 1985 | if (ha->mqenable) { |
1963 | if (qla25xx_setup_mode(base_vha)) | 1986 | if (qla25xx_setup_mode(base_vha)) { |
1964 | qla_printk(KERN_WARNING, ha, | 1987 | qla_printk(KERN_WARNING, ha, |
1965 | "Can't create queues, falling back to single" | 1988 | "Can't create queues, falling back to single" |
1966 | " queue mode\n"); | 1989 | " queue mode\n"); |
1990 | goto que_init; | ||
1991 | } | ||
1992 | } | ||
1967 | 1993 | ||
1968 | if (ha->flags.running_gold_fw) | 1994 | if (ha->flags.running_gold_fw) |
1969 | goto skip_dpc; | 1995 | goto skip_dpc; |
@@ -2155,17 +2181,19 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport, | |||
2155 | int defer) | 2181 | int defer) |
2156 | { | 2182 | { |
2157 | struct fc_rport *rport; | 2183 | struct fc_rport *rport; |
2184 | scsi_qla_host_t *base_vha; | ||
2158 | 2185 | ||
2159 | if (!fcport->rport) | 2186 | if (!fcport->rport) |
2160 | return; | 2187 | return; |
2161 | 2188 | ||
2162 | rport = fcport->rport; | 2189 | rport = fcport->rport; |
2163 | if (defer) { | 2190 | if (defer) { |
2191 | base_vha = pci_get_drvdata(vha->hw->pdev); | ||
2164 | spin_lock_irq(vha->host->host_lock); | 2192 | spin_lock_irq(vha->host->host_lock); |
2165 | fcport->drport = rport; | 2193 | fcport->drport = rport; |
2166 | spin_unlock_irq(vha->host->host_lock); | 2194 | spin_unlock_irq(vha->host->host_lock); |
2167 | set_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags); | 2195 | set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); |
2168 | qla2xxx_wake_dpc(vha); | 2196 | qla2xxx_wake_dpc(base_vha); |
2169 | } else | 2197 | } else |
2170 | fc_remote_port_delete(rport); | 2198 | fc_remote_port_delete(rport); |
2171 | } | 2199 | } |
@@ -2237,8 +2265,9 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer) | |||
2237 | fc_port_t *fcport; | 2265 | fc_port_t *fcport; |
2238 | 2266 | ||
2239 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 2267 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
2240 | if (vha->vp_idx != fcport->vp_idx) | 2268 | if (vha->vp_idx != 0 && vha->vp_idx != fcport->vp_idx) |
2241 | continue; | 2269 | continue; |
2270 | |||
2242 | /* | 2271 | /* |
2243 | * No point in marking the device as lost, if the device is | 2272 | * No point in marking the device as lost, if the device is |
2244 | * already DEAD. | 2273 | * already DEAD. |
@@ -2246,10 +2275,12 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer) | |||
2246 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) | 2275 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) |
2247 | continue; | 2276 | continue; |
2248 | if (atomic_read(&fcport->state) == FCS_ONLINE) { | 2277 | if (atomic_read(&fcport->state) == FCS_ONLINE) { |
2249 | atomic_set(&fcport->state, FCS_DEVICE_LOST); | 2278 | if (defer) |
2250 | qla2x00_schedule_rport_del(vha, fcport, defer); | 2279 | qla2x00_schedule_rport_del(vha, fcport, defer); |
2251 | } else | 2280 | else if (vha->vp_idx == fcport->vp_idx) |
2252 | atomic_set(&fcport->state, FCS_DEVICE_LOST); | 2281 | qla2x00_schedule_rport_del(vha, fcport, defer); |
2282 | } | ||
2283 | atomic_set(&fcport->state, FCS_DEVICE_LOST); | ||
2253 | } | 2284 | } |
2254 | } | 2285 | } |
2255 | 2286 | ||
@@ -2598,7 +2629,31 @@ qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb) | |||
2598 | return qla2x00_post_work(vha, e); | 2629 | return qla2x00_post_work(vha, e); |
2599 | } | 2630 | } |
2600 | 2631 | ||
2601 | static void | 2632 | #define qla2x00_post_async_work(name, type) \ |
2633 | int qla2x00_post_async_##name##_work( \ | ||
2634 | struct scsi_qla_host *vha, \ | ||
2635 | fc_port_t *fcport, uint16_t *data) \ | ||
2636 | { \ | ||
2637 | struct qla_work_evt *e; \ | ||
2638 | \ | ||
2639 | e = qla2x00_alloc_work(vha, type); \ | ||
2640 | if (!e) \ | ||
2641 | return QLA_FUNCTION_FAILED; \ | ||
2642 | \ | ||
2643 | e->u.logio.fcport = fcport; \ | ||
2644 | if (data) { \ | ||
2645 | e->u.logio.data[0] = data[0]; \ | ||
2646 | e->u.logio.data[1] = data[1]; \ | ||
2647 | } \ | ||
2648 | return qla2x00_post_work(vha, e); \ | ||
2649 | } | ||
2650 | |||
2651 | qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN); | ||
2652 | qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE); | ||
2653 | qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); | ||
2654 | qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE); | ||
2655 | |||
2656 | void | ||
2602 | qla2x00_do_work(struct scsi_qla_host *vha) | 2657 | qla2x00_do_work(struct scsi_qla_host *vha) |
2603 | { | 2658 | { |
2604 | struct qla_work_evt *e, *tmp; | 2659 | struct qla_work_evt *e, *tmp; |
@@ -2620,6 +2675,21 @@ qla2x00_do_work(struct scsi_qla_host *vha) | |||
2620 | case QLA_EVT_IDC_ACK: | 2675 | case QLA_EVT_IDC_ACK: |
2621 | qla81xx_idc_ack(vha, e->u.idc_ack.mb); | 2676 | qla81xx_idc_ack(vha, e->u.idc_ack.mb); |
2622 | break; | 2677 | break; |
2678 | case QLA_EVT_ASYNC_LOGIN: | ||
2679 | qla2x00_async_login(vha, e->u.logio.fcport, | ||
2680 | e->u.logio.data); | ||
2681 | break; | ||
2682 | case QLA_EVT_ASYNC_LOGIN_DONE: | ||
2683 | qla2x00_async_login_done(vha, e->u.logio.fcport, | ||
2684 | e->u.logio.data); | ||
2685 | break; | ||
2686 | case QLA_EVT_ASYNC_LOGOUT: | ||
2687 | qla2x00_async_logout(vha, e->u.logio.fcport); | ||
2688 | break; | ||
2689 | case QLA_EVT_ASYNC_LOGOUT_DONE: | ||
2690 | qla2x00_async_logout_done(vha, e->u.logio.fcport, | ||
2691 | e->u.logio.data); | ||
2692 | break; | ||
2623 | } | 2693 | } |
2624 | if (e->flags & QLA_EVT_FLAG_FREE) | 2694 | if (e->flags & QLA_EVT_FLAG_FREE) |
2625 | kfree(e); | 2695 | kfree(e); |
@@ -2635,6 +2705,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha) | |||
2635 | int status; | 2705 | int status; |
2636 | uint16_t next_loopid = 0; | 2706 | uint16_t next_loopid = 0; |
2637 | struct qla_hw_data *ha = vha->hw; | 2707 | struct qla_hw_data *ha = vha->hw; |
2708 | uint16_t data[2]; | ||
2638 | 2709 | ||
2639 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 2710 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
2640 | /* | 2711 | /* |
@@ -2644,6 +2715,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha) | |||
2644 | if (atomic_read(&fcport->state) != | 2715 | if (atomic_read(&fcport->state) != |
2645 | FCS_ONLINE && fcport->login_retry) { | 2716 | FCS_ONLINE && fcport->login_retry) { |
2646 | 2717 | ||
2718 | fcport->login_retry--; | ||
2647 | if (fcport->flags & FCF_FABRIC_DEVICE) { | 2719 | if (fcport->flags & FCF_FABRIC_DEVICE) { |
2648 | if (fcport->flags & FCF_TAPE_PRESENT) | 2720 | if (fcport->flags & FCF_TAPE_PRESENT) |
2649 | ha->isp_ops->fabric_logout(vha, | 2721 | ha->isp_ops->fabric_logout(vha, |
@@ -2652,13 +2724,22 @@ void qla2x00_relogin(struct scsi_qla_host *vha) | |||
2652 | fcport->d_id.b.area, | 2724 | fcport->d_id.b.area, |
2653 | fcport->d_id.b.al_pa); | 2725 | fcport->d_id.b.al_pa); |
2654 | 2726 | ||
2655 | status = qla2x00_fabric_login(vha, fcport, | 2727 | if (IS_ALOGIO_CAPABLE(ha)) { |
2656 | &next_loopid); | 2728 | data[0] = 0; |
2729 | data[1] = QLA_LOGIO_LOGIN_RETRIED; | ||
2730 | status = qla2x00_post_async_login_work( | ||
2731 | vha, fcport, data); | ||
2732 | if (status == QLA_SUCCESS) | ||
2733 | continue; | ||
2734 | /* Attempt a retry. */ | ||
2735 | status = 1; | ||
2736 | } else | ||
2737 | status = qla2x00_fabric_login(vha, | ||
2738 | fcport, &next_loopid); | ||
2657 | } else | 2739 | } else |
2658 | status = qla2x00_local_device_login(vha, | 2740 | status = qla2x00_local_device_login(vha, |
2659 | fcport); | 2741 | fcport); |
2660 | 2742 | ||
2661 | fcport->login_retry--; | ||
2662 | if (status == QLA_SUCCESS) { | 2743 | if (status == QLA_SUCCESS) { |
2663 | fcport->old_loop_id = fcport->loop_id; | 2744 | fcport->old_loop_id = fcport->loop_id; |
2664 | 2745 | ||
@@ -2831,6 +2912,9 @@ qla2x00_do_dpc(void *data) | |||
2831 | */ | 2912 | */ |
2832 | ha->dpc_active = 0; | 2913 | ha->dpc_active = 0; |
2833 | 2914 | ||
2915 | /* Cleanup any residual CTX SRBs. */ | ||
2916 | qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); | ||
2917 | |||
2834 | return 0; | 2918 | return 0; |
2835 | } | 2919 | } |
2836 | 2920 | ||
@@ -2971,6 +3055,8 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
2971 | sp = req->outstanding_cmds[index]; | 3055 | sp = req->outstanding_cmds[index]; |
2972 | if (!sp) | 3056 | if (!sp) |
2973 | continue; | 3057 | continue; |
3058 | if (sp->ctx) | ||
3059 | continue; | ||
2974 | sfcp = sp->fcport; | 3060 | sfcp = sp->fcport; |
2975 | if (!(sfcp->flags & FCF_TAPE_PRESENT)) | 3061 | if (!(sfcp->flags & FCF_TAPE_PRESENT)) |
2976 | continue; | 3062 | continue; |
@@ -2987,8 +3073,7 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
2987 | 3073 | ||
2988 | /* if the loop has been down for 4 minutes, reinit adapter */ | 3074 | /* if the loop has been down for 4 minutes, reinit adapter */ |
2989 | if (atomic_dec_and_test(&vha->loop_down_timer) != 0) { | 3075 | if (atomic_dec_and_test(&vha->loop_down_timer) != 0) { |
2990 | if (!(vha->device_flags & DFLG_NO_CABLE) && | 3076 | if (!(vha->device_flags & DFLG_NO_CABLE)) { |
2991 | !vha->vp_idx) { | ||
2992 | DEBUG(printk("scsi(%ld): Loop down - " | 3077 | DEBUG(printk("scsi(%ld): Loop down - " |
2993 | "aborting ISP.\n", | 3078 | "aborting ISP.\n", |
2994 | vha->host_no)); | 3079 | vha->host_no)); |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 84369705a9ad..ac107a2c34a4 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -7,7 +7,7 @@ | |||
7 | /* | 7 | /* |
8 | * Driver version | 8 | * Driver version |
9 | */ | 9 | */ |
10 | #define QLA2XXX_VERSION "8.03.01-k4" | 10 | #define QLA2XXX_VERSION "8.03.01-k6" |
11 | 11 | ||
12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
13 | #define QLA_DRIVER_MINOR_VER 3 | 13 | #define QLA_DRIVER_MINOR_VER 3 |