Skip to content

Commit ac280b6

Browse files
avasquez01James Bottomley
authored andcommitted
[SCSI] qla2xxx: Add asynchronous-login support.
ISPs which support this feature include 23xx and above. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
1 parent cf53b06 commit ac280b6

File tree

7 files changed

+784
-9
lines changed

7 files changed

+784
-9
lines changed

drivers/scsi/qla2xxx/qla_def.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,28 @@ typedef struct srb {
206206
*/
207207
#define SRB_DMA_VALID BIT_0 /* Command sent to ISP */
208208

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+
209231
/*
210232
* ISP I/O Register Set structure definitions.
211233
*/
@@ -2096,6 +2118,10 @@ struct qla_msix_entry {
20962118
enum qla_work_type {
20972119
QLA_EVT_AEN,
20982120
QLA_EVT_IDC_ACK,
2121+
QLA_EVT_ASYNC_LOGIN,
2122+
QLA_EVT_ASYNC_LOGIN_DONE,
2123+
QLA_EVT_ASYNC_LOGOUT,
2124+
QLA_EVT_ASYNC_LOGOUT_DONE,
20992125
};
21002126

21012127

@@ -2114,6 +2140,11 @@ struct qla_work_evt {
21142140
#define QLA_IDC_ACK_REGS 7
21152141
uint16_t mb[QLA_IDC_ACK_REGS];
21162142
} idc_ack;
2143+
struct {
2144+
struct fc_port *fcport;
2145+
#define QLA_LOGIO_LOGIN_RETRIED BIT_0
2146+
u16 data[2];
2147+
} logio;
21172148
} u;
21182149
};
21192150

@@ -2354,6 +2385,7 @@ struct qla_hw_data {
23542385
(ha)->flags.msix_enabled)
23552386
#define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha))
23562387
#define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha))
2388+
#define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha))
23572389

23582390
#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
23592391
#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)

drivers/scsi/qla2xxx/qla_gbl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
5252

5353
extern void qla84xx_put_chip(struct scsi_qla_host *);
5454

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+
5563
/*
5664
* Global Data in qla_os.c source file.
5765
*/
@@ -76,13 +84,24 @@ extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
7684
extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
7785
fc_host_event_code, u32);
7886
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+
7996
extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
8097

8198
extern void qla2x00_abort_fcport_cmds(fc_port_t *);
8299
extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
83100
struct qla_hw_data *);
84101
extern void qla2x00_free_host(struct scsi_qla_host *);
85102
extern void qla2x00_relogin(struct scsi_qla_host *);
103+
extern void qla2x00_do_work(struct scsi_qla_host *);
104+
86105
/*
87106
* Global Functions in qla_mid.c source file.
88107
*/
@@ -135,6 +154,7 @@ int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
135154
uint16_t, uint16_t, uint8_t);
136155
int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
137156
uint16_t, uint16_t, uint8_t);
157+
extern int qla2x00_start_sp(srb_t *);
138158

139159
/*
140160
* Global Function Prototypes in qla_mbx.c source file.

drivers/scsi/qla2xxx/qla_init.c

Lines changed: 212 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,210 @@ static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
4040
static int qla84xx_init_chip(scsi_qla_host_t *);
4141
static int qla25xx_init_queues(struct qla_hw_data *);
4242

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+
43247
/****************************************************************************/
44248
/* QLogic ISP2x00 Hardware Support Functions. */
45249
/****************************************************************************/
@@ -1977,7 +2181,7 @@ qla2x00_rport_del(void *data)
19772181
struct fc_rport *rport;
19782182

19792183
spin_lock_irq(fcport->vha->host->host_lock);
1980-
rport = fcport->drport;
2184+
rport = fcport->drport ? fcport->drport: fcport->rport;
19812185
fcport->drport = NULL;
19822186
spin_unlock_irq(fcport->vha->host->host_lock);
19832187
if (rport)
@@ -2344,8 +2548,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
23442548
struct fc_rport *rport;
23452549
struct qla_hw_data *ha = vha->hw;
23462550

2347-
if (fcport->drport)
2348-
qla2x00_rport_del(fcport);
2551+
qla2x00_rport_del(fcport);
23492552

23502553
rport_ids.node_name = wwn_to_u64(fcport->node_name);
23512554
rport_ids.port_name = wwn_to_u64(fcport->port_name);
@@ -3038,6 +3241,12 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport,
30383241
rval = QLA_SUCCESS;
30393242
retry = 0;
30403243

3244+
if (IS_ALOGIO_CAPABLE(ha)) {
3245+
rval = qla2x00_post_async_login_work(vha, fcport, NULL);
3246+
if (!rval)
3247+
return rval;
3248+
}
3249+
30413250
rval = qla2x00_fabric_login(vha, fcport, next_loopid);
30423251
if (rval == QLA_SUCCESS) {
30433252
/* Send an ADISC to tape devices.*/

0 commit comments

Comments
 (0)