blob: f80b702730ad7ec6c8d7744e49e033d192addec6 [file] [log] [blame]
David Somayajuluafaf5a22006-09-19 10:28:00 -07001/*
2 * QLogic iSCSI HBA Driver
Vikas Chaudhary7d01d062010-12-02 22:12:51 -08003 * Copyright (c) 2003-2010 QLogic Corporation
David Somayajuluafaf5a22006-09-19 10:28:00 -07004 *
5 * See LICENSE.qla4xxx for copyright and licensing details.
6 */
7#include <linux/moduleparam.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09008#include <linux/slab.h>
David Somayajuluafaf5a22006-09-19 10:28:00 -07009
10#include <scsi/scsi_tcq.h>
11#include <scsi/scsicam.h>
12
13#include "ql4_def.h"
David C Somayajulubee4fe82007-05-23 18:03:32 -070014#include "ql4_version.h"
15#include "ql4_glbl.h"
16#include "ql4_dbg.h"
17#include "ql4_inline.h"
David Somayajuluafaf5a22006-09-19 10:28:00 -070018
19/*
20 * Driver version
21 */
Adrian Bunk47975472007-04-26 00:35:16 -070022static char qla4xxx_version_str[40];
David Somayajuluafaf5a22006-09-19 10:28:00 -070023
24/*
25 * SRB allocation cache
26 */
Christoph Lametere18b8902006-12-06 20:33:20 -080027static struct kmem_cache *srb_cachep;
David Somayajuluafaf5a22006-09-19 10:28:00 -070028
29/*
30 * Module parameter information and variables
31 */
David Somayajuluafaf5a22006-09-19 10:28:00 -070032int ql4xdontresethba = 0;
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +053033module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
David Somayajuluafaf5a22006-09-19 10:28:00 -070034MODULE_PARM_DESC(ql4xdontresethba,
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +053035 "Don't reset the HBA for driver recovery \n"
36 " 0 - It will reset HBA (Default)\n"
37 " 1 - It will NOT reset HBA");
David Somayajuluafaf5a22006-09-19 10:28:00 -070038
Andrew Vasquez11010fe2006-10-06 09:54:59 -070039int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +053040module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR);
Andrew Vasquez11010fe2006-10-06 09:54:59 -070041MODULE_PARM_DESC(ql4xextended_error_logging,
David Somayajuluafaf5a22006-09-19 10:28:00 -070042 "Option to enable extended error logging, "
43 "Default is 0 - no logging, 1 - debug logging");
44
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +053045int ql4xenablemsix = 1;
46module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR);
47MODULE_PARM_DESC(ql4xenablemsix,
48 "Set to enable MSI or MSI-X interrupt mechanism.\n"
49 " 0 = enable INTx interrupt mechanism.\n"
50 " 1 = enable MSI-X interrupt mechanism (Default).\n"
51 " 2 = enable MSI interrupt mechanism.");
David C Somayajulu477ffb92007-01-22 12:26:11 -080052
Mike Christied510d962008-07-11 19:50:33 -050053#define QL4_DEF_QDEPTH 32
54
David Somayajuluafaf5a22006-09-19 10:28:00 -070055/*
56 * SCSI host template entry points
57 */
Adrian Bunk47975472007-04-26 00:35:16 -070058static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -070059
60/*
61 * iSCSI template entry points
62 */
Mike Christie2174a042007-05-30 12:57:10 -050063static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
64 enum iscsi_tgt_dscvr type, uint32_t enable,
65 struct sockaddr *dst_addr);
David Somayajuluafaf5a22006-09-19 10:28:00 -070066static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
67 enum iscsi_param param, char *buf);
68static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
69 enum iscsi_param param, char *buf);
Mike Christieaa1e93a2007-05-30 12:57:09 -050070static int qla4xxx_host_get_param(struct Scsi_Host *shost,
71 enum iscsi_host_param param, char *buf);
David Somayajuluafaf5a22006-09-19 10:28:00 -070072static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
Mike Christie5c656af2009-07-15 15:02:59 -050073static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
David Somayajuluafaf5a22006-09-19 10:28:00 -070074
75/*
76 * SCSI host template entry points
77 */
Jeff Garzikf2812332010-11-16 02:10:29 -050078static int qla4xxx_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +053079static int qla4xxx_eh_abort(struct scsi_cmnd *cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -070080static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
Mike Christiece545032008-02-29 18:25:20 -060081static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -070082static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
83static int qla4xxx_slave_alloc(struct scsi_device *device);
84static int qla4xxx_slave_configure(struct scsi_device *device);
85static void qla4xxx_slave_destroy(struct scsi_device *sdev);
Mike Christie024f8012008-03-04 13:26:54 -060086static void qla4xxx_scan_start(struct Scsi_Host *shost);
David Somayajuluafaf5a22006-09-19 10:28:00 -070087
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +053088static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
89 QLA82XX_LEGACY_INTR_CONFIG;
90
David Somayajuluafaf5a22006-09-19 10:28:00 -070091static struct scsi_host_template qla4xxx_driver_template = {
92 .module = THIS_MODULE,
93 .name = DRIVER_NAME,
94 .proc_name = DRIVER_NAME,
95 .queuecommand = qla4xxx_queuecommand,
96
Vikas Chaudhary09a0f712010-04-28 11:42:24 +053097 .eh_abort_handler = qla4xxx_eh_abort,
David Somayajuluafaf5a22006-09-19 10:28:00 -070098 .eh_device_reset_handler = qla4xxx_eh_device_reset,
Mike Christiece545032008-02-29 18:25:20 -060099 .eh_target_reset_handler = qla4xxx_eh_target_reset,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700100 .eh_host_reset_handler = qla4xxx_eh_host_reset,
Mike Christie5c656af2009-07-15 15:02:59 -0500101 .eh_timed_out = qla4xxx_eh_cmd_timed_out,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700102
103 .slave_configure = qla4xxx_slave_configure,
104 .slave_alloc = qla4xxx_slave_alloc,
105 .slave_destroy = qla4xxx_slave_destroy,
106
Mike Christie921601b2008-01-31 13:36:49 -0600107 .scan_finished = iscsi_scan_finished,
Mike Christie024f8012008-03-04 13:26:54 -0600108 .scan_start = qla4xxx_scan_start,
Mike Christie921601b2008-01-31 13:36:49 -0600109
David Somayajuluafaf5a22006-09-19 10:28:00 -0700110 .this_id = -1,
111 .cmd_per_lun = 3,
112 .use_clustering = ENABLE_CLUSTERING,
113 .sg_tablesize = SG_ALL,
114
115 .max_sectors = 0xFFFF,
116};
117
118static struct iscsi_transport qla4xxx_iscsi_transport = {
119 .owner = THIS_MODULE,
120 .name = DRIVER_NAME,
Mike Christied8196ed2007-05-30 12:57:25 -0500121 .caps = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
122 CAP_DATA_PATH_OFFLOAD,
Mike Christieaa1e93a2007-05-30 12:57:09 -0500123 .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
Vikas Chaudhary3b2bef12010-07-10 14:51:30 +0530124 ISCSI_TARGET_NAME | ISCSI_TPGT |
125 ISCSI_TARGET_ALIAS,
Mike Christie8ad57812007-05-30 12:57:13 -0500126 .host_param_mask = ISCSI_HOST_HWADDRESS |
Mike Christie22236962007-05-30 12:57:24 -0500127 ISCSI_HOST_IPADDRESS |
Mike Christie8ad57812007-05-30 12:57:13 -0500128 ISCSI_HOST_INITIATOR_NAME,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700129 .tgt_dscvr = qla4xxx_tgt_dscvr,
130 .get_conn_param = qla4xxx_conn_get_param,
131 .get_session_param = qla4xxx_sess_get_param,
Mike Christieaa1e93a2007-05-30 12:57:09 -0500132 .get_host_param = qla4xxx_host_get_param,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700133 .session_recovery_timedout = qla4xxx_recovery_timedout,
134};
135
136static struct scsi_transport_template *qla4xxx_scsi_transport;
137
Mike Christie5c656af2009-07-15 15:02:59 -0500138static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
139{
140 struct iscsi_cls_session *session;
141 struct ddb_entry *ddb_entry;
142
143 session = starget_to_session(scsi_target(sc->device));
144 ddb_entry = session->dd_data;
145
146 /* if we are not logged in then the LLD is going to clean up the cmd */
147 if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
148 return BLK_EH_RESET_TIMER;
149 else
150 return BLK_EH_NOT_HANDLED;
151}
152
David Somayajuluafaf5a22006-09-19 10:28:00 -0700153static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
154{
155 struct ddb_entry *ddb_entry = session->dd_data;
156 struct scsi_qla_host *ha = ddb_entry->ha;
157
Mike Christie568d3032008-01-31 13:36:47 -0600158 if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
159 atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700160
Vikas Chaudhary3013cea2010-07-30 14:25:46 +0530161 DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout "
Mike Christie568d3032008-01-31 13:36:47 -0600162 "of (%d) secs exhausted, marking device DEAD.\n",
163 ha->host_no, __func__, ddb_entry->fw_ddb_index,
Vikas Chaudhary3013cea2010-07-30 14:25:46 +0530164 QL4_SESS_RECOVERY_TMO));
Mike Christie568d3032008-01-31 13:36:47 -0600165 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700166}
167
Mike Christieaa1e93a2007-05-30 12:57:09 -0500168static int qla4xxx_host_get_param(struct Scsi_Host *shost,
169 enum iscsi_host_param param, char *buf)
170{
171 struct scsi_qla_host *ha = to_qla_host(shost);
172 int len;
173
174 switch (param) {
175 case ISCSI_HOST_PARAM_HWADDRESS:
Michael Chan7ffc49a2007-12-24 21:28:09 -0800176 len = sysfs_format_mac(buf, ha->my_mac, MAC_ADDR_LEN);
Mike Christieaa1e93a2007-05-30 12:57:09 -0500177 break;
Mike Christie22236962007-05-30 12:57:24 -0500178 case ISCSI_HOST_PARAM_IPADDRESS:
179 len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0],
180 ha->ip_address[1], ha->ip_address[2],
181 ha->ip_address[3]);
182 break;
Mike Christie8ad57812007-05-30 12:57:13 -0500183 case ISCSI_HOST_PARAM_INITIATOR_NAME:
Mike Christie22236962007-05-30 12:57:24 -0500184 len = sprintf(buf, "%s\n", ha->name_string);
Mike Christie8ad57812007-05-30 12:57:13 -0500185 break;
Mike Christieaa1e93a2007-05-30 12:57:09 -0500186 default:
187 return -ENOSYS;
188 }
189
190 return len;
191}
192
David Somayajuluafaf5a22006-09-19 10:28:00 -0700193static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
194 enum iscsi_param param, char *buf)
195{
196 struct ddb_entry *ddb_entry = sess->dd_data;
197 int len;
198
199 switch (param) {
200 case ISCSI_PARAM_TARGET_NAME:
201 len = snprintf(buf, PAGE_SIZE - 1, "%s\n",
202 ddb_entry->iscsi_name);
203 break;
204 case ISCSI_PARAM_TPGT:
205 len = sprintf(buf, "%u\n", ddb_entry->tpgt);
206 break;
Vikas Chaudhary3b2bef12010-07-10 14:51:30 +0530207 case ISCSI_PARAM_TARGET_ALIAS:
208 len = snprintf(buf, PAGE_SIZE - 1, "%s\n",
209 ddb_entry->iscsi_alias);
210 break;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700211 default:
212 return -ENOSYS;
213 }
214
215 return len;
216}
217
218static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
219 enum iscsi_param param, char *buf)
220{
221 struct iscsi_cls_session *session;
222 struct ddb_entry *ddb_entry;
223 int len;
224
225 session = iscsi_dev_to_session(conn->dev.parent);
226 ddb_entry = session->dd_data;
227
228 switch (param) {
229 case ISCSI_PARAM_CONN_PORT:
230 len = sprintf(buf, "%hu\n", ddb_entry->port);
231 break;
232 case ISCSI_PARAM_CONN_ADDRESS:
233 /* TODO: what are the ipv6 bits */
Harvey Harrison63779432008-10-31 00:56:00 -0700234 len = sprintf(buf, "%pI4\n", &ddb_entry->ip_addr);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700235 break;
236 default:
237 return -ENOSYS;
238 }
239
240 return len;
241}
242
Mike Christie2174a042007-05-30 12:57:10 -0500243static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
244 enum iscsi_tgt_dscvr type, uint32_t enable,
245 struct sockaddr *dst_addr)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700246{
247 struct scsi_qla_host *ha;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700248 struct sockaddr_in *addr;
249 struct sockaddr_in6 *addr6;
250 int ret = 0;
251
David Somayajuluafaf5a22006-09-19 10:28:00 -0700252 ha = (struct scsi_qla_host *) shost->hostdata;
253
254 switch (type) {
255 case ISCSI_TGT_DSCVR_SEND_TARGETS:
256 if (dst_addr->sa_family == AF_INET) {
257 addr = (struct sockaddr_in *)dst_addr;
258 if (qla4xxx_send_tgts(ha, (char *)&addr->sin_addr,
259 addr->sin_port) != QLA_SUCCESS)
260 ret = -EIO;
261 } else if (dst_addr->sa_family == AF_INET6) {
262 /*
263 * TODO: fix qla4xxx_send_tgts
264 */
265 addr6 = (struct sockaddr_in6 *)dst_addr;
266 if (qla4xxx_send_tgts(ha, (char *)&addr6->sin6_addr,
267 addr6->sin6_port) != QLA_SUCCESS)
268 ret = -EIO;
269 } else
270 ret = -ENOSYS;
271 break;
272 default:
273 ret = -ENOSYS;
274 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700275 return ret;
276}
277
278void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry)
279{
280 if (!ddb_entry->sess)
281 return;
282
283 if (ddb_entry->conn) {
Mike Christie26974782007-12-13 12:43:29 -0600284 atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700285 iscsi_remove_session(ddb_entry->sess);
286 }
287 iscsi_free_session(ddb_entry->sess);
288}
289
290int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
291{
292 int err;
293
Vikas Chaudhary3013cea2010-07-30 14:25:46 +0530294 ddb_entry->sess->recovery_tmo = QL4_SESS_RECOVERY_TMO;
295
David Somayajuluafaf5a22006-09-19 10:28:00 -0700296 err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
297 if (err) {
298 DEBUG2(printk(KERN_ERR "Could not add session.\n"));
299 return err;
300 }
301
Mike Christie5d91e202008-05-21 15:54:01 -0500302 ddb_entry->conn = iscsi_create_conn(ddb_entry->sess, 0, 0);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700303 if (!ddb_entry->conn) {
304 iscsi_remove_session(ddb_entry->sess);
305 DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
306 return -ENOMEM;
307 }
Mike Christieb6359302008-01-31 13:36:44 -0600308
309 /* finally ready to go */
310 iscsi_unblock_session(ddb_entry->sess);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700311 return 0;
312}
313
314struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha)
315{
316 struct ddb_entry *ddb_entry;
317 struct iscsi_cls_session *sess;
318
Mike Christie5d91e202008-05-21 15:54:01 -0500319 sess = iscsi_alloc_session(ha->host, &qla4xxx_iscsi_transport,
320 sizeof(struct ddb_entry));
David Somayajuluafaf5a22006-09-19 10:28:00 -0700321 if (!sess)
322 return NULL;
323
324 ddb_entry = sess->dd_data;
325 memset(ddb_entry, 0, sizeof(*ddb_entry));
326 ddb_entry->ha = ha;
327 ddb_entry->sess = sess;
328 return ddb_entry;
329}
330
Mike Christie024f8012008-03-04 13:26:54 -0600331static void qla4xxx_scan_start(struct Scsi_Host *shost)
332{
333 struct scsi_qla_host *ha = shost_priv(shost);
334 struct ddb_entry *ddb_entry, *ddbtemp;
335
336 /* finish setup of sessions that were already setup in firmware */
337 list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
338 if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE)
339 qla4xxx_add_sess(ddb_entry);
340 }
341}
342
David Somayajuluafaf5a22006-09-19 10:28:00 -0700343/*
344 * Timer routines
345 */
346
347static void qla4xxx_start_timer(struct scsi_qla_host *ha, void *func,
348 unsigned long interval)
349{
350 DEBUG(printk("scsi: %s: Starting timer thread for adapter %d\n",
351 __func__, ha->host->host_no));
352 init_timer(&ha->timer);
353 ha->timer.expires = jiffies + interval * HZ;
354 ha->timer.data = (unsigned long)ha;
355 ha->timer.function = (void (*)(unsigned long))func;
356 add_timer(&ha->timer);
357 ha->timer_active = 1;
358}
359
360static void qla4xxx_stop_timer(struct scsi_qla_host *ha)
361{
362 del_timer_sync(&ha->timer);
363 ha->timer_active = 0;
364}
365
366/***
367 * qla4xxx_mark_device_missing - mark a device as missing.
368 * @ha: Pointer to host adapter structure.
369 * @ddb_entry: Pointer to device database entry
370 *
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530371 * This routine marks a device missing and close connection.
David Somayajuluafaf5a22006-09-19 10:28:00 -0700372 **/
373void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
374 struct ddb_entry *ddb_entry)
375{
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530376 if ((atomic_read(&ddb_entry->state) != DDB_STATE_DEAD)) {
377 atomic_set(&ddb_entry->state, DDB_STATE_MISSING);
378 DEBUG2(printk("scsi%ld: ddb [%d] marked MISSING\n",
379 ha->host_no, ddb_entry->fw_ddb_index));
380 } else
381 DEBUG2(printk("scsi%ld: ddb [%d] DEAD\n", ha->host_no,
382 ddb_entry->fw_ddb_index))
383
Mike Christieb6359302008-01-31 13:36:44 -0600384 iscsi_block_session(ddb_entry->sess);
Mike Christiee5bd7b52008-09-24 11:46:10 -0500385 iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700386}
387
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530388/**
389 * qla4xxx_mark_all_devices_missing - mark all devices as missing.
390 * @ha: Pointer to host adapter structure.
391 *
392 * This routine marks a device missing and resets the relogin retry count.
393 **/
394void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha)
395{
396 struct ddb_entry *ddb_entry, *ddbtemp;
397 list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
398 qla4xxx_mark_device_missing(ha, ddb_entry);
399 }
400}
401
David Somayajuluafaf5a22006-09-19 10:28:00 -0700402static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
403 struct ddb_entry *ddb_entry,
404 struct scsi_cmnd *cmd,
405 void (*done)(struct scsi_cmnd *))
406{
407 struct srb *srb;
408
409 srb = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
410 if (!srb)
411 return srb;
412
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530413 kref_init(&srb->srb_ref);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700414 srb->ha = ha;
415 srb->ddb = ddb_entry;
416 srb->cmd = cmd;
417 srb->flags = 0;
Vikas Chaudhary53698872010-04-28 11:41:59 +0530418 CMD_SP(cmd) = (void *)srb;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700419 cmd->scsi_done = done;
420
421 return srb;
422}
423
424static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb)
425{
426 struct scsi_cmnd *cmd = srb->cmd;
427
428 if (srb->flags & SRB_DMA_VALID) {
FUJITA Tomonori5f7186c2007-05-26 14:08:20 +0900429 scsi_dma_unmap(cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700430 srb->flags &= ~SRB_DMA_VALID;
431 }
Vikas Chaudhary53698872010-04-28 11:41:59 +0530432 CMD_SP(cmd) = NULL;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700433}
434
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530435void qla4xxx_srb_compl(struct kref *ref)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700436{
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530437 struct srb *srb = container_of(ref, struct srb, srb_ref);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700438 struct scsi_cmnd *cmd = srb->cmd;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530439 struct scsi_qla_host *ha = srb->ha;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700440
441 qla4xxx_srb_free_dma(ha, srb);
442
443 mempool_free(srb, ha->srb_mempool);
444
445 cmd->scsi_done(cmd);
446}
447
448/**
449 * qla4xxx_queuecommand - scsi layer issues scsi command to driver.
450 * @cmd: Pointer to Linux's SCSI command structure
451 * @done_fn: Function that the driver calls to notify the SCSI mid-layer
452 * that the command has been processed.
453 *
454 * Remarks:
455 * This routine is invoked by Linux to send a SCSI command to the driver.
456 * The mid-level driver tries to ensure that queuecommand never gets
457 * invoked concurrently with itself or the interrupt handler (although
458 * the interrupt handler may call this routine as part of request-
459 * completion handling). Unfortunely, it sometimes calls the scheduler
460 * in interrupt context which is a big NO! NO!.
461 **/
Jeff Garzikf2812332010-11-16 02:10:29 -0500462static int qla4xxx_queuecommand_lck(struct scsi_cmnd *cmd,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700463 void (*done)(struct scsi_cmnd *))
464{
465 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
466 struct ddb_entry *ddb_entry = cmd->device->hostdata;
Mike Christie7fb19212008-01-31 13:36:45 -0600467 struct iscsi_cls_session *sess = ddb_entry->sess;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700468 struct srb *srb;
469 int rval;
470
Lalit Chandivade2232be02010-07-30 14:38:47 +0530471 if (test_bit(AF_EEH_BUSY, &ha->flags)) {
472 if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))
473 cmd->result = DID_NO_CONNECT << 16;
474 else
475 cmd->result = DID_REQUEUE << 16;
476 goto qc_fail_command;
477 }
478
Mike Christie7fb19212008-01-31 13:36:45 -0600479 if (!sess) {
480 cmd->result = DID_IMM_RETRY << 16;
481 goto qc_fail_command;
482 }
483
484 rval = iscsi_session_chkready(sess);
485 if (rval) {
486 cmd->result = rval;
487 goto qc_fail_command;
488 }
489
David Somayajuluafaf5a22006-09-19 10:28:00 -0700490 if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
491 if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) {
492 cmd->result = DID_NO_CONNECT << 16;
493 goto qc_fail_command;
494 }
Mike Christiec5e98e92008-08-17 15:24:39 -0500495 return SCSI_MLQUEUE_TARGET_BUSY;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700496 }
497
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530498 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
499 test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
500 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
501 test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||
502 test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||
503 !test_bit(AF_ONLINE, &ha->flags) ||
504 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))
David C Somayajulu477ffb92007-01-22 12:26:11 -0800505 goto qc_host_busy;
506
David Somayajuluafaf5a22006-09-19 10:28:00 -0700507 spin_unlock_irq(ha->host->host_lock);
508
509 srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done);
510 if (!srb)
511 goto qc_host_busy_lock;
512
513 rval = qla4xxx_send_command_to_isp(ha, srb);
514 if (rval != QLA_SUCCESS)
515 goto qc_host_busy_free_sp;
516
517 spin_lock_irq(ha->host->host_lock);
518 return 0;
519
520qc_host_busy_free_sp:
521 qla4xxx_srb_free_dma(ha, srb);
522 mempool_free(srb, ha->srb_mempool);
523
524qc_host_busy_lock:
525 spin_lock_irq(ha->host->host_lock);
526
527qc_host_busy:
528 return SCSI_MLQUEUE_HOST_BUSY;
529
530qc_fail_command:
531 done(cmd);
532
533 return 0;
534}
535
Jeff Garzikf2812332010-11-16 02:10:29 -0500536static DEF_SCSI_QCMD(qla4xxx_queuecommand)
537
David Somayajuluafaf5a22006-09-19 10:28:00 -0700538/**
539 * qla4xxx_mem_free - frees memory allocated to adapter
540 * @ha: Pointer to host adapter structure.
541 *
542 * Frees memory previously allocated by qla4xxx_mem_alloc
543 **/
544static void qla4xxx_mem_free(struct scsi_qla_host *ha)
545{
546 if (ha->queues)
547 dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues,
548 ha->queues_dma);
549
550 ha->queues_len = 0;
551 ha->queues = NULL;
552 ha->queues_dma = 0;
553 ha->request_ring = NULL;
554 ha->request_dma = 0;
555 ha->response_ring = NULL;
556 ha->response_dma = 0;
557 ha->shadow_regs = NULL;
558 ha->shadow_regs_dma = 0;
559
560 /* Free srb pool. */
561 if (ha->srb_mempool)
562 mempool_destroy(ha->srb_mempool);
563
564 ha->srb_mempool = NULL;
565
566 /* release io space registers */
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530567 if (is_qla8022(ha)) {
568 if (ha->nx_pcibase)
569 iounmap(
570 (struct device_reg_82xx __iomem *)ha->nx_pcibase);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530571 } else if (ha->reg)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700572 iounmap(ha->reg);
573 pci_release_regions(ha->pdev);
574}
575
576/**
577 * qla4xxx_mem_alloc - allocates memory for use by adapter.
578 * @ha: Pointer to host adapter structure
579 *
580 * Allocates DMA memory for request and response queues. Also allocates memory
581 * for srbs.
582 **/
583static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
584{
585 unsigned long align;
586
587 /* Allocate contiguous block of DMA memory for queues. */
588 ha->queues_len = ((REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +
589 (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE) +
590 sizeof(struct shadow_regs) +
591 MEM_ALIGN_VALUE +
592 (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
593 ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len,
594 &ha->queues_dma, GFP_KERNEL);
595 if (ha->queues == NULL) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +0530596 ql4_printk(KERN_WARNING, ha,
597 "Memory Allocation failed - queues.\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -0700598
599 goto mem_alloc_error_exit;
600 }
601 memset(ha->queues, 0, ha->queues_len);
602
603 /*
604 * As per RISC alignment requirements -- the bus-address must be a
605 * multiple of the request-ring size (in bytes).
606 */
607 align = 0;
608 if ((unsigned long)ha->queues_dma & (MEM_ALIGN_VALUE - 1))
609 align = MEM_ALIGN_VALUE - ((unsigned long)ha->queues_dma &
610 (MEM_ALIGN_VALUE - 1));
611
612 /* Update request and response queue pointers. */
613 ha->request_dma = ha->queues_dma + align;
614 ha->request_ring = (struct queue_entry *) (ha->queues + align);
615 ha->response_dma = ha->queues_dma + align +
616 (REQUEST_QUEUE_DEPTH * QUEUE_SIZE);
617 ha->response_ring = (struct queue_entry *) (ha->queues + align +
618 (REQUEST_QUEUE_DEPTH *
619 QUEUE_SIZE));
620 ha->shadow_regs_dma = ha->queues_dma + align +
621 (REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +
622 (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE);
623 ha->shadow_regs = (struct shadow_regs *) (ha->queues + align +
624 (REQUEST_QUEUE_DEPTH *
625 QUEUE_SIZE) +
626 (RESPONSE_QUEUE_DEPTH *
627 QUEUE_SIZE));
628
629 /* Allocate memory for srb pool. */
630 ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab,
631 mempool_free_slab, srb_cachep);
632 if (ha->srb_mempool == NULL) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +0530633 ql4_printk(KERN_WARNING, ha,
634 "Memory Allocation failed - SRB Pool.\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -0700635
636 goto mem_alloc_error_exit;
637 }
638
639 return QLA_SUCCESS;
640
641mem_alloc_error_exit:
642 qla4xxx_mem_free(ha);
643 return QLA_ERROR;
644}
645
646/**
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530647 * qla4_8xxx_check_fw_alive - Check firmware health
648 * @ha: Pointer to host adapter structure.
649 *
650 * Context: Interrupt
651 **/
652static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha)
653{
654 uint32_t fw_heartbeat_counter, halt_status;
655
656 fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
Lalit Chandivade2232be02010-07-30 14:38:47 +0530657 /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */
658 if (fw_heartbeat_counter == 0xffffffff) {
659 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen "
660 "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n",
661 ha->host_no, __func__));
662 return;
663 }
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530664
665 if (ha->fw_heartbeat_counter == fw_heartbeat_counter) {
666 ha->seconds_since_last_heartbeat++;
667 /* FW not alive after 2 seconds */
668 if (ha->seconds_since_last_heartbeat == 2) {
669 ha->seconds_since_last_heartbeat = 0;
670 halt_status = qla4_8xxx_rd_32(ha,
671 QLA82XX_PEG_HALT_STATUS1);
Nilesh Javali21033632010-07-30 14:28:07 +0530672
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530673 /* Since we cannot change dev_state in interrupt
674 * context, set appropriate DPC flag then wakeup
675 * DPC */
676 if (halt_status & HALT_STATUS_UNRECOVERABLE)
677 set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
678 else {
679 printk("scsi%ld: %s: detect abort needed!\n",
680 ha->host_no, __func__);
681 set_bit(DPC_RESET_HA, &ha->dpc_flags);
682 }
683 qla4xxx_wake_dpc(ha);
Nilesh Javali21033632010-07-30 14:28:07 +0530684 qla4xxx_mailbox_premature_completion(ha);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530685 }
Lalit Chandivade99457d72010-10-06 22:49:32 -0700686 } else
687 ha->seconds_since_last_heartbeat = 0;
688
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530689 ha->fw_heartbeat_counter = fw_heartbeat_counter;
690}
691
692/**
693 * qla4_8xxx_watchdog - Poll dev state
694 * @ha: Pointer to host adapter structure.
695 *
696 * Context: Interrupt
697 **/
698void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
699{
700 uint32_t dev_state;
701
702 dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
703
704 /* don't poll if reset is going on */
Lalit Chandivaded56a1f72010-12-02 22:12:45 -0800705 if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
706 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
707 test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags))) {
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530708 if (dev_state == QLA82XX_DEV_NEED_RESET &&
709 !test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
Vikas Chaudhary3930b8c2010-12-02 22:12:47 -0800710 if (!ql4xdontresethba) {
711 ql4_printk(KERN_INFO, ha, "%s: HW State: "
712 "NEED RESET!\n", __func__);
713 set_bit(DPC_RESET_HA, &ha->dpc_flags);
714 qla4xxx_wake_dpc(ha);
715 qla4xxx_mailbox_premature_completion(ha);
716 }
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530717 } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
718 !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {
Vikas Chaudhary3930b8c2010-12-02 22:12:47 -0800719 ql4_printk(KERN_INFO, ha, "%s: HW State: NEED QUIES!\n",
720 __func__);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530721 set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags);
722 qla4xxx_wake_dpc(ha);
723 } else {
724 /* Check firmware health */
725 qla4_8xxx_check_fw_alive(ha);
726 }
727 }
728}
729
730/**
David Somayajuluafaf5a22006-09-19 10:28:00 -0700731 * qla4xxx_timer - checks every second for work to do.
732 * @ha: Pointer to host adapter structure.
733 **/
734static void qla4xxx_timer(struct scsi_qla_host *ha)
735{
736 struct ddb_entry *ddb_entry, *dtemp;
737 int start_dpc = 0;
Lalit Chandivade2232be02010-07-30 14:38:47 +0530738 uint16_t w;
739
740 /* If we are in the middle of AER/EEH processing
741 * skip any processing and reschedule the timer
742 */
743 if (test_bit(AF_EEH_BUSY, &ha->flags)) {
744 mod_timer(&ha->timer, jiffies + HZ);
745 return;
746 }
747
748 /* Hardware read to trigger an EEH error during mailbox waits. */
749 if (!pci_channel_offline(ha->pdev))
750 pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700751
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530752 if (is_qla8022(ha)) {
753 qla4_8xxx_watchdog(ha);
754 }
755
David Somayajuluafaf5a22006-09-19 10:28:00 -0700756 /* Search for relogin's to time-out and port down retry. */
757 list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
758 /* Count down time between sending relogins */
759 if (adapter_up(ha) &&
760 !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
761 atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
762 if (atomic_read(&ddb_entry->retry_relogin_timer) !=
763 INVALID_ENTRY) {
764 if (atomic_read(&ddb_entry->retry_relogin_timer)
765 == 0) {
766 atomic_set(&ddb_entry->
767 retry_relogin_timer,
768 INVALID_ENTRY);
769 set_bit(DPC_RELOGIN_DEVICE,
770 &ha->dpc_flags);
771 set_bit(DF_RELOGIN, &ddb_entry->flags);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530772 DEBUG2(printk("scsi%ld: %s: ddb [%d]"
David Somayajuluafaf5a22006-09-19 10:28:00 -0700773 " login device\n",
774 ha->host_no, __func__,
775 ddb_entry->fw_ddb_index));
776 } else
777 atomic_dec(&ddb_entry->
778 retry_relogin_timer);
779 }
780 }
781
782 /* Wait for relogin to timeout */
783 if (atomic_read(&ddb_entry->relogin_timer) &&
784 (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) {
785 /*
786 * If the relogin times out and the device is
787 * still NOT ONLINE then try and relogin again.
788 */
789 if (atomic_read(&ddb_entry->state) !=
790 DDB_STATE_ONLINE &&
791 ddb_entry->fw_ddb_device_state ==
792 DDB_DS_SESSION_FAILED) {
793 /* Reset retry relogin timer */
794 atomic_inc(&ddb_entry->relogin_retry_count);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530795 DEBUG2(printk("scsi%ld: ddb [%d] relogin"
David Somayajuluafaf5a22006-09-19 10:28:00 -0700796 " timed out-retrying"
797 " relogin (%d)\n",
798 ha->host_no,
799 ddb_entry->fw_ddb_index,
800 atomic_read(&ddb_entry->
801 relogin_retry_count))
802 );
803 start_dpc++;
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530804 DEBUG(printk("scsi%ld:%d:%d: ddb [%d] "
Justin P. Mattockcd09b2c2011-01-28 11:49:08 -0800805 "initiate relogin after"
David Somayajuluafaf5a22006-09-19 10:28:00 -0700806 " %d seconds\n",
807 ha->host_no, ddb_entry->bus,
808 ddb_entry->target,
809 ddb_entry->fw_ddb_index,
810 ddb_entry->default_time2wait + 4)
811 );
812
813 atomic_set(&ddb_entry->retry_relogin_timer,
814 ddb_entry->default_time2wait + 4);
815 }
816 }
817 }
818
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530819 if (!is_qla8022(ha)) {
820 /* Check for heartbeat interval. */
821 if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE &&
822 ha->heartbeat_interval != 0) {
823 ha->seconds_since_last_heartbeat++;
824 if (ha->seconds_since_last_heartbeat >
825 ha->heartbeat_interval + 2)
826 set_bit(DPC_RESET_HA, &ha->dpc_flags);
827 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700828 }
829
David Somayajuluafaf5a22006-09-19 10:28:00 -0700830 /* Wakeup the dpc routine for this adapter, if needed. */
831 if ((start_dpc ||
832 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
833 test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) ||
834 test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) ||
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530835 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||
David Somayajuluafaf5a22006-09-19 10:28:00 -0700836 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
837 test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +0530838 test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) ||
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530839 test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||
840 test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||
David Somayajuluafaf5a22006-09-19 10:28:00 -0700841 test_bit(DPC_AEN, &ha->dpc_flags)) &&
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530842 !test_bit(AF_DPC_SCHEDULED, &ha->flags) &&
David Somayajuluafaf5a22006-09-19 10:28:00 -0700843 ha->dpc_thread) {
844 DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
845 " - dpc flags = 0x%lx\n",
846 ha->host_no, __func__, ha->dpc_flags));
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530847 qla4xxx_wake_dpc(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700848 }
849
850 /* Reschedule timer thread to call us back in one second */
851 mod_timer(&ha->timer, jiffies + HZ);
852
853 DEBUG2(ha->seconds_since_last_intr++);
854}
855
856/**
857 * qla4xxx_cmd_wait - waits for all outstanding commands to complete
858 * @ha: Pointer to host adapter structure.
859 *
860 * This routine stalls the driver until all outstanding commands are returned.
861 * Caller must release the Hardware Lock prior to calling this routine.
862 **/
863static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
864{
865 uint32_t index = 0;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700866 unsigned long flags;
867 struct scsi_cmnd *cmd;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700868
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530869 unsigned long wtime = jiffies + (WAIT_CMD_TOV * HZ);
870
871 DEBUG2(ql4_printk(KERN_INFO, ha, "Wait up to %d seconds for cmds to "
872 "complete\n", WAIT_CMD_TOV));
873
874 while (!time_after_eq(jiffies, wtime)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -0700875 spin_lock_irqsave(&ha->hardware_lock, flags);
876 /* Find a command that hasn't completed. */
877 for (index = 0; index < ha->host->can_queue; index++) {
878 cmd = scsi_host_find_tag(ha->host, index);
Mike Christiea1e00632010-10-26 05:45:30 -0700879 /*
880 * We cannot just check if the index is valid,
881 * becase if we are run from the scsi eh, then
882 * the scsi/block layer is going to prevent
883 * the tag from being released.
884 */
885 if (cmd != NULL && CMD_SP(cmd))
David Somayajuluafaf5a22006-09-19 10:28:00 -0700886 break;
887 }
888 spin_unlock_irqrestore(&ha->hardware_lock, flags);
889
890 /* If No Commands are pending, wait is complete */
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530891 if (index == ha->host->can_queue)
892 return QLA_SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700893
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530894 msleep(1000);
895 }
896 /* If we timed out on waiting for commands to come back
897 * return ERROR. */
898 return QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700899}
900
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530901int qla4xxx_hw_reset(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700902{
David Somayajuluafaf5a22006-09-19 10:28:00 -0700903 uint32_t ctrl_status;
David C Somayajulu477ffb92007-01-22 12:26:11 -0800904 unsigned long flags = 0;
905
906 DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));
David Somayajuluafaf5a22006-09-19 10:28:00 -0700907
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530908 if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS)
909 return QLA_ERROR;
910
David Somayajuluafaf5a22006-09-19 10:28:00 -0700911 spin_lock_irqsave(&ha->hardware_lock, flags);
912
913 /*
914 * If the SCSI Reset Interrupt bit is set, clear it.
915 * Otherwise, the Soft Reset won't work.
916 */
917 ctrl_status = readw(&ha->reg->ctrl_status);
918 if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0)
919 writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);
920
921 /* Issue Soft Reset */
922 writel(set_rmask(CSR_SOFT_RESET), &ha->reg->ctrl_status);
923 readl(&ha->reg->ctrl_status);
924
925 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +0530926 return QLA_SUCCESS;
David C Somayajulu477ffb92007-01-22 12:26:11 -0800927}
928
929/**
930 * qla4xxx_soft_reset - performs soft reset.
931 * @ha: Pointer to host adapter structure.
932 **/
933int qla4xxx_soft_reset(struct scsi_qla_host *ha)
934{
935 uint32_t max_wait_time;
936 unsigned long flags = 0;
Vikas Chaudharyf931c532010-10-06 22:48:07 -0700937 int status;
David C Somayajulu477ffb92007-01-22 12:26:11 -0800938 uint32_t ctrl_status;
939
Vikas Chaudharyf931c532010-10-06 22:48:07 -0700940 status = qla4xxx_hw_reset(ha);
941 if (status != QLA_SUCCESS)
942 return status;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700943
Vikas Chaudharyf931c532010-10-06 22:48:07 -0700944 status = QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700945 /* Wait until the Network Reset Intr bit is cleared */
946 max_wait_time = RESET_INTR_TOV;
947 do {
948 spin_lock_irqsave(&ha->hardware_lock, flags);
949 ctrl_status = readw(&ha->reg->ctrl_status);
950 spin_unlock_irqrestore(&ha->hardware_lock, flags);
951
952 if ((ctrl_status & CSR_NET_RESET_INTR) == 0)
953 break;
954
955 msleep(1000);
956 } while ((--max_wait_time));
957
958 if ((ctrl_status & CSR_NET_RESET_INTR) != 0) {
959 DEBUG2(printk(KERN_WARNING
960 "scsi%ld: Network Reset Intr not cleared by "
961 "Network function, clearing it now!\n",
962 ha->host_no));
963 spin_lock_irqsave(&ha->hardware_lock, flags);
964 writel(set_rmask(CSR_NET_RESET_INTR), &ha->reg->ctrl_status);
965 readl(&ha->reg->ctrl_status);
966 spin_unlock_irqrestore(&ha->hardware_lock, flags);
967 }
968
969 /* Wait until the firmware tells us the Soft Reset is done */
970 max_wait_time = SOFT_RESET_TOV;
971 do {
972 spin_lock_irqsave(&ha->hardware_lock, flags);
973 ctrl_status = readw(&ha->reg->ctrl_status);
974 spin_unlock_irqrestore(&ha->hardware_lock, flags);
975
976 if ((ctrl_status & CSR_SOFT_RESET) == 0) {
977 status = QLA_SUCCESS;
978 break;
979 }
980
981 msleep(1000);
982 } while ((--max_wait_time));
983
984 /*
985 * Also, make sure that the SCSI Reset Interrupt bit has been cleared
986 * after the soft reset has taken place.
987 */
988 spin_lock_irqsave(&ha->hardware_lock, flags);
989 ctrl_status = readw(&ha->reg->ctrl_status);
990 if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0) {
991 writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);
992 readl(&ha->reg->ctrl_status);
993 }
994 spin_unlock_irqrestore(&ha->hardware_lock, flags);
995
996 /* If soft reset fails then most probably the bios on other
997 * function is also enabled.
998 * Since the initialization is sequential the other fn
999 * wont be able to acknowledge the soft reset.
1000 * Issue a force soft reset to workaround this scenario.
1001 */
1002 if (max_wait_time == 0) {
1003 /* Issue Force Soft Reset */
1004 spin_lock_irqsave(&ha->hardware_lock, flags);
1005 writel(set_rmask(CSR_FORCE_SOFT_RESET), &ha->reg->ctrl_status);
1006 readl(&ha->reg->ctrl_status);
1007 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1008 /* Wait until the firmware tells us the Soft Reset is done */
1009 max_wait_time = SOFT_RESET_TOV;
1010 do {
1011 spin_lock_irqsave(&ha->hardware_lock, flags);
1012 ctrl_status = readw(&ha->reg->ctrl_status);
1013 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1014
1015 if ((ctrl_status & CSR_FORCE_SOFT_RESET) == 0) {
1016 status = QLA_SUCCESS;
1017 break;
1018 }
1019
1020 msleep(1000);
1021 } while ((--max_wait_time));
1022 }
1023
1024 return status;
1025}
1026
1027/**
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301028 * qla4xxx_abort_active_cmds - returns all outstanding i/o requests to O.S.
David Somayajuluafaf5a22006-09-19 10:28:00 -07001029 * @ha: Pointer to host adapter structure.
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301030 * @res: returned scsi status
David Somayajuluafaf5a22006-09-19 10:28:00 -07001031 *
1032 * This routine is called just prior to a HARD RESET to return all
1033 * outstanding commands back to the Operating System.
1034 * Caller should make sure that the following locks are released
1035 * before this calling routine: Hardware lock, and io_request_lock.
1036 **/
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301037static void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001038{
1039 struct srb *srb;
1040 int i;
1041 unsigned long flags;
1042
1043 spin_lock_irqsave(&ha->hardware_lock, flags);
1044 for (i = 0; i < ha->host->can_queue; i++) {
1045 srb = qla4xxx_del_from_active_array(ha, i);
1046 if (srb != NULL) {
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301047 srb->cmd->result = res;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05301048 kref_put(&srb->srb_ref, qla4xxx_srb_compl);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001049 }
1050 }
1051 spin_unlock_irqrestore(&ha->hardware_lock, flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001052}
1053
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301054void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha)
1055{
1056 clear_bit(AF_ONLINE, &ha->flags);
1057
1058 /* Disable the board */
1059 ql4_printk(KERN_INFO, ha, "Disabling the board\n");
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301060
1061 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
1062 qla4xxx_mark_all_devices_missing(ha);
1063 clear_bit(AF_INIT_DONE, &ha->flags);
1064}
1065
David Somayajuluafaf5a22006-09-19 10:28:00 -07001066/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07001067 * qla4xxx_recover_adapter - recovers adapter after a fatal error
1068 * @ha: Pointer to host adapter structure.
David Somayajuluafaf5a22006-09-19 10:28:00 -07001069 **/
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301070static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001071{
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301072 int status = QLA_ERROR;
1073 uint8_t reset_chip = 0;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001074
1075 /* Stall incoming I/O until we are done */
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301076 scsi_block_requests(ha->host);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001077 clear_bit(AF_ONLINE, &ha->flags);
Mike Christie50a29ae2008-03-04 13:26:53 -06001078
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301079 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__));
David Somayajuluafaf5a22006-09-19 10:28:00 -07001080
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301081 set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001082
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301083 if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
1084 reset_chip = 1;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001085
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301086 /* For the DPC_RESET_HA_INTR case (ISP-4xxx specific)
1087 * do not reset adapter, jump to initialize_adapter */
1088 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
1089 status = QLA_SUCCESS;
1090 goto recover_ha_init_adapter;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001091 }
1092
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301093 /* For the ISP-82xx adapter, issue a stop_firmware if invoked
1094 * from eh_host_reset or ioctl module */
1095 if (is_qla8022(ha) && !reset_chip &&
1096 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) {
1097
1098 DEBUG2(ql4_printk(KERN_INFO, ha,
1099 "scsi%ld: %s - Performing stop_firmware...\n",
1100 ha->host_no, __func__));
1101 status = ha->isp_ops->reset_firmware(ha);
1102 if (status == QLA_SUCCESS) {
Nilesh Javali2bd1e2b2010-10-06 22:49:20 -07001103 if (!test_bit(AF_FW_RECOVERY, &ha->flags))
1104 qla4xxx_cmd_wait(ha);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301105 ha->isp_ops->disable_intrs(ha);
1106 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
1107 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
1108 } else {
1109 /* If the stop_firmware fails then
1110 * reset the entire chip */
1111 reset_chip = 1;
1112 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
1113 set_bit(DPC_RESET_HA, &ha->dpc_flags);
1114 }
1115 }
1116
1117 /* Issue full chip reset if recovering from a catastrophic error,
1118 * or if stop_firmware fails for ISP-82xx.
1119 * This is the default case for ISP-4xxx */
1120 if (!is_qla8022(ha) || reset_chip) {
Nilesh Javali2bd1e2b2010-10-06 22:49:20 -07001121 if (!test_bit(AF_FW_RECOVERY, &ha->flags))
1122 qla4xxx_cmd_wait(ha);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301123 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
1124 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
1125 DEBUG2(ql4_printk(KERN_INFO, ha,
1126 "scsi%ld: %s - Performing chip reset..\n",
1127 ha->host_no, __func__));
1128 status = ha->isp_ops->reset_chip(ha);
1129 }
1130
1131 /* Flush any pending ddb changed AENs */
1132 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
1133
1134recover_ha_init_adapter:
1135 /* Upon successful firmware/chip reset, re-initialize the adapter */
1136 if (status == QLA_SUCCESS) {
1137 /* For ISP-4xxx, force function 1 to always initialize
1138 * before function 3 to prevent both funcions from
1139 * stepping on top of the other */
1140 if (!is_qla8022(ha) && (ha->mac_index == 3))
1141 ssleep(6);
1142
1143 /* NOTE: AF_ONLINE flag set upon successful completion of
1144 * qla4xxx_initialize_adapter */
1145 status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST);
1146 }
1147
1148 /* Retry failed adapter initialization, if necessary
1149 * Do not retry initialize_adapter for RESET_HA_INTR (ISP-4xxx specific)
1150 * case to prevent ping-pong resets between functions */
1151 if (!test_bit(AF_ONLINE, &ha->flags) &&
1152 !test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07001153 /* Adapter initialization failed, see if we can retry
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301154 * resetting the ha.
1155 * Since we don't want to block the DPC for too long
1156 * with multiple resets in the same thread,
1157 * utilize DPC to retry */
David Somayajuluafaf5a22006-09-19 10:28:00 -07001158 if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) {
1159 ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES;
1160 DEBUG2(printk("scsi%ld: recover adapter - retrying "
1161 "(%d) more times\n", ha->host_no,
1162 ha->retry_reset_ha_cnt));
1163 set_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
1164 status = QLA_ERROR;
1165 } else {
1166 if (ha->retry_reset_ha_cnt > 0) {
1167 /* Schedule another Reset HA--DPC will retry */
1168 ha->retry_reset_ha_cnt--;
1169 DEBUG2(printk("scsi%ld: recover adapter - "
1170 "retry remaining %d\n",
1171 ha->host_no,
1172 ha->retry_reset_ha_cnt));
1173 status = QLA_ERROR;
1174 }
1175
1176 if (ha->retry_reset_ha_cnt == 0) {
1177 /* Recover adapter retries have been exhausted.
1178 * Adapter DEAD */
1179 DEBUG2(printk("scsi%ld: recover adapter "
1180 "failed - board disabled\n",
1181 ha->host_no));
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301182 qla4xxx_dead_adapter_cleanup(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001183 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
1184 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301185 clear_bit(DPC_RESET_HA_FW_CONTEXT,
David Somayajuluafaf5a22006-09-19 10:28:00 -07001186 &ha->dpc_flags);
1187 status = QLA_ERROR;
1188 }
1189 }
1190 } else {
1191 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301192 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001193 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
1194 }
1195
1196 ha->adapter_error_count++;
1197
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301198 if (test_bit(AF_ONLINE, &ha->flags))
1199 ha->isp_ops->enable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001200
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301201 scsi_unblock_requests(ha->host);
1202
1203 clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
1204 DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no,
1205 status == QLA_ERROR ? "FAILED" : "SUCCEDED"));
1206
David Somayajuluafaf5a22006-09-19 10:28:00 -07001207 return status;
1208}
1209
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301210void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
1211{
1212 if (ha->dpc_thread &&
1213 !test_bit(AF_DPC_SCHEDULED, &ha->flags)) {
1214 set_bit(AF_DPC_SCHEDULED, &ha->flags);
1215 queue_work(ha->dpc_thread, &ha->dpc_work);
1216 }
1217}
1218
David Somayajuluafaf5a22006-09-19 10:28:00 -07001219/**
1220 * qla4xxx_do_dpc - dpc routine
1221 * @data: in our case pointer to adapter structure
1222 *
1223 * This routine is a task that is schedule by the interrupt handler
1224 * to perform the background processing for interrupts. We put it
1225 * on a task queue that is consumed whenever the scheduler runs; that's
1226 * so you can do anything (i.e. put the process to sleep etc). In fact,
1227 * the mid-level tries to sleep when it reaches the driver threshold
1228 * "host->can_queue". This can cause a panic if we were in our interrupt code.
1229 **/
David Howellsc4028952006-11-22 14:57:56 +00001230static void qla4xxx_do_dpc(struct work_struct *work)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001231{
David Howellsc4028952006-11-22 14:57:56 +00001232 struct scsi_qla_host *ha =
1233 container_of(work, struct scsi_qla_host, dpc_work);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001234 struct ddb_entry *ddb_entry, *dtemp;
David C Somayajulu477ffb92007-01-22 12:26:11 -08001235 int status = QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001236
David C Somayajuluf26b9042006-11-15 16:41:09 -08001237 DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301238 "flags = 0x%08lx, dpc_flags = 0x%08lx\n",
1239 ha->host_no, __func__, ha->flags, ha->dpc_flags))
David Somayajuluafaf5a22006-09-19 10:28:00 -07001240
1241 /* Initialization not yet finished. Don't do anything yet. */
1242 if (!test_bit(AF_INIT_DONE, &ha->flags))
Vikas Chaudhary0753b482010-07-30 14:27:19 +05301243 goto do_dpc_exit;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001244
Lalit Chandivade2232be02010-07-30 14:38:47 +05301245 if (test_bit(AF_EEH_BUSY, &ha->flags)) {
1246 DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n",
1247 ha->host_no, __func__, ha->flags));
1248 goto do_dpc_exit;
1249 }
1250
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301251 if (is_qla8022(ha)) {
1252 if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
1253 qla4_8xxx_idc_lock(ha);
1254 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
1255 QLA82XX_DEV_FAILED);
1256 qla4_8xxx_idc_unlock(ha);
1257 ql4_printk(KERN_INFO, ha, "HW State: FAILED\n");
1258 qla4_8xxx_device_state_handler(ha);
1259 }
1260 if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {
1261 qla4_8xxx_need_qsnt_handler(ha);
1262 }
1263 }
1264
1265 if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) &&
1266 (test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
David Somayajuluafaf5a22006-09-19 10:28:00 -07001267 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301268 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) {
1269 if (ql4xdontresethba) {
1270 DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
1271 ha->host_no, __func__));
1272 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
1273 clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
1274 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
1275 goto dpc_post_reset_ha;
1276 }
1277 if (test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||
1278 test_bit(DPC_RESET_HA, &ha->dpc_flags))
1279 qla4xxx_recover_adapter(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001280
David C Somayajulu477ffb92007-01-22 12:26:11 -08001281 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07001282 uint8_t wait_time = RESET_INTR_TOV;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001283
David Somayajuluafaf5a22006-09-19 10:28:00 -07001284 while ((readw(&ha->reg->ctrl_status) &
1285 (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
1286 if (--wait_time == 0)
1287 break;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001288 msleep(1000);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001289 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07001290 if (wait_time == 0)
1291 DEBUG2(printk("scsi%ld: %s: SR|FSR "
1292 "bit not cleared-- resetting\n",
1293 ha->host_no, __func__));
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301294 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
David C Somayajulu477ffb92007-01-22 12:26:11 -08001295 if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {
1296 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301297 status = qla4xxx_recover_adapter(ha);
David C Somayajulu477ffb92007-01-22 12:26:11 -08001298 }
1299 clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
1300 if (status == QLA_SUCCESS)
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301301 ha->isp_ops->enable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001302 }
1303 }
1304
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301305dpc_post_reset_ha:
David Somayajuluafaf5a22006-09-19 10:28:00 -07001306 /* ---- process AEN? --- */
1307 if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
1308 qla4xxx_process_aen(ha, PROCESS_ALL_AENS);
1309
1310 /* ---- Get DHCP IP Address? --- */
1311 if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
1312 qla4xxx_get_dhcp_ip_address(ha);
1313
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05301314 /* ---- link change? --- */
1315 if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
1316 if (!test_bit(AF_LINK_UP, &ha->flags)) {
1317 /* ---- link down? --- */
1318 list_for_each_entry_safe(ddb_entry, dtemp,
1319 &ha->ddb_list, list) {
1320 if (atomic_read(&ddb_entry->state) ==
1321 DDB_STATE_ONLINE)
1322 qla4xxx_mark_device_missing(ha,
1323 ddb_entry);
1324 }
1325 } else {
1326 /* ---- link up? --- *
1327 * F/W will auto login to all devices ONLY ONCE after
1328 * link up during driver initialization and runtime
1329 * fatal error recovery. Therefore, the driver must
1330 * manually relogin to devices when recovering from
1331 * connection failures, logouts, expired KATO, etc. */
1332
1333 list_for_each_entry_safe(ddb_entry, dtemp,
1334 &ha->ddb_list, list) {
1335 if ((atomic_read(&ddb_entry->state) ==
1336 DDB_STATE_MISSING) ||
1337 (atomic_read(&ddb_entry->state) ==
1338 DDB_STATE_DEAD)) {
1339 if (ddb_entry->fw_ddb_device_state ==
1340 DDB_DS_SESSION_ACTIVE) {
1341 atomic_set(&ddb_entry->state,
1342 DDB_STATE_ONLINE);
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301343 ql4_printk(KERN_INFO, ha,
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05301344 "scsi%ld: %s: ddb[%d]"
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301345 " marked ONLINE\n",
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05301346 ha->host_no, __func__,
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301347 ddb_entry->fw_ddb_index);
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05301348
1349 iscsi_unblock_session(
1350 ddb_entry->sess);
1351 } else
1352 qla4xxx_relogin_device(
1353 ha, ddb_entry);
1354 }
1355
1356 }
1357 }
1358 }
1359
David Somayajuluafaf5a22006-09-19 10:28:00 -07001360 /* ---- relogin device? --- */
1361 if (adapter_up(ha) &&
1362 test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
1363 list_for_each_entry_safe(ddb_entry, dtemp,
1364 &ha->ddb_list, list) {
1365 if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) &&
1366 atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
1367 qla4xxx_relogin_device(ha, ddb_entry);
1368
1369 /*
1370 * If mbx cmd times out there is no point
1371 * in continuing further.
1372 * With large no of targets this can hang
1373 * the system.
1374 */
1375 if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
1376 printk(KERN_WARNING "scsi%ld: %s: "
1377 "need to reset hba\n",
1378 ha->host_no, __func__);
1379 break;
1380 }
1381 }
1382 }
Vikas Chaudhary0753b482010-07-30 14:27:19 +05301383
1384do_dpc_exit:
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301385 clear_bit(AF_DPC_SCHEDULED, &ha->flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001386}
1387
1388/**
1389 * qla4xxx_free_adapter - release the adapter
1390 * @ha: pointer to adapter structure
1391 **/
1392static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
1393{
1394
1395 if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) {
1396 /* Turn-off interrupts on the card. */
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301397 ha->isp_ops->disable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001398 }
1399
David Somayajuluafaf5a22006-09-19 10:28:00 -07001400 /* Remove timer thread, if present */
1401 if (ha->timer_active)
1402 qla4xxx_stop_timer(ha);
1403
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301404 /* Kill the kernel thread for this host */
1405 if (ha->dpc_thread)
1406 destroy_workqueue(ha->dpc_thread);
1407
1408 /* Put firmware in known state */
1409 ha->isp_ops->reset_firmware(ha);
1410
1411 if (is_qla8022(ha)) {
1412 qla4_8xxx_idc_lock(ha);
1413 qla4_8xxx_clear_drv_active(ha);
1414 qla4_8xxx_idc_unlock(ha);
1415 }
1416
David Somayajuluafaf5a22006-09-19 10:28:00 -07001417 /* Detach interrupts */
1418 if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301419 qla4xxx_free_irqs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001420
David C Somayajulubee4fe82007-05-23 18:03:32 -07001421 /* free extra memory */
1422 qla4xxx_mem_free(ha);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301423}
David C Somayajulubee4fe82007-05-23 18:03:32 -07001424
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301425int qla4_8xxx_iospace_config(struct scsi_qla_host *ha)
1426{
1427 int status = 0;
1428 uint8_t revision_id;
1429 unsigned long mem_base, mem_len, db_base, db_len;
1430 struct pci_dev *pdev = ha->pdev;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001431
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301432 status = pci_request_regions(pdev, DRIVER_NAME);
1433 if (status) {
1434 printk(KERN_WARNING
1435 "scsi(%ld) Failed to reserve PIO regions (%s) "
1436 "status=%d\n", ha->host_no, pci_name(pdev), status);
1437 goto iospace_error_exit;
1438 }
1439
1440 pci_read_config_byte(pdev, PCI_REVISION_ID, &revision_id);
1441 DEBUG2(printk(KERN_INFO "%s: revision-id=%d\n",
1442 __func__, revision_id));
1443 ha->revision_id = revision_id;
1444
1445 /* remap phys address */
1446 mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
1447 mem_len = pci_resource_len(pdev, 0);
1448 DEBUG2(printk(KERN_INFO "%s: ioremap from %lx a size of %lx\n",
1449 __func__, mem_base, mem_len));
1450
1451 /* mapping of pcibase pointer */
1452 ha->nx_pcibase = (unsigned long)ioremap(mem_base, mem_len);
1453 if (!ha->nx_pcibase) {
1454 printk(KERN_ERR
1455 "cannot remap MMIO (%s), aborting\n", pci_name(pdev));
1456 pci_release_regions(ha->pdev);
1457 goto iospace_error_exit;
1458 }
1459
1460 /* Mapping of IO base pointer, door bell read and write pointer */
1461
1462 /* mapping of IO base pointer */
1463 ha->qla4_8xxx_reg =
1464 (struct device_reg_82xx __iomem *)((uint8_t *)ha->nx_pcibase +
1465 0xbc000 + (ha->pdev->devfn << 11));
1466
1467 db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */
1468 db_len = pci_resource_len(pdev, 4);
1469
Shyam Sundar2657c802010-10-06 22:50:29 -07001470 ha->nx_db_wr_ptr = (ha->pdev->devfn == 4 ? QLA82XX_CAM_RAM_DB1 :
1471 QLA82XX_CAM_RAM_DB2);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301472
Shyam Sundar2657c802010-10-06 22:50:29 -07001473 return 0;
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301474iospace_error_exit:
1475 return -ENOMEM;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001476}
1477
1478/***
1479 * qla4xxx_iospace_config - maps registers
1480 * @ha: pointer to adapter structure
1481 *
1482 * This routines maps HBA's registers from the pci address space
1483 * into the kernel virtual address space for memory mapped i/o.
1484 **/
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301485int qla4xxx_iospace_config(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001486{
1487 unsigned long pio, pio_len, pio_flags;
1488 unsigned long mmio, mmio_len, mmio_flags;
1489
1490 pio = pci_resource_start(ha->pdev, 0);
1491 pio_len = pci_resource_len(ha->pdev, 0);
1492 pio_flags = pci_resource_flags(ha->pdev, 0);
1493 if (pio_flags & IORESOURCE_IO) {
1494 if (pio_len < MIN_IOBASE_LEN) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301495 ql4_printk(KERN_WARNING, ha,
David Somayajuluafaf5a22006-09-19 10:28:00 -07001496 "Invalid PCI I/O region size\n");
1497 pio = 0;
1498 }
1499 } else {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301500 ql4_printk(KERN_WARNING, ha, "region #0 not a PIO resource\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001501 pio = 0;
1502 }
1503
1504 /* Use MMIO operations for all accesses. */
1505 mmio = pci_resource_start(ha->pdev, 1);
1506 mmio_len = pci_resource_len(ha->pdev, 1);
1507 mmio_flags = pci_resource_flags(ha->pdev, 1);
1508
1509 if (!(mmio_flags & IORESOURCE_MEM)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301510 ql4_printk(KERN_ERR, ha,
1511 "region #0 not an MMIO resource, aborting\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001512
1513 goto iospace_error_exit;
1514 }
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301515
David Somayajuluafaf5a22006-09-19 10:28:00 -07001516 if (mmio_len < MIN_IOBASE_LEN) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301517 ql4_printk(KERN_ERR, ha,
1518 "Invalid PCI mem region size, aborting\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001519 goto iospace_error_exit;
1520 }
1521
1522 if (pci_request_regions(ha->pdev, DRIVER_NAME)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301523 ql4_printk(KERN_WARNING, ha,
1524 "Failed to reserve PIO/MMIO regions\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001525
1526 goto iospace_error_exit;
1527 }
1528
1529 ha->pio_address = pio;
1530 ha->pio_length = pio_len;
1531 ha->reg = ioremap(mmio, MIN_IOBASE_LEN);
1532 if (!ha->reg) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301533 ql4_printk(KERN_ERR, ha,
1534 "cannot remap MMIO, aborting\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001535
1536 goto iospace_error_exit;
1537 }
1538
1539 return 0;
1540
1541iospace_error_exit:
1542 return -ENOMEM;
1543}
1544
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301545static struct isp_operations qla4xxx_isp_ops = {
1546 .iospace_config = qla4xxx_iospace_config,
1547 .pci_config = qla4xxx_pci_config,
1548 .disable_intrs = qla4xxx_disable_intrs,
1549 .enable_intrs = qla4xxx_enable_intrs,
1550 .start_firmware = qla4xxx_start_firmware,
1551 .intr_handler = qla4xxx_intr_handler,
1552 .interrupt_service_routine = qla4xxx_interrupt_service_routine,
1553 .reset_chip = qla4xxx_soft_reset,
1554 .reset_firmware = qla4xxx_hw_reset,
1555 .queue_iocb = qla4xxx_queue_iocb,
1556 .complete_iocb = qla4xxx_complete_iocb,
1557 .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out,
1558 .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in,
1559 .get_sys_info = qla4xxx_get_sys_info,
1560};
1561
1562static struct isp_operations qla4_8xxx_isp_ops = {
1563 .iospace_config = qla4_8xxx_iospace_config,
1564 .pci_config = qla4_8xxx_pci_config,
1565 .disable_intrs = qla4_8xxx_disable_intrs,
1566 .enable_intrs = qla4_8xxx_enable_intrs,
1567 .start_firmware = qla4_8xxx_load_risc,
1568 .intr_handler = qla4_8xxx_intr_handler,
1569 .interrupt_service_routine = qla4_8xxx_interrupt_service_routine,
1570 .reset_chip = qla4_8xxx_isp_reset,
1571 .reset_firmware = qla4_8xxx_stop_firmware,
1572 .queue_iocb = qla4_8xxx_queue_iocb,
1573 .complete_iocb = qla4_8xxx_complete_iocb,
1574 .rd_shdw_req_q_out = qla4_8xxx_rd_shdw_req_q_out,
1575 .rd_shdw_rsp_q_in = qla4_8xxx_rd_shdw_rsp_q_in,
1576 .get_sys_info = qla4_8xxx_get_sys_info,
1577};
1578
1579uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
1580{
1581 return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out);
1582}
1583
1584uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
1585{
1586 return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->req_q_out));
1587}
1588
1589uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
1590{
1591 return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in);
1592}
1593
1594uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
1595{
1596 return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in));
1597}
1598
David Somayajuluafaf5a22006-09-19 10:28:00 -07001599/**
1600 * qla4xxx_probe_adapter - callback function to probe HBA
1601 * @pdev: pointer to pci_dev structure
1602 * @pci_device_id: pointer to pci_device entry
1603 *
1604 * This routine will probe for Qlogic 4xxx iSCSI host adapters.
1605 * It returns zero if successful. It also initializes all data necessary for
1606 * the driver.
1607 **/
1608static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
1609 const struct pci_device_id *ent)
1610{
1611 int ret = -ENODEV, status;
1612 struct Scsi_Host *host;
1613 struct scsi_qla_host *ha;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001614 uint8_t init_retry_count = 0;
1615 char buf[34];
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301616 struct qla4_8xxx_legacy_intr_set *nx_legacy_intr;
Prasanna Mumbaif9880e72011-03-21 03:34:26 -07001617 uint32_t dev_state;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001618
1619 if (pci_enable_device(pdev))
1620 return -1;
1621
1622 host = scsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha));
1623 if (host == NULL) {
1624 printk(KERN_WARNING
1625 "qla4xxx: Couldn't allocate host from scsi layer!\n");
1626 goto probe_disable_device;
1627 }
1628
1629 /* Clear our data area */
1630 ha = (struct scsi_qla_host *) host->hostdata;
1631 memset(ha, 0, sizeof(*ha));
1632
1633 /* Save the information from PCI BIOS. */
1634 ha->pdev = pdev;
1635 ha->host = host;
1636 ha->host_no = host->host_no;
1637
Lalit Chandivade2232be02010-07-30 14:38:47 +05301638 pci_enable_pcie_error_reporting(pdev);
1639
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301640 /* Setup Runtime configurable options */
1641 if (is_qla8022(ha)) {
1642 ha->isp_ops = &qla4_8xxx_isp_ops;
1643 rwlock_init(&ha->hw_lock);
1644 ha->qdr_sn_window = -1;
1645 ha->ddr_mn_window = -1;
1646 ha->curr_window = 255;
1647 ha->func_num = PCI_FUNC(ha->pdev->devfn);
1648 nx_legacy_intr = &legacy_intr[ha->func_num];
1649 ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;
1650 ha->nx_legacy_intr.tgt_status_reg =
1651 nx_legacy_intr->tgt_status_reg;
1652 ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;
1653 ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
1654 } else {
1655 ha->isp_ops = &qla4xxx_isp_ops;
1656 }
1657
Lalit Chandivade2232be02010-07-30 14:38:47 +05301658 /* Set EEH reset type to fundamental if required by hba */
1659 if (is_qla8022(ha))
1660 pdev->needs_freset = 1;
1661
David Somayajuluafaf5a22006-09-19 10:28:00 -07001662 /* Configure PCI I/O space. */
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301663 ret = ha->isp_ops->iospace_config(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001664 if (ret)
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301665 goto probe_failed_ioconfig;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001666
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301667 ql4_printk(KERN_INFO, ha, "Found an ISP%04x, irq %d, iobase 0x%p\n",
David Somayajuluafaf5a22006-09-19 10:28:00 -07001668 pdev->device, pdev->irq, ha->reg);
1669
1670 qla4xxx_config_dma_addressing(ha);
1671
1672 /* Initialize lists and spinlocks. */
1673 INIT_LIST_HEAD(&ha->ddb_list);
1674 INIT_LIST_HEAD(&ha->free_srb_q);
1675
1676 mutex_init(&ha->mbox_sem);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301677 init_completion(&ha->mbx_intr_comp);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001678
1679 spin_lock_init(&ha->hardware_lock);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001680
1681 /* Allocate dma buffers */
1682 if (qla4xxx_mem_alloc(ha)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301683 ql4_printk(KERN_WARNING, ha,
1684 "[ERROR] Failed to allocate memory for adapter\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001685
1686 ret = -ENOMEM;
1687 goto probe_failed;
1688 }
1689
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301690 if (is_qla8022(ha))
1691 (void) qla4_8xxx_get_flash_info(ha);
1692
David Somayajuluafaf5a22006-09-19 10:28:00 -07001693 /*
1694 * Initialize the Host adapter request/response queues and
1695 * firmware
1696 * NOTE: interrupts enabled upon successful completion
1697 */
1698 status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301699 while ((!test_bit(AF_ONLINE, &ha->flags)) &&
1700 init_retry_count++ < MAX_INIT_RETRIES) {
Prasanna Mumbaif9880e72011-03-21 03:34:26 -07001701
1702 if (is_qla8022(ha)) {
1703 qla4_8xxx_idc_lock(ha);
1704 dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
1705 qla4_8xxx_idc_unlock(ha);
1706 if (dev_state == QLA82XX_DEV_FAILED) {
1707 ql4_printk(KERN_WARNING, ha, "%s: don't retry "
1708 "initialize adapter. H/W is in failed state\n",
1709 __func__);
1710 break;
1711 }
1712 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07001713 DEBUG2(printk("scsi: %s: retrying adapter initialization "
1714 "(%d)\n", __func__, init_retry_count));
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301715
1716 if (ha->isp_ops->reset_chip(ha) == QLA_ERROR)
1717 continue;
1718
David Somayajuluafaf5a22006-09-19 10:28:00 -07001719 status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
1720 }
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301721
1722 if (!test_bit(AF_ONLINE, &ha->flags)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301723 ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001724
Lalit Chandivadefe998522010-12-02 22:12:36 -08001725 if (is_qla8022(ha) && ql4xdontresethba) {
1726 /* Put the device in failed state. */
1727 DEBUG2(printk(KERN_ERR "HW STATE: FAILED\n"));
1728 qla4_8xxx_idc_lock(ha);
1729 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
1730 QLA82XX_DEV_FAILED);
1731 qla4_8xxx_idc_unlock(ha);
1732 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07001733 ret = -ENODEV;
1734 goto probe_failed;
1735 }
1736
1737 host->cmd_per_lun = 3;
1738 host->max_channel = 0;
1739 host->max_lun = MAX_LUNS - 1;
1740 host->max_id = MAX_TARGETS;
1741 host->max_cmd_len = IOCB_MAX_CDB_LEN;
1742 host->can_queue = MAX_SRBS ;
1743 host->transportt = qla4xxx_scsi_transport;
1744
1745 ret = scsi_init_shared_tag_map(host, MAX_SRBS);
1746 if (ret) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301747 ql4_printk(KERN_WARNING, ha,
1748 "scsi_init_shared_tag_map failed\n");
1749 goto probe_failed;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001750 }
1751
1752 /* Startup the kernel thread for this host adapter. */
1753 DEBUG2(printk("scsi: %s: Starting kernel thread for "
1754 "qla4xxx_dpc\n", __func__));
1755 sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no);
1756 ha->dpc_thread = create_singlethread_workqueue(buf);
1757 if (!ha->dpc_thread) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301758 ql4_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001759 ret = -ENODEV;
1760 goto probe_failed;
1761 }
David Howellsc4028952006-11-22 14:57:56 +00001762 INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001763
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301764 /* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc
1765 * (which is called indirectly by qla4xxx_initialize_adapter),
1766 * so that irqs will be registered after crbinit but before
1767 * mbx_intr_enable.
1768 */
1769 if (!is_qla8022(ha)) {
1770 ret = qla4xxx_request_irqs(ha);
1771 if (ret) {
1772 ql4_printk(KERN_WARNING, ha, "Failed to reserve "
1773 "interrupt %d already in use.\n", pdev->irq);
1774 goto probe_failed;
1775 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07001776 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07001777
Lalit Chandivade2232be02010-07-30 14:38:47 +05301778 pci_save_state(ha->pdev);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301779 ha->isp_ops->enable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001780
1781 /* Start timer thread. */
1782 qla4xxx_start_timer(ha, qla4xxx_timer, 1);
1783
1784 set_bit(AF_INIT_DONE, &ha->flags);
1785
1786 pci_set_drvdata(pdev, ha);
1787
1788 ret = scsi_add_host(host, &pdev->dev);
1789 if (ret)
1790 goto probe_failed;
1791
David Somayajuluafaf5a22006-09-19 10:28:00 -07001792 printk(KERN_INFO
1793 " QLogic iSCSI HBA Driver version: %s\n"
1794 " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",
1795 qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),
1796 ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
1797 ha->patch_number, ha->build_number);
Mike Christie921601b2008-01-31 13:36:49 -06001798 scsi_scan_host(host);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001799 return 0;
1800
David Somayajuluafaf5a22006-09-19 10:28:00 -07001801probe_failed:
1802 qla4xxx_free_adapter(ha);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301803
1804probe_failed_ioconfig:
Lalit Chandivade2232be02010-07-30 14:38:47 +05301805 pci_disable_pcie_error_reporting(pdev);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001806 scsi_host_put(ha->host);
1807
1808probe_disable_device:
1809 pci_disable_device(pdev);
1810
1811 return ret;
1812}
1813
1814/**
Karen Higgins7eece5a2011-03-21 03:34:29 -07001815 * qla4xxx_prevent_other_port_reinit - prevent other port from re-initialize
1816 * @ha: pointer to adapter structure
1817 *
1818 * Mark the other ISP-4xxx port to indicate that the driver is being removed,
1819 * so that the other port will not re-initialize while in the process of
1820 * removing the ha due to driver unload or hba hotplug.
1821 **/
1822static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha)
1823{
1824 struct scsi_qla_host *other_ha = NULL;
1825 struct pci_dev *other_pdev = NULL;
1826 int fn = ISP4XXX_PCI_FN_2;
1827
1828 /*iscsi function numbers for ISP4xxx is 1 and 3*/
1829 if (PCI_FUNC(ha->pdev->devfn) & BIT_1)
1830 fn = ISP4XXX_PCI_FN_1;
1831
1832 other_pdev =
1833 pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
1834 ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
1835 fn));
1836
1837 /* Get other_ha if other_pdev is valid and state is enable*/
1838 if (other_pdev) {
1839 if (atomic_read(&other_pdev->enable_cnt)) {
1840 other_ha = pci_get_drvdata(other_pdev);
1841 if (other_ha) {
1842 set_bit(AF_HA_REMOVAL, &other_ha->flags);
1843 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: "
1844 "Prevent %s reinit\n", __func__,
1845 dev_name(&other_ha->pdev->dev)));
1846 }
1847 }
1848 pci_dev_put(other_pdev);
1849 }
1850}
1851
1852/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07001853 * qla4xxx_remove_adapter - calback function to remove adapter.
1854 * @pci_dev: PCI device pointer
1855 **/
1856static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
1857{
1858 struct scsi_qla_host *ha;
1859
1860 ha = pci_get_drvdata(pdev);
1861
Karen Higgins7eece5a2011-03-21 03:34:29 -07001862 if (!is_qla8022(ha))
1863 qla4xxx_prevent_other_port_reinit(ha);
David C Somayajulubee4fe82007-05-23 18:03:32 -07001864
David Somayajuluafaf5a22006-09-19 10:28:00 -07001865 /* remove devs from iscsi_sessions to scsi_devices */
1866 qla4xxx_free_ddb_list(ha);
1867
1868 scsi_remove_host(ha->host);
1869
1870 qla4xxx_free_adapter(ha);
1871
1872 scsi_host_put(ha->host);
1873
Lalit Chandivade2232be02010-07-30 14:38:47 +05301874 pci_disable_pcie_error_reporting(pdev);
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301875 pci_disable_device(pdev);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001876 pci_set_drvdata(pdev, NULL);
1877}
1878
1879/**
1880 * qla4xxx_config_dma_addressing() - Configure OS DMA addressing method.
1881 * @ha: HA context
1882 *
1883 * At exit, the @ha's flags.enable_64bit_addressing set to indicated
1884 * supported addressing method.
1885 */
Adrian Bunk47975472007-04-26 00:35:16 -07001886static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001887{
1888 int retval;
1889
1890 /* Update our PCI device dma_mask for full 64 bit mask */
Yang Hongyang6a355282009-04-06 19:01:13 -07001891 if (pci_set_dma_mask(ha->pdev, DMA_BIT_MASK(64)) == 0) {
1892 if (pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07001893 dev_dbg(&ha->pdev->dev,
1894 "Failed to set 64 bit PCI consistent mask; "
1895 "using 32 bit.\n");
1896 retval = pci_set_consistent_dma_mask(ha->pdev,
Yang Hongyang284901a2009-04-06 19:01:15 -07001897 DMA_BIT_MASK(32));
David Somayajuluafaf5a22006-09-19 10:28:00 -07001898 }
1899 } else
Yang Hongyang284901a2009-04-06 19:01:15 -07001900 retval = pci_set_dma_mask(ha->pdev, DMA_BIT_MASK(32));
David Somayajuluafaf5a22006-09-19 10:28:00 -07001901}
1902
1903static int qla4xxx_slave_alloc(struct scsi_device *sdev)
1904{
1905 struct iscsi_cls_session *sess = starget_to_session(sdev->sdev_target);
1906 struct ddb_entry *ddb = sess->dd_data;
1907
1908 sdev->hostdata = ddb;
1909 sdev->tagged_supported = 1;
Mike Christied510d962008-07-11 19:50:33 -05001910 scsi_activate_tcq(sdev, QL4_DEF_QDEPTH);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001911 return 0;
1912}
1913
1914static int qla4xxx_slave_configure(struct scsi_device *sdev)
1915{
1916 sdev->tagged_supported = 1;
1917 return 0;
1918}
1919
1920static void qla4xxx_slave_destroy(struct scsi_device *sdev)
1921{
1922 scsi_deactivate_tcq(sdev, 1);
1923}
1924
1925/**
1926 * qla4xxx_del_from_active_array - returns an active srb
1927 * @ha: Pointer to host adapter structure.
Anand Gadiyarfd589a82009-07-16 17:13:03 +02001928 * @index: index into the active_array
David Somayajuluafaf5a22006-09-19 10:28:00 -07001929 *
1930 * This routine removes and returns the srb at the specified index
1931 **/
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05301932struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
1933 uint32_t index)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001934{
1935 struct srb *srb = NULL;
Vikas Chaudhary53698872010-04-28 11:41:59 +05301936 struct scsi_cmnd *cmd = NULL;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001937
Vikas Chaudhary53698872010-04-28 11:41:59 +05301938 cmd = scsi_host_find_tag(ha->host, index);
1939 if (!cmd)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001940 return srb;
1941
Vikas Chaudhary53698872010-04-28 11:41:59 +05301942 srb = (struct srb *)CMD_SP(cmd);
1943 if (!srb)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001944 return srb;
1945
1946 /* update counters */
1947 if (srb->flags & SRB_DMA_VALID) {
1948 ha->req_q_count += srb->iocb_cnt;
1949 ha->iocb_cnt -= srb->iocb_cnt;
1950 if (srb->cmd)
Vikas Chaudhary53698872010-04-28 11:41:59 +05301951 srb->cmd->host_scribble =
1952 (unsigned char *)(unsigned long) MAX_SRBS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001953 }
1954 return srb;
1955}
1956
1957/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07001958 * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05301959 * @ha: Pointer to host adapter structure.
David Somayajuluafaf5a22006-09-19 10:28:00 -07001960 * @cmd: Scsi Command to wait on.
1961 *
1962 * This routine waits for the command to be returned by the Firmware
1963 * for some max time.
1964 **/
1965static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha,
1966 struct scsi_cmnd *cmd)
1967{
1968 int done = 0;
1969 struct srb *rp;
1970 uint32_t max_wait_time = EH_WAIT_CMD_TOV;
Lalit Chandivade2232be02010-07-30 14:38:47 +05301971 int ret = SUCCESS;
1972
1973 /* Dont wait on command if PCI error is being handled
1974 * by PCI AER driver
1975 */
1976 if (unlikely(pci_channel_offline(ha->pdev)) ||
1977 (test_bit(AF_EEH_BUSY, &ha->flags))) {
1978 ql4_printk(KERN_WARNING, ha, "scsi%ld: Return from %s\n",
1979 ha->host_no, __func__);
1980 return ret;
1981 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07001982
1983 do {
1984 /* Checking to see if its returned to OS */
Vikas Chaudhary53698872010-04-28 11:41:59 +05301985 rp = (struct srb *) CMD_SP(cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001986 if (rp == NULL) {
1987 done++;
1988 break;
1989 }
1990
1991 msleep(2000);
1992 } while (max_wait_time--);
1993
1994 return done;
1995}
1996
1997/**
1998 * qla4xxx_wait_for_hba_online - waits for HBA to come online
1999 * @ha: Pointer to host adapter structure
2000 **/
2001static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
2002{
2003 unsigned long wait_online;
2004
Vikas Chaudharyf581a3f2010-10-06 22:47:48 -07002005 wait_online = jiffies + (HBA_ONLINE_TOV * HZ);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002006 while (time_before(jiffies, wait_online)) {
2007
2008 if (adapter_up(ha))
2009 return QLA_SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002010
2011 msleep(2000);
2012 }
2013
2014 return QLA_ERROR;
2015}
2016
2017/**
Mike Christiece545032008-02-29 18:25:20 -06002018 * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
Anand Gadiyarfd589a82009-07-16 17:13:03 +02002019 * @ha: pointer to HBA
David Somayajuluafaf5a22006-09-19 10:28:00 -07002020 * @t: target id
2021 * @l: lun id
2022 *
2023 * This function waits for all outstanding commands to a lun to complete. It
2024 * returns 0 if all pending commands are returned and 1 otherwise.
2025 **/
Mike Christiece545032008-02-29 18:25:20 -06002026static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
2027 struct scsi_target *stgt,
2028 struct scsi_device *sdev)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002029{
2030 int cnt;
2031 int status = 0;
2032 struct scsi_cmnd *cmd;
2033
2034 /*
Mike Christiece545032008-02-29 18:25:20 -06002035 * Waiting for all commands for the designated target or dev
2036 * in the active array
David Somayajuluafaf5a22006-09-19 10:28:00 -07002037 */
2038 for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
2039 cmd = scsi_host_find_tag(ha->host, cnt);
Mike Christiece545032008-02-29 18:25:20 -06002040 if (cmd && stgt == scsi_target(cmd->device) &&
2041 (!sdev || sdev == cmd->device)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07002042 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
2043 status++;
2044 break;
2045 }
2046 }
2047 }
2048 return status;
2049}
2050
2051/**
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302052 * qla4xxx_eh_abort - callback for abort task.
2053 * @cmd: Pointer to Linux's SCSI command structure
2054 *
2055 * This routine is called by the Linux OS to abort the specified
2056 * command.
2057 **/
2058static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
2059{
2060 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
2061 unsigned int id = cmd->device->id;
2062 unsigned int lun = cmd->device->lun;
2063 unsigned long serial = cmd->serial_number;
Mike Christie92b3e5b2010-10-06 22:51:17 -07002064 unsigned long flags;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302065 struct srb *srb = NULL;
2066 int ret = SUCCESS;
2067 int wait = 0;
2068
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302069 ql4_printk(KERN_INFO, ha,
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302070 "scsi%ld:%d:%d: Abort command issued cmd=%p, pid=%ld\n",
2071 ha->host_no, id, lun, cmd, serial);
2072
Mike Christie92b3e5b2010-10-06 22:51:17 -07002073 spin_lock_irqsave(&ha->hardware_lock, flags);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302074 srb = (struct srb *) CMD_SP(cmd);
Mike Christie92b3e5b2010-10-06 22:51:17 -07002075 if (!srb) {
2076 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302077 return SUCCESS;
Mike Christie92b3e5b2010-10-06 22:51:17 -07002078 }
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302079 kref_get(&srb->srb_ref);
Mike Christie92b3e5b2010-10-06 22:51:17 -07002080 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302081
2082 if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) {
2083 DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx failed.\n",
2084 ha->host_no, id, lun));
2085 ret = FAILED;
2086 } else {
2087 DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx success.\n",
2088 ha->host_no, id, lun));
2089 wait = 1;
2090 }
2091
2092 kref_put(&srb->srb_ref, qla4xxx_srb_compl);
2093
2094 /* Wait for command to complete */
2095 if (wait) {
2096 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
2097 DEBUG2(printk("scsi%ld:%d:%d: Abort handler timed out\n",
2098 ha->host_no, id, lun));
2099 ret = FAILED;
2100 }
2101 }
2102
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302103 ql4_printk(KERN_INFO, ha,
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302104 "scsi%ld:%d:%d: Abort command - %s\n",
2105 ha->host_no, id, lun, (ret == SUCCESS) ? "succeded" : "failed");
2106
2107 return ret;
2108}
2109
2110/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07002111 * qla4xxx_eh_device_reset - callback for target reset.
2112 * @cmd: Pointer to Linux's SCSI command structure
2113 *
2114 * This routine is called by the Linux OS to reset all luns on the
2115 * specified target.
2116 **/
2117static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
2118{
2119 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
2120 struct ddb_entry *ddb_entry = cmd->device->hostdata;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002121 int ret = FAILED, stat;
2122
Karen Higgins612f7342009-07-15 15:03:01 -05002123 if (!ddb_entry)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002124 return ret;
2125
Mike Christiec01be6d2010-07-22 16:59:49 +05302126 ret = iscsi_block_scsi_eh(cmd);
2127 if (ret)
2128 return ret;
2129 ret = FAILED;
2130
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302131 ql4_printk(KERN_INFO, ha,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002132 "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no,
2133 cmd->device->channel, cmd->device->id, cmd->device->lun);
2134
2135 DEBUG2(printk(KERN_INFO
2136 "scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x,"
2137 "dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no,
Jens Axboe242f9dc2008-09-14 05:55:09 -07002138 cmd, jiffies, cmd->request->timeout / HZ,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002139 ha->dpc_flags, cmd->result, cmd->allowed));
2140
2141 /* FIXME: wait for hba to go online */
2142 stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun);
2143 if (stat != QLA_SUCCESS) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302144 ql4_printk(KERN_INFO, ha, "DEVICE RESET FAILED. %d\n", stat);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002145 goto eh_dev_reset_done;
2146 }
2147
Mike Christiece545032008-02-29 18:25:20 -06002148 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
2149 cmd->device)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302150 ql4_printk(KERN_INFO, ha,
Mike Christiece545032008-02-29 18:25:20 -06002151 "DEVICE RESET FAILED - waiting for "
2152 "commands.\n");
2153 goto eh_dev_reset_done;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002154 }
2155
David C Somayajulu9d562912008-03-19 11:23:03 -07002156 /* Send marker. */
2157 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
2158 MM_LUN_RESET) != QLA_SUCCESS)
2159 goto eh_dev_reset_done;
2160
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302161 ql4_printk(KERN_INFO, ha,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002162 "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
2163 ha->host_no, cmd->device->channel, cmd->device->id,
2164 cmd->device->lun);
2165
2166 ret = SUCCESS;
2167
2168eh_dev_reset_done:
2169
2170 return ret;
2171}
2172
2173/**
Mike Christiece545032008-02-29 18:25:20 -06002174 * qla4xxx_eh_target_reset - callback for target reset.
2175 * @cmd: Pointer to Linux's SCSI command structure
2176 *
2177 * This routine is called by the Linux OS to reset the target.
2178 **/
2179static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
2180{
2181 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
2182 struct ddb_entry *ddb_entry = cmd->device->hostdata;
Mike Christiec01be6d2010-07-22 16:59:49 +05302183 int stat, ret;
Mike Christiece545032008-02-29 18:25:20 -06002184
2185 if (!ddb_entry)
2186 return FAILED;
2187
Mike Christiec01be6d2010-07-22 16:59:49 +05302188 ret = iscsi_block_scsi_eh(cmd);
2189 if (ret)
2190 return ret;
2191
Mike Christiece545032008-02-29 18:25:20 -06002192 starget_printk(KERN_INFO, scsi_target(cmd->device),
2193 "WARM TARGET RESET ISSUED.\n");
2194
2195 DEBUG2(printk(KERN_INFO
2196 "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
2197 "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
Jens Axboe242f9dc2008-09-14 05:55:09 -07002198 ha->host_no, cmd, jiffies, cmd->request->timeout / HZ,
Mike Christiece545032008-02-29 18:25:20 -06002199 ha->dpc_flags, cmd->result, cmd->allowed));
2200
2201 stat = qla4xxx_reset_target(ha, ddb_entry);
2202 if (stat != QLA_SUCCESS) {
2203 starget_printk(KERN_INFO, scsi_target(cmd->device),
2204 "WARM TARGET RESET FAILED.\n");
2205 return FAILED;
2206 }
2207
Mike Christiece545032008-02-29 18:25:20 -06002208 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
2209 NULL)) {
2210 starget_printk(KERN_INFO, scsi_target(cmd->device),
2211 "WARM TARGET DEVICE RESET FAILED - "
2212 "waiting for commands.\n");
2213 return FAILED;
2214 }
2215
David C Somayajulu9d562912008-03-19 11:23:03 -07002216 /* Send marker. */
2217 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
2218 MM_TGT_WARM_RESET) != QLA_SUCCESS) {
2219 starget_printk(KERN_INFO, scsi_target(cmd->device),
2220 "WARM TARGET DEVICE RESET FAILED - "
2221 "marker iocb failed.\n");
2222 return FAILED;
2223 }
2224
Mike Christiece545032008-02-29 18:25:20 -06002225 starget_printk(KERN_INFO, scsi_target(cmd->device),
2226 "WARM TARGET RESET SUCCEEDED.\n");
2227 return SUCCESS;
2228}
2229
2230/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07002231 * qla4xxx_eh_host_reset - kernel callback
2232 * @cmd: Pointer to Linux's SCSI command structure
2233 *
2234 * This routine is invoked by the Linux kernel to perform fatal error
2235 * recovery on the specified adapter.
2236 **/
2237static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
2238{
2239 int return_status = FAILED;
2240 struct scsi_qla_host *ha;
2241
2242 ha = (struct scsi_qla_host *) cmd->device->host->hostdata;
2243
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05302244 if (ql4xdontresethba) {
2245 DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
2246 ha->host_no, __func__));
2247 return FAILED;
2248 }
2249
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302250 ql4_printk(KERN_INFO, ha,
Karen Higginsdca05c42009-07-15 15:03:00 -05002251 "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002252 cmd->device->channel, cmd->device->id, cmd->device->lun);
2253
2254 if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) {
2255 DEBUG2(printk("scsi%ld:%d: %s: Unable to reset host. Adapter "
2256 "DEAD.\n", ha->host_no, cmd->device->channel,
2257 __func__));
2258
2259 return FAILED;
2260 }
2261
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05302262 if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
2263 if (is_qla8022(ha))
2264 set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
2265 else
2266 set_bit(DPC_RESET_HA, &ha->dpc_flags);
2267 }
Mike Christie50a29ae2008-03-04 13:26:53 -06002268
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05302269 if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002270 return_status = SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002271
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302272 ql4_printk(KERN_INFO, ha, "HOST RESET %s.\n",
David Somayajuluafaf5a22006-09-19 10:28:00 -07002273 return_status == FAILED ? "FAILED" : "SUCCEDED");
2274
2275 return return_status;
2276}
2277
Lalit Chandivade2232be02010-07-30 14:38:47 +05302278/* PCI AER driver recovers from all correctable errors w/o
2279 * driver intervention. For uncorrectable errors PCI AER
2280 * driver calls the following device driver's callbacks
2281 *
2282 * - Fatal Errors - link_reset
2283 * - Non-Fatal Errors - driver's pci_error_detected() which
2284 * returns CAN_RECOVER, NEED_RESET or DISCONNECT.
2285 *
2286 * PCI AER driver calls
2287 * CAN_RECOVER - driver's pci_mmio_enabled(), mmio_enabled
2288 * returns RECOVERED or NEED_RESET if fw_hung
2289 * NEED_RESET - driver's slot_reset()
2290 * DISCONNECT - device is dead & cannot recover
2291 * RECOVERED - driver's pci_resume()
2292 */
2293static pci_ers_result_t
2294qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
2295{
2296 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
2297
2298 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: error detected:state %x\n",
2299 ha->host_no, __func__, state);
2300
2301 if (!is_aer_supported(ha))
2302 return PCI_ERS_RESULT_NONE;
2303
2304 switch (state) {
2305 case pci_channel_io_normal:
2306 clear_bit(AF_EEH_BUSY, &ha->flags);
2307 return PCI_ERS_RESULT_CAN_RECOVER;
2308 case pci_channel_io_frozen:
2309 set_bit(AF_EEH_BUSY, &ha->flags);
2310 qla4xxx_mailbox_premature_completion(ha);
2311 qla4xxx_free_irqs(ha);
2312 pci_disable_device(pdev);
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002313 /* Return back all IOs */
2314 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
Lalit Chandivade2232be02010-07-30 14:38:47 +05302315 return PCI_ERS_RESULT_NEED_RESET;
2316 case pci_channel_io_perm_failure:
2317 set_bit(AF_EEH_BUSY, &ha->flags);
2318 set_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags);
2319 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
2320 return PCI_ERS_RESULT_DISCONNECT;
2321 }
2322 return PCI_ERS_RESULT_NEED_RESET;
2323}
2324
2325/**
2326 * qla4xxx_pci_mmio_enabled() gets called if
2327 * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER
2328 * and read/write to the device still works.
2329 **/
2330static pci_ers_result_t
2331qla4xxx_pci_mmio_enabled(struct pci_dev *pdev)
2332{
2333 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
2334
2335 if (!is_aer_supported(ha))
2336 return PCI_ERS_RESULT_NONE;
2337
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002338 return PCI_ERS_RESULT_RECOVERED;
Lalit Chandivade2232be02010-07-30 14:38:47 +05302339}
2340
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002341static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
Lalit Chandivade2232be02010-07-30 14:38:47 +05302342{
2343 uint32_t rval = QLA_ERROR;
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002344 uint32_t ret = 0;
Lalit Chandivade2232be02010-07-30 14:38:47 +05302345 int fn;
2346 struct pci_dev *other_pdev = NULL;
2347
2348 ql4_printk(KERN_WARNING, ha, "scsi%ld: In %s\n", ha->host_no, __func__);
2349
2350 set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
2351
2352 if (test_bit(AF_ONLINE, &ha->flags)) {
2353 clear_bit(AF_ONLINE, &ha->flags);
2354 qla4xxx_mark_all_devices_missing(ha);
2355 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
Lalit Chandivade2232be02010-07-30 14:38:47 +05302356 }
2357
2358 fn = PCI_FUNC(ha->pdev->devfn);
2359 while (fn > 0) {
2360 fn--;
2361 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Finding PCI device at "
2362 "func %x\n", ha->host_no, __func__, fn);
2363 /* Get the pci device given the domain, bus,
2364 * slot/function number */
2365 other_pdev =
2366 pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
2367 ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
2368 fn));
2369
2370 if (!other_pdev)
2371 continue;
2372
2373 if (atomic_read(&other_pdev->enable_cnt)) {
2374 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Found PCI "
2375 "func in enabled state%x\n", ha->host_no,
2376 __func__, fn);
2377 pci_dev_put(other_pdev);
2378 break;
2379 }
2380 pci_dev_put(other_pdev);
2381 }
2382
2383 /* The first function on the card, the reset owner will
2384 * start & initialize the firmware. The other functions
2385 * on the card will reset the firmware context
2386 */
2387 if (!fn) {
2388 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn being reset "
2389 "0x%x is the owner\n", ha->host_no, __func__,
2390 ha->pdev->devfn);
2391
2392 qla4_8xxx_idc_lock(ha);
2393 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
2394 QLA82XX_DEV_COLD);
2395
2396 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION,
2397 QLA82XX_IDC_VERSION);
2398
2399 qla4_8xxx_idc_unlock(ha);
2400 clear_bit(AF_FW_RECOVERY, &ha->flags);
2401 rval = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST);
2402 qla4_8xxx_idc_lock(ha);
2403
2404 if (rval != QLA_SUCCESS) {
2405 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: "
2406 "FAILED\n", ha->host_no, __func__);
2407 qla4_8xxx_clear_drv_active(ha);
2408 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
2409 QLA82XX_DEV_FAILED);
2410 } else {
2411 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: "
2412 "READY\n", ha->host_no, __func__);
2413 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
2414 QLA82XX_DEV_READY);
2415 /* Clear driver state register */
2416 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
2417 qla4_8xxx_set_drv_active(ha);
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002418 ret = qla4xxx_request_irqs(ha);
2419 if (ret) {
2420 ql4_printk(KERN_WARNING, ha, "Failed to "
2421 "reserve interrupt %d already in use.\n",
2422 ha->pdev->irq);
2423 rval = QLA_ERROR;
2424 } else {
2425 ha->isp_ops->enable_intrs(ha);
2426 rval = QLA_SUCCESS;
2427 }
Lalit Chandivade2232be02010-07-30 14:38:47 +05302428 }
2429 qla4_8xxx_idc_unlock(ha);
2430 } else {
2431 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not "
2432 "the reset owner\n", ha->host_no, __func__,
2433 ha->pdev->devfn);
2434 if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
2435 QLA82XX_DEV_READY)) {
2436 clear_bit(AF_FW_RECOVERY, &ha->flags);
2437 rval = qla4xxx_initialize_adapter(ha,
2438 PRESERVE_DDB_LIST);
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002439 if (rval == QLA_SUCCESS) {
2440 ret = qla4xxx_request_irqs(ha);
2441 if (ret) {
2442 ql4_printk(KERN_WARNING, ha, "Failed to"
2443 " reserve interrupt %d already in"
2444 " use.\n", ha->pdev->irq);
2445 rval = QLA_ERROR;
2446 } else {
2447 ha->isp_ops->enable_intrs(ha);
2448 rval = QLA_SUCCESS;
2449 }
2450 }
Lalit Chandivade2232be02010-07-30 14:38:47 +05302451 qla4_8xxx_idc_lock(ha);
2452 qla4_8xxx_set_drv_active(ha);
2453 qla4_8xxx_idc_unlock(ha);
2454 }
2455 }
2456 clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
2457 return rval;
2458}
2459
2460static pci_ers_result_t
2461qla4xxx_pci_slot_reset(struct pci_dev *pdev)
2462{
2463 pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
2464 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
2465 int rc;
2466
2467 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: slot_reset\n",
2468 ha->host_no, __func__);
2469
2470 if (!is_aer_supported(ha))
2471 return PCI_ERS_RESULT_NONE;
2472
2473 /* Restore the saved state of PCIe device -
2474 * BAR registers, PCI Config space, PCIX, MSI,
2475 * IOV states
2476 */
2477 pci_restore_state(pdev);
2478
2479 /* pci_restore_state() clears the saved_state flag of the device
2480 * save restored state which resets saved_state flag
2481 */
2482 pci_save_state(pdev);
2483
2484 /* Initialize device or resume if in suspended state */
2485 rc = pci_enable_device(pdev);
2486 if (rc) {
2487 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cant re-enable "
2488 "device after reset\n", ha->host_no, __func__);
2489 goto exit_slot_reset;
2490 }
2491
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002492 ha->isp_ops->disable_intrs(ha);
Lalit Chandivade2232be02010-07-30 14:38:47 +05302493
2494 if (is_qla8022(ha)) {
2495 if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) {
2496 ret = PCI_ERS_RESULT_RECOVERED;
2497 goto exit_slot_reset;
2498 } else
2499 goto exit_slot_reset;
2500 }
2501
2502exit_slot_reset:
2503 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Return=%x\n"
2504 "device after reset\n", ha->host_no, __func__, ret);
2505 return ret;
2506}
2507
2508static void
2509qla4xxx_pci_resume(struct pci_dev *pdev)
2510{
2511 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
2512 int ret;
2513
2514 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: pci_resume\n",
2515 ha->host_no, __func__);
2516
2517 ret = qla4xxx_wait_for_hba_online(ha);
2518 if (ret != QLA_SUCCESS) {
2519 ql4_printk(KERN_ERR, ha, "scsi%ld: %s: the device failed to "
2520 "resume I/O from slot/link_reset\n", ha->host_no,
2521 __func__);
2522 }
2523
2524 pci_cleanup_aer_uncorrect_error_status(pdev);
2525 clear_bit(AF_EEH_BUSY, &ha->flags);
2526}
2527
2528static struct pci_error_handlers qla4xxx_err_handler = {
2529 .error_detected = qla4xxx_pci_error_detected,
2530 .mmio_enabled = qla4xxx_pci_mmio_enabled,
2531 .slot_reset = qla4xxx_pci_slot_reset,
2532 .resume = qla4xxx_pci_resume,
2533};
2534
David Somayajuluafaf5a22006-09-19 10:28:00 -07002535static struct pci_device_id qla4xxx_pci_tbl[] = {
2536 {
2537 .vendor = PCI_VENDOR_ID_QLOGIC,
2538 .device = PCI_DEVICE_ID_QLOGIC_ISP4010,
2539 .subvendor = PCI_ANY_ID,
2540 .subdevice = PCI_ANY_ID,
2541 },
2542 {
2543 .vendor = PCI_VENDOR_ID_QLOGIC,
2544 .device = PCI_DEVICE_ID_QLOGIC_ISP4022,
2545 .subvendor = PCI_ANY_ID,
2546 .subdevice = PCI_ANY_ID,
2547 },
David C Somayajulud9150582006-11-15 17:38:40 -08002548 {
2549 .vendor = PCI_VENDOR_ID_QLOGIC,
2550 .device = PCI_DEVICE_ID_QLOGIC_ISP4032,
2551 .subvendor = PCI_ANY_ID,
2552 .subdevice = PCI_ANY_ID,
2553 },
Vikas Chaudharyf4f5df232010-07-28 15:53:44 +05302554 {
2555 .vendor = PCI_VENDOR_ID_QLOGIC,
2556 .device = PCI_DEVICE_ID_QLOGIC_ISP8022,
2557 .subvendor = PCI_ANY_ID,
2558 .subdevice = PCI_ANY_ID,
2559 },
David Somayajuluafaf5a22006-09-19 10:28:00 -07002560 {0, 0},
2561};
2562MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl);
2563
Adrian Bunk47975472007-04-26 00:35:16 -07002564static struct pci_driver qla4xxx_pci_driver = {
David Somayajuluafaf5a22006-09-19 10:28:00 -07002565 .name = DRIVER_NAME,
2566 .id_table = qla4xxx_pci_tbl,
2567 .probe = qla4xxx_probe_adapter,
2568 .remove = qla4xxx_remove_adapter,
Lalit Chandivade2232be02010-07-30 14:38:47 +05302569 .err_handler = &qla4xxx_err_handler,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002570};
2571
2572static int __init qla4xxx_module_init(void)
2573{
2574 int ret;
2575
2576 /* Allocate cache for SRBs. */
2577 srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0,
Paul Mundt20c2df82007-07-20 10:11:58 +09002578 SLAB_HWCACHE_ALIGN, NULL);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002579 if (srb_cachep == NULL) {
2580 printk(KERN_ERR
2581 "%s: Unable to allocate SRB cache..."
2582 "Failing load!\n", DRIVER_NAME);
2583 ret = -ENOMEM;
2584 goto no_srp_cache;
2585 }
2586
2587 /* Derive version string. */
2588 strcpy(qla4xxx_version_str, QLA4XXX_DRIVER_VERSION);
Andrew Vasquez11010fe2006-10-06 09:54:59 -07002589 if (ql4xextended_error_logging)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002590 strcat(qla4xxx_version_str, "-debug");
2591
2592 qla4xxx_scsi_transport =
2593 iscsi_register_transport(&qla4xxx_iscsi_transport);
2594 if (!qla4xxx_scsi_transport){
2595 ret = -ENODEV;
2596 goto release_srb_cache;
2597 }
2598
David Somayajuluafaf5a22006-09-19 10:28:00 -07002599 ret = pci_register_driver(&qla4xxx_pci_driver);
2600 if (ret)
2601 goto unregister_transport;
2602
2603 printk(KERN_INFO "QLogic iSCSI HBA Driver\n");
2604 return 0;
Doug Maxey5ae16db2006-10-05 23:50:07 -05002605
David Somayajuluafaf5a22006-09-19 10:28:00 -07002606unregister_transport:
2607 iscsi_unregister_transport(&qla4xxx_iscsi_transport);
2608release_srb_cache:
2609 kmem_cache_destroy(srb_cachep);
2610no_srp_cache:
2611 return ret;
2612}
2613
2614static void __exit qla4xxx_module_exit(void)
2615{
David Somayajuluafaf5a22006-09-19 10:28:00 -07002616 pci_unregister_driver(&qla4xxx_pci_driver);
2617 iscsi_unregister_transport(&qla4xxx_iscsi_transport);
2618 kmem_cache_destroy(srb_cachep);
2619}
2620
2621module_init(qla4xxx_module_init);
2622module_exit(qla4xxx_module_exit);
2623
2624MODULE_AUTHOR("QLogic Corporation");
2625MODULE_DESCRIPTION("QLogic iSCSI HBA Driver");
2626MODULE_LICENSE("GPL");
2627MODULE_VERSION(QLA4XXX_DRIVER_VERSION);