blob: 21e4f858d72be1e7acf490851f598079f974c5ba [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 Chaudharyf4f5df22010-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 Chaudharyf4f5df22010-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 Chaudharyf4f5df22010-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 Chaudharyf4f5df22010-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
Vikas Chaudhary8bb40332011-03-21 03:34:31 -070054static int ql4xmaxqdepth = QL4_DEF_QDEPTH;
55module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR);
56MODULE_PARM_DESC(ql4xmaxqdepth,
57 "Maximum queue depth to report for target devices.\n"
58 " Default: 32.");
Mike Christied510d962008-07-11 19:50:33 -050059
Vikas Chaudhary30387272011-03-21 03:34:32 -070060static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
61module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
62MODULE_PARM_DESC(ql4xsess_recovery_tmo,
63 "Target Session Recovery Timeout.\n"
64 " Default: 30 sec.");
65
David Somayajuluafaf5a22006-09-19 10:28:00 -070066/*
67 * SCSI host template entry points
68 */
Adrian Bunk47975472007-04-26 00:35:16 -070069static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -070070
71/*
72 * iSCSI template entry points
73 */
Mike Christie2174a042007-05-30 12:57:10 -050074static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
75 enum iscsi_tgt_dscvr type, uint32_t enable,
76 struct sockaddr *dst_addr);
David Somayajuluafaf5a22006-09-19 10:28:00 -070077static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
78 enum iscsi_param param, char *buf);
79static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
80 enum iscsi_param param, char *buf);
Mike Christieaa1e93a2007-05-30 12:57:09 -050081static int qla4xxx_host_get_param(struct Scsi_Host *shost,
82 enum iscsi_host_param param, char *buf);
Mike Christied00efe32011-07-25 13:48:38 -050083static int qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data,
84 int count);
David Somayajuluafaf5a22006-09-19 10:28:00 -070085static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
Mike Christie5c656af2009-07-15 15:02:59 -050086static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
David Somayajuluafaf5a22006-09-19 10:28:00 -070087
88/*
89 * SCSI host template entry points
90 */
Jeff Garzikf2812332010-11-16 02:10:29 -050091static int qla4xxx_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +053092static int qla4xxx_eh_abort(struct scsi_cmnd *cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -070093static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
Mike Christiece545032008-02-29 18:25:20 -060094static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -070095static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
96static int qla4xxx_slave_alloc(struct scsi_device *device);
97static int qla4xxx_slave_configure(struct scsi_device *device);
98static void qla4xxx_slave_destroy(struct scsi_device *sdev);
Mike Christie024f8012008-03-04 13:26:54 -060099static void qla4xxx_scan_start(struct Scsi_Host *shost);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700100
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530101static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
102 QLA82XX_LEGACY_INTR_CONFIG;
103
David Somayajuluafaf5a22006-09-19 10:28:00 -0700104static struct scsi_host_template qla4xxx_driver_template = {
105 .module = THIS_MODULE,
106 .name = DRIVER_NAME,
107 .proc_name = DRIVER_NAME,
108 .queuecommand = qla4xxx_queuecommand,
109
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530110 .eh_abort_handler = qla4xxx_eh_abort,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700111 .eh_device_reset_handler = qla4xxx_eh_device_reset,
Mike Christiece545032008-02-29 18:25:20 -0600112 .eh_target_reset_handler = qla4xxx_eh_target_reset,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700113 .eh_host_reset_handler = qla4xxx_eh_host_reset,
Mike Christie5c656af2009-07-15 15:02:59 -0500114 .eh_timed_out = qla4xxx_eh_cmd_timed_out,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700115
116 .slave_configure = qla4xxx_slave_configure,
117 .slave_alloc = qla4xxx_slave_alloc,
118 .slave_destroy = qla4xxx_slave_destroy,
119
Mike Christie921601b2008-01-31 13:36:49 -0600120 .scan_finished = iscsi_scan_finished,
Mike Christie024f8012008-03-04 13:26:54 -0600121 .scan_start = qla4xxx_scan_start,
Mike Christie921601b2008-01-31 13:36:49 -0600122
David Somayajuluafaf5a22006-09-19 10:28:00 -0700123 .this_id = -1,
124 .cmd_per_lun = 3,
125 .use_clustering = ENABLE_CLUSTERING,
126 .sg_tablesize = SG_ALL,
127
128 .max_sectors = 0xFFFF,
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -0700129 .shost_attrs = qla4xxx_host_attrs,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700130};
131
132static struct iscsi_transport qla4xxx_iscsi_transport = {
133 .owner = THIS_MODULE,
134 .name = DRIVER_NAME,
Mike Christied8196ed2007-05-30 12:57:25 -0500135 .caps = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
136 CAP_DATA_PATH_OFFLOAD,
Mike Christieaa1e93a2007-05-30 12:57:09 -0500137 .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
Vikas Chaudhary3b2bef12010-07-10 14:51:30 +0530138 ISCSI_TARGET_NAME | ISCSI_TPGT |
139 ISCSI_TARGET_ALIAS,
Mike Christie8ad57812007-05-30 12:57:13 -0500140 .host_param_mask = ISCSI_HOST_HWADDRESS |
Mike Christie22236962007-05-30 12:57:24 -0500141 ISCSI_HOST_IPADDRESS |
Mike Christie8ad57812007-05-30 12:57:13 -0500142 ISCSI_HOST_INITIATOR_NAME,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700143 .tgt_dscvr = qla4xxx_tgt_dscvr,
144 .get_conn_param = qla4xxx_conn_get_param,
145 .get_session_param = qla4xxx_sess_get_param,
Mike Christieaa1e93a2007-05-30 12:57:09 -0500146 .get_host_param = qla4xxx_host_get_param,
Mike Christied00efe32011-07-25 13:48:38 -0500147 .set_iface_param = qla4xxx_iface_set_param,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700148 .session_recovery_timedout = qla4xxx_recovery_timedout,
149};
150
151static struct scsi_transport_template *qla4xxx_scsi_transport;
152
Mike Christie5c656af2009-07-15 15:02:59 -0500153static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
154{
155 struct iscsi_cls_session *session;
156 struct ddb_entry *ddb_entry;
157
158 session = starget_to_session(scsi_target(sc->device));
159 ddb_entry = session->dd_data;
160
161 /* if we are not logged in then the LLD is going to clean up the cmd */
162 if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
163 return BLK_EH_RESET_TIMER;
164 else
165 return BLK_EH_NOT_HANDLED;
166}
167
David Somayajuluafaf5a22006-09-19 10:28:00 -0700168static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
169{
170 struct ddb_entry *ddb_entry = session->dd_data;
171 struct scsi_qla_host *ha = ddb_entry->ha;
172
Mike Christie568d3032008-01-31 13:36:47 -0600173 if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
174 atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700175
Vikas Chaudhary3013cea2010-07-30 14:25:46 +0530176 DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout "
Mike Christie568d3032008-01-31 13:36:47 -0600177 "of (%d) secs exhausted, marking device DEAD.\n",
178 ha->host_no, __func__, ddb_entry->fw_ddb_index,
Vikas Chaudhary30387272011-03-21 03:34:32 -0700179 ddb_entry->sess->recovery_tmo));
Mike Christie568d3032008-01-31 13:36:47 -0600180 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700181}
182
Mike Christieaa1e93a2007-05-30 12:57:09 -0500183static int qla4xxx_host_get_param(struct Scsi_Host *shost,
184 enum iscsi_host_param param, char *buf)
185{
186 struct scsi_qla_host *ha = to_qla_host(shost);
187 int len;
188
189 switch (param) {
190 case ISCSI_HOST_PARAM_HWADDRESS:
Michael Chan7ffc49a2007-12-24 21:28:09 -0800191 len = sysfs_format_mac(buf, ha->my_mac, MAC_ADDR_LEN);
Mike Christieaa1e93a2007-05-30 12:57:09 -0500192 break;
Mike Christie22236962007-05-30 12:57:24 -0500193 case ISCSI_HOST_PARAM_IPADDRESS:
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500194 len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);
Mike Christie22236962007-05-30 12:57:24 -0500195 break;
Mike Christie8ad57812007-05-30 12:57:13 -0500196 case ISCSI_HOST_PARAM_INITIATOR_NAME:
Mike Christie22236962007-05-30 12:57:24 -0500197 len = sprintf(buf, "%s\n", ha->name_string);
Mike Christie8ad57812007-05-30 12:57:13 -0500198 break;
Mike Christieaa1e93a2007-05-30 12:57:09 -0500199 default:
200 return -ENOSYS;
201 }
202
203 return len;
204}
205
Mike Christied00efe32011-07-25 13:48:38 -0500206static void qla4xxx_set_ipv6(struct scsi_qla_host *ha,
207 struct iscsi_iface_param_info *iface_param,
208 struct addr_ctrl_blk *init_fw_cb)
209{
210 /*
211 * iface_num 0 is valid for IPv6 Addr, linklocal, router, autocfg.
212 * iface_num 1 is valid only for IPv6 Addr.
213 */
214 switch (iface_param->param) {
215 case ISCSI_NET_PARAM_IPV6_ADDR:
216 if (iface_param->iface_num & 0x1)
217 /* IPv6 Addr 1 */
218 memcpy(init_fw_cb->ipv6_addr1, iface_param->value,
219 sizeof(init_fw_cb->ipv6_addr1));
220 else
221 /* IPv6 Addr 0 */
222 memcpy(init_fw_cb->ipv6_addr0, iface_param->value,
223 sizeof(init_fw_cb->ipv6_addr0));
224 break;
225 case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
226 if (iface_param->iface_num & 0x1)
227 break;
228 memcpy(init_fw_cb->ipv6_if_id, &iface_param->value[8],
229 sizeof(init_fw_cb->ipv6_if_id));
230 break;
231 case ISCSI_NET_PARAM_IPV6_ROUTER:
232 if (iface_param->iface_num & 0x1)
233 break;
234 memcpy(init_fw_cb->ipv6_dflt_rtr_addr, iface_param->value,
235 sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
236 break;
237 case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
238 /* Autocfg applies to even interface */
239 if (iface_param->iface_num & 0x1)
240 break;
241
242 if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_DISABLE)
243 init_fw_cb->ipv6_addtl_opts &=
244 cpu_to_le16(
245 ~IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
246 else if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_ND_ENABLE)
247 init_fw_cb->ipv6_addtl_opts |=
248 cpu_to_le16(
249 IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
250 else
251 ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
252 "IPv6 addr\n");
253 break;
254 case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
255 /* Autocfg applies to even interface */
256 if (iface_param->iface_num & 0x1)
257 break;
258
259 if (iface_param->value[0] ==
260 ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE)
261 init_fw_cb->ipv6_addtl_opts |= cpu_to_le16(
262 IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
263 else if (iface_param->value[0] ==
264 ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE)
265 init_fw_cb->ipv6_addtl_opts &= cpu_to_le16(
266 ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
267 else
268 ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
269 "IPv6 linklocal addr\n");
270 break;
271 case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG:
272 /* Autocfg applies to even interface */
273 if (iface_param->iface_num & 0x1)
274 break;
275
276 if (iface_param->value[0] == ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE)
277 memset(init_fw_cb->ipv6_dflt_rtr_addr, 0,
278 sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
279 break;
280 case ISCSI_NET_PARAM_IFACE_ENABLE:
281 if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
282 init_fw_cb->ipv6_opts |=
283 cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE);
284 else
285 init_fw_cb->ipv6_opts &=
286 cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE &
287 0xFFFF);
288 break;
289 case ISCSI_NET_PARAM_VLAN_ID:
290 if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag))
291 break;
292 init_fw_cb->ipv6_vlan_tag = *(uint16_t *)iface_param->value;
293 break;
294 default:
295 ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n",
296 iface_param->param);
297 break;
298 }
299}
300
301static void qla4xxx_set_ipv4(struct scsi_qla_host *ha,
302 struct iscsi_iface_param_info *iface_param,
303 struct addr_ctrl_blk *init_fw_cb)
304{
305 switch (iface_param->param) {
306 case ISCSI_NET_PARAM_IPV4_ADDR:
307 memcpy(init_fw_cb->ipv4_addr, iface_param->value,
308 sizeof(init_fw_cb->ipv4_addr));
309 break;
310 case ISCSI_NET_PARAM_IPV4_SUBNET:
311 memcpy(init_fw_cb->ipv4_subnet, iface_param->value,
312 sizeof(init_fw_cb->ipv4_subnet));
313 break;
314 case ISCSI_NET_PARAM_IPV4_GW:
315 memcpy(init_fw_cb->ipv4_gw_addr, iface_param->value,
316 sizeof(init_fw_cb->ipv4_gw_addr));
317 break;
318 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
319 if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
320 init_fw_cb->ipv4_tcp_opts |=
321 cpu_to_le16(TCPOPT_DHCP_ENABLE);
322 else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
323 init_fw_cb->ipv4_tcp_opts &=
324 cpu_to_le16(~TCPOPT_DHCP_ENABLE);
325 else
326 ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n");
327 break;
328 case ISCSI_NET_PARAM_IFACE_ENABLE:
329 if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
330 init_fw_cb->ipv4_ip_opts |=
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500331 cpu_to_le16(IPOPT_IPV4_PROTOCOL_ENABLE);
Mike Christied00efe32011-07-25 13:48:38 -0500332 else
333 init_fw_cb->ipv4_ip_opts &=
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500334 cpu_to_le16(~IPOPT_IPV4_PROTOCOL_ENABLE &
Mike Christied00efe32011-07-25 13:48:38 -0500335 0xFFFF);
336 break;
337 case ISCSI_NET_PARAM_VLAN_ID:
338 if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag))
339 break;
340 init_fw_cb->ipv4_vlan_tag = *(uint16_t *)iface_param->value;
341 break;
342 default:
343 ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n",
344 iface_param->param);
345 break;
346 }
347}
348
349static void
350qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb)
351{
352 struct addr_ctrl_blk_def *acb;
353 acb = (struct addr_ctrl_blk_def *)init_fw_cb;
354 memset(acb->reserved1, 0, sizeof(acb->reserved1));
355 memset(acb->reserved2, 0, sizeof(acb->reserved2));
356 memset(acb->reserved3, 0, sizeof(acb->reserved3));
357 memset(acb->reserved4, 0, sizeof(acb->reserved4));
358 memset(acb->reserved5, 0, sizeof(acb->reserved5));
359 memset(acb->reserved6, 0, sizeof(acb->reserved6));
360 memset(acb->reserved7, 0, sizeof(acb->reserved7));
361 memset(acb->reserved8, 0, sizeof(acb->reserved8));
362 memset(acb->reserved9, 0, sizeof(acb->reserved9));
363 memset(acb->reserved10, 0, sizeof(acb->reserved10));
364 memset(acb->reserved11, 0, sizeof(acb->reserved11));
365 memset(acb->reserved12, 0, sizeof(acb->reserved12));
366 memset(acb->reserved13, 0, sizeof(acb->reserved13));
367 memset(acb->reserved14, 0, sizeof(acb->reserved14));
368 memset(acb->reserved15, 0, sizeof(acb->reserved15));
369}
370
371static int
372qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data, int count)
373{
374 struct scsi_qla_host *ha = to_qla_host(shost);
375 int rval = 0;
376 struct iscsi_iface_param_info *iface_param = NULL;
377 struct addr_ctrl_blk *init_fw_cb = NULL;
378 dma_addr_t init_fw_cb_dma;
379 uint32_t mbox_cmd[MBOX_REG_COUNT];
380 uint32_t mbox_sts[MBOX_REG_COUNT];
381 uint32_t total_param_count;
382 uint32_t length;
383
384 init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
385 sizeof(struct addr_ctrl_blk),
386 &init_fw_cb_dma, GFP_KERNEL);
387 if (!init_fw_cb) {
388 ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",
389 __func__);
390 return -ENOMEM;
391 }
392
393 memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
394 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
395 memset(&mbox_sts, 0, sizeof(mbox_sts));
396
397 if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)) {
398 ql4_printk(KERN_ERR, ha, "%s: get ifcb failed\n", __func__);
399 rval = -EIO;
400 goto exit_init_fw_cb;
401 }
402
403 total_param_count = count;
404 iface_param = (struct iscsi_iface_param_info *)data;
405
406 for ( ; total_param_count != 0; total_param_count--) {
407 length = iface_param->len;
408
409 if (iface_param->param_type != ISCSI_NET_PARAM)
410 continue;
411
412 switch (iface_param->iface_type) {
413 case ISCSI_IFACE_TYPE_IPV4:
414 switch (iface_param->iface_num) {
415 case 0:
416 qla4xxx_set_ipv4(ha, iface_param, init_fw_cb);
417 break;
418 default:
419 /* Cannot have more than one IPv4 interface */
420 ql4_printk(KERN_ERR, ha, "Invalid IPv4 iface "
421 "number = %d\n",
422 iface_param->iface_num);
423 break;
424 }
425 break;
426 case ISCSI_IFACE_TYPE_IPV6:
427 switch (iface_param->iface_num) {
428 case 0:
429 case 1:
430 qla4xxx_set_ipv6(ha, iface_param, init_fw_cb);
431 break;
432 default:
433 /* Cannot have more than two IPv6 interface */
434 ql4_printk(KERN_ERR, ha, "Invalid IPv6 iface "
435 "number = %d\n",
436 iface_param->iface_num);
437 break;
438 }
439 break;
440 default:
441 ql4_printk(KERN_ERR, ha, "Invalid iface type\n");
442 break;
443 }
444
445 iface_param = (struct iscsi_iface_param_info *)
446 ((uint8_t *)iface_param +
447 sizeof(struct iscsi_iface_param_info) + length);
448 }
449
450 init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A);
451
452 rval = qla4xxx_set_flash(ha, init_fw_cb_dma, FLASH_SEGMENT_IFCB,
453 sizeof(struct addr_ctrl_blk),
454 FLASH_OPT_RMW_COMMIT);
455 if (rval != QLA_SUCCESS) {
456 ql4_printk(KERN_ERR, ha, "%s: set flash mbx failed\n",
457 __func__);
458 rval = -EIO;
459 goto exit_init_fw_cb;
460 }
461
462 qla4xxx_disable_acb(ha);
463
464 qla4xxx_initcb_to_acb(init_fw_cb);
465
466 rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma);
467 if (rval != QLA_SUCCESS) {
468 ql4_printk(KERN_ERR, ha, "%s: set acb mbx failed\n",
469 __func__);
470 rval = -EIO;
471 goto exit_init_fw_cb;
472 }
473
474 memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
475 qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb,
476 init_fw_cb_dma);
477
478exit_init_fw_cb:
479 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
480 init_fw_cb, init_fw_cb_dma);
481
482 return rval;
483}
484
David Somayajuluafaf5a22006-09-19 10:28:00 -0700485static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
486 enum iscsi_param param, char *buf)
487{
488 struct ddb_entry *ddb_entry = sess->dd_data;
489 int len;
490
491 switch (param) {
492 case ISCSI_PARAM_TARGET_NAME:
493 len = snprintf(buf, PAGE_SIZE - 1, "%s\n",
494 ddb_entry->iscsi_name);
495 break;
496 case ISCSI_PARAM_TPGT:
497 len = sprintf(buf, "%u\n", ddb_entry->tpgt);
498 break;
Vikas Chaudhary3b2bef12010-07-10 14:51:30 +0530499 case ISCSI_PARAM_TARGET_ALIAS:
500 len = snprintf(buf, PAGE_SIZE - 1, "%s\n",
501 ddb_entry->iscsi_alias);
502 break;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700503 default:
504 return -ENOSYS;
505 }
506
507 return len;
508}
509
510static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
511 enum iscsi_param param, char *buf)
512{
513 struct iscsi_cls_session *session;
514 struct ddb_entry *ddb_entry;
515 int len;
516
517 session = iscsi_dev_to_session(conn->dev.parent);
518 ddb_entry = session->dd_data;
519
520 switch (param) {
521 case ISCSI_PARAM_CONN_PORT:
522 len = sprintf(buf, "%hu\n", ddb_entry->port);
523 break;
524 case ISCSI_PARAM_CONN_ADDRESS:
525 /* TODO: what are the ipv6 bits */
Harvey Harrison63779432008-10-31 00:56:00 -0700526 len = sprintf(buf, "%pI4\n", &ddb_entry->ip_addr);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700527 break;
528 default:
529 return -ENOSYS;
530 }
531
532 return len;
533}
534
Mike Christie2174a042007-05-30 12:57:10 -0500535static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
536 enum iscsi_tgt_dscvr type, uint32_t enable,
537 struct sockaddr *dst_addr)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700538{
539 struct scsi_qla_host *ha;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700540 struct sockaddr_in *addr;
541 struct sockaddr_in6 *addr6;
542 int ret = 0;
543
David Somayajuluafaf5a22006-09-19 10:28:00 -0700544 ha = (struct scsi_qla_host *) shost->hostdata;
545
546 switch (type) {
547 case ISCSI_TGT_DSCVR_SEND_TARGETS:
548 if (dst_addr->sa_family == AF_INET) {
549 addr = (struct sockaddr_in *)dst_addr;
550 if (qla4xxx_send_tgts(ha, (char *)&addr->sin_addr,
551 addr->sin_port) != QLA_SUCCESS)
552 ret = -EIO;
553 } else if (dst_addr->sa_family == AF_INET6) {
554 /*
555 * TODO: fix qla4xxx_send_tgts
556 */
557 addr6 = (struct sockaddr_in6 *)dst_addr;
558 if (qla4xxx_send_tgts(ha, (char *)&addr6->sin6_addr,
559 addr6->sin6_port) != QLA_SUCCESS)
560 ret = -EIO;
561 } else
562 ret = -ENOSYS;
563 break;
564 default:
565 ret = -ENOSYS;
566 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700567 return ret;
568}
569
570void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry)
571{
572 if (!ddb_entry->sess)
573 return;
574
575 if (ddb_entry->conn) {
Mike Christie26974782007-12-13 12:43:29 -0600576 atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700577 iscsi_remove_session(ddb_entry->sess);
578 }
579 iscsi_free_session(ddb_entry->sess);
580}
581
582int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
583{
584 int err;
585
Vikas Chaudhary30387272011-03-21 03:34:32 -0700586 ddb_entry->sess->recovery_tmo = ql4xsess_recovery_tmo;
Vikas Chaudhary3013cea2010-07-30 14:25:46 +0530587
David Somayajuluafaf5a22006-09-19 10:28:00 -0700588 err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
589 if (err) {
590 DEBUG2(printk(KERN_ERR "Could not add session.\n"));
591 return err;
592 }
593
Mike Christie5d91e202008-05-21 15:54:01 -0500594 ddb_entry->conn = iscsi_create_conn(ddb_entry->sess, 0, 0);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700595 if (!ddb_entry->conn) {
596 iscsi_remove_session(ddb_entry->sess);
597 DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
598 return -ENOMEM;
599 }
Mike Christieb6359302008-01-31 13:36:44 -0600600
601 /* finally ready to go */
602 iscsi_unblock_session(ddb_entry->sess);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700603 return 0;
604}
605
606struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha)
607{
608 struct ddb_entry *ddb_entry;
609 struct iscsi_cls_session *sess;
610
Mike Christie5d91e202008-05-21 15:54:01 -0500611 sess = iscsi_alloc_session(ha->host, &qla4xxx_iscsi_transport,
612 sizeof(struct ddb_entry));
David Somayajuluafaf5a22006-09-19 10:28:00 -0700613 if (!sess)
614 return NULL;
615
616 ddb_entry = sess->dd_data;
617 memset(ddb_entry, 0, sizeof(*ddb_entry));
618 ddb_entry->ha = ha;
619 ddb_entry->sess = sess;
620 return ddb_entry;
621}
622
Mike Christie024f8012008-03-04 13:26:54 -0600623static void qla4xxx_scan_start(struct Scsi_Host *shost)
624{
625 struct scsi_qla_host *ha = shost_priv(shost);
626 struct ddb_entry *ddb_entry, *ddbtemp;
627
628 /* finish setup of sessions that were already setup in firmware */
629 list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
630 if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE)
631 qla4xxx_add_sess(ddb_entry);
632 }
633}
634
David Somayajuluafaf5a22006-09-19 10:28:00 -0700635/*
636 * Timer routines
637 */
638
639static void qla4xxx_start_timer(struct scsi_qla_host *ha, void *func,
640 unsigned long interval)
641{
642 DEBUG(printk("scsi: %s: Starting timer thread for adapter %d\n",
643 __func__, ha->host->host_no));
644 init_timer(&ha->timer);
645 ha->timer.expires = jiffies + interval * HZ;
646 ha->timer.data = (unsigned long)ha;
647 ha->timer.function = (void (*)(unsigned long))func;
648 add_timer(&ha->timer);
649 ha->timer_active = 1;
650}
651
652static void qla4xxx_stop_timer(struct scsi_qla_host *ha)
653{
654 del_timer_sync(&ha->timer);
655 ha->timer_active = 0;
656}
657
658/***
659 * qla4xxx_mark_device_missing - mark a device as missing.
660 * @ha: Pointer to host adapter structure.
661 * @ddb_entry: Pointer to device database entry
662 *
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530663 * This routine marks a device missing and close connection.
David Somayajuluafaf5a22006-09-19 10:28:00 -0700664 **/
665void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
666 struct ddb_entry *ddb_entry)
667{
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530668 if ((atomic_read(&ddb_entry->state) != DDB_STATE_DEAD)) {
669 atomic_set(&ddb_entry->state, DDB_STATE_MISSING);
670 DEBUG2(printk("scsi%ld: ddb [%d] marked MISSING\n",
671 ha->host_no, ddb_entry->fw_ddb_index));
672 } else
673 DEBUG2(printk("scsi%ld: ddb [%d] DEAD\n", ha->host_no,
674 ddb_entry->fw_ddb_index))
675
Mike Christieb6359302008-01-31 13:36:44 -0600676 iscsi_block_session(ddb_entry->sess);
Mike Christiee5bd7b52008-09-24 11:46:10 -0500677 iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700678}
679
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530680/**
681 * qla4xxx_mark_all_devices_missing - mark all devices as missing.
682 * @ha: Pointer to host adapter structure.
683 *
684 * This routine marks a device missing and resets the relogin retry count.
685 **/
686void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha)
687{
688 struct ddb_entry *ddb_entry, *ddbtemp;
689 list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
690 qla4xxx_mark_device_missing(ha, ddb_entry);
691 }
692}
693
David Somayajuluafaf5a22006-09-19 10:28:00 -0700694static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
695 struct ddb_entry *ddb_entry,
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -0700696 struct scsi_cmnd *cmd)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700697{
698 struct srb *srb;
699
700 srb = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
701 if (!srb)
702 return srb;
703
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530704 kref_init(&srb->srb_ref);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700705 srb->ha = ha;
706 srb->ddb = ddb_entry;
707 srb->cmd = cmd;
708 srb->flags = 0;
Vikas Chaudhary53698872010-04-28 11:41:59 +0530709 CMD_SP(cmd) = (void *)srb;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700710
711 return srb;
712}
713
714static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb)
715{
716 struct scsi_cmnd *cmd = srb->cmd;
717
718 if (srb->flags & SRB_DMA_VALID) {
FUJITA Tomonori5f7186c2007-05-26 14:08:20 +0900719 scsi_dma_unmap(cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700720 srb->flags &= ~SRB_DMA_VALID;
721 }
Vikas Chaudhary53698872010-04-28 11:41:59 +0530722 CMD_SP(cmd) = NULL;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700723}
724
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530725void qla4xxx_srb_compl(struct kref *ref)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700726{
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530727 struct srb *srb = container_of(ref, struct srb, srb_ref);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700728 struct scsi_cmnd *cmd = srb->cmd;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530729 struct scsi_qla_host *ha = srb->ha;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700730
731 qla4xxx_srb_free_dma(ha, srb);
732
733 mempool_free(srb, ha->srb_mempool);
734
735 cmd->scsi_done(cmd);
736}
737
738/**
739 * qla4xxx_queuecommand - scsi layer issues scsi command to driver.
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -0700740 * @host: scsi host
David Somayajuluafaf5a22006-09-19 10:28:00 -0700741 * @cmd: Pointer to Linux's SCSI command structure
David Somayajuluafaf5a22006-09-19 10:28:00 -0700742 *
743 * Remarks:
744 * This routine is invoked by Linux to send a SCSI command to the driver.
745 * The mid-level driver tries to ensure that queuecommand never gets
746 * invoked concurrently with itself or the interrupt handler (although
747 * the interrupt handler may call this routine as part of request-
748 * completion handling). Unfortunely, it sometimes calls the scheduler
749 * in interrupt context which is a big NO! NO!.
750 **/
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -0700751static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700752{
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -0700753 struct scsi_qla_host *ha = to_qla_host(host);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700754 struct ddb_entry *ddb_entry = cmd->device->hostdata;
Mike Christie7fb19212008-01-31 13:36:45 -0600755 struct iscsi_cls_session *sess = ddb_entry->sess;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700756 struct srb *srb;
757 int rval;
758
Lalit Chandivade2232be02010-07-30 14:38:47 +0530759 if (test_bit(AF_EEH_BUSY, &ha->flags)) {
760 if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))
761 cmd->result = DID_NO_CONNECT << 16;
762 else
763 cmd->result = DID_REQUEUE << 16;
764 goto qc_fail_command;
765 }
766
Mike Christie7fb19212008-01-31 13:36:45 -0600767 if (!sess) {
768 cmd->result = DID_IMM_RETRY << 16;
769 goto qc_fail_command;
770 }
771
772 rval = iscsi_session_chkready(sess);
773 if (rval) {
774 cmd->result = rval;
775 goto qc_fail_command;
776 }
777
David Somayajuluafaf5a22006-09-19 10:28:00 -0700778 if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
779 if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) {
780 cmd->result = DID_NO_CONNECT << 16;
781 goto qc_fail_command;
782 }
Mike Christiec5e98e92008-08-17 15:24:39 -0500783 return SCSI_MLQUEUE_TARGET_BUSY;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700784 }
785
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530786 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
787 test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
788 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
789 test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||
790 test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||
791 !test_bit(AF_ONLINE, &ha->flags) ||
792 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))
David C Somayajulu477ffb92007-01-22 12:26:11 -0800793 goto qc_host_busy;
794
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -0700795 srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700796 if (!srb)
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -0700797 goto qc_host_busy;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700798
799 rval = qla4xxx_send_command_to_isp(ha, srb);
800 if (rval != QLA_SUCCESS)
801 goto qc_host_busy_free_sp;
802
David Somayajuluafaf5a22006-09-19 10:28:00 -0700803 return 0;
804
805qc_host_busy_free_sp:
806 qla4xxx_srb_free_dma(ha, srb);
807 mempool_free(srb, ha->srb_mempool);
808
David Somayajuluafaf5a22006-09-19 10:28:00 -0700809qc_host_busy:
810 return SCSI_MLQUEUE_HOST_BUSY;
811
812qc_fail_command:
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -0700813 cmd->scsi_done(cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700814
815 return 0;
816}
817
818/**
819 * qla4xxx_mem_free - frees memory allocated to adapter
820 * @ha: Pointer to host adapter structure.
821 *
822 * Frees memory previously allocated by qla4xxx_mem_alloc
823 **/
824static void qla4xxx_mem_free(struct scsi_qla_host *ha)
825{
826 if (ha->queues)
827 dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues,
828 ha->queues_dma);
829
830 ha->queues_len = 0;
831 ha->queues = NULL;
832 ha->queues_dma = 0;
833 ha->request_ring = NULL;
834 ha->request_dma = 0;
835 ha->response_ring = NULL;
836 ha->response_dma = 0;
837 ha->shadow_regs = NULL;
838 ha->shadow_regs_dma = 0;
839
840 /* Free srb pool. */
841 if (ha->srb_mempool)
842 mempool_destroy(ha->srb_mempool);
843
844 ha->srb_mempool = NULL;
845
846 /* release io space registers */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530847 if (is_qla8022(ha)) {
848 if (ha->nx_pcibase)
849 iounmap(
850 (struct device_reg_82xx __iomem *)ha->nx_pcibase);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530851 } else if (ha->reg)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700852 iounmap(ha->reg);
853 pci_release_regions(ha->pdev);
854}
855
856/**
857 * qla4xxx_mem_alloc - allocates memory for use by adapter.
858 * @ha: Pointer to host adapter structure
859 *
860 * Allocates DMA memory for request and response queues. Also allocates memory
861 * for srbs.
862 **/
863static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
864{
865 unsigned long align;
866
867 /* Allocate contiguous block of DMA memory for queues. */
868 ha->queues_len = ((REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +
869 (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE) +
870 sizeof(struct shadow_regs) +
871 MEM_ALIGN_VALUE +
872 (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
873 ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len,
874 &ha->queues_dma, GFP_KERNEL);
875 if (ha->queues == NULL) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +0530876 ql4_printk(KERN_WARNING, ha,
877 "Memory Allocation failed - queues.\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -0700878
879 goto mem_alloc_error_exit;
880 }
881 memset(ha->queues, 0, ha->queues_len);
882
883 /*
884 * As per RISC alignment requirements -- the bus-address must be a
885 * multiple of the request-ring size (in bytes).
886 */
887 align = 0;
888 if ((unsigned long)ha->queues_dma & (MEM_ALIGN_VALUE - 1))
889 align = MEM_ALIGN_VALUE - ((unsigned long)ha->queues_dma &
890 (MEM_ALIGN_VALUE - 1));
891
892 /* Update request and response queue pointers. */
893 ha->request_dma = ha->queues_dma + align;
894 ha->request_ring = (struct queue_entry *) (ha->queues + align);
895 ha->response_dma = ha->queues_dma + align +
896 (REQUEST_QUEUE_DEPTH * QUEUE_SIZE);
897 ha->response_ring = (struct queue_entry *) (ha->queues + align +
898 (REQUEST_QUEUE_DEPTH *
899 QUEUE_SIZE));
900 ha->shadow_regs_dma = ha->queues_dma + align +
901 (REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +
902 (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE);
903 ha->shadow_regs = (struct shadow_regs *) (ha->queues + align +
904 (REQUEST_QUEUE_DEPTH *
905 QUEUE_SIZE) +
906 (RESPONSE_QUEUE_DEPTH *
907 QUEUE_SIZE));
908
909 /* Allocate memory for srb pool. */
910 ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab,
911 mempool_free_slab, srb_cachep);
912 if (ha->srb_mempool == NULL) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +0530913 ql4_printk(KERN_WARNING, ha,
914 "Memory Allocation failed - SRB Pool.\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -0700915
916 goto mem_alloc_error_exit;
917 }
918
919 return QLA_SUCCESS;
920
921mem_alloc_error_exit:
922 qla4xxx_mem_free(ha);
923 return QLA_ERROR;
924}
925
926/**
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530927 * qla4_8xxx_check_fw_alive - Check firmware health
928 * @ha: Pointer to host adapter structure.
929 *
930 * Context: Interrupt
931 **/
932static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha)
933{
934 uint32_t fw_heartbeat_counter, halt_status;
935
936 fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
Lalit Chandivade2232be02010-07-30 14:38:47 +0530937 /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */
938 if (fw_heartbeat_counter == 0xffffffff) {
939 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen "
940 "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n",
941 ha->host_no, __func__));
942 return;
943 }
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530944
945 if (ha->fw_heartbeat_counter == fw_heartbeat_counter) {
946 ha->seconds_since_last_heartbeat++;
947 /* FW not alive after 2 seconds */
948 if (ha->seconds_since_last_heartbeat == 2) {
949 ha->seconds_since_last_heartbeat = 0;
950 halt_status = qla4_8xxx_rd_32(ha,
Vikas Chaudhary68d92eb2011-05-17 23:17:05 -0700951 QLA82XX_PEG_HALT_STATUS1);
952
953 ql4_printk(KERN_INFO, ha,
954 "scsi(%ld): %s, Dumping hw/fw registers:\n "
955 " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2:"
956 " 0x%x,\n PEG_NET_0_PC: 0x%x, PEG_NET_1_PC:"
957 " 0x%x,\n PEG_NET_2_PC: 0x%x, PEG_NET_3_PC:"
958 " 0x%x,\n PEG_NET_4_PC: 0x%x\n",
959 ha->host_no, __func__, halt_status,
960 qla4_8xxx_rd_32(ha,
961 QLA82XX_PEG_HALT_STATUS2),
962 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_0 +
963 0x3c),
964 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_1 +
965 0x3c),
966 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_2 +
967 0x3c),
968 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_3 +
969 0x3c),
970 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 +
971 0x3c));
Nilesh Javali21033632010-07-30 14:28:07 +0530972
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530973 /* Since we cannot change dev_state in interrupt
974 * context, set appropriate DPC flag then wakeup
975 * DPC */
976 if (halt_status & HALT_STATUS_UNRECOVERABLE)
977 set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
978 else {
979 printk("scsi%ld: %s: detect abort needed!\n",
980 ha->host_no, __func__);
981 set_bit(DPC_RESET_HA, &ha->dpc_flags);
982 }
983 qla4xxx_wake_dpc(ha);
Nilesh Javali21033632010-07-30 14:28:07 +0530984 qla4xxx_mailbox_premature_completion(ha);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530985 }
Lalit Chandivade99457d72010-10-06 22:49:32 -0700986 } else
987 ha->seconds_since_last_heartbeat = 0;
988
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530989 ha->fw_heartbeat_counter = fw_heartbeat_counter;
990}
991
992/**
993 * qla4_8xxx_watchdog - Poll dev state
994 * @ha: Pointer to host adapter structure.
995 *
996 * Context: Interrupt
997 **/
998void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
999{
1000 uint32_t dev_state;
1001
1002 dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
1003
1004 /* don't poll if reset is going on */
Lalit Chandivaded56a1f72010-12-02 22:12:45 -08001005 if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
1006 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
Vikas Chaudhary977f46a2011-05-17 23:17:08 -07001007 test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) {
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301008 if (dev_state == QLA82XX_DEV_NEED_RESET &&
1009 !test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
Vikas Chaudhary3930b8c2010-12-02 22:12:47 -08001010 if (!ql4xdontresethba) {
1011 ql4_printk(KERN_INFO, ha, "%s: HW State: "
1012 "NEED RESET!\n", __func__);
1013 set_bit(DPC_RESET_HA, &ha->dpc_flags);
1014 qla4xxx_wake_dpc(ha);
1015 qla4xxx_mailbox_premature_completion(ha);
1016 }
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301017 } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
1018 !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {
Vikas Chaudhary3930b8c2010-12-02 22:12:47 -08001019 ql4_printk(KERN_INFO, ha, "%s: HW State: NEED QUIES!\n",
1020 __func__);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301021 set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags);
1022 qla4xxx_wake_dpc(ha);
1023 } else {
1024 /* Check firmware health */
1025 qla4_8xxx_check_fw_alive(ha);
1026 }
1027 }
1028}
1029
1030/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07001031 * qla4xxx_timer - checks every second for work to do.
1032 * @ha: Pointer to host adapter structure.
1033 **/
1034static void qla4xxx_timer(struct scsi_qla_host *ha)
1035{
1036 struct ddb_entry *ddb_entry, *dtemp;
1037 int start_dpc = 0;
Lalit Chandivade2232be02010-07-30 14:38:47 +05301038 uint16_t w;
1039
1040 /* If we are in the middle of AER/EEH processing
1041 * skip any processing and reschedule the timer
1042 */
1043 if (test_bit(AF_EEH_BUSY, &ha->flags)) {
1044 mod_timer(&ha->timer, jiffies + HZ);
1045 return;
1046 }
1047
1048 /* Hardware read to trigger an EEH error during mailbox waits. */
1049 if (!pci_channel_offline(ha->pdev))
1050 pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001051
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301052 if (is_qla8022(ha)) {
1053 qla4_8xxx_watchdog(ha);
1054 }
1055
David Somayajuluafaf5a22006-09-19 10:28:00 -07001056 /* Search for relogin's to time-out and port down retry. */
1057 list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
1058 /* Count down time between sending relogins */
1059 if (adapter_up(ha) &&
1060 !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
1061 atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
1062 if (atomic_read(&ddb_entry->retry_relogin_timer) !=
1063 INVALID_ENTRY) {
1064 if (atomic_read(&ddb_entry->retry_relogin_timer)
1065 == 0) {
1066 atomic_set(&ddb_entry->
1067 retry_relogin_timer,
1068 INVALID_ENTRY);
1069 set_bit(DPC_RELOGIN_DEVICE,
1070 &ha->dpc_flags);
1071 set_bit(DF_RELOGIN, &ddb_entry->flags);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301072 DEBUG2(printk("scsi%ld: %s: ddb [%d]"
David Somayajuluafaf5a22006-09-19 10:28:00 -07001073 " login device\n",
1074 ha->host_no, __func__,
1075 ddb_entry->fw_ddb_index));
1076 } else
1077 atomic_dec(&ddb_entry->
1078 retry_relogin_timer);
1079 }
1080 }
1081
1082 /* Wait for relogin to timeout */
1083 if (atomic_read(&ddb_entry->relogin_timer) &&
1084 (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) {
1085 /*
1086 * If the relogin times out and the device is
1087 * still NOT ONLINE then try and relogin again.
1088 */
1089 if (atomic_read(&ddb_entry->state) !=
1090 DDB_STATE_ONLINE &&
1091 ddb_entry->fw_ddb_device_state ==
1092 DDB_DS_SESSION_FAILED) {
1093 /* Reset retry relogin timer */
1094 atomic_inc(&ddb_entry->relogin_retry_count);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301095 DEBUG2(printk("scsi%ld: ddb [%d] relogin"
David Somayajuluafaf5a22006-09-19 10:28:00 -07001096 " timed out-retrying"
1097 " relogin (%d)\n",
1098 ha->host_no,
1099 ddb_entry->fw_ddb_index,
1100 atomic_read(&ddb_entry->
1101 relogin_retry_count))
1102 );
1103 start_dpc++;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301104 DEBUG(printk("scsi%ld:%d:%d: ddb [%d] "
Justin P. Mattockcd09b2c2011-01-28 11:49:08 -08001105 "initiate relogin after"
David Somayajuluafaf5a22006-09-19 10:28:00 -07001106 " %d seconds\n",
1107 ha->host_no, ddb_entry->bus,
1108 ddb_entry->target,
1109 ddb_entry->fw_ddb_index,
1110 ddb_entry->default_time2wait + 4)
1111 );
1112
1113 atomic_set(&ddb_entry->retry_relogin_timer,
1114 ddb_entry->default_time2wait + 4);
1115 }
1116 }
1117 }
1118
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301119 if (!is_qla8022(ha)) {
1120 /* Check for heartbeat interval. */
1121 if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE &&
1122 ha->heartbeat_interval != 0) {
1123 ha->seconds_since_last_heartbeat++;
1124 if (ha->seconds_since_last_heartbeat >
1125 ha->heartbeat_interval + 2)
1126 set_bit(DPC_RESET_HA, &ha->dpc_flags);
1127 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07001128 }
1129
David Somayajuluafaf5a22006-09-19 10:28:00 -07001130 /* Wakeup the dpc routine for this adapter, if needed. */
Lalit Chandivade1b468072011-05-17 23:17:09 -07001131 if (start_dpc ||
David Somayajuluafaf5a22006-09-19 10:28:00 -07001132 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
1133 test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) ||
1134 test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) ||
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301135 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||
David Somayajuluafaf5a22006-09-19 10:28:00 -07001136 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
1137 test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05301138 test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) ||
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301139 test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||
1140 test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||
Lalit Chandivade1b468072011-05-17 23:17:09 -07001141 test_bit(DPC_AEN, &ha->dpc_flags)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07001142 DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
1143 " - dpc flags = 0x%lx\n",
1144 ha->host_no, __func__, ha->dpc_flags));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301145 qla4xxx_wake_dpc(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001146 }
1147
1148 /* Reschedule timer thread to call us back in one second */
1149 mod_timer(&ha->timer, jiffies + HZ);
1150
1151 DEBUG2(ha->seconds_since_last_intr++);
1152}
1153
1154/**
1155 * qla4xxx_cmd_wait - waits for all outstanding commands to complete
1156 * @ha: Pointer to host adapter structure.
1157 *
1158 * This routine stalls the driver until all outstanding commands are returned.
1159 * Caller must release the Hardware Lock prior to calling this routine.
1160 **/
1161static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
1162{
1163 uint32_t index = 0;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001164 unsigned long flags;
1165 struct scsi_cmnd *cmd;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001166
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301167 unsigned long wtime = jiffies + (WAIT_CMD_TOV * HZ);
1168
1169 DEBUG2(ql4_printk(KERN_INFO, ha, "Wait up to %d seconds for cmds to "
1170 "complete\n", WAIT_CMD_TOV));
1171
1172 while (!time_after_eq(jiffies, wtime)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07001173 spin_lock_irqsave(&ha->hardware_lock, flags);
1174 /* Find a command that hasn't completed. */
1175 for (index = 0; index < ha->host->can_queue; index++) {
1176 cmd = scsi_host_find_tag(ha->host, index);
Mike Christiea1e00632010-10-26 05:45:30 -07001177 /*
1178 * We cannot just check if the index is valid,
1179 * becase if we are run from the scsi eh, then
1180 * the scsi/block layer is going to prevent
1181 * the tag from being released.
1182 */
1183 if (cmd != NULL && CMD_SP(cmd))
David Somayajuluafaf5a22006-09-19 10:28:00 -07001184 break;
1185 }
1186 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1187
1188 /* If No Commands are pending, wait is complete */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301189 if (index == ha->host->can_queue)
1190 return QLA_SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001191
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301192 msleep(1000);
1193 }
1194 /* If we timed out on waiting for commands to come back
1195 * return ERROR. */
1196 return QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001197}
1198
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301199int qla4xxx_hw_reset(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001200{
David Somayajuluafaf5a22006-09-19 10:28:00 -07001201 uint32_t ctrl_status;
David C Somayajulu477ffb92007-01-22 12:26:11 -08001202 unsigned long flags = 0;
1203
1204 DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));
David Somayajuluafaf5a22006-09-19 10:28:00 -07001205
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301206 if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS)
1207 return QLA_ERROR;
1208
David Somayajuluafaf5a22006-09-19 10:28:00 -07001209 spin_lock_irqsave(&ha->hardware_lock, flags);
1210
1211 /*
1212 * If the SCSI Reset Interrupt bit is set, clear it.
1213 * Otherwise, the Soft Reset won't work.
1214 */
1215 ctrl_status = readw(&ha->reg->ctrl_status);
1216 if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0)
1217 writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);
1218
1219 /* Issue Soft Reset */
1220 writel(set_rmask(CSR_SOFT_RESET), &ha->reg->ctrl_status);
1221 readl(&ha->reg->ctrl_status);
1222
1223 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301224 return QLA_SUCCESS;
David C Somayajulu477ffb92007-01-22 12:26:11 -08001225}
1226
1227/**
1228 * qla4xxx_soft_reset - performs soft reset.
1229 * @ha: Pointer to host adapter structure.
1230 **/
1231int qla4xxx_soft_reset(struct scsi_qla_host *ha)
1232{
1233 uint32_t max_wait_time;
1234 unsigned long flags = 0;
Vikas Chaudharyf931c532010-10-06 22:48:07 -07001235 int status;
David C Somayajulu477ffb92007-01-22 12:26:11 -08001236 uint32_t ctrl_status;
1237
Vikas Chaudharyf931c532010-10-06 22:48:07 -07001238 status = qla4xxx_hw_reset(ha);
1239 if (status != QLA_SUCCESS)
1240 return status;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001241
Vikas Chaudharyf931c532010-10-06 22:48:07 -07001242 status = QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001243 /* Wait until the Network Reset Intr bit is cleared */
1244 max_wait_time = RESET_INTR_TOV;
1245 do {
1246 spin_lock_irqsave(&ha->hardware_lock, flags);
1247 ctrl_status = readw(&ha->reg->ctrl_status);
1248 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1249
1250 if ((ctrl_status & CSR_NET_RESET_INTR) == 0)
1251 break;
1252
1253 msleep(1000);
1254 } while ((--max_wait_time));
1255
1256 if ((ctrl_status & CSR_NET_RESET_INTR) != 0) {
1257 DEBUG2(printk(KERN_WARNING
1258 "scsi%ld: Network Reset Intr not cleared by "
1259 "Network function, clearing it now!\n",
1260 ha->host_no));
1261 spin_lock_irqsave(&ha->hardware_lock, flags);
1262 writel(set_rmask(CSR_NET_RESET_INTR), &ha->reg->ctrl_status);
1263 readl(&ha->reg->ctrl_status);
1264 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1265 }
1266
1267 /* Wait until the firmware tells us the Soft Reset is done */
1268 max_wait_time = SOFT_RESET_TOV;
1269 do {
1270 spin_lock_irqsave(&ha->hardware_lock, flags);
1271 ctrl_status = readw(&ha->reg->ctrl_status);
1272 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1273
1274 if ((ctrl_status & CSR_SOFT_RESET) == 0) {
1275 status = QLA_SUCCESS;
1276 break;
1277 }
1278
1279 msleep(1000);
1280 } while ((--max_wait_time));
1281
1282 /*
1283 * Also, make sure that the SCSI Reset Interrupt bit has been cleared
1284 * after the soft reset has taken place.
1285 */
1286 spin_lock_irqsave(&ha->hardware_lock, flags);
1287 ctrl_status = readw(&ha->reg->ctrl_status);
1288 if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0) {
1289 writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);
1290 readl(&ha->reg->ctrl_status);
1291 }
1292 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1293
1294 /* If soft reset fails then most probably the bios on other
1295 * function is also enabled.
1296 * Since the initialization is sequential the other fn
1297 * wont be able to acknowledge the soft reset.
1298 * Issue a force soft reset to workaround this scenario.
1299 */
1300 if (max_wait_time == 0) {
1301 /* Issue Force Soft Reset */
1302 spin_lock_irqsave(&ha->hardware_lock, flags);
1303 writel(set_rmask(CSR_FORCE_SOFT_RESET), &ha->reg->ctrl_status);
1304 readl(&ha->reg->ctrl_status);
1305 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1306 /* Wait until the firmware tells us the Soft Reset is done */
1307 max_wait_time = SOFT_RESET_TOV;
1308 do {
1309 spin_lock_irqsave(&ha->hardware_lock, flags);
1310 ctrl_status = readw(&ha->reg->ctrl_status);
1311 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1312
1313 if ((ctrl_status & CSR_FORCE_SOFT_RESET) == 0) {
1314 status = QLA_SUCCESS;
1315 break;
1316 }
1317
1318 msleep(1000);
1319 } while ((--max_wait_time));
1320 }
1321
1322 return status;
1323}
1324
1325/**
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301326 * qla4xxx_abort_active_cmds - returns all outstanding i/o requests to O.S.
David Somayajuluafaf5a22006-09-19 10:28:00 -07001327 * @ha: Pointer to host adapter structure.
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301328 * @res: returned scsi status
David Somayajuluafaf5a22006-09-19 10:28:00 -07001329 *
1330 * This routine is called just prior to a HARD RESET to return all
1331 * outstanding commands back to the Operating System.
1332 * Caller should make sure that the following locks are released
1333 * before this calling routine: Hardware lock, and io_request_lock.
1334 **/
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301335static void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001336{
1337 struct srb *srb;
1338 int i;
1339 unsigned long flags;
1340
1341 spin_lock_irqsave(&ha->hardware_lock, flags);
1342 for (i = 0; i < ha->host->can_queue; i++) {
1343 srb = qla4xxx_del_from_active_array(ha, i);
1344 if (srb != NULL) {
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301345 srb->cmd->result = res;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05301346 kref_put(&srb->srb_ref, qla4xxx_srb_compl);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001347 }
1348 }
1349 spin_unlock_irqrestore(&ha->hardware_lock, flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001350}
1351
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301352void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha)
1353{
1354 clear_bit(AF_ONLINE, &ha->flags);
1355
1356 /* Disable the board */
1357 ql4_printk(KERN_INFO, ha, "Disabling the board\n");
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301358
1359 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
1360 qla4xxx_mark_all_devices_missing(ha);
1361 clear_bit(AF_INIT_DONE, &ha->flags);
1362}
1363
David Somayajuluafaf5a22006-09-19 10:28:00 -07001364/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07001365 * qla4xxx_recover_adapter - recovers adapter after a fatal error
1366 * @ha: Pointer to host adapter structure.
David Somayajuluafaf5a22006-09-19 10:28:00 -07001367 **/
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301368static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001369{
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301370 int status = QLA_ERROR;
1371 uint8_t reset_chip = 0;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001372
1373 /* Stall incoming I/O until we are done */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301374 scsi_block_requests(ha->host);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001375 clear_bit(AF_ONLINE, &ha->flags);
Mike Christie50a29ae2008-03-04 13:26:53 -06001376
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301377 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__));
David Somayajuluafaf5a22006-09-19 10:28:00 -07001378
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301379 set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001380
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301381 if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
1382 reset_chip = 1;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001383
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301384 /* For the DPC_RESET_HA_INTR case (ISP-4xxx specific)
1385 * do not reset adapter, jump to initialize_adapter */
1386 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
1387 status = QLA_SUCCESS;
1388 goto recover_ha_init_adapter;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001389 }
1390
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301391 /* For the ISP-82xx adapter, issue a stop_firmware if invoked
1392 * from eh_host_reset or ioctl module */
1393 if (is_qla8022(ha) && !reset_chip &&
1394 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) {
1395
1396 DEBUG2(ql4_printk(KERN_INFO, ha,
1397 "scsi%ld: %s - Performing stop_firmware...\n",
1398 ha->host_no, __func__));
1399 status = ha->isp_ops->reset_firmware(ha);
1400 if (status == QLA_SUCCESS) {
Nilesh Javali2bd1e2be2010-10-06 22:49:20 -07001401 if (!test_bit(AF_FW_RECOVERY, &ha->flags))
1402 qla4xxx_cmd_wait(ha);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301403 ha->isp_ops->disable_intrs(ha);
1404 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
1405 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
1406 } else {
1407 /* If the stop_firmware fails then
1408 * reset the entire chip */
1409 reset_chip = 1;
1410 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
1411 set_bit(DPC_RESET_HA, &ha->dpc_flags);
1412 }
1413 }
1414
1415 /* Issue full chip reset if recovering from a catastrophic error,
1416 * or if stop_firmware fails for ISP-82xx.
1417 * This is the default case for ISP-4xxx */
1418 if (!is_qla8022(ha) || reset_chip) {
Nilesh Javali2bd1e2be2010-10-06 22:49:20 -07001419 if (!test_bit(AF_FW_RECOVERY, &ha->flags))
1420 qla4xxx_cmd_wait(ha);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301421 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
1422 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
1423 DEBUG2(ql4_printk(KERN_INFO, ha,
1424 "scsi%ld: %s - Performing chip reset..\n",
1425 ha->host_no, __func__));
1426 status = ha->isp_ops->reset_chip(ha);
1427 }
1428
1429 /* Flush any pending ddb changed AENs */
1430 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
1431
1432recover_ha_init_adapter:
1433 /* Upon successful firmware/chip reset, re-initialize the adapter */
1434 if (status == QLA_SUCCESS) {
1435 /* For ISP-4xxx, force function 1 to always initialize
1436 * before function 3 to prevent both funcions from
1437 * stepping on top of the other */
1438 if (!is_qla8022(ha) && (ha->mac_index == 3))
1439 ssleep(6);
1440
1441 /* NOTE: AF_ONLINE flag set upon successful completion of
1442 * qla4xxx_initialize_adapter */
1443 status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST);
1444 }
1445
1446 /* Retry failed adapter initialization, if necessary
1447 * Do not retry initialize_adapter for RESET_HA_INTR (ISP-4xxx specific)
1448 * case to prevent ping-pong resets between functions */
1449 if (!test_bit(AF_ONLINE, &ha->flags) &&
1450 !test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07001451 /* Adapter initialization failed, see if we can retry
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301452 * resetting the ha.
1453 * Since we don't want to block the DPC for too long
1454 * with multiple resets in the same thread,
1455 * utilize DPC to retry */
David Somayajuluafaf5a22006-09-19 10:28:00 -07001456 if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) {
1457 ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES;
1458 DEBUG2(printk("scsi%ld: recover adapter - retrying "
1459 "(%d) more times\n", ha->host_no,
1460 ha->retry_reset_ha_cnt));
1461 set_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
1462 status = QLA_ERROR;
1463 } else {
1464 if (ha->retry_reset_ha_cnt > 0) {
1465 /* Schedule another Reset HA--DPC will retry */
1466 ha->retry_reset_ha_cnt--;
1467 DEBUG2(printk("scsi%ld: recover adapter - "
1468 "retry remaining %d\n",
1469 ha->host_no,
1470 ha->retry_reset_ha_cnt));
1471 status = QLA_ERROR;
1472 }
1473
1474 if (ha->retry_reset_ha_cnt == 0) {
1475 /* Recover adapter retries have been exhausted.
1476 * Adapter DEAD */
1477 DEBUG2(printk("scsi%ld: recover adapter "
1478 "failed - board disabled\n",
1479 ha->host_no));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301480 qla4xxx_dead_adapter_cleanup(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001481 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
1482 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301483 clear_bit(DPC_RESET_HA_FW_CONTEXT,
David Somayajuluafaf5a22006-09-19 10:28:00 -07001484 &ha->dpc_flags);
1485 status = QLA_ERROR;
1486 }
1487 }
1488 } else {
1489 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301490 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001491 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
1492 }
1493
1494 ha->adapter_error_count++;
1495
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301496 if (test_bit(AF_ONLINE, &ha->flags))
1497 ha->isp_ops->enable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001498
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301499 scsi_unblock_requests(ha->host);
1500
1501 clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
1502 DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no,
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001503 status == QLA_ERROR ? "FAILED" : "SUCCEEDED"));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301504
David Somayajuluafaf5a22006-09-19 10:28:00 -07001505 return status;
1506}
1507
Vikas Chaudhary2d7924e2011-03-21 03:34:33 -07001508static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)
1509{
1510 struct ddb_entry *ddb_entry, *dtemp;
1511
1512 list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
1513 if ((atomic_read(&ddb_entry->state) == DDB_STATE_MISSING) ||
1514 (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD)) {
1515 if (ddb_entry->fw_ddb_device_state ==
1516 DDB_DS_SESSION_ACTIVE) {
1517 atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
1518 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
1519 " marked ONLINE\n", ha->host_no, __func__,
1520 ddb_entry->fw_ddb_index);
1521
1522 iscsi_unblock_session(ddb_entry->sess);
1523 } else
1524 qla4xxx_relogin_device(ha, ddb_entry);
1525 }
1526 }
1527}
1528
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301529void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
1530{
Lalit Chandivade1b468072011-05-17 23:17:09 -07001531 if (ha->dpc_thread)
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301532 queue_work(ha->dpc_thread, &ha->dpc_work);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301533}
1534
David Somayajuluafaf5a22006-09-19 10:28:00 -07001535/**
1536 * qla4xxx_do_dpc - dpc routine
1537 * @data: in our case pointer to adapter structure
1538 *
1539 * This routine is a task that is schedule by the interrupt handler
1540 * to perform the background processing for interrupts. We put it
1541 * on a task queue that is consumed whenever the scheduler runs; that's
1542 * so you can do anything (i.e. put the process to sleep etc). In fact,
1543 * the mid-level tries to sleep when it reaches the driver threshold
1544 * "host->can_queue". This can cause a panic if we were in our interrupt code.
1545 **/
David Howellsc4028952006-11-22 14:57:56 +00001546static void qla4xxx_do_dpc(struct work_struct *work)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001547{
David Howellsc4028952006-11-22 14:57:56 +00001548 struct scsi_qla_host *ha =
1549 container_of(work, struct scsi_qla_host, dpc_work);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001550 struct ddb_entry *ddb_entry, *dtemp;
David C Somayajulu477ffb92007-01-22 12:26:11 -08001551 int status = QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001552
David C Somayajuluf26b9042006-11-15 16:41:09 -08001553 DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301554 "flags = 0x%08lx, dpc_flags = 0x%08lx\n",
1555 ha->host_no, __func__, ha->flags, ha->dpc_flags))
David Somayajuluafaf5a22006-09-19 10:28:00 -07001556
1557 /* Initialization not yet finished. Don't do anything yet. */
1558 if (!test_bit(AF_INIT_DONE, &ha->flags))
Lalit Chandivade1b468072011-05-17 23:17:09 -07001559 return;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001560
Lalit Chandivade2232be02010-07-30 14:38:47 +05301561 if (test_bit(AF_EEH_BUSY, &ha->flags)) {
1562 DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n",
1563 ha->host_no, __func__, ha->flags));
Lalit Chandivade1b468072011-05-17 23:17:09 -07001564 return;
Lalit Chandivade2232be02010-07-30 14:38:47 +05301565 }
1566
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301567 if (is_qla8022(ha)) {
1568 if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
1569 qla4_8xxx_idc_lock(ha);
1570 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
1571 QLA82XX_DEV_FAILED);
1572 qla4_8xxx_idc_unlock(ha);
1573 ql4_printk(KERN_INFO, ha, "HW State: FAILED\n");
1574 qla4_8xxx_device_state_handler(ha);
1575 }
1576 if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {
1577 qla4_8xxx_need_qsnt_handler(ha);
1578 }
1579 }
1580
1581 if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) &&
1582 (test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
David Somayajuluafaf5a22006-09-19 10:28:00 -07001583 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301584 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) {
1585 if (ql4xdontresethba) {
1586 DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
1587 ha->host_no, __func__));
1588 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
1589 clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
1590 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
1591 goto dpc_post_reset_ha;
1592 }
1593 if (test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||
1594 test_bit(DPC_RESET_HA, &ha->dpc_flags))
1595 qla4xxx_recover_adapter(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001596
David C Somayajulu477ffb92007-01-22 12:26:11 -08001597 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07001598 uint8_t wait_time = RESET_INTR_TOV;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001599
David Somayajuluafaf5a22006-09-19 10:28:00 -07001600 while ((readw(&ha->reg->ctrl_status) &
1601 (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
1602 if (--wait_time == 0)
1603 break;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001604 msleep(1000);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001605 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07001606 if (wait_time == 0)
1607 DEBUG2(printk("scsi%ld: %s: SR|FSR "
1608 "bit not cleared-- resetting\n",
1609 ha->host_no, __func__));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301610 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
David C Somayajulu477ffb92007-01-22 12:26:11 -08001611 if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {
1612 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301613 status = qla4xxx_recover_adapter(ha);
David C Somayajulu477ffb92007-01-22 12:26:11 -08001614 }
1615 clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
1616 if (status == QLA_SUCCESS)
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301617 ha->isp_ops->enable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001618 }
1619 }
1620
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301621dpc_post_reset_ha:
David Somayajuluafaf5a22006-09-19 10:28:00 -07001622 /* ---- process AEN? --- */
1623 if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
1624 qla4xxx_process_aen(ha, PROCESS_ALL_AENS);
1625
1626 /* ---- Get DHCP IP Address? --- */
1627 if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
1628 qla4xxx_get_dhcp_ip_address(ha);
1629
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05301630 /* ---- link change? --- */
1631 if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
1632 if (!test_bit(AF_LINK_UP, &ha->flags)) {
1633 /* ---- link down? --- */
Vikas Chaudhary2d7924e2011-03-21 03:34:33 -07001634 qla4xxx_mark_all_devices_missing(ha);
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05301635 } else {
1636 /* ---- link up? --- *
1637 * F/W will auto login to all devices ONLY ONCE after
1638 * link up during driver initialization and runtime
1639 * fatal error recovery. Therefore, the driver must
1640 * manually relogin to devices when recovering from
1641 * connection failures, logouts, expired KATO, etc. */
1642
Vikas Chaudhary2d7924e2011-03-21 03:34:33 -07001643 qla4xxx_relogin_all_devices(ha);
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05301644 }
1645 }
1646
David Somayajuluafaf5a22006-09-19 10:28:00 -07001647 /* ---- relogin device? --- */
1648 if (adapter_up(ha) &&
1649 test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
1650 list_for_each_entry_safe(ddb_entry, dtemp,
1651 &ha->ddb_list, list) {
1652 if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) &&
1653 atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
1654 qla4xxx_relogin_device(ha, ddb_entry);
1655
1656 /*
1657 * If mbx cmd times out there is no point
1658 * in continuing further.
1659 * With large no of targets this can hang
1660 * the system.
1661 */
1662 if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
1663 printk(KERN_WARNING "scsi%ld: %s: "
1664 "need to reset hba\n",
1665 ha->host_no, __func__);
1666 break;
1667 }
1668 }
1669 }
Vikas Chaudhary0753b482010-07-30 14:27:19 +05301670
David Somayajuluafaf5a22006-09-19 10:28:00 -07001671}
1672
1673/**
1674 * qla4xxx_free_adapter - release the adapter
1675 * @ha: pointer to adapter structure
1676 **/
1677static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
1678{
1679
1680 if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) {
1681 /* Turn-off interrupts on the card. */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301682 ha->isp_ops->disable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001683 }
1684
David Somayajuluafaf5a22006-09-19 10:28:00 -07001685 /* Remove timer thread, if present */
1686 if (ha->timer_active)
1687 qla4xxx_stop_timer(ha);
1688
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301689 /* Kill the kernel thread for this host */
1690 if (ha->dpc_thread)
1691 destroy_workqueue(ha->dpc_thread);
1692
1693 /* Put firmware in known state */
1694 ha->isp_ops->reset_firmware(ha);
1695
1696 if (is_qla8022(ha)) {
1697 qla4_8xxx_idc_lock(ha);
1698 qla4_8xxx_clear_drv_active(ha);
1699 qla4_8xxx_idc_unlock(ha);
1700 }
1701
David Somayajuluafaf5a22006-09-19 10:28:00 -07001702 /* Detach interrupts */
1703 if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301704 qla4xxx_free_irqs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001705
David C Somayajulubee4fe82007-05-23 18:03:32 -07001706 /* free extra memory */
1707 qla4xxx_mem_free(ha);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301708}
David C Somayajulubee4fe82007-05-23 18:03:32 -07001709
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301710int qla4_8xxx_iospace_config(struct scsi_qla_host *ha)
1711{
1712 int status = 0;
1713 uint8_t revision_id;
1714 unsigned long mem_base, mem_len, db_base, db_len;
1715 struct pci_dev *pdev = ha->pdev;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001716
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301717 status = pci_request_regions(pdev, DRIVER_NAME);
1718 if (status) {
1719 printk(KERN_WARNING
1720 "scsi(%ld) Failed to reserve PIO regions (%s) "
1721 "status=%d\n", ha->host_no, pci_name(pdev), status);
1722 goto iospace_error_exit;
1723 }
1724
1725 pci_read_config_byte(pdev, PCI_REVISION_ID, &revision_id);
1726 DEBUG2(printk(KERN_INFO "%s: revision-id=%d\n",
1727 __func__, revision_id));
1728 ha->revision_id = revision_id;
1729
1730 /* remap phys address */
1731 mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
1732 mem_len = pci_resource_len(pdev, 0);
1733 DEBUG2(printk(KERN_INFO "%s: ioremap from %lx a size of %lx\n",
1734 __func__, mem_base, mem_len));
1735
1736 /* mapping of pcibase pointer */
1737 ha->nx_pcibase = (unsigned long)ioremap(mem_base, mem_len);
1738 if (!ha->nx_pcibase) {
1739 printk(KERN_ERR
1740 "cannot remap MMIO (%s), aborting\n", pci_name(pdev));
1741 pci_release_regions(ha->pdev);
1742 goto iospace_error_exit;
1743 }
1744
1745 /* Mapping of IO base pointer, door bell read and write pointer */
1746
1747 /* mapping of IO base pointer */
1748 ha->qla4_8xxx_reg =
1749 (struct device_reg_82xx __iomem *)((uint8_t *)ha->nx_pcibase +
1750 0xbc000 + (ha->pdev->devfn << 11));
1751
1752 db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */
1753 db_len = pci_resource_len(pdev, 4);
1754
Shyam Sundar2657c802010-10-06 22:50:29 -07001755 ha->nx_db_wr_ptr = (ha->pdev->devfn == 4 ? QLA82XX_CAM_RAM_DB1 :
1756 QLA82XX_CAM_RAM_DB2);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301757
Shyam Sundar2657c802010-10-06 22:50:29 -07001758 return 0;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301759iospace_error_exit:
1760 return -ENOMEM;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001761}
1762
1763/***
1764 * qla4xxx_iospace_config - maps registers
1765 * @ha: pointer to adapter structure
1766 *
1767 * This routines maps HBA's registers from the pci address space
1768 * into the kernel virtual address space for memory mapped i/o.
1769 **/
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301770int qla4xxx_iospace_config(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001771{
1772 unsigned long pio, pio_len, pio_flags;
1773 unsigned long mmio, mmio_len, mmio_flags;
1774
1775 pio = pci_resource_start(ha->pdev, 0);
1776 pio_len = pci_resource_len(ha->pdev, 0);
1777 pio_flags = pci_resource_flags(ha->pdev, 0);
1778 if (pio_flags & IORESOURCE_IO) {
1779 if (pio_len < MIN_IOBASE_LEN) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301780 ql4_printk(KERN_WARNING, ha,
David Somayajuluafaf5a22006-09-19 10:28:00 -07001781 "Invalid PCI I/O region size\n");
1782 pio = 0;
1783 }
1784 } else {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301785 ql4_printk(KERN_WARNING, ha, "region #0 not a PIO resource\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001786 pio = 0;
1787 }
1788
1789 /* Use MMIO operations for all accesses. */
1790 mmio = pci_resource_start(ha->pdev, 1);
1791 mmio_len = pci_resource_len(ha->pdev, 1);
1792 mmio_flags = pci_resource_flags(ha->pdev, 1);
1793
1794 if (!(mmio_flags & IORESOURCE_MEM)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301795 ql4_printk(KERN_ERR, ha,
1796 "region #0 not an MMIO resource, aborting\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001797
1798 goto iospace_error_exit;
1799 }
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301800
David Somayajuluafaf5a22006-09-19 10:28:00 -07001801 if (mmio_len < MIN_IOBASE_LEN) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301802 ql4_printk(KERN_ERR, ha,
1803 "Invalid PCI mem region size, aborting\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001804 goto iospace_error_exit;
1805 }
1806
1807 if (pci_request_regions(ha->pdev, DRIVER_NAME)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301808 ql4_printk(KERN_WARNING, ha,
1809 "Failed to reserve PIO/MMIO regions\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001810
1811 goto iospace_error_exit;
1812 }
1813
1814 ha->pio_address = pio;
1815 ha->pio_length = pio_len;
1816 ha->reg = ioremap(mmio, MIN_IOBASE_LEN);
1817 if (!ha->reg) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301818 ql4_printk(KERN_ERR, ha,
1819 "cannot remap MMIO, aborting\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001820
1821 goto iospace_error_exit;
1822 }
1823
1824 return 0;
1825
1826iospace_error_exit:
1827 return -ENOMEM;
1828}
1829
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301830static struct isp_operations qla4xxx_isp_ops = {
1831 .iospace_config = qla4xxx_iospace_config,
1832 .pci_config = qla4xxx_pci_config,
1833 .disable_intrs = qla4xxx_disable_intrs,
1834 .enable_intrs = qla4xxx_enable_intrs,
1835 .start_firmware = qla4xxx_start_firmware,
1836 .intr_handler = qla4xxx_intr_handler,
1837 .interrupt_service_routine = qla4xxx_interrupt_service_routine,
1838 .reset_chip = qla4xxx_soft_reset,
1839 .reset_firmware = qla4xxx_hw_reset,
1840 .queue_iocb = qla4xxx_queue_iocb,
1841 .complete_iocb = qla4xxx_complete_iocb,
1842 .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out,
1843 .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in,
1844 .get_sys_info = qla4xxx_get_sys_info,
1845};
1846
1847static struct isp_operations qla4_8xxx_isp_ops = {
1848 .iospace_config = qla4_8xxx_iospace_config,
1849 .pci_config = qla4_8xxx_pci_config,
1850 .disable_intrs = qla4_8xxx_disable_intrs,
1851 .enable_intrs = qla4_8xxx_enable_intrs,
1852 .start_firmware = qla4_8xxx_load_risc,
1853 .intr_handler = qla4_8xxx_intr_handler,
1854 .interrupt_service_routine = qla4_8xxx_interrupt_service_routine,
1855 .reset_chip = qla4_8xxx_isp_reset,
1856 .reset_firmware = qla4_8xxx_stop_firmware,
1857 .queue_iocb = qla4_8xxx_queue_iocb,
1858 .complete_iocb = qla4_8xxx_complete_iocb,
1859 .rd_shdw_req_q_out = qla4_8xxx_rd_shdw_req_q_out,
1860 .rd_shdw_rsp_q_in = qla4_8xxx_rd_shdw_rsp_q_in,
1861 .get_sys_info = qla4_8xxx_get_sys_info,
1862};
1863
1864uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
1865{
1866 return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out);
1867}
1868
1869uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
1870{
1871 return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->req_q_out));
1872}
1873
1874uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
1875{
1876 return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in);
1877}
1878
1879uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
1880{
1881 return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in));
1882}
1883
David Somayajuluafaf5a22006-09-19 10:28:00 -07001884/**
1885 * qla4xxx_probe_adapter - callback function to probe HBA
1886 * @pdev: pointer to pci_dev structure
1887 * @pci_device_id: pointer to pci_device entry
1888 *
1889 * This routine will probe for Qlogic 4xxx iSCSI host adapters.
1890 * It returns zero if successful. It also initializes all data necessary for
1891 * the driver.
1892 **/
1893static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
1894 const struct pci_device_id *ent)
1895{
1896 int ret = -ENODEV, status;
1897 struct Scsi_Host *host;
1898 struct scsi_qla_host *ha;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001899 uint8_t init_retry_count = 0;
1900 char buf[34];
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301901 struct qla4_8xxx_legacy_intr_set *nx_legacy_intr;
Prasanna Mumbaif9880e72011-03-21 03:34:26 -07001902 uint32_t dev_state;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001903
1904 if (pci_enable_device(pdev))
1905 return -1;
1906
1907 host = scsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha));
1908 if (host == NULL) {
1909 printk(KERN_WARNING
1910 "qla4xxx: Couldn't allocate host from scsi layer!\n");
1911 goto probe_disable_device;
1912 }
1913
1914 /* Clear our data area */
1915 ha = (struct scsi_qla_host *) host->hostdata;
1916 memset(ha, 0, sizeof(*ha));
1917
1918 /* Save the information from PCI BIOS. */
1919 ha->pdev = pdev;
1920 ha->host = host;
1921 ha->host_no = host->host_no;
1922
Lalit Chandivade2232be02010-07-30 14:38:47 +05301923 pci_enable_pcie_error_reporting(pdev);
1924
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301925 /* Setup Runtime configurable options */
1926 if (is_qla8022(ha)) {
1927 ha->isp_ops = &qla4_8xxx_isp_ops;
1928 rwlock_init(&ha->hw_lock);
1929 ha->qdr_sn_window = -1;
1930 ha->ddr_mn_window = -1;
1931 ha->curr_window = 255;
1932 ha->func_num = PCI_FUNC(ha->pdev->devfn);
1933 nx_legacy_intr = &legacy_intr[ha->func_num];
1934 ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;
1935 ha->nx_legacy_intr.tgt_status_reg =
1936 nx_legacy_intr->tgt_status_reg;
1937 ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;
1938 ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
1939 } else {
1940 ha->isp_ops = &qla4xxx_isp_ops;
1941 }
1942
Lalit Chandivade2232be02010-07-30 14:38:47 +05301943 /* Set EEH reset type to fundamental if required by hba */
1944 if (is_qla8022(ha))
1945 pdev->needs_freset = 1;
1946
David Somayajuluafaf5a22006-09-19 10:28:00 -07001947 /* Configure PCI I/O space. */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301948 ret = ha->isp_ops->iospace_config(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001949 if (ret)
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301950 goto probe_failed_ioconfig;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001951
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301952 ql4_printk(KERN_INFO, ha, "Found an ISP%04x, irq %d, iobase 0x%p\n",
David Somayajuluafaf5a22006-09-19 10:28:00 -07001953 pdev->device, pdev->irq, ha->reg);
1954
1955 qla4xxx_config_dma_addressing(ha);
1956
1957 /* Initialize lists and spinlocks. */
1958 INIT_LIST_HEAD(&ha->ddb_list);
1959 INIT_LIST_HEAD(&ha->free_srb_q);
1960
1961 mutex_init(&ha->mbox_sem);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301962 init_completion(&ha->mbx_intr_comp);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001963
1964 spin_lock_init(&ha->hardware_lock);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001965
1966 /* Allocate dma buffers */
1967 if (qla4xxx_mem_alloc(ha)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05301968 ql4_printk(KERN_WARNING, ha,
1969 "[ERROR] Failed to allocate memory for adapter\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07001970
1971 ret = -ENOMEM;
1972 goto probe_failed;
1973 }
1974
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301975 if (is_qla8022(ha))
1976 (void) qla4_8xxx_get_flash_info(ha);
1977
David Somayajuluafaf5a22006-09-19 10:28:00 -07001978 /*
1979 * Initialize the Host adapter request/response queues and
1980 * firmware
1981 * NOTE: interrupts enabled upon successful completion
1982 */
1983 status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301984 while ((!test_bit(AF_ONLINE, &ha->flags)) &&
1985 init_retry_count++ < MAX_INIT_RETRIES) {
Prasanna Mumbaif9880e72011-03-21 03:34:26 -07001986
1987 if (is_qla8022(ha)) {
1988 qla4_8xxx_idc_lock(ha);
1989 dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
1990 qla4_8xxx_idc_unlock(ha);
1991 if (dev_state == QLA82XX_DEV_FAILED) {
1992 ql4_printk(KERN_WARNING, ha, "%s: don't retry "
1993 "initialize adapter. H/W is in failed state\n",
1994 __func__);
1995 break;
1996 }
1997 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07001998 DEBUG2(printk("scsi: %s: retrying adapter initialization "
1999 "(%d)\n", __func__, init_retry_count));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302000
2001 if (ha->isp_ops->reset_chip(ha) == QLA_ERROR)
2002 continue;
2003
David Somayajuluafaf5a22006-09-19 10:28:00 -07002004 status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
2005 }
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302006
2007 if (!test_bit(AF_ONLINE, &ha->flags)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302008 ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07002009
Lalit Chandivadefe998522010-12-02 22:12:36 -08002010 if (is_qla8022(ha) && ql4xdontresethba) {
2011 /* Put the device in failed state. */
2012 DEBUG2(printk(KERN_ERR "HW STATE: FAILED\n"));
2013 qla4_8xxx_idc_lock(ha);
2014 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
2015 QLA82XX_DEV_FAILED);
2016 qla4_8xxx_idc_unlock(ha);
2017 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07002018 ret = -ENODEV;
2019 goto probe_failed;
2020 }
2021
2022 host->cmd_per_lun = 3;
2023 host->max_channel = 0;
2024 host->max_lun = MAX_LUNS - 1;
2025 host->max_id = MAX_TARGETS;
2026 host->max_cmd_len = IOCB_MAX_CDB_LEN;
2027 host->can_queue = MAX_SRBS ;
2028 host->transportt = qla4xxx_scsi_transport;
2029
2030 ret = scsi_init_shared_tag_map(host, MAX_SRBS);
2031 if (ret) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302032 ql4_printk(KERN_WARNING, ha,
2033 "scsi_init_shared_tag_map failed\n");
2034 goto probe_failed;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002035 }
2036
2037 /* Startup the kernel thread for this host adapter. */
2038 DEBUG2(printk("scsi: %s: Starting kernel thread for "
2039 "qla4xxx_dpc\n", __func__));
2040 sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no);
2041 ha->dpc_thread = create_singlethread_workqueue(buf);
2042 if (!ha->dpc_thread) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302043 ql4_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07002044 ret = -ENODEV;
2045 goto probe_failed;
2046 }
David Howellsc4028952006-11-22 14:57:56 +00002047 INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002048
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302049 /* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc
2050 * (which is called indirectly by qla4xxx_initialize_adapter),
2051 * so that irqs will be registered after crbinit but before
2052 * mbx_intr_enable.
2053 */
2054 if (!is_qla8022(ha)) {
2055 ret = qla4xxx_request_irqs(ha);
2056 if (ret) {
2057 ql4_printk(KERN_WARNING, ha, "Failed to reserve "
2058 "interrupt %d already in use.\n", pdev->irq);
2059 goto probe_failed;
2060 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07002061 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07002062
Lalit Chandivade2232be02010-07-30 14:38:47 +05302063 pci_save_state(ha->pdev);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302064 ha->isp_ops->enable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002065
2066 /* Start timer thread. */
2067 qla4xxx_start_timer(ha, qla4xxx_timer, 1);
2068
2069 set_bit(AF_INIT_DONE, &ha->flags);
2070
2071 pci_set_drvdata(pdev, ha);
2072
2073 ret = scsi_add_host(host, &pdev->dev);
2074 if (ret)
2075 goto probe_failed;
2076
David Somayajuluafaf5a22006-09-19 10:28:00 -07002077 printk(KERN_INFO
2078 " QLogic iSCSI HBA Driver version: %s\n"
2079 " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",
2080 qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),
2081 ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
2082 ha->patch_number, ha->build_number);
Mike Christie921601b2008-01-31 13:36:49 -06002083 scsi_scan_host(host);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002084 return 0;
2085
David Somayajuluafaf5a22006-09-19 10:28:00 -07002086probe_failed:
2087 qla4xxx_free_adapter(ha);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302088
2089probe_failed_ioconfig:
Lalit Chandivade2232be02010-07-30 14:38:47 +05302090 pci_disable_pcie_error_reporting(pdev);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002091 scsi_host_put(ha->host);
2092
2093probe_disable_device:
2094 pci_disable_device(pdev);
2095
2096 return ret;
2097}
2098
2099/**
Karen Higgins7eece5a2011-03-21 03:34:29 -07002100 * qla4xxx_prevent_other_port_reinit - prevent other port from re-initialize
2101 * @ha: pointer to adapter structure
2102 *
2103 * Mark the other ISP-4xxx port to indicate that the driver is being removed,
2104 * so that the other port will not re-initialize while in the process of
2105 * removing the ha due to driver unload or hba hotplug.
2106 **/
2107static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha)
2108{
2109 struct scsi_qla_host *other_ha = NULL;
2110 struct pci_dev *other_pdev = NULL;
2111 int fn = ISP4XXX_PCI_FN_2;
2112
2113 /*iscsi function numbers for ISP4xxx is 1 and 3*/
2114 if (PCI_FUNC(ha->pdev->devfn) & BIT_1)
2115 fn = ISP4XXX_PCI_FN_1;
2116
2117 other_pdev =
2118 pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
2119 ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
2120 fn));
2121
2122 /* Get other_ha if other_pdev is valid and state is enable*/
2123 if (other_pdev) {
2124 if (atomic_read(&other_pdev->enable_cnt)) {
2125 other_ha = pci_get_drvdata(other_pdev);
2126 if (other_ha) {
2127 set_bit(AF_HA_REMOVAL, &other_ha->flags);
2128 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: "
2129 "Prevent %s reinit\n", __func__,
2130 dev_name(&other_ha->pdev->dev)));
2131 }
2132 }
2133 pci_dev_put(other_pdev);
2134 }
2135}
2136
2137/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07002138 * qla4xxx_remove_adapter - calback function to remove adapter.
2139 * @pci_dev: PCI device pointer
2140 **/
2141static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
2142{
2143 struct scsi_qla_host *ha;
2144
2145 ha = pci_get_drvdata(pdev);
2146
Karen Higgins7eece5a2011-03-21 03:34:29 -07002147 if (!is_qla8022(ha))
2148 qla4xxx_prevent_other_port_reinit(ha);
David C Somayajulubee4fe82007-05-23 18:03:32 -07002149
David Somayajuluafaf5a22006-09-19 10:28:00 -07002150 /* remove devs from iscsi_sessions to scsi_devices */
2151 qla4xxx_free_ddb_list(ha);
2152
2153 scsi_remove_host(ha->host);
2154
2155 qla4xxx_free_adapter(ha);
2156
2157 scsi_host_put(ha->host);
2158
Lalit Chandivade2232be02010-07-30 14:38:47 +05302159 pci_disable_pcie_error_reporting(pdev);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302160 pci_disable_device(pdev);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002161 pci_set_drvdata(pdev, NULL);
2162}
2163
2164/**
2165 * qla4xxx_config_dma_addressing() - Configure OS DMA addressing method.
2166 * @ha: HA context
2167 *
2168 * At exit, the @ha's flags.enable_64bit_addressing set to indicated
2169 * supported addressing method.
2170 */
Adrian Bunk47975472007-04-26 00:35:16 -07002171static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002172{
2173 int retval;
2174
2175 /* Update our PCI device dma_mask for full 64 bit mask */
Yang Hongyang6a355282009-04-06 19:01:13 -07002176 if (pci_set_dma_mask(ha->pdev, DMA_BIT_MASK(64)) == 0) {
2177 if (pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07002178 dev_dbg(&ha->pdev->dev,
2179 "Failed to set 64 bit PCI consistent mask; "
2180 "using 32 bit.\n");
2181 retval = pci_set_consistent_dma_mask(ha->pdev,
Yang Hongyang284901a2009-04-06 19:01:15 -07002182 DMA_BIT_MASK(32));
David Somayajuluafaf5a22006-09-19 10:28:00 -07002183 }
2184 } else
Yang Hongyang284901a2009-04-06 19:01:15 -07002185 retval = pci_set_dma_mask(ha->pdev, DMA_BIT_MASK(32));
David Somayajuluafaf5a22006-09-19 10:28:00 -07002186}
2187
2188static int qla4xxx_slave_alloc(struct scsi_device *sdev)
2189{
2190 struct iscsi_cls_session *sess = starget_to_session(sdev->sdev_target);
2191 struct ddb_entry *ddb = sess->dd_data;
Vikas Chaudhary8bb40332011-03-21 03:34:31 -07002192 int queue_depth = QL4_DEF_QDEPTH;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002193
2194 sdev->hostdata = ddb;
2195 sdev->tagged_supported = 1;
Vikas Chaudhary8bb40332011-03-21 03:34:31 -07002196
2197 if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU)
2198 queue_depth = ql4xmaxqdepth;
2199
2200 scsi_activate_tcq(sdev, queue_depth);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002201 return 0;
2202}
2203
2204static int qla4xxx_slave_configure(struct scsi_device *sdev)
2205{
2206 sdev->tagged_supported = 1;
2207 return 0;
2208}
2209
2210static void qla4xxx_slave_destroy(struct scsi_device *sdev)
2211{
2212 scsi_deactivate_tcq(sdev, 1);
2213}
2214
2215/**
2216 * qla4xxx_del_from_active_array - returns an active srb
2217 * @ha: Pointer to host adapter structure.
Anand Gadiyarfd589a82009-07-16 17:13:03 +02002218 * @index: index into the active_array
David Somayajuluafaf5a22006-09-19 10:28:00 -07002219 *
2220 * This routine removes and returns the srb at the specified index
2221 **/
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302222struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
2223 uint32_t index)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002224{
2225 struct srb *srb = NULL;
Vikas Chaudhary53698872010-04-28 11:41:59 +05302226 struct scsi_cmnd *cmd = NULL;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002227
Vikas Chaudhary53698872010-04-28 11:41:59 +05302228 cmd = scsi_host_find_tag(ha->host, index);
2229 if (!cmd)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002230 return srb;
2231
Vikas Chaudhary53698872010-04-28 11:41:59 +05302232 srb = (struct srb *)CMD_SP(cmd);
2233 if (!srb)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002234 return srb;
2235
2236 /* update counters */
2237 if (srb->flags & SRB_DMA_VALID) {
2238 ha->req_q_count += srb->iocb_cnt;
2239 ha->iocb_cnt -= srb->iocb_cnt;
2240 if (srb->cmd)
Vikas Chaudhary53698872010-04-28 11:41:59 +05302241 srb->cmd->host_scribble =
2242 (unsigned char *)(unsigned long) MAX_SRBS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002243 }
2244 return srb;
2245}
2246
2247/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07002248 * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302249 * @ha: Pointer to host adapter structure.
David Somayajuluafaf5a22006-09-19 10:28:00 -07002250 * @cmd: Scsi Command to wait on.
2251 *
2252 * This routine waits for the command to be returned by the Firmware
2253 * for some max time.
2254 **/
2255static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha,
2256 struct scsi_cmnd *cmd)
2257{
2258 int done = 0;
2259 struct srb *rp;
2260 uint32_t max_wait_time = EH_WAIT_CMD_TOV;
Lalit Chandivade2232be02010-07-30 14:38:47 +05302261 int ret = SUCCESS;
2262
2263 /* Dont wait on command if PCI error is being handled
2264 * by PCI AER driver
2265 */
2266 if (unlikely(pci_channel_offline(ha->pdev)) ||
2267 (test_bit(AF_EEH_BUSY, &ha->flags))) {
2268 ql4_printk(KERN_WARNING, ha, "scsi%ld: Return from %s\n",
2269 ha->host_no, __func__);
2270 return ret;
2271 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07002272
2273 do {
2274 /* Checking to see if its returned to OS */
Vikas Chaudhary53698872010-04-28 11:41:59 +05302275 rp = (struct srb *) CMD_SP(cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002276 if (rp == NULL) {
2277 done++;
2278 break;
2279 }
2280
2281 msleep(2000);
2282 } while (max_wait_time--);
2283
2284 return done;
2285}
2286
2287/**
2288 * qla4xxx_wait_for_hba_online - waits for HBA to come online
2289 * @ha: Pointer to host adapter structure
2290 **/
2291static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
2292{
2293 unsigned long wait_online;
2294
Vikas Chaudharyf581a3f2010-10-06 22:47:48 -07002295 wait_online = jiffies + (HBA_ONLINE_TOV * HZ);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002296 while (time_before(jiffies, wait_online)) {
2297
2298 if (adapter_up(ha))
2299 return QLA_SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002300
2301 msleep(2000);
2302 }
2303
2304 return QLA_ERROR;
2305}
2306
2307/**
Mike Christiece545032008-02-29 18:25:20 -06002308 * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
Anand Gadiyarfd589a82009-07-16 17:13:03 +02002309 * @ha: pointer to HBA
David Somayajuluafaf5a22006-09-19 10:28:00 -07002310 * @t: target id
2311 * @l: lun id
2312 *
2313 * This function waits for all outstanding commands to a lun to complete. It
2314 * returns 0 if all pending commands are returned and 1 otherwise.
2315 **/
Mike Christiece545032008-02-29 18:25:20 -06002316static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
2317 struct scsi_target *stgt,
2318 struct scsi_device *sdev)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002319{
2320 int cnt;
2321 int status = 0;
2322 struct scsi_cmnd *cmd;
2323
2324 /*
Mike Christiece545032008-02-29 18:25:20 -06002325 * Waiting for all commands for the designated target or dev
2326 * in the active array
David Somayajuluafaf5a22006-09-19 10:28:00 -07002327 */
2328 for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
2329 cmd = scsi_host_find_tag(ha->host, cnt);
Mike Christiece545032008-02-29 18:25:20 -06002330 if (cmd && stgt == scsi_target(cmd->device) &&
2331 (!sdev || sdev == cmd->device)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07002332 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
2333 status++;
2334 break;
2335 }
2336 }
2337 }
2338 return status;
2339}
2340
2341/**
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302342 * qla4xxx_eh_abort - callback for abort task.
2343 * @cmd: Pointer to Linux's SCSI command structure
2344 *
2345 * This routine is called by the Linux OS to abort the specified
2346 * command.
2347 **/
2348static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
2349{
2350 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
2351 unsigned int id = cmd->device->id;
2352 unsigned int lun = cmd->device->lun;
Mike Christie92b3e5b2010-10-06 22:51:17 -07002353 unsigned long flags;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302354 struct srb *srb = NULL;
2355 int ret = SUCCESS;
2356 int wait = 0;
2357
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302358 ql4_printk(KERN_INFO, ha,
Christoph Hellwig5cd049a2011-04-04 09:42:14 -04002359 "scsi%ld:%d:%d: Abort command issued cmd=%p\n",
2360 ha->host_no, id, lun, cmd);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302361
Mike Christie92b3e5b2010-10-06 22:51:17 -07002362 spin_lock_irqsave(&ha->hardware_lock, flags);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302363 srb = (struct srb *) CMD_SP(cmd);
Mike Christie92b3e5b2010-10-06 22:51:17 -07002364 if (!srb) {
2365 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302366 return SUCCESS;
Mike Christie92b3e5b2010-10-06 22:51:17 -07002367 }
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302368 kref_get(&srb->srb_ref);
Mike Christie92b3e5b2010-10-06 22:51:17 -07002369 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302370
2371 if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) {
2372 DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx failed.\n",
2373 ha->host_no, id, lun));
2374 ret = FAILED;
2375 } else {
2376 DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx success.\n",
2377 ha->host_no, id, lun));
2378 wait = 1;
2379 }
2380
2381 kref_put(&srb->srb_ref, qla4xxx_srb_compl);
2382
2383 /* Wait for command to complete */
2384 if (wait) {
2385 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
2386 DEBUG2(printk("scsi%ld:%d:%d: Abort handler timed out\n",
2387 ha->host_no, id, lun));
2388 ret = FAILED;
2389 }
2390 }
2391
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302392 ql4_printk(KERN_INFO, ha,
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302393 "scsi%ld:%d:%d: Abort command - %s\n",
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002394 ha->host_no, id, lun, (ret == SUCCESS) ? "succeeded" : "failed");
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302395
2396 return ret;
2397}
2398
2399/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07002400 * qla4xxx_eh_device_reset - callback for target reset.
2401 * @cmd: Pointer to Linux's SCSI command structure
2402 *
2403 * This routine is called by the Linux OS to reset all luns on the
2404 * specified target.
2405 **/
2406static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
2407{
2408 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
2409 struct ddb_entry *ddb_entry = cmd->device->hostdata;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002410 int ret = FAILED, stat;
2411
Karen Higgins612f73482009-07-15 15:03:01 -05002412 if (!ddb_entry)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002413 return ret;
2414
Mike Christiec01be6d2010-07-22 16:59:49 +05302415 ret = iscsi_block_scsi_eh(cmd);
2416 if (ret)
2417 return ret;
2418 ret = FAILED;
2419
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302420 ql4_printk(KERN_INFO, ha,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002421 "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no,
2422 cmd->device->channel, cmd->device->id, cmd->device->lun);
2423
2424 DEBUG2(printk(KERN_INFO
2425 "scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x,"
2426 "dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no,
Jens Axboe242f9dc2008-09-14 05:55:09 -07002427 cmd, jiffies, cmd->request->timeout / HZ,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002428 ha->dpc_flags, cmd->result, cmd->allowed));
2429
2430 /* FIXME: wait for hba to go online */
2431 stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun);
2432 if (stat != QLA_SUCCESS) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302433 ql4_printk(KERN_INFO, ha, "DEVICE RESET FAILED. %d\n", stat);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002434 goto eh_dev_reset_done;
2435 }
2436
Mike Christiece545032008-02-29 18:25:20 -06002437 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
2438 cmd->device)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302439 ql4_printk(KERN_INFO, ha,
Mike Christiece545032008-02-29 18:25:20 -06002440 "DEVICE RESET FAILED - waiting for "
2441 "commands.\n");
2442 goto eh_dev_reset_done;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002443 }
2444
David C Somayajulu9d562912008-03-19 11:23:03 -07002445 /* Send marker. */
2446 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
2447 MM_LUN_RESET) != QLA_SUCCESS)
2448 goto eh_dev_reset_done;
2449
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302450 ql4_printk(KERN_INFO, ha,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002451 "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
2452 ha->host_no, cmd->device->channel, cmd->device->id,
2453 cmd->device->lun);
2454
2455 ret = SUCCESS;
2456
2457eh_dev_reset_done:
2458
2459 return ret;
2460}
2461
2462/**
Mike Christiece545032008-02-29 18:25:20 -06002463 * qla4xxx_eh_target_reset - callback for target reset.
2464 * @cmd: Pointer to Linux's SCSI command structure
2465 *
2466 * This routine is called by the Linux OS to reset the target.
2467 **/
2468static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
2469{
2470 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
2471 struct ddb_entry *ddb_entry = cmd->device->hostdata;
Mike Christiec01be6d2010-07-22 16:59:49 +05302472 int stat, ret;
Mike Christiece545032008-02-29 18:25:20 -06002473
2474 if (!ddb_entry)
2475 return FAILED;
2476
Mike Christiec01be6d2010-07-22 16:59:49 +05302477 ret = iscsi_block_scsi_eh(cmd);
2478 if (ret)
2479 return ret;
2480
Mike Christiece545032008-02-29 18:25:20 -06002481 starget_printk(KERN_INFO, scsi_target(cmd->device),
2482 "WARM TARGET RESET ISSUED.\n");
2483
2484 DEBUG2(printk(KERN_INFO
2485 "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
2486 "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
Jens Axboe242f9dc2008-09-14 05:55:09 -07002487 ha->host_no, cmd, jiffies, cmd->request->timeout / HZ,
Mike Christiece545032008-02-29 18:25:20 -06002488 ha->dpc_flags, cmd->result, cmd->allowed));
2489
2490 stat = qla4xxx_reset_target(ha, ddb_entry);
2491 if (stat != QLA_SUCCESS) {
2492 starget_printk(KERN_INFO, scsi_target(cmd->device),
2493 "WARM TARGET RESET FAILED.\n");
2494 return FAILED;
2495 }
2496
Mike Christiece545032008-02-29 18:25:20 -06002497 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
2498 NULL)) {
2499 starget_printk(KERN_INFO, scsi_target(cmd->device),
2500 "WARM TARGET DEVICE RESET FAILED - "
2501 "waiting for commands.\n");
2502 return FAILED;
2503 }
2504
David C Somayajulu9d562912008-03-19 11:23:03 -07002505 /* Send marker. */
2506 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
2507 MM_TGT_WARM_RESET) != QLA_SUCCESS) {
2508 starget_printk(KERN_INFO, scsi_target(cmd->device),
2509 "WARM TARGET DEVICE RESET FAILED - "
2510 "marker iocb failed.\n");
2511 return FAILED;
2512 }
2513
Mike Christiece545032008-02-29 18:25:20 -06002514 starget_printk(KERN_INFO, scsi_target(cmd->device),
2515 "WARM TARGET RESET SUCCEEDED.\n");
2516 return SUCCESS;
2517}
2518
2519/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07002520 * qla4xxx_eh_host_reset - kernel callback
2521 * @cmd: Pointer to Linux's SCSI command structure
2522 *
2523 * This routine is invoked by the Linux kernel to perform fatal error
2524 * recovery on the specified adapter.
2525 **/
2526static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
2527{
2528 int return_status = FAILED;
2529 struct scsi_qla_host *ha;
2530
2531 ha = (struct scsi_qla_host *) cmd->device->host->hostdata;
2532
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302533 if (ql4xdontresethba) {
2534 DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
2535 ha->host_no, __func__));
2536 return FAILED;
2537 }
2538
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302539 ql4_printk(KERN_INFO, ha,
Karen Higginsdca05c42009-07-15 15:03:00 -05002540 "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002541 cmd->device->channel, cmd->device->id, cmd->device->lun);
2542
2543 if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) {
2544 DEBUG2(printk("scsi%ld:%d: %s: Unable to reset host. Adapter "
2545 "DEAD.\n", ha->host_no, cmd->device->channel,
2546 __func__));
2547
2548 return FAILED;
2549 }
2550
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302551 if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
2552 if (is_qla8022(ha))
2553 set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
2554 else
2555 set_bit(DPC_RESET_HA, &ha->dpc_flags);
2556 }
Mike Christie50a29ae2008-03-04 13:26:53 -06002557
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302558 if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002559 return_status = SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002560
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302561 ql4_printk(KERN_INFO, ha, "HOST RESET %s.\n",
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002562 return_status == FAILED ? "FAILED" : "SUCCEEDED");
David Somayajuluafaf5a22006-09-19 10:28:00 -07002563
2564 return return_status;
2565}
2566
Lalit Chandivade2232be02010-07-30 14:38:47 +05302567/* PCI AER driver recovers from all correctable errors w/o
2568 * driver intervention. For uncorrectable errors PCI AER
2569 * driver calls the following device driver's callbacks
2570 *
2571 * - Fatal Errors - link_reset
2572 * - Non-Fatal Errors - driver's pci_error_detected() which
2573 * returns CAN_RECOVER, NEED_RESET or DISCONNECT.
2574 *
2575 * PCI AER driver calls
2576 * CAN_RECOVER - driver's pci_mmio_enabled(), mmio_enabled
2577 * returns RECOVERED or NEED_RESET if fw_hung
2578 * NEED_RESET - driver's slot_reset()
2579 * DISCONNECT - device is dead & cannot recover
2580 * RECOVERED - driver's pci_resume()
2581 */
2582static pci_ers_result_t
2583qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
2584{
2585 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
2586
2587 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: error detected:state %x\n",
2588 ha->host_no, __func__, state);
2589
2590 if (!is_aer_supported(ha))
2591 return PCI_ERS_RESULT_NONE;
2592
2593 switch (state) {
2594 case pci_channel_io_normal:
2595 clear_bit(AF_EEH_BUSY, &ha->flags);
2596 return PCI_ERS_RESULT_CAN_RECOVER;
2597 case pci_channel_io_frozen:
2598 set_bit(AF_EEH_BUSY, &ha->flags);
2599 qla4xxx_mailbox_premature_completion(ha);
2600 qla4xxx_free_irqs(ha);
2601 pci_disable_device(pdev);
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002602 /* Return back all IOs */
2603 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
Lalit Chandivade2232be02010-07-30 14:38:47 +05302604 return PCI_ERS_RESULT_NEED_RESET;
2605 case pci_channel_io_perm_failure:
2606 set_bit(AF_EEH_BUSY, &ha->flags);
2607 set_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags);
2608 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
2609 return PCI_ERS_RESULT_DISCONNECT;
2610 }
2611 return PCI_ERS_RESULT_NEED_RESET;
2612}
2613
2614/**
2615 * qla4xxx_pci_mmio_enabled() gets called if
2616 * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER
2617 * and read/write to the device still works.
2618 **/
2619static pci_ers_result_t
2620qla4xxx_pci_mmio_enabled(struct pci_dev *pdev)
2621{
2622 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
2623
2624 if (!is_aer_supported(ha))
2625 return PCI_ERS_RESULT_NONE;
2626
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002627 return PCI_ERS_RESULT_RECOVERED;
Lalit Chandivade2232be02010-07-30 14:38:47 +05302628}
2629
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002630static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
Lalit Chandivade2232be02010-07-30 14:38:47 +05302631{
2632 uint32_t rval = QLA_ERROR;
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002633 uint32_t ret = 0;
Lalit Chandivade2232be02010-07-30 14:38:47 +05302634 int fn;
2635 struct pci_dev *other_pdev = NULL;
2636
2637 ql4_printk(KERN_WARNING, ha, "scsi%ld: In %s\n", ha->host_no, __func__);
2638
2639 set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
2640
2641 if (test_bit(AF_ONLINE, &ha->flags)) {
2642 clear_bit(AF_ONLINE, &ha->flags);
2643 qla4xxx_mark_all_devices_missing(ha);
2644 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
Lalit Chandivade2232be02010-07-30 14:38:47 +05302645 }
2646
2647 fn = PCI_FUNC(ha->pdev->devfn);
2648 while (fn > 0) {
2649 fn--;
2650 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Finding PCI device at "
2651 "func %x\n", ha->host_no, __func__, fn);
2652 /* Get the pci device given the domain, bus,
2653 * slot/function number */
2654 other_pdev =
2655 pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
2656 ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
2657 fn));
2658
2659 if (!other_pdev)
2660 continue;
2661
2662 if (atomic_read(&other_pdev->enable_cnt)) {
2663 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Found PCI "
2664 "func in enabled state%x\n", ha->host_no,
2665 __func__, fn);
2666 pci_dev_put(other_pdev);
2667 break;
2668 }
2669 pci_dev_put(other_pdev);
2670 }
2671
2672 /* The first function on the card, the reset owner will
2673 * start & initialize the firmware. The other functions
2674 * on the card will reset the firmware context
2675 */
2676 if (!fn) {
2677 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn being reset "
2678 "0x%x is the owner\n", ha->host_no, __func__,
2679 ha->pdev->devfn);
2680
2681 qla4_8xxx_idc_lock(ha);
2682 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
2683 QLA82XX_DEV_COLD);
2684
2685 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION,
2686 QLA82XX_IDC_VERSION);
2687
2688 qla4_8xxx_idc_unlock(ha);
2689 clear_bit(AF_FW_RECOVERY, &ha->flags);
2690 rval = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST);
2691 qla4_8xxx_idc_lock(ha);
2692
2693 if (rval != QLA_SUCCESS) {
2694 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: "
2695 "FAILED\n", ha->host_no, __func__);
2696 qla4_8xxx_clear_drv_active(ha);
2697 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
2698 QLA82XX_DEV_FAILED);
2699 } else {
2700 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: "
2701 "READY\n", ha->host_no, __func__);
2702 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
2703 QLA82XX_DEV_READY);
2704 /* Clear driver state register */
2705 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
2706 qla4_8xxx_set_drv_active(ha);
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002707 ret = qla4xxx_request_irqs(ha);
2708 if (ret) {
2709 ql4_printk(KERN_WARNING, ha, "Failed to "
2710 "reserve interrupt %d already in use.\n",
2711 ha->pdev->irq);
2712 rval = QLA_ERROR;
2713 } else {
2714 ha->isp_ops->enable_intrs(ha);
2715 rval = QLA_SUCCESS;
2716 }
Lalit Chandivade2232be02010-07-30 14:38:47 +05302717 }
2718 qla4_8xxx_idc_unlock(ha);
2719 } else {
2720 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not "
2721 "the reset owner\n", ha->host_no, __func__,
2722 ha->pdev->devfn);
2723 if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
2724 QLA82XX_DEV_READY)) {
2725 clear_bit(AF_FW_RECOVERY, &ha->flags);
2726 rval = qla4xxx_initialize_adapter(ha,
2727 PRESERVE_DDB_LIST);
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002728 if (rval == QLA_SUCCESS) {
2729 ret = qla4xxx_request_irqs(ha);
2730 if (ret) {
2731 ql4_printk(KERN_WARNING, ha, "Failed to"
2732 " reserve interrupt %d already in"
2733 " use.\n", ha->pdev->irq);
2734 rval = QLA_ERROR;
2735 } else {
2736 ha->isp_ops->enable_intrs(ha);
2737 rval = QLA_SUCCESS;
2738 }
2739 }
Lalit Chandivade2232be02010-07-30 14:38:47 +05302740 qla4_8xxx_idc_lock(ha);
2741 qla4_8xxx_set_drv_active(ha);
2742 qla4_8xxx_idc_unlock(ha);
2743 }
2744 }
2745 clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
2746 return rval;
2747}
2748
2749static pci_ers_result_t
2750qla4xxx_pci_slot_reset(struct pci_dev *pdev)
2751{
2752 pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
2753 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
2754 int rc;
2755
2756 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: slot_reset\n",
2757 ha->host_no, __func__);
2758
2759 if (!is_aer_supported(ha))
2760 return PCI_ERS_RESULT_NONE;
2761
2762 /* Restore the saved state of PCIe device -
2763 * BAR registers, PCI Config space, PCIX, MSI,
2764 * IOV states
2765 */
2766 pci_restore_state(pdev);
2767
2768 /* pci_restore_state() clears the saved_state flag of the device
2769 * save restored state which resets saved_state flag
2770 */
2771 pci_save_state(pdev);
2772
2773 /* Initialize device or resume if in suspended state */
2774 rc = pci_enable_device(pdev);
2775 if (rc) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002776 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Can't re-enable "
Lalit Chandivade2232be02010-07-30 14:38:47 +05302777 "device after reset\n", ha->host_no, __func__);
2778 goto exit_slot_reset;
2779 }
2780
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07002781 ha->isp_ops->disable_intrs(ha);
Lalit Chandivade2232be02010-07-30 14:38:47 +05302782
2783 if (is_qla8022(ha)) {
2784 if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) {
2785 ret = PCI_ERS_RESULT_RECOVERED;
2786 goto exit_slot_reset;
2787 } else
2788 goto exit_slot_reset;
2789 }
2790
2791exit_slot_reset:
2792 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Return=%x\n"
2793 "device after reset\n", ha->host_no, __func__, ret);
2794 return ret;
2795}
2796
2797static void
2798qla4xxx_pci_resume(struct pci_dev *pdev)
2799{
2800 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
2801 int ret;
2802
2803 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: pci_resume\n",
2804 ha->host_no, __func__);
2805
2806 ret = qla4xxx_wait_for_hba_online(ha);
2807 if (ret != QLA_SUCCESS) {
2808 ql4_printk(KERN_ERR, ha, "scsi%ld: %s: the device failed to "
2809 "resume I/O from slot/link_reset\n", ha->host_no,
2810 __func__);
2811 }
2812
2813 pci_cleanup_aer_uncorrect_error_status(pdev);
2814 clear_bit(AF_EEH_BUSY, &ha->flags);
2815}
2816
2817static struct pci_error_handlers qla4xxx_err_handler = {
2818 .error_detected = qla4xxx_pci_error_detected,
2819 .mmio_enabled = qla4xxx_pci_mmio_enabled,
2820 .slot_reset = qla4xxx_pci_slot_reset,
2821 .resume = qla4xxx_pci_resume,
2822};
2823
David Somayajuluafaf5a22006-09-19 10:28:00 -07002824static struct pci_device_id qla4xxx_pci_tbl[] = {
2825 {
2826 .vendor = PCI_VENDOR_ID_QLOGIC,
2827 .device = PCI_DEVICE_ID_QLOGIC_ISP4010,
2828 .subvendor = PCI_ANY_ID,
2829 .subdevice = PCI_ANY_ID,
2830 },
2831 {
2832 .vendor = PCI_VENDOR_ID_QLOGIC,
2833 .device = PCI_DEVICE_ID_QLOGIC_ISP4022,
2834 .subvendor = PCI_ANY_ID,
2835 .subdevice = PCI_ANY_ID,
2836 },
David C Somayajulud9150582006-11-15 17:38:40 -08002837 {
2838 .vendor = PCI_VENDOR_ID_QLOGIC,
2839 .device = PCI_DEVICE_ID_QLOGIC_ISP4032,
2840 .subvendor = PCI_ANY_ID,
2841 .subdevice = PCI_ANY_ID,
2842 },
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302843 {
2844 .vendor = PCI_VENDOR_ID_QLOGIC,
2845 .device = PCI_DEVICE_ID_QLOGIC_ISP8022,
2846 .subvendor = PCI_ANY_ID,
2847 .subdevice = PCI_ANY_ID,
2848 },
David Somayajuluafaf5a22006-09-19 10:28:00 -07002849 {0, 0},
2850};
2851MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl);
2852
Adrian Bunk47975472007-04-26 00:35:16 -07002853static struct pci_driver qla4xxx_pci_driver = {
David Somayajuluafaf5a22006-09-19 10:28:00 -07002854 .name = DRIVER_NAME,
2855 .id_table = qla4xxx_pci_tbl,
2856 .probe = qla4xxx_probe_adapter,
2857 .remove = qla4xxx_remove_adapter,
Lalit Chandivade2232be02010-07-30 14:38:47 +05302858 .err_handler = &qla4xxx_err_handler,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002859};
2860
2861static int __init qla4xxx_module_init(void)
2862{
2863 int ret;
2864
2865 /* Allocate cache for SRBs. */
2866 srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0,
Paul Mundt20c2df82007-07-20 10:11:58 +09002867 SLAB_HWCACHE_ALIGN, NULL);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002868 if (srb_cachep == NULL) {
2869 printk(KERN_ERR
2870 "%s: Unable to allocate SRB cache..."
2871 "Failing load!\n", DRIVER_NAME);
2872 ret = -ENOMEM;
2873 goto no_srp_cache;
2874 }
2875
2876 /* Derive version string. */
2877 strcpy(qla4xxx_version_str, QLA4XXX_DRIVER_VERSION);
Andrew Vasquez11010fe2006-10-06 09:54:59 -07002878 if (ql4xextended_error_logging)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002879 strcat(qla4xxx_version_str, "-debug");
2880
2881 qla4xxx_scsi_transport =
2882 iscsi_register_transport(&qla4xxx_iscsi_transport);
2883 if (!qla4xxx_scsi_transport){
2884 ret = -ENODEV;
2885 goto release_srb_cache;
2886 }
2887
David Somayajuluafaf5a22006-09-19 10:28:00 -07002888 ret = pci_register_driver(&qla4xxx_pci_driver);
2889 if (ret)
2890 goto unregister_transport;
2891
2892 printk(KERN_INFO "QLogic iSCSI HBA Driver\n");
2893 return 0;
Doug Maxey5ae16db2006-10-05 23:50:07 -05002894
David Somayajuluafaf5a22006-09-19 10:28:00 -07002895unregister_transport:
2896 iscsi_unregister_transport(&qla4xxx_iscsi_transport);
2897release_srb_cache:
2898 kmem_cache_destroy(srb_cachep);
2899no_srp_cache:
2900 return ret;
2901}
2902
2903static void __exit qla4xxx_module_exit(void)
2904{
David Somayajuluafaf5a22006-09-19 10:28:00 -07002905 pci_unregister_driver(&qla4xxx_pci_driver);
2906 iscsi_unregister_transport(&qla4xxx_iscsi_transport);
2907 kmem_cache_destroy(srb_cachep);
2908}
2909
2910module_init(qla4xxx_module_init);
2911module_exit(qla4xxx_module_exit);
2912
2913MODULE_AUTHOR("QLogic Corporation");
2914MODULE_DESCRIPTION("QLogic iSCSI HBA Driver");
2915MODULE_LICENSE("GPL");
2916MODULE_VERSION(QLA4XXX_DRIVER_VERSION);