blob: c6cfe324ab2f92c09c23e85ed2b6b3dc8f0be575 [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>
Manish Rangankar2a991c22011-07-25 13:48:55 -05009#include <linux/blkdev.h>
10#include <linux/iscsi_boot_sysfs.h>
Mike Christie13483732011-12-01 21:38:41 -060011#include <linux/inet.h>
David Somayajuluafaf5a22006-09-19 10:28:00 -070012
13#include <scsi/scsi_tcq.h>
14#include <scsi/scsicam.h>
15
16#include "ql4_def.h"
David C Somayajulubee4fe82007-05-23 18:03:32 -070017#include "ql4_version.h"
18#include "ql4_glbl.h"
19#include "ql4_dbg.h"
20#include "ql4_inline.h"
David Somayajuluafaf5a22006-09-19 10:28:00 -070021
22/*
23 * Driver version
24 */
Adrian Bunk47975472007-04-26 00:35:16 -070025static char qla4xxx_version_str[40];
David Somayajuluafaf5a22006-09-19 10:28:00 -070026
27/*
28 * SRB allocation cache
29 */
Christoph Lametere18b8902006-12-06 20:33:20 -080030static struct kmem_cache *srb_cachep;
David Somayajuluafaf5a22006-09-19 10:28:00 -070031
32/*
33 * Module parameter information and variables
34 */
Mike Christie13483732011-12-01 21:38:41 -060035int ql4xdisablesysfsboot = 1;
36module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR);
37MODULE_PARM_DESC(ql4xdisablesysfsboot,
Karen Higginsa4e8a712012-01-11 02:44:20 -080038 " Set to disable exporting boot targets to sysfs.\n"
39 "\t\t 0 - Export boot targets\n"
40 "\t\t 1 - Do not export boot targets (Default)");
Mike Christie13483732011-12-01 21:38:41 -060041
David Somayajuluafaf5a22006-09-19 10:28:00 -070042int ql4xdontresethba = 0;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +053043module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
David Somayajuluafaf5a22006-09-19 10:28:00 -070044MODULE_PARM_DESC(ql4xdontresethba,
Karen Higginsa4e8a712012-01-11 02:44:20 -080045 " Don't reset the HBA for driver recovery.\n"
46 "\t\t 0 - It will reset HBA (Default)\n"
47 "\t\t 1 - It will NOT reset HBA");
David Somayajuluafaf5a22006-09-19 10:28:00 -070048
Karen Higginsa4e8a712012-01-11 02:44:20 -080049int ql4xextended_error_logging;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +053050module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR);
Andrew Vasquez11010fe2006-10-06 09:54:59 -070051MODULE_PARM_DESC(ql4xextended_error_logging,
Karen Higginsa4e8a712012-01-11 02:44:20 -080052 " Option to enable extended error logging.\n"
53 "\t\t 0 - no logging (Default)\n"
54 "\t\t 2 - debug logging");
David Somayajuluafaf5a22006-09-19 10:28:00 -070055
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +053056int ql4xenablemsix = 1;
57module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR);
58MODULE_PARM_DESC(ql4xenablemsix,
Karen Higginsa4e8a712012-01-11 02:44:20 -080059 " Set to enable MSI or MSI-X interrupt mechanism.\n"
60 "\t\t 0 = enable INTx interrupt mechanism.\n"
61 "\t\t 1 = enable MSI-X interrupt mechanism (Default).\n"
62 "\t\t 2 = enable MSI interrupt mechanism.");
David C Somayajulu477ffb92007-01-22 12:26:11 -080063
Mike Christied510d962008-07-11 19:50:33 -050064#define QL4_DEF_QDEPTH 32
Vikas Chaudhary8bb40332011-03-21 03:34:31 -070065static int ql4xmaxqdepth = QL4_DEF_QDEPTH;
66module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR);
67MODULE_PARM_DESC(ql4xmaxqdepth,
Karen Higginsa4e8a712012-01-11 02:44:20 -080068 " Maximum queue depth to report for target devices.\n"
69 "\t\t Default: 32.");
Mike Christied510d962008-07-11 19:50:33 -050070
Vikas Chaudhary30387272011-03-21 03:34:32 -070071static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
72module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
73MODULE_PARM_DESC(ql4xsess_recovery_tmo,
74 "Target Session Recovery Timeout.\n"
Karen Higginsa4e8a712012-01-11 02:44:20 -080075 "\t\t Default: 120 sec.");
Vikas Chaudhary30387272011-03-21 03:34:32 -070076
Manish Rangankarb3a271a2011-07-25 13:48:53 -050077static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -070078/*
79 * SCSI host template entry points
80 */
Adrian Bunk47975472007-04-26 00:35:16 -070081static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -070082
83/*
84 * iSCSI template entry points
85 */
David Somayajuluafaf5a22006-09-19 10:28:00 -070086static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
87 enum iscsi_param param, char *buf);
Mike Christieaa1e93a2007-05-30 12:57:09 -050088static int qla4xxx_host_get_param(struct Scsi_Host *shost,
89 enum iscsi_host_param param, char *buf);
Mike Christie00c31882011-10-06 03:56:59 -050090static int qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data,
91 uint32_t len);
Vikas Chaudharyed1086e2011-07-25 13:48:41 -050092static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
93 enum iscsi_param_type param_type,
94 int param, char *buf);
Mike Christie5c656af2009-07-15 15:02:59 -050095static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
Manish Rangankarb3a271a2011-07-25 13:48:53 -050096static struct iscsi_endpoint *qla4xxx_ep_connect(struct Scsi_Host *shost,
97 struct sockaddr *dst_addr,
98 int non_blocking);
99static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms);
100static void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep);
101static int qla4xxx_get_ep_param(struct iscsi_endpoint *ep,
102 enum iscsi_param param, char *buf);
103static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
104static struct iscsi_cls_conn *
105qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx);
106static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
107 struct iscsi_cls_conn *cls_conn,
108 uint64_t transport_fd, int is_leading);
109static void qla4xxx_conn_destroy(struct iscsi_cls_conn *conn);
110static struct iscsi_cls_session *
111qla4xxx_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
112 uint16_t qdepth, uint32_t initial_cmdsn);
113static void qla4xxx_session_destroy(struct iscsi_cls_session *sess);
114static void qla4xxx_task_work(struct work_struct *wdata);
115static int qla4xxx_alloc_pdu(struct iscsi_task *, uint8_t);
116static int qla4xxx_task_xmit(struct iscsi_task *);
117static void qla4xxx_task_cleanup(struct iscsi_task *);
118static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session);
119static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,
120 struct iscsi_stats *stats);
Vikas Chaudharyc0b9d3f2012-02-13 18:30:49 +0530121static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,
122 uint32_t iface_type, uint32_t payload_size,
123 uint32_t pid, struct sockaddr *dst_addr);
Nilesh Javali376738a2012-02-27 03:08:52 -0800124static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,
125 uint32_t *num_entries, char *buf);
126static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx);
Vikas Chaudharyc0b9d3f2012-02-13 18:30:49 +0530127
David Somayajuluafaf5a22006-09-19 10:28:00 -0700128/*
129 * SCSI host template entry points
130 */
Jeff Garzikf2812332010-11-16 02:10:29 -0500131static int qla4xxx_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530132static int qla4xxx_eh_abort(struct scsi_cmnd *cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700133static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
Mike Christiece545032008-02-29 18:25:20 -0600134static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700135static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
136static int qla4xxx_slave_alloc(struct scsi_device *device);
137static int qla4xxx_slave_configure(struct scsi_device *device);
138static void qla4xxx_slave_destroy(struct scsi_device *sdev);
Al Viro587a1f12011-07-23 23:11:19 -0400139static umode_t ql4_attr_is_visible(int param_type, int param);
Vikas Chaudhary95d31262011-08-12 02:51:29 -0700140static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700141
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530142static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
143 QLA82XX_LEGACY_INTR_CONFIG;
144
David Somayajuluafaf5a22006-09-19 10:28:00 -0700145static struct scsi_host_template qla4xxx_driver_template = {
146 .module = THIS_MODULE,
147 .name = DRIVER_NAME,
148 .proc_name = DRIVER_NAME,
149 .queuecommand = qla4xxx_queuecommand,
150
Vikas Chaudhary09a0f712010-04-28 11:42:24 +0530151 .eh_abort_handler = qla4xxx_eh_abort,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700152 .eh_device_reset_handler = qla4xxx_eh_device_reset,
Mike Christiece545032008-02-29 18:25:20 -0600153 .eh_target_reset_handler = qla4xxx_eh_target_reset,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700154 .eh_host_reset_handler = qla4xxx_eh_host_reset,
Mike Christie5c656af2009-07-15 15:02:59 -0500155 .eh_timed_out = qla4xxx_eh_cmd_timed_out,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700156
157 .slave_configure = qla4xxx_slave_configure,
158 .slave_alloc = qla4xxx_slave_alloc,
159 .slave_destroy = qla4xxx_slave_destroy,
160
161 .this_id = -1,
162 .cmd_per_lun = 3,
163 .use_clustering = ENABLE_CLUSTERING,
164 .sg_tablesize = SG_ALL,
165
166 .max_sectors = 0xFFFF,
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -0700167 .shost_attrs = qla4xxx_host_attrs,
Vikas Chaudhary95d31262011-08-12 02:51:29 -0700168 .host_reset = qla4xxx_host_reset,
Vikas Chaudharya3559432011-07-25 13:48:51 -0500169 .vendor_id = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700170};
171
172static struct iscsi_transport qla4xxx_iscsi_transport = {
173 .owner = THIS_MODULE,
174 .name = DRIVER_NAME,
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500175 .caps = CAP_TEXT_NEGO |
176 CAP_DATA_PATH_OFFLOAD | CAP_HDRDGST |
177 CAP_DATADGST | CAP_LOGIN_OFFLOAD |
178 CAP_MULTI_R2T,
Mike Christie3128c6c2011-07-25 13:48:42 -0500179 .attr_is_visible = ql4_attr_is_visible,
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500180 .create_session = qla4xxx_session_create,
181 .destroy_session = qla4xxx_session_destroy,
182 .start_conn = qla4xxx_conn_start,
183 .create_conn = qla4xxx_conn_create,
184 .bind_conn = qla4xxx_conn_bind,
185 .stop_conn = iscsi_conn_stop,
186 .destroy_conn = qla4xxx_conn_destroy,
187 .set_param = iscsi_set_param,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700188 .get_conn_param = qla4xxx_conn_get_param,
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500189 .get_session_param = iscsi_session_get_param,
190 .get_ep_param = qla4xxx_get_ep_param,
191 .ep_connect = qla4xxx_ep_connect,
192 .ep_poll = qla4xxx_ep_poll,
193 .ep_disconnect = qla4xxx_ep_disconnect,
194 .get_stats = qla4xxx_conn_get_stats,
195 .send_pdu = iscsi_conn_send_pdu,
196 .xmit_task = qla4xxx_task_xmit,
197 .cleanup_task = qla4xxx_task_cleanup,
198 .alloc_pdu = qla4xxx_alloc_pdu,
199
Mike Christieaa1e93a2007-05-30 12:57:09 -0500200 .get_host_param = qla4xxx_host_get_param,
Mike Christied00efe32011-07-25 13:48:38 -0500201 .set_iface_param = qla4xxx_iface_set_param,
Vikas Chaudharyed1086e2011-07-25 13:48:41 -0500202 .get_iface_param = qla4xxx_get_iface_param,
Vikas Chaudharya3559432011-07-25 13:48:51 -0500203 .bsg_request = qla4xxx_bsg_request,
Vikas Chaudharyc0b9d3f2012-02-13 18:30:49 +0530204 .send_ping = qla4xxx_send_ping,
Nilesh Javali376738a2012-02-27 03:08:52 -0800205 .get_chap = qla4xxx_get_chap_list,
206 .delete_chap = qla4xxx_delete_chap,
David Somayajuluafaf5a22006-09-19 10:28:00 -0700207};
208
209static struct scsi_transport_template *qla4xxx_scsi_transport;
210
Vikas Chaudharyc0b9d3f2012-02-13 18:30:49 +0530211static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,
212 uint32_t iface_type, uint32_t payload_size,
213 uint32_t pid, struct sockaddr *dst_addr)
214{
215 struct scsi_qla_host *ha = to_qla_host(shost);
216 struct sockaddr_in *addr;
217 struct sockaddr_in6 *addr6;
218 uint32_t options = 0;
219 uint8_t ipaddr[IPv6_ADDR_LEN];
220 int rval;
221
222 memset(ipaddr, 0, IPv6_ADDR_LEN);
223 /* IPv4 to IPv4 */
224 if ((iface_type == ISCSI_IFACE_TYPE_IPV4) &&
225 (dst_addr->sa_family == AF_INET)) {
226 addr = (struct sockaddr_in *)dst_addr;
227 memcpy(ipaddr, &addr->sin_addr.s_addr, IP_ADDR_LEN);
228 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv4 Ping src: %pI4 "
229 "dest: %pI4\n", __func__,
230 &ha->ip_config.ip_address, ipaddr));
231 rval = qla4xxx_ping_iocb(ha, options, payload_size, pid,
232 ipaddr);
233 if (rval)
234 rval = -EINVAL;
235 } else if ((iface_type == ISCSI_IFACE_TYPE_IPV6) &&
236 (dst_addr->sa_family == AF_INET6)) {
237 /* IPv6 to IPv6 */
238 addr6 = (struct sockaddr_in6 *)dst_addr;
239 memcpy(ipaddr, &addr6->sin6_addr.in6_u.u6_addr8, IPv6_ADDR_LEN);
240
241 options |= PING_IPV6_PROTOCOL_ENABLE;
242
243 /* Ping using LinkLocal address */
244 if ((iface_num == 0) || (iface_num == 1)) {
245 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: LinkLocal Ping "
246 "src: %pI6 dest: %pI6\n", __func__,
247 &ha->ip_config.ipv6_link_local_addr,
248 ipaddr));
249 options |= PING_IPV6_LINKLOCAL_ADDR;
250 rval = qla4xxx_ping_iocb(ha, options, payload_size,
251 pid, ipaddr);
252 } else {
253 ql4_printk(KERN_WARNING, ha, "%s: iface num = %d "
254 "not supported\n", __func__, iface_num);
255 rval = -ENOSYS;
256 goto exit_send_ping;
257 }
258
259 /*
260 * If ping using LinkLocal address fails, try ping using
261 * IPv6 address
262 */
263 if (rval != QLA_SUCCESS) {
264 options &= ~PING_IPV6_LINKLOCAL_ADDR;
265 if (iface_num == 0) {
266 options |= PING_IPV6_ADDR0;
267 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 "
268 "Ping src: %pI6 "
269 "dest: %pI6\n", __func__,
270 &ha->ip_config.ipv6_addr0,
271 ipaddr));
272 } else if (iface_num == 1) {
273 options |= PING_IPV6_ADDR1;
274 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 "
275 "Ping src: %pI6 "
276 "dest: %pI6\n", __func__,
277 &ha->ip_config.ipv6_addr1,
278 ipaddr));
279 }
280 rval = qla4xxx_ping_iocb(ha, options, payload_size,
281 pid, ipaddr);
282 if (rval)
283 rval = -EINVAL;
284 }
285 } else
286 rval = -ENOSYS;
287exit_send_ping:
288 return rval;
289}
290
Al Viro587a1f12011-07-23 23:11:19 -0400291static umode_t ql4_attr_is_visible(int param_type, int param)
Mike Christie3128c6c2011-07-25 13:48:42 -0500292{
293 switch (param_type) {
Mike Christief27fb2e2011-07-25 13:48:45 -0500294 case ISCSI_HOST_PARAM:
295 switch (param) {
296 case ISCSI_HOST_PARAM_HWADDRESS:
297 case ISCSI_HOST_PARAM_IPADDRESS:
298 case ISCSI_HOST_PARAM_INITIATOR_NAME:
Vikas Chaudhary3254dbe2012-01-19 03:06:56 -0800299 case ISCSI_HOST_PARAM_PORT_STATE:
300 case ISCSI_HOST_PARAM_PORT_SPEED:
Mike Christief27fb2e2011-07-25 13:48:45 -0500301 return S_IRUGO;
302 default:
303 return 0;
304 }
Mike Christie3128c6c2011-07-25 13:48:42 -0500305 case ISCSI_PARAM:
306 switch (param) {
Mike Christie590134f2011-10-17 22:42:13 -0500307 case ISCSI_PARAM_PERSISTENT_ADDRESS:
308 case ISCSI_PARAM_PERSISTENT_PORT:
Mike Christie3128c6c2011-07-25 13:48:42 -0500309 case ISCSI_PARAM_CONN_ADDRESS:
310 case ISCSI_PARAM_CONN_PORT:
Mike Christie1d063c12011-07-25 13:48:43 -0500311 case ISCSI_PARAM_TARGET_NAME:
312 case ISCSI_PARAM_TPGT:
313 case ISCSI_PARAM_TARGET_ALIAS:
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500314 case ISCSI_PARAM_MAX_BURST:
315 case ISCSI_PARAM_MAX_R2T:
316 case ISCSI_PARAM_FIRST_BURST:
317 case ISCSI_PARAM_MAX_RECV_DLENGTH:
318 case ISCSI_PARAM_MAX_XMIT_DLENGTH:
Mike Christiede379202011-08-14 20:42:56 -0500319 case ISCSI_PARAM_IFACE_NAME:
Mike Christie3128c6c2011-07-25 13:48:42 -0500320 return S_IRUGO;
321 default:
322 return 0;
323 }
Mike Christieb78dbba2011-07-25 13:48:44 -0500324 case ISCSI_NET_PARAM:
325 switch (param) {
326 case ISCSI_NET_PARAM_IPV4_ADDR:
327 case ISCSI_NET_PARAM_IPV4_SUBNET:
328 case ISCSI_NET_PARAM_IPV4_GW:
329 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
330 case ISCSI_NET_PARAM_IFACE_ENABLE:
331 case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
332 case ISCSI_NET_PARAM_IPV6_ADDR:
333 case ISCSI_NET_PARAM_IPV6_ROUTER:
334 case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
335 case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
Vikas Chaudhary6ac73e82011-07-25 13:48:49 -0500336 case ISCSI_NET_PARAM_VLAN_ID:
337 case ISCSI_NET_PARAM_VLAN_PRIORITY:
338 case ISCSI_NET_PARAM_VLAN_ENABLED:
Vikas Chaudhary943c1572011-08-01 03:26:13 -0700339 case ISCSI_NET_PARAM_MTU:
Vikas Chaudhary2ada7fc2011-08-01 03:26:19 -0700340 case ISCSI_NET_PARAM_PORT:
Mike Christieb78dbba2011-07-25 13:48:44 -0500341 return S_IRUGO;
342 default:
343 return 0;
344 }
Mike Christie3128c6c2011-07-25 13:48:42 -0500345 }
346
347 return 0;
348}
349
Nilesh Javali376738a2012-02-27 03:08:52 -0800350static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,
351 uint32_t *num_entries, char *buf)
352{
353 struct scsi_qla_host *ha = to_qla_host(shost);
354 struct ql4_chap_table *chap_table;
355 struct iscsi_chap_rec *chap_rec;
356 int max_chap_entries = 0;
357 int valid_chap_entries = 0;
358 int ret = 0, i;
359
360 if (is_qla8022(ha))
361 max_chap_entries = (ha->hw.flt_chap_size / 2) /
362 sizeof(struct ql4_chap_table);
363 else
364 max_chap_entries = MAX_CHAP_ENTRIES_40XX;
365
366 ql4_printk(KERN_INFO, ha, "%s: num_entries = %d, CHAP idx = %d\n",
367 __func__, *num_entries, chap_tbl_idx);
368
369 if (!buf) {
370 ret = -ENOMEM;
371 goto exit_get_chap_list;
372 }
373
374 chap_rec = (struct iscsi_chap_rec *) buf;
375 mutex_lock(&ha->chap_sem);
376 for (i = chap_tbl_idx; i < max_chap_entries; i++) {
377 chap_table = (struct ql4_chap_table *)ha->chap_list + i;
378 if (chap_table->cookie !=
379 __constant_cpu_to_le16(CHAP_VALID_COOKIE))
380 continue;
381
382 chap_rec->chap_tbl_idx = i;
383 strncpy(chap_rec->username, chap_table->name,
384 ISCSI_CHAP_AUTH_NAME_MAX_LEN);
385 strncpy(chap_rec->password, chap_table->secret,
386 QL4_CHAP_MAX_SECRET_LEN);
387 chap_rec->password_length = chap_table->secret_len;
388
389 if (chap_table->flags & BIT_7) /* local */
390 chap_rec->chap_type = CHAP_TYPE_OUT;
391
392 if (chap_table->flags & BIT_6) /* peer */
393 chap_rec->chap_type = CHAP_TYPE_IN;
394
395 chap_rec++;
396
397 valid_chap_entries++;
398 if (valid_chap_entries == *num_entries)
399 break;
400 else
401 continue;
402 }
403 mutex_unlock(&ha->chap_sem);
404
405exit_get_chap_list:
406 ql4_printk(KERN_INFO, ha, "%s: Valid CHAP Entries = %d\n",
407 __func__, valid_chap_entries);
408 *num_entries = valid_chap_entries;
409 return ret;
410}
411
412static int __qla4xxx_is_chap_active(struct device *dev, void *data)
413{
414 int ret = 0;
415 uint16_t *chap_tbl_idx = (uint16_t *) data;
416 struct iscsi_cls_session *cls_session;
417 struct iscsi_session *sess;
418 struct ddb_entry *ddb_entry;
419
420 if (!iscsi_is_session_dev(dev))
421 goto exit_is_chap_active;
422
423 cls_session = iscsi_dev_to_session(dev);
424 sess = cls_session->dd_data;
425 ddb_entry = sess->dd_data;
426
427 if (iscsi_session_chkready(cls_session))
428 goto exit_is_chap_active;
429
430 if (ddb_entry->chap_tbl_idx == *chap_tbl_idx)
431 ret = 1;
432
433exit_is_chap_active:
434 return ret;
435}
436
437static int qla4xxx_is_chap_active(struct Scsi_Host *shost,
438 uint16_t chap_tbl_idx)
439{
440 int ret = 0;
441
442 ret = device_for_each_child(&shost->shost_gendev, &chap_tbl_idx,
443 __qla4xxx_is_chap_active);
444
445 return ret;
446}
447
448static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx)
449{
450 struct scsi_qla_host *ha = to_qla_host(shost);
451 struct ql4_chap_table *chap_table;
452 dma_addr_t chap_dma;
453 int max_chap_entries = 0;
454 uint32_t offset = 0;
455 uint32_t chap_size;
456 int ret = 0;
457
458 chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
459 if (chap_table == NULL)
460 return -ENOMEM;
461
462 memset(chap_table, 0, sizeof(struct ql4_chap_table));
463
464 if (is_qla8022(ha))
465 max_chap_entries = (ha->hw.flt_chap_size / 2) /
466 sizeof(struct ql4_chap_table);
467 else
468 max_chap_entries = MAX_CHAP_ENTRIES_40XX;
469
470 if (chap_tbl_idx > max_chap_entries) {
471 ret = -EINVAL;
472 goto exit_delete_chap;
473 }
474
475 /* Check if chap index is in use.
476 * If chap is in use don't delet chap entry */
477 ret = qla4xxx_is_chap_active(shost, chap_tbl_idx);
478 if (ret) {
479 ql4_printk(KERN_INFO, ha, "CHAP entry %d is in use, cannot "
480 "delete from flash\n", chap_tbl_idx);
481 ret = -EBUSY;
482 goto exit_delete_chap;
483 }
484
485 chap_size = sizeof(struct ql4_chap_table);
486 if (is_qla40XX(ha))
487 offset = FLASH_CHAP_OFFSET | (chap_tbl_idx * chap_size);
488 else {
489 offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
490 /* flt_chap_size is CHAP table size for both ports
491 * so divide it by 2 to calculate the offset for second port
492 */
493 if (ha->port_num == 1)
494 offset += (ha->hw.flt_chap_size / 2);
495 offset += (chap_tbl_idx * chap_size);
496 }
497
498 ret = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
499 if (ret != QLA_SUCCESS) {
500 ret = -EINVAL;
501 goto exit_delete_chap;
502 }
503
504 DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
505 __le16_to_cpu(chap_table->cookie)));
506
507 if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
508 ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");
509 goto exit_delete_chap;
510 }
511
512 chap_table->cookie = __constant_cpu_to_le16(0xFFFF);
513
514 offset = FLASH_CHAP_OFFSET |
515 (chap_tbl_idx * sizeof(struct ql4_chap_table));
516 ret = qla4xxx_set_flash(ha, chap_dma, offset, chap_size,
517 FLASH_OPT_RMW_COMMIT);
518 if (ret == QLA_SUCCESS && ha->chap_list) {
519 mutex_lock(&ha->chap_sem);
520 /* Update ha chap_list cache */
521 memcpy((struct ql4_chap_table *)ha->chap_list + chap_tbl_idx,
522 chap_table, sizeof(struct ql4_chap_table));
523 mutex_unlock(&ha->chap_sem);
524 }
525 if (ret != QLA_SUCCESS)
526 ret = -EINVAL;
527
528exit_delete_chap:
529 dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
530 return ret;
531}
532
Vikas Chaudharyed1086e2011-07-25 13:48:41 -0500533static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
534 enum iscsi_param_type param_type,
535 int param, char *buf)
536{
537 struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
538 struct scsi_qla_host *ha = to_qla_host(shost);
539 int len = -ENOSYS;
540
541 if (param_type != ISCSI_NET_PARAM)
542 return -ENOSYS;
543
544 switch (param) {
545 case ISCSI_NET_PARAM_IPV4_ADDR:
546 len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);
547 break;
548 case ISCSI_NET_PARAM_IPV4_SUBNET:
549 len = sprintf(buf, "%pI4\n", &ha->ip_config.subnet_mask);
550 break;
551 case ISCSI_NET_PARAM_IPV4_GW:
552 len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway);
553 break;
554 case ISCSI_NET_PARAM_IFACE_ENABLE:
555 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
556 len = sprintf(buf, "%s\n",
557 (ha->ip_config.ipv4_options &
558 IPOPT_IPV4_PROTOCOL_ENABLE) ?
559 "enabled" : "disabled");
560 else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
561 len = sprintf(buf, "%s\n",
562 (ha->ip_config.ipv6_options &
563 IPV6_OPT_IPV6_PROTOCOL_ENABLE) ?
564 "enabled" : "disabled");
565 break;
566 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
567 len = sprintf(buf, "%s\n",
568 (ha->ip_config.tcp_options & TCPOPT_DHCP_ENABLE) ?
569 "dhcp" : "static");
570 break;
571 case ISCSI_NET_PARAM_IPV6_ADDR:
572 if (iface->iface_num == 0)
573 len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr0);
574 if (iface->iface_num == 1)
575 len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr1);
576 break;
577 case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
578 len = sprintf(buf, "%pI6\n",
579 &ha->ip_config.ipv6_link_local_addr);
580 break;
581 case ISCSI_NET_PARAM_IPV6_ROUTER:
582 len = sprintf(buf, "%pI6\n",
583 &ha->ip_config.ipv6_default_router_addr);
584 break;
585 case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
586 len = sprintf(buf, "%s\n",
587 (ha->ip_config.ipv6_addl_options &
588 IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ?
589 "nd" : "static");
590 break;
591 case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
592 len = sprintf(buf, "%s\n",
593 (ha->ip_config.ipv6_addl_options &
594 IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ?
595 "auto" : "static");
596 break;
Vikas Chaudhary6ac73e82011-07-25 13:48:49 -0500597 case ISCSI_NET_PARAM_VLAN_ID:
598 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
599 len = sprintf(buf, "%d\n",
600 (ha->ip_config.ipv4_vlan_tag &
601 ISCSI_MAX_VLAN_ID));
602 else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
603 len = sprintf(buf, "%d\n",
604 (ha->ip_config.ipv6_vlan_tag &
605 ISCSI_MAX_VLAN_ID));
606 break;
607 case ISCSI_NET_PARAM_VLAN_PRIORITY:
608 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
609 len = sprintf(buf, "%d\n",
610 ((ha->ip_config.ipv4_vlan_tag >> 13) &
611 ISCSI_MAX_VLAN_PRIORITY));
612 else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
613 len = sprintf(buf, "%d\n",
614 ((ha->ip_config.ipv6_vlan_tag >> 13) &
615 ISCSI_MAX_VLAN_PRIORITY));
616 break;
617 case ISCSI_NET_PARAM_VLAN_ENABLED:
618 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
619 len = sprintf(buf, "%s\n",
620 (ha->ip_config.ipv4_options &
621 IPOPT_VLAN_TAGGING_ENABLE) ?
622 "enabled" : "disabled");
623 else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
624 len = sprintf(buf, "%s\n",
625 (ha->ip_config.ipv6_options &
626 IPV6_OPT_VLAN_TAGGING_ENABLE) ?
627 "enabled" : "disabled");
628 break;
Vikas Chaudhary943c1572011-08-01 03:26:13 -0700629 case ISCSI_NET_PARAM_MTU:
630 len = sprintf(buf, "%d\n", ha->ip_config.eth_mtu_size);
631 break;
Vikas Chaudhary2ada7fc2011-08-01 03:26:19 -0700632 case ISCSI_NET_PARAM_PORT:
633 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
634 len = sprintf(buf, "%d\n", ha->ip_config.ipv4_port);
635 else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
636 len = sprintf(buf, "%d\n", ha->ip_config.ipv6_port);
637 break;
Vikas Chaudharyed1086e2011-07-25 13:48:41 -0500638 default:
639 len = -ENOSYS;
640 }
641
642 return len;
643}
644
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500645static struct iscsi_endpoint *
646qla4xxx_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
647 int non_blocking)
648{
649 int ret;
650 struct iscsi_endpoint *ep;
651 struct qla_endpoint *qla_ep;
652 struct scsi_qla_host *ha;
653 struct sockaddr_in *addr;
654 struct sockaddr_in6 *addr6;
655
656 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
657 if (!shost) {
658 ret = -ENXIO;
659 printk(KERN_ERR "%s: shost is NULL\n",
660 __func__);
661 return ERR_PTR(ret);
662 }
663
664 ha = iscsi_host_priv(shost);
665
666 ep = iscsi_create_endpoint(sizeof(struct qla_endpoint));
667 if (!ep) {
668 ret = -ENOMEM;
669 return ERR_PTR(ret);
670 }
671
672 qla_ep = ep->dd_data;
673 memset(qla_ep, 0, sizeof(struct qla_endpoint));
674 if (dst_addr->sa_family == AF_INET) {
675 memcpy(&qla_ep->dst_addr, dst_addr, sizeof(struct sockaddr_in));
676 addr = (struct sockaddr_in *)&qla_ep->dst_addr;
677 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI4\n", __func__,
678 (char *)&addr->sin_addr));
679 } else if (dst_addr->sa_family == AF_INET6) {
680 memcpy(&qla_ep->dst_addr, dst_addr,
681 sizeof(struct sockaddr_in6));
682 addr6 = (struct sockaddr_in6 *)&qla_ep->dst_addr;
683 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI6\n", __func__,
684 (char *)&addr6->sin6_addr));
685 }
686
687 qla_ep->host = shost;
688
689 return ep;
690}
691
692static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
693{
694 struct qla_endpoint *qla_ep;
695 struct scsi_qla_host *ha;
696 int ret = 0;
697
698 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
699 qla_ep = ep->dd_data;
700 ha = to_qla_host(qla_ep->host);
701
Mike Christie13483732011-12-01 21:38:41 -0600702 if (adapter_up(ha) && !test_bit(AF_BUILD_DDB_LIST, &ha->flags))
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500703 ret = 1;
704
705 return ret;
706}
707
708static void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep)
709{
710 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
711 iscsi_destroy_endpoint(ep);
712}
713
714static int qla4xxx_get_ep_param(struct iscsi_endpoint *ep,
715 enum iscsi_param param,
716 char *buf)
717{
718 struct qla_endpoint *qla_ep = ep->dd_data;
719 struct sockaddr *dst_addr;
720
721 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
722
723 switch (param) {
724 case ISCSI_PARAM_CONN_PORT:
725 case ISCSI_PARAM_CONN_ADDRESS:
726 if (!qla_ep)
727 return -ENOTCONN;
728
729 dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
730 if (!dst_addr)
731 return -ENOTCONN;
732
733 return iscsi_conn_get_addr_param((struct sockaddr_storage *)
734 &qla_ep->dst_addr, param, buf);
735 default:
736 return -ENOSYS;
737 }
738}
739
740static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,
741 struct iscsi_stats *stats)
742{
743 struct iscsi_session *sess;
744 struct iscsi_cls_session *cls_sess;
745 struct ddb_entry *ddb_entry;
746 struct scsi_qla_host *ha;
747 struct ql_iscsi_stats *ql_iscsi_stats;
748 int stats_size;
749 int ret;
750 dma_addr_t iscsi_stats_dma;
751
752 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
753
754 cls_sess = iscsi_conn_to_session(cls_conn);
755 sess = cls_sess->dd_data;
756 ddb_entry = sess->dd_data;
757 ha = ddb_entry->ha;
758
759 stats_size = PAGE_ALIGN(sizeof(struct ql_iscsi_stats));
760 /* Allocate memory */
761 ql_iscsi_stats = dma_alloc_coherent(&ha->pdev->dev, stats_size,
762 &iscsi_stats_dma, GFP_KERNEL);
763 if (!ql_iscsi_stats) {
764 ql4_printk(KERN_ERR, ha,
765 "Unable to allocate memory for iscsi stats\n");
766 goto exit_get_stats;
767 }
768
769 ret = qla4xxx_get_mgmt_data(ha, ddb_entry->fw_ddb_index, stats_size,
770 iscsi_stats_dma);
771 if (ret != QLA_SUCCESS) {
772 ql4_printk(KERN_ERR, ha,
773 "Unable to retreive iscsi stats\n");
774 goto free_stats;
775 }
776
777 /* octets */
778 stats->txdata_octets = le64_to_cpu(ql_iscsi_stats->tx_data_octets);
779 stats->rxdata_octets = le64_to_cpu(ql_iscsi_stats->rx_data_octets);
780 /* xmit pdus */
781 stats->noptx_pdus = le32_to_cpu(ql_iscsi_stats->tx_nopout_pdus);
782 stats->scsicmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_cmd_pdus);
783 stats->tmfcmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_tmf_cmd_pdus);
784 stats->login_pdus = le32_to_cpu(ql_iscsi_stats->tx_login_cmd_pdus);
785 stats->text_pdus = le32_to_cpu(ql_iscsi_stats->tx_text_cmd_pdus);
786 stats->dataout_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_write_pdus);
787 stats->logout_pdus = le32_to_cpu(ql_iscsi_stats->tx_logout_cmd_pdus);
788 stats->snack_pdus = le32_to_cpu(ql_iscsi_stats->tx_snack_req_pdus);
789 /* recv pdus */
790 stats->noprx_pdus = le32_to_cpu(ql_iscsi_stats->rx_nopin_pdus);
791 stats->scsirsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_resp_pdus);
792 stats->tmfrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_tmf_resp_pdus);
793 stats->textrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_text_resp_pdus);
794 stats->datain_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_read_pdus);
795 stats->logoutrsp_pdus =
796 le32_to_cpu(ql_iscsi_stats->rx_logout_resp_pdus);
797 stats->r2t_pdus = le32_to_cpu(ql_iscsi_stats->rx_r2t_pdus);
798 stats->async_pdus = le32_to_cpu(ql_iscsi_stats->rx_async_pdus);
799 stats->rjt_pdus = le32_to_cpu(ql_iscsi_stats->rx_reject_pdus);
800
801free_stats:
802 dma_free_coherent(&ha->pdev->dev, stats_size, ql_iscsi_stats,
803 iscsi_stats_dma);
804exit_get_stats:
805 return;
806}
807
Mike Christie5c656af2009-07-15 15:02:59 -0500808static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
809{
810 struct iscsi_cls_session *session;
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500811 struct iscsi_session *sess;
812 unsigned long flags;
813 enum blk_eh_timer_return ret = BLK_EH_NOT_HANDLED;
Mike Christie5c656af2009-07-15 15:02:59 -0500814
815 session = starget_to_session(scsi_target(sc->device));
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500816 sess = session->dd_data;
Mike Christie5c656af2009-07-15 15:02:59 -0500817
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500818 spin_lock_irqsave(&session->lock, flags);
819 if (session->state == ISCSI_SESSION_FAILED)
820 ret = BLK_EH_RESET_TIMER;
821 spin_unlock_irqrestore(&session->lock, flags);
Mike Christie5c656af2009-07-15 15:02:59 -0500822
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500823 return ret;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700824}
825
Vikas Chaudhary3254dbe2012-01-19 03:06:56 -0800826static void qla4xxx_set_port_speed(struct Scsi_Host *shost)
827{
828 struct scsi_qla_host *ha = to_qla_host(shost);
829 struct iscsi_cls_host *ihost = shost_priv(shost);
830 uint32_t speed = ISCSI_PORT_SPEED_UNKNOWN;
831
832 qla4xxx_get_firmware_state(ha);
833
834 switch (ha->addl_fw_state & 0x0F00) {
835 case FW_ADDSTATE_LINK_SPEED_10MBPS:
836 speed = ISCSI_PORT_SPEED_10MBPS;
837 break;
838 case FW_ADDSTATE_LINK_SPEED_100MBPS:
839 speed = ISCSI_PORT_SPEED_100MBPS;
840 break;
841 case FW_ADDSTATE_LINK_SPEED_1GBPS:
842 speed = ISCSI_PORT_SPEED_1GBPS;
843 break;
844 case FW_ADDSTATE_LINK_SPEED_10GBPS:
845 speed = ISCSI_PORT_SPEED_10GBPS;
846 break;
847 }
848 ihost->port_speed = speed;
849}
850
851static void qla4xxx_set_port_state(struct Scsi_Host *shost)
852{
853 struct scsi_qla_host *ha = to_qla_host(shost);
854 struct iscsi_cls_host *ihost = shost_priv(shost);
855 uint32_t state = ISCSI_PORT_STATE_DOWN;
856
857 if (test_bit(AF_LINK_UP, &ha->flags))
858 state = ISCSI_PORT_STATE_UP;
859
860 ihost->port_state = state;
861}
862
Mike Christieaa1e93a2007-05-30 12:57:09 -0500863static int qla4xxx_host_get_param(struct Scsi_Host *shost,
864 enum iscsi_host_param param, char *buf)
865{
866 struct scsi_qla_host *ha = to_qla_host(shost);
867 int len;
868
869 switch (param) {
870 case ISCSI_HOST_PARAM_HWADDRESS:
Michael Chan7ffc49a2007-12-24 21:28:09 -0800871 len = sysfs_format_mac(buf, ha->my_mac, MAC_ADDR_LEN);
Mike Christieaa1e93a2007-05-30 12:57:09 -0500872 break;
Mike Christie22236962007-05-30 12:57:24 -0500873 case ISCSI_HOST_PARAM_IPADDRESS:
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500874 len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);
Mike Christie22236962007-05-30 12:57:24 -0500875 break;
Mike Christie8ad57812007-05-30 12:57:13 -0500876 case ISCSI_HOST_PARAM_INITIATOR_NAME:
Mike Christie22236962007-05-30 12:57:24 -0500877 len = sprintf(buf, "%s\n", ha->name_string);
Mike Christie8ad57812007-05-30 12:57:13 -0500878 break;
Vikas Chaudhary3254dbe2012-01-19 03:06:56 -0800879 case ISCSI_HOST_PARAM_PORT_STATE:
880 qla4xxx_set_port_state(shost);
881 len = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
882 break;
883 case ISCSI_HOST_PARAM_PORT_SPEED:
884 qla4xxx_set_port_speed(shost);
885 len = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
886 break;
Mike Christieaa1e93a2007-05-30 12:57:09 -0500887 default:
888 return -ENOSYS;
889 }
890
891 return len;
892}
893
Vikas Chaudharyed1086e2011-07-25 13:48:41 -0500894static void qla4xxx_create_ipv4_iface(struct scsi_qla_host *ha)
895{
896 if (ha->iface_ipv4)
897 return;
898
899 /* IPv4 */
900 ha->iface_ipv4 = iscsi_create_iface(ha->host,
901 &qla4xxx_iscsi_transport,
902 ISCSI_IFACE_TYPE_IPV4, 0, 0);
903 if (!ha->iface_ipv4)
904 ql4_printk(KERN_ERR, ha, "Could not create IPv4 iSCSI "
905 "iface0.\n");
906}
907
908static void qla4xxx_create_ipv6_iface(struct scsi_qla_host *ha)
909{
910 if (!ha->iface_ipv6_0)
911 /* IPv6 iface-0 */
912 ha->iface_ipv6_0 = iscsi_create_iface(ha->host,
913 &qla4xxx_iscsi_transport,
914 ISCSI_IFACE_TYPE_IPV6, 0,
915 0);
916 if (!ha->iface_ipv6_0)
917 ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI "
918 "iface0.\n");
919
920 if (!ha->iface_ipv6_1)
921 /* IPv6 iface-1 */
922 ha->iface_ipv6_1 = iscsi_create_iface(ha->host,
923 &qla4xxx_iscsi_transport,
924 ISCSI_IFACE_TYPE_IPV6, 1,
925 0);
926 if (!ha->iface_ipv6_1)
927 ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI "
928 "iface1.\n");
929}
930
931static void qla4xxx_create_ifaces(struct scsi_qla_host *ha)
932{
933 if (ha->ip_config.ipv4_options & IPOPT_IPV4_PROTOCOL_ENABLE)
934 qla4xxx_create_ipv4_iface(ha);
935
936 if (ha->ip_config.ipv6_options & IPV6_OPT_IPV6_PROTOCOL_ENABLE)
937 qla4xxx_create_ipv6_iface(ha);
938}
939
940static void qla4xxx_destroy_ipv4_iface(struct scsi_qla_host *ha)
941{
942 if (ha->iface_ipv4) {
943 iscsi_destroy_iface(ha->iface_ipv4);
944 ha->iface_ipv4 = NULL;
945 }
946}
947
948static void qla4xxx_destroy_ipv6_iface(struct scsi_qla_host *ha)
949{
950 if (ha->iface_ipv6_0) {
951 iscsi_destroy_iface(ha->iface_ipv6_0);
952 ha->iface_ipv6_0 = NULL;
953 }
954 if (ha->iface_ipv6_1) {
955 iscsi_destroy_iface(ha->iface_ipv6_1);
956 ha->iface_ipv6_1 = NULL;
957 }
958}
959
960static void qla4xxx_destroy_ifaces(struct scsi_qla_host *ha)
961{
962 qla4xxx_destroy_ipv4_iface(ha);
963 qla4xxx_destroy_ipv6_iface(ha);
964}
965
Mike Christied00efe32011-07-25 13:48:38 -0500966static void qla4xxx_set_ipv6(struct scsi_qla_host *ha,
967 struct iscsi_iface_param_info *iface_param,
968 struct addr_ctrl_blk *init_fw_cb)
969{
970 /*
971 * iface_num 0 is valid for IPv6 Addr, linklocal, router, autocfg.
972 * iface_num 1 is valid only for IPv6 Addr.
973 */
974 switch (iface_param->param) {
975 case ISCSI_NET_PARAM_IPV6_ADDR:
976 if (iface_param->iface_num & 0x1)
977 /* IPv6 Addr 1 */
978 memcpy(init_fw_cb->ipv6_addr1, iface_param->value,
979 sizeof(init_fw_cb->ipv6_addr1));
980 else
981 /* IPv6 Addr 0 */
982 memcpy(init_fw_cb->ipv6_addr0, iface_param->value,
983 sizeof(init_fw_cb->ipv6_addr0));
984 break;
985 case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
986 if (iface_param->iface_num & 0x1)
987 break;
988 memcpy(init_fw_cb->ipv6_if_id, &iface_param->value[8],
989 sizeof(init_fw_cb->ipv6_if_id));
990 break;
991 case ISCSI_NET_PARAM_IPV6_ROUTER:
992 if (iface_param->iface_num & 0x1)
993 break;
994 memcpy(init_fw_cb->ipv6_dflt_rtr_addr, iface_param->value,
995 sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
996 break;
997 case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
998 /* Autocfg applies to even interface */
999 if (iface_param->iface_num & 0x1)
1000 break;
1001
1002 if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_DISABLE)
1003 init_fw_cb->ipv6_addtl_opts &=
1004 cpu_to_le16(
1005 ~IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
1006 else if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_ND_ENABLE)
1007 init_fw_cb->ipv6_addtl_opts |=
1008 cpu_to_le16(
1009 IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
1010 else
1011 ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
1012 "IPv6 addr\n");
1013 break;
1014 case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
1015 /* Autocfg applies to even interface */
1016 if (iface_param->iface_num & 0x1)
1017 break;
1018
1019 if (iface_param->value[0] ==
1020 ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE)
1021 init_fw_cb->ipv6_addtl_opts |= cpu_to_le16(
1022 IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
1023 else if (iface_param->value[0] ==
1024 ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE)
1025 init_fw_cb->ipv6_addtl_opts &= cpu_to_le16(
1026 ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
1027 else
1028 ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
1029 "IPv6 linklocal addr\n");
1030 break;
1031 case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG:
1032 /* Autocfg applies to even interface */
1033 if (iface_param->iface_num & 0x1)
1034 break;
1035
1036 if (iface_param->value[0] == ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE)
1037 memset(init_fw_cb->ipv6_dflt_rtr_addr, 0,
1038 sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
1039 break;
1040 case ISCSI_NET_PARAM_IFACE_ENABLE:
Vikas Chaudharyed1086e2011-07-25 13:48:41 -05001041 if (iface_param->value[0] == ISCSI_IFACE_ENABLE) {
Mike Christied00efe32011-07-25 13:48:38 -05001042 init_fw_cb->ipv6_opts |=
1043 cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE);
Vikas Chaudharyed1086e2011-07-25 13:48:41 -05001044 qla4xxx_create_ipv6_iface(ha);
1045 } else {
Mike Christied00efe32011-07-25 13:48:38 -05001046 init_fw_cb->ipv6_opts &=
1047 cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE &
1048 0xFFFF);
Vikas Chaudharyed1086e2011-07-25 13:48:41 -05001049 qla4xxx_destroy_ipv6_iface(ha);
1050 }
Mike Christied00efe32011-07-25 13:48:38 -05001051 break;
Mike Christie2d636732011-10-11 17:55:11 -05001052 case ISCSI_NET_PARAM_VLAN_TAG:
Mike Christied00efe32011-07-25 13:48:38 -05001053 if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag))
1054 break;
Vikas Chaudhary6ac73e82011-07-25 13:48:49 -05001055 init_fw_cb->ipv6_vlan_tag =
1056 cpu_to_be16(*(uint16_t *)iface_param->value);
1057 break;
1058 case ISCSI_NET_PARAM_VLAN_ENABLED:
1059 if (iface_param->value[0] == ISCSI_VLAN_ENABLE)
1060 init_fw_cb->ipv6_opts |=
1061 cpu_to_le16(IPV6_OPT_VLAN_TAGGING_ENABLE);
1062 else
1063 init_fw_cb->ipv6_opts &=
1064 cpu_to_le16(~IPV6_OPT_VLAN_TAGGING_ENABLE);
Mike Christied00efe32011-07-25 13:48:38 -05001065 break;
Vikas Chaudhary943c1572011-08-01 03:26:13 -07001066 case ISCSI_NET_PARAM_MTU:
1067 init_fw_cb->eth_mtu_size =
1068 cpu_to_le16(*(uint16_t *)iface_param->value);
1069 break;
Vikas Chaudhary2ada7fc2011-08-01 03:26:19 -07001070 case ISCSI_NET_PARAM_PORT:
1071 /* Autocfg applies to even interface */
1072 if (iface_param->iface_num & 0x1)
1073 break;
1074
1075 init_fw_cb->ipv6_port =
1076 cpu_to_le16(*(uint16_t *)iface_param->value);
1077 break;
Mike Christied00efe32011-07-25 13:48:38 -05001078 default:
1079 ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n",
1080 iface_param->param);
1081 break;
1082 }
1083}
1084
1085static void qla4xxx_set_ipv4(struct scsi_qla_host *ha,
1086 struct iscsi_iface_param_info *iface_param,
1087 struct addr_ctrl_blk *init_fw_cb)
1088{
1089 switch (iface_param->param) {
1090 case ISCSI_NET_PARAM_IPV4_ADDR:
1091 memcpy(init_fw_cb->ipv4_addr, iface_param->value,
1092 sizeof(init_fw_cb->ipv4_addr));
1093 break;
1094 case ISCSI_NET_PARAM_IPV4_SUBNET:
1095 memcpy(init_fw_cb->ipv4_subnet, iface_param->value,
1096 sizeof(init_fw_cb->ipv4_subnet));
1097 break;
1098 case ISCSI_NET_PARAM_IPV4_GW:
1099 memcpy(init_fw_cb->ipv4_gw_addr, iface_param->value,
1100 sizeof(init_fw_cb->ipv4_gw_addr));
1101 break;
1102 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
1103 if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
1104 init_fw_cb->ipv4_tcp_opts |=
1105 cpu_to_le16(TCPOPT_DHCP_ENABLE);
1106 else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
1107 init_fw_cb->ipv4_tcp_opts &=
1108 cpu_to_le16(~TCPOPT_DHCP_ENABLE);
1109 else
1110 ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n");
1111 break;
1112 case ISCSI_NET_PARAM_IFACE_ENABLE:
Vikas Chaudharyed1086e2011-07-25 13:48:41 -05001113 if (iface_param->value[0] == ISCSI_IFACE_ENABLE) {
Mike Christied00efe32011-07-25 13:48:38 -05001114 init_fw_cb->ipv4_ip_opts |=
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -05001115 cpu_to_le16(IPOPT_IPV4_PROTOCOL_ENABLE);
Vikas Chaudharyed1086e2011-07-25 13:48:41 -05001116 qla4xxx_create_ipv4_iface(ha);
1117 } else {
Mike Christied00efe32011-07-25 13:48:38 -05001118 init_fw_cb->ipv4_ip_opts &=
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -05001119 cpu_to_le16(~IPOPT_IPV4_PROTOCOL_ENABLE &
Mike Christied00efe32011-07-25 13:48:38 -05001120 0xFFFF);
Vikas Chaudharyed1086e2011-07-25 13:48:41 -05001121 qla4xxx_destroy_ipv4_iface(ha);
1122 }
Mike Christied00efe32011-07-25 13:48:38 -05001123 break;
Mike Christie2d636732011-10-11 17:55:11 -05001124 case ISCSI_NET_PARAM_VLAN_TAG:
Mike Christied00efe32011-07-25 13:48:38 -05001125 if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag))
1126 break;
Vikas Chaudhary6ac73e82011-07-25 13:48:49 -05001127 init_fw_cb->ipv4_vlan_tag =
1128 cpu_to_be16(*(uint16_t *)iface_param->value);
1129 break;
1130 case ISCSI_NET_PARAM_VLAN_ENABLED:
1131 if (iface_param->value[0] == ISCSI_VLAN_ENABLE)
1132 init_fw_cb->ipv4_ip_opts |=
1133 cpu_to_le16(IPOPT_VLAN_TAGGING_ENABLE);
1134 else
1135 init_fw_cb->ipv4_ip_opts &=
1136 cpu_to_le16(~IPOPT_VLAN_TAGGING_ENABLE);
Mike Christied00efe32011-07-25 13:48:38 -05001137 break;
Vikas Chaudhary943c1572011-08-01 03:26:13 -07001138 case ISCSI_NET_PARAM_MTU:
1139 init_fw_cb->eth_mtu_size =
1140 cpu_to_le16(*(uint16_t *)iface_param->value);
1141 break;
Vikas Chaudhary2ada7fc2011-08-01 03:26:19 -07001142 case ISCSI_NET_PARAM_PORT:
1143 init_fw_cb->ipv4_port =
1144 cpu_to_le16(*(uint16_t *)iface_param->value);
1145 break;
Mike Christied00efe32011-07-25 13:48:38 -05001146 default:
1147 ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n",
1148 iface_param->param);
1149 break;
1150 }
1151}
1152
1153static void
1154qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb)
1155{
1156 struct addr_ctrl_blk_def *acb;
1157 acb = (struct addr_ctrl_blk_def *)init_fw_cb;
1158 memset(acb->reserved1, 0, sizeof(acb->reserved1));
1159 memset(acb->reserved2, 0, sizeof(acb->reserved2));
1160 memset(acb->reserved3, 0, sizeof(acb->reserved3));
1161 memset(acb->reserved4, 0, sizeof(acb->reserved4));
1162 memset(acb->reserved5, 0, sizeof(acb->reserved5));
1163 memset(acb->reserved6, 0, sizeof(acb->reserved6));
1164 memset(acb->reserved7, 0, sizeof(acb->reserved7));
1165 memset(acb->reserved8, 0, sizeof(acb->reserved8));
1166 memset(acb->reserved9, 0, sizeof(acb->reserved9));
1167 memset(acb->reserved10, 0, sizeof(acb->reserved10));
1168 memset(acb->reserved11, 0, sizeof(acb->reserved11));
1169 memset(acb->reserved12, 0, sizeof(acb->reserved12));
1170 memset(acb->reserved13, 0, sizeof(acb->reserved13));
1171 memset(acb->reserved14, 0, sizeof(acb->reserved14));
1172 memset(acb->reserved15, 0, sizeof(acb->reserved15));
1173}
1174
1175static int
Mike Christie00c31882011-10-06 03:56:59 -05001176qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
Mike Christied00efe32011-07-25 13:48:38 -05001177{
1178 struct scsi_qla_host *ha = to_qla_host(shost);
1179 int rval = 0;
1180 struct iscsi_iface_param_info *iface_param = NULL;
1181 struct addr_ctrl_blk *init_fw_cb = NULL;
1182 dma_addr_t init_fw_cb_dma;
1183 uint32_t mbox_cmd[MBOX_REG_COUNT];
1184 uint32_t mbox_sts[MBOX_REG_COUNT];
Mike Christie00c31882011-10-06 03:56:59 -05001185 uint32_t rem = len;
1186 struct nlattr *attr;
Mike Christied00efe32011-07-25 13:48:38 -05001187
1188 init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
1189 sizeof(struct addr_ctrl_blk),
1190 &init_fw_cb_dma, GFP_KERNEL);
1191 if (!init_fw_cb) {
1192 ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",
1193 __func__);
1194 return -ENOMEM;
1195 }
1196
1197 memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
1198 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1199 memset(&mbox_sts, 0, sizeof(mbox_sts));
1200
1201 if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)) {
1202 ql4_printk(KERN_ERR, ha, "%s: get ifcb failed\n", __func__);
1203 rval = -EIO;
1204 goto exit_init_fw_cb;
1205 }
1206
Mike Christie00c31882011-10-06 03:56:59 -05001207 nla_for_each_attr(attr, data, len, rem) {
1208 iface_param = nla_data(attr);
Mike Christied00efe32011-07-25 13:48:38 -05001209
1210 if (iface_param->param_type != ISCSI_NET_PARAM)
1211 continue;
1212
1213 switch (iface_param->iface_type) {
1214 case ISCSI_IFACE_TYPE_IPV4:
1215 switch (iface_param->iface_num) {
1216 case 0:
1217 qla4xxx_set_ipv4(ha, iface_param, init_fw_cb);
1218 break;
1219 default:
1220 /* Cannot have more than one IPv4 interface */
1221 ql4_printk(KERN_ERR, ha, "Invalid IPv4 iface "
1222 "number = %d\n",
1223 iface_param->iface_num);
1224 break;
1225 }
1226 break;
1227 case ISCSI_IFACE_TYPE_IPV6:
1228 switch (iface_param->iface_num) {
1229 case 0:
1230 case 1:
1231 qla4xxx_set_ipv6(ha, iface_param, init_fw_cb);
1232 break;
1233 default:
1234 /* Cannot have more than two IPv6 interface */
1235 ql4_printk(KERN_ERR, ha, "Invalid IPv6 iface "
1236 "number = %d\n",
1237 iface_param->iface_num);
1238 break;
1239 }
1240 break;
1241 default:
1242 ql4_printk(KERN_ERR, ha, "Invalid iface type\n");
1243 break;
1244 }
Mike Christied00efe32011-07-25 13:48:38 -05001245 }
1246
1247 init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A);
1248
1249 rval = qla4xxx_set_flash(ha, init_fw_cb_dma, FLASH_SEGMENT_IFCB,
1250 sizeof(struct addr_ctrl_blk),
1251 FLASH_OPT_RMW_COMMIT);
1252 if (rval != QLA_SUCCESS) {
1253 ql4_printk(KERN_ERR, ha, "%s: set flash mbx failed\n",
1254 __func__);
1255 rval = -EIO;
1256 goto exit_init_fw_cb;
1257 }
1258
Vikas Chaudharyce505f92011-12-01 22:42:10 -08001259 rval = qla4xxx_disable_acb(ha);
1260 if (rval != QLA_SUCCESS) {
1261 ql4_printk(KERN_ERR, ha, "%s: disable acb mbx failed\n",
1262 __func__);
1263 rval = -EIO;
1264 goto exit_init_fw_cb;
1265 }
1266
1267 wait_for_completion_timeout(&ha->disable_acb_comp,
1268 DISABLE_ACB_TOV * HZ);
Mike Christied00efe32011-07-25 13:48:38 -05001269
1270 qla4xxx_initcb_to_acb(init_fw_cb);
1271
1272 rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma);
1273 if (rval != QLA_SUCCESS) {
1274 ql4_printk(KERN_ERR, ha, "%s: set acb mbx failed\n",
1275 __func__);
1276 rval = -EIO;
1277 goto exit_init_fw_cb;
1278 }
1279
1280 memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
1281 qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb,
1282 init_fw_cb_dma);
1283
1284exit_init_fw_cb:
1285 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
1286 init_fw_cb, init_fw_cb_dma);
1287
1288 return rval;
1289}
1290
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001291static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn,
David Somayajuluafaf5a22006-09-19 10:28:00 -07001292 enum iscsi_param param, char *buf)
1293{
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001294 struct iscsi_conn *conn;
1295 struct qla_conn *qla_conn;
1296 struct sockaddr *dst_addr;
1297 int len = 0;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001298
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001299 conn = cls_conn->dd_data;
1300 qla_conn = conn->dd_data;
1301 dst_addr = &qla_conn->qla_ep->dst_addr;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001302
1303 switch (param) {
1304 case ISCSI_PARAM_CONN_PORT:
David Somayajuluafaf5a22006-09-19 10:28:00 -07001305 case ISCSI_PARAM_CONN_ADDRESS:
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001306 return iscsi_conn_get_addr_param((struct sockaddr_storage *)
1307 dst_addr, param, buf);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001308 default:
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001309 return iscsi_conn_get_param(cls_conn, param, buf);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001310 }
1311
1312 return len;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001313
David Somayajuluafaf5a22006-09-19 10:28:00 -07001314}
1315
Mike Christie13483732011-12-01 21:38:41 -06001316int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index)
1317{
1318 uint32_t mbx_sts = 0;
1319 uint16_t tmp_ddb_index;
1320 int ret;
1321
1322get_ddb_index:
1323 tmp_ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES);
1324
1325 if (tmp_ddb_index >= MAX_DDB_ENTRIES) {
1326 DEBUG2(ql4_printk(KERN_INFO, ha,
1327 "Free DDB index not available\n"));
1328 ret = QLA_ERROR;
1329 goto exit_get_ddb_index;
1330 }
1331
1332 if (test_and_set_bit(tmp_ddb_index, ha->ddb_idx_map))
1333 goto get_ddb_index;
1334
1335 DEBUG2(ql4_printk(KERN_INFO, ha,
1336 "Found a free DDB index at %d\n", tmp_ddb_index));
1337 ret = qla4xxx_req_ddb_entry(ha, tmp_ddb_index, &mbx_sts);
1338 if (ret == QLA_ERROR) {
1339 if (mbx_sts == MBOX_STS_COMMAND_ERROR) {
1340 ql4_printk(KERN_INFO, ha,
1341 "DDB index = %d not available trying next\n",
1342 tmp_ddb_index);
1343 goto get_ddb_index;
1344 }
1345 DEBUG2(ql4_printk(KERN_INFO, ha,
1346 "Free FW DDB not available\n"));
1347 }
1348
1349 *ddb_index = tmp_ddb_index;
1350
1351exit_get_ddb_index:
1352 return ret;
1353}
1354
1355static int qla4xxx_match_ipaddress(struct scsi_qla_host *ha,
1356 struct ddb_entry *ddb_entry,
1357 char *existing_ipaddr,
1358 char *user_ipaddr)
1359{
1360 uint8_t dst_ipaddr[IPv6_ADDR_LEN];
1361 char formatted_ipaddr[DDB_IPADDR_LEN];
1362 int status = QLA_SUCCESS, ret = 0;
1363
1364 if (ddb_entry->fw_ddb_entry.options & DDB_OPT_IPV6_DEVICE) {
1365 ret = in6_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr,
1366 '\0', NULL);
1367 if (ret == 0) {
1368 status = QLA_ERROR;
1369 goto out_match;
1370 }
1371 ret = sprintf(formatted_ipaddr, "%pI6", dst_ipaddr);
1372 } else {
1373 ret = in4_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr,
1374 '\0', NULL);
1375 if (ret == 0) {
1376 status = QLA_ERROR;
1377 goto out_match;
1378 }
1379 ret = sprintf(formatted_ipaddr, "%pI4", dst_ipaddr);
1380 }
1381
1382 if (strcmp(existing_ipaddr, formatted_ipaddr))
1383 status = QLA_ERROR;
1384
1385out_match:
1386 return status;
1387}
1388
1389static int qla4xxx_match_fwdb_session(struct scsi_qla_host *ha,
1390 struct iscsi_cls_conn *cls_conn)
1391{
1392 int idx = 0, max_ddbs, rval;
1393 struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);
1394 struct iscsi_session *sess, *existing_sess;
1395 struct iscsi_conn *conn, *existing_conn;
1396 struct ddb_entry *ddb_entry;
1397
1398 sess = cls_sess->dd_data;
1399 conn = cls_conn->dd_data;
1400
1401 if (sess->targetname == NULL ||
1402 conn->persistent_address == NULL ||
1403 conn->persistent_port == 0)
1404 return QLA_ERROR;
1405
1406 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
1407 MAX_DEV_DB_ENTRIES;
1408
1409 for (idx = 0; idx < max_ddbs; idx++) {
1410 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
1411 if (ddb_entry == NULL)
1412 continue;
1413
1414 if (ddb_entry->ddb_type != FLASH_DDB)
1415 continue;
1416
1417 existing_sess = ddb_entry->sess->dd_data;
1418 existing_conn = ddb_entry->conn->dd_data;
1419
1420 if (existing_sess->targetname == NULL ||
1421 existing_conn->persistent_address == NULL ||
1422 existing_conn->persistent_port == 0)
1423 continue;
1424
1425 DEBUG2(ql4_printk(KERN_INFO, ha,
1426 "IQN = %s User IQN = %s\n",
1427 existing_sess->targetname,
1428 sess->targetname));
1429
1430 DEBUG2(ql4_printk(KERN_INFO, ha,
1431 "IP = %s User IP = %s\n",
1432 existing_conn->persistent_address,
1433 conn->persistent_address));
1434
1435 DEBUG2(ql4_printk(KERN_INFO, ha,
1436 "Port = %d User Port = %d\n",
1437 existing_conn->persistent_port,
1438 conn->persistent_port));
1439
1440 if (strcmp(existing_sess->targetname, sess->targetname))
1441 continue;
1442 rval = qla4xxx_match_ipaddress(ha, ddb_entry,
1443 existing_conn->persistent_address,
1444 conn->persistent_address);
1445 if (rval == QLA_ERROR)
1446 continue;
1447 if (existing_conn->persistent_port != conn->persistent_port)
1448 continue;
1449 break;
1450 }
1451
1452 if (idx == max_ddbs)
1453 return QLA_ERROR;
1454
1455 DEBUG2(ql4_printk(KERN_INFO, ha,
1456 "Match found in fwdb sessions\n"));
1457 return QLA_SUCCESS;
1458}
1459
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001460static struct iscsi_cls_session *
1461qla4xxx_session_create(struct iscsi_endpoint *ep,
1462 uint16_t cmds_max, uint16_t qdepth,
1463 uint32_t initial_cmdsn)
1464{
1465 struct iscsi_cls_session *cls_sess;
1466 struct scsi_qla_host *ha;
1467 struct qla_endpoint *qla_ep;
1468 struct ddb_entry *ddb_entry;
Mike Christie13483732011-12-01 21:38:41 -06001469 uint16_t ddb_index;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001470 struct iscsi_session *sess;
1471 struct sockaddr *dst_addr;
1472 int ret;
1473
1474 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
1475 if (!ep) {
1476 printk(KERN_ERR "qla4xxx: missing ep.\n");
1477 return NULL;
1478 }
1479
1480 qla_ep = ep->dd_data;
1481 dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
1482 ha = to_qla_host(qla_ep->host);
Manish Rangankar736cf362011-10-07 16:55:46 -07001483
Mike Christie13483732011-12-01 21:38:41 -06001484 ret = qla4xxx_get_ddb_index(ha, &ddb_index);
1485 if (ret == QLA_ERROR)
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001486 return NULL;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001487
1488 cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, qla_ep->host,
1489 cmds_max, sizeof(struct ddb_entry),
1490 sizeof(struct ql4_task_data),
1491 initial_cmdsn, ddb_index);
1492 if (!cls_sess)
1493 return NULL;
1494
1495 sess = cls_sess->dd_data;
1496 ddb_entry = sess->dd_data;
1497 ddb_entry->fw_ddb_index = ddb_index;
1498 ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
1499 ddb_entry->ha = ha;
1500 ddb_entry->sess = cls_sess;
Mike Christie13483732011-12-01 21:38:41 -06001501 ddb_entry->unblock_sess = qla4xxx_unblock_ddb;
1502 ddb_entry->ddb_change = qla4xxx_ddb_change;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001503 cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
1504 ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry;
1505 ha->tot_ddbs++;
1506
1507 return cls_sess;
1508}
1509
1510static void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess)
1511{
1512 struct iscsi_session *sess;
1513 struct ddb_entry *ddb_entry;
1514 struct scsi_qla_host *ha;
1515 unsigned long flags;
1516
1517 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
1518 sess = cls_sess->dd_data;
1519 ddb_entry = sess->dd_data;
1520 ha = ddb_entry->ha;
1521
Manish Rangankar736cf362011-10-07 16:55:46 -07001522 qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
1523
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001524 spin_lock_irqsave(&ha->hardware_lock, flags);
1525 qla4xxx_free_ddb(ha, ddb_entry);
1526 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1527 iscsi_session_teardown(cls_sess);
1528}
1529
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001530static struct iscsi_cls_conn *
1531qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx)
1532{
1533 struct iscsi_cls_conn *cls_conn;
1534 struct iscsi_session *sess;
1535 struct ddb_entry *ddb_entry;
1536
1537 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
1538 cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn),
1539 conn_idx);
Mike Christieff1d0312011-12-01 21:38:43 -06001540 if (!cls_conn)
1541 return NULL;
1542
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001543 sess = cls_sess->dd_data;
1544 ddb_entry = sess->dd_data;
1545 ddb_entry->conn = cls_conn;
1546
1547 return cls_conn;
1548}
1549
1550static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
1551 struct iscsi_cls_conn *cls_conn,
1552 uint64_t transport_fd, int is_leading)
1553{
1554 struct iscsi_conn *conn;
1555 struct qla_conn *qla_conn;
1556 struct iscsi_endpoint *ep;
1557
1558 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
1559
1560 if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
1561 return -EINVAL;
1562 ep = iscsi_lookup_endpoint(transport_fd);
1563 conn = cls_conn->dd_data;
1564 qla_conn = conn->dd_data;
1565 qla_conn->qla_ep = ep->dd_data;
1566 return 0;
1567}
1568
1569static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)
1570{
1571 struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);
1572 struct iscsi_session *sess;
1573 struct ddb_entry *ddb_entry;
1574 struct scsi_qla_host *ha;
Mike Christie13483732011-12-01 21:38:41 -06001575 struct dev_db_entry *fw_ddb_entry = NULL;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001576 dma_addr_t fw_ddb_entry_dma;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001577 uint32_t mbx_sts = 0;
1578 int ret = 0;
1579 int status = QLA_SUCCESS;
1580
1581 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
1582 sess = cls_sess->dd_data;
1583 ddb_entry = sess->dd_data;
1584 ha = ddb_entry->ha;
1585
Mike Christie13483732011-12-01 21:38:41 -06001586 /* Check if we have matching FW DDB, if yes then do not
1587 * login to this target. This could cause target to logout previous
1588 * connection
1589 */
1590 ret = qla4xxx_match_fwdb_session(ha, cls_conn);
1591 if (ret == QLA_SUCCESS) {
1592 ql4_printk(KERN_INFO, ha,
1593 "Session already exist in FW.\n");
1594 ret = -EEXIST;
1595 goto exit_conn_start;
1596 }
1597
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001598 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1599 &fw_ddb_entry_dma, GFP_KERNEL);
1600 if (!fw_ddb_entry) {
1601 ql4_printk(KERN_ERR, ha,
1602 "%s: Unable to allocate dma buffer\n", __func__);
Mike Christie13483732011-12-01 21:38:41 -06001603 ret = -ENOMEM;
1604 goto exit_conn_start;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001605 }
1606
1607 ret = qla4xxx_set_param_ddbentry(ha, ddb_entry, cls_conn, &mbx_sts);
1608 if (ret) {
1609 /* If iscsid is stopped and started then no need to do
1610 * set param again since ddb state will be already
1611 * active and FW does not allow set ddb to an
1612 * active session.
1613 */
1614 if (mbx_sts)
1615 if (ddb_entry->fw_ddb_device_state ==
Manish Rangankarf922da72011-10-07 16:55:49 -07001616 DDB_DS_SESSION_ACTIVE) {
Mike Christie13483732011-12-01 21:38:41 -06001617 ddb_entry->unblock_sess(ddb_entry->sess);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001618 goto exit_set_param;
Manish Rangankarf922da72011-10-07 16:55:49 -07001619 }
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001620
1621 ql4_printk(KERN_ERR, ha, "%s: Failed set param for index[%d]\n",
1622 __func__, ddb_entry->fw_ddb_index);
1623 goto exit_conn_start;
1624 }
1625
1626 status = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index);
1627 if (status == QLA_ERROR) {
Manish Rangankar0e7e8502011-07-25 13:48:54 -05001628 ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__,
1629 sess->targetname);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001630 ret = -EINVAL;
1631 goto exit_conn_start;
1632 }
1633
Manish Rangankar98270ab2011-10-07 16:55:47 -07001634 if (ddb_entry->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE)
1635 ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
1636
1637 DEBUG2(printk(KERN_INFO "%s: DDB state [%d]\n", __func__,
1638 ddb_entry->fw_ddb_device_state));
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001639
1640exit_set_param:
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001641 ret = 0;
1642
1643exit_conn_start:
Mike Christie13483732011-12-01 21:38:41 -06001644 if (fw_ddb_entry)
1645 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1646 fw_ddb_entry, fw_ddb_entry_dma);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001647 return ret;
1648}
1649
1650static void qla4xxx_conn_destroy(struct iscsi_cls_conn *cls_conn)
1651{
1652 struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);
1653 struct iscsi_session *sess;
1654 struct scsi_qla_host *ha;
1655 struct ddb_entry *ddb_entry;
1656 int options;
1657
1658 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
1659 sess = cls_sess->dd_data;
1660 ddb_entry = sess->dd_data;
1661 ha = ddb_entry->ha;
1662
1663 options = LOGOUT_OPTION_CLOSE_SESSION;
1664 if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR)
1665 ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001666}
1667
1668static void qla4xxx_task_work(struct work_struct *wdata)
1669{
1670 struct ql4_task_data *task_data;
1671 struct scsi_qla_host *ha;
1672 struct passthru_status *sts;
1673 struct iscsi_task *task;
1674 struct iscsi_hdr *hdr;
1675 uint8_t *data;
1676 uint32_t data_len;
1677 struct iscsi_conn *conn;
1678 int hdr_len;
1679 itt_t itt;
1680
1681 task_data = container_of(wdata, struct ql4_task_data, task_work);
1682 ha = task_data->ha;
1683 task = task_data->task;
1684 sts = &task_data->sts;
1685 hdr_len = sizeof(struct iscsi_hdr);
1686
1687 DEBUG3(printk(KERN_INFO "Status returned\n"));
1688 DEBUG3(qla4xxx_dump_buffer(sts, 64));
1689 DEBUG3(printk(KERN_INFO "Response buffer"));
1690 DEBUG3(qla4xxx_dump_buffer(task_data->resp_buffer, 64));
1691
1692 conn = task->conn;
1693
1694 switch (sts->completionStatus) {
1695 case PASSTHRU_STATUS_COMPLETE:
1696 hdr = (struct iscsi_hdr *)task_data->resp_buffer;
1697 /* Assign back the itt in hdr, until we use the PREASSIGN_TAG */
1698 itt = sts->handle;
1699 hdr->itt = itt;
1700 data = task_data->resp_buffer + hdr_len;
1701 data_len = task_data->resp_len - hdr_len;
1702 iscsi_complete_pdu(conn, hdr, data, data_len);
1703 break;
1704 default:
1705 ql4_printk(KERN_ERR, ha, "Passthru failed status = 0x%x\n",
1706 sts->completionStatus);
1707 break;
1708 }
1709 return;
1710}
1711
1712static int qla4xxx_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
1713{
1714 struct ql4_task_data *task_data;
1715 struct iscsi_session *sess;
1716 struct ddb_entry *ddb_entry;
1717 struct scsi_qla_host *ha;
1718 int hdr_len;
1719
1720 sess = task->conn->session;
1721 ddb_entry = sess->dd_data;
1722 ha = ddb_entry->ha;
1723 task_data = task->dd_data;
1724 memset(task_data, 0, sizeof(struct ql4_task_data));
1725
1726 if (task->sc) {
1727 ql4_printk(KERN_INFO, ha,
1728 "%s: SCSI Commands not implemented\n", __func__);
1729 return -EINVAL;
1730 }
1731
1732 hdr_len = sizeof(struct iscsi_hdr);
1733 task_data->ha = ha;
1734 task_data->task = task;
1735
1736 if (task->data_count) {
1737 task_data->data_dma = dma_map_single(&ha->pdev->dev, task->data,
1738 task->data_count,
1739 PCI_DMA_TODEVICE);
1740 }
1741
1742 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",
1743 __func__, task->conn->max_recv_dlength, hdr_len));
1744
Manish Rangankar69ca2162011-10-07 16:55:50 -07001745 task_data->resp_len = task->conn->max_recv_dlength + hdr_len;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001746 task_data->resp_buffer = dma_alloc_coherent(&ha->pdev->dev,
1747 task_data->resp_len,
1748 &task_data->resp_dma,
1749 GFP_ATOMIC);
1750 if (!task_data->resp_buffer)
1751 goto exit_alloc_pdu;
1752
Manish Rangankar69ca2162011-10-07 16:55:50 -07001753 task_data->req_len = task->data_count + hdr_len;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001754 task_data->req_buffer = dma_alloc_coherent(&ha->pdev->dev,
Manish Rangankar69ca2162011-10-07 16:55:50 -07001755 task_data->req_len,
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001756 &task_data->req_dma,
1757 GFP_ATOMIC);
1758 if (!task_data->req_buffer)
1759 goto exit_alloc_pdu;
1760
1761 task->hdr = task_data->req_buffer;
1762
1763 INIT_WORK(&task_data->task_work, qla4xxx_task_work);
1764
1765 return 0;
1766
1767exit_alloc_pdu:
1768 if (task_data->resp_buffer)
1769 dma_free_coherent(&ha->pdev->dev, task_data->resp_len,
1770 task_data->resp_buffer, task_data->resp_dma);
1771
1772 if (task_data->req_buffer)
Manish Rangankar69ca2162011-10-07 16:55:50 -07001773 dma_free_coherent(&ha->pdev->dev, task_data->req_len,
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001774 task_data->req_buffer, task_data->req_dma);
1775 return -ENOMEM;
1776}
1777
1778static void qla4xxx_task_cleanup(struct iscsi_task *task)
1779{
1780 struct ql4_task_data *task_data;
1781 struct iscsi_session *sess;
1782 struct ddb_entry *ddb_entry;
1783 struct scsi_qla_host *ha;
1784 int hdr_len;
1785
1786 hdr_len = sizeof(struct iscsi_hdr);
1787 sess = task->conn->session;
1788 ddb_entry = sess->dd_data;
1789 ha = ddb_entry->ha;
1790 task_data = task->dd_data;
1791
1792 if (task->data_count) {
1793 dma_unmap_single(&ha->pdev->dev, task_data->data_dma,
1794 task->data_count, PCI_DMA_TODEVICE);
1795 }
1796
1797 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",
1798 __func__, task->conn->max_recv_dlength, hdr_len));
1799
1800 dma_free_coherent(&ha->pdev->dev, task_data->resp_len,
1801 task_data->resp_buffer, task_data->resp_dma);
Manish Rangankar69ca2162011-10-07 16:55:50 -07001802 dma_free_coherent(&ha->pdev->dev, task_data->req_len,
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001803 task_data->req_buffer, task_data->req_dma);
1804 return;
1805}
1806
1807static int qla4xxx_task_xmit(struct iscsi_task *task)
1808{
1809 struct scsi_cmnd *sc = task->sc;
1810 struct iscsi_session *sess = task->conn->session;
1811 struct ddb_entry *ddb_entry = sess->dd_data;
1812 struct scsi_qla_host *ha = ddb_entry->ha;
1813
1814 if (!sc)
1815 return qla4xxx_send_passthru0(task);
1816
1817 ql4_printk(KERN_INFO, ha, "%s: scsi cmd xmit not implemented\n",
1818 __func__);
1819 return -ENOSYS;
1820}
1821
Mike Christie13483732011-12-01 21:38:41 -06001822static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha,
1823 struct dev_db_entry *fw_ddb_entry,
1824 struct iscsi_cls_session *cls_sess,
1825 struct iscsi_cls_conn *cls_conn)
1826{
1827 int buflen = 0;
1828 struct iscsi_session *sess;
Nilesh Javali376738a2012-02-27 03:08:52 -08001829 struct ddb_entry *ddb_entry;
Mike Christie13483732011-12-01 21:38:41 -06001830 struct iscsi_conn *conn;
1831 char ip_addr[DDB_IPADDR_LEN];
1832 uint16_t options = 0;
1833
1834 sess = cls_sess->dd_data;
Nilesh Javali376738a2012-02-27 03:08:52 -08001835 ddb_entry = sess->dd_data;
Mike Christie13483732011-12-01 21:38:41 -06001836 conn = cls_conn->dd_data;
1837
Nilesh Javali376738a2012-02-27 03:08:52 -08001838 ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx);
1839
Mike Christie13483732011-12-01 21:38:41 -06001840 conn->max_recv_dlength = BYTE_UNITS *
1841 le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
1842
1843 conn->max_xmit_dlength = BYTE_UNITS *
1844 le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len);
1845
1846 sess->initial_r2t_en =
1847 (BIT_10 & le16_to_cpu(fw_ddb_entry->iscsi_options));
1848
1849 sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t);
1850
1851 sess->imm_data_en = (BIT_11 & le16_to_cpu(fw_ddb_entry->iscsi_options));
1852
1853 sess->first_burst = BYTE_UNITS *
1854 le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len);
1855
1856 sess->max_burst = BYTE_UNITS *
1857 le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len);
1858
1859 sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
1860
1861 sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain);
1862
1863 conn->persistent_port = le16_to_cpu(fw_ddb_entry->port);
1864
1865 sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
1866
1867 options = le16_to_cpu(fw_ddb_entry->options);
1868 if (options & DDB_OPT_IPV6_DEVICE)
1869 sprintf(ip_addr, "%pI6", fw_ddb_entry->ip_addr);
1870 else
1871 sprintf(ip_addr, "%pI4", fw_ddb_entry->ip_addr);
1872
1873 iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_NAME,
1874 (char *)fw_ddb_entry->iscsi_name, buflen);
1875 iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME,
1876 (char *)ha->name_string, buflen);
1877 iscsi_set_param(cls_conn, ISCSI_PARAM_PERSISTENT_ADDRESS,
1878 (char *)ip_addr, buflen);
Vikas Chaudhary6c1b8782012-01-19 03:06:54 -08001879 iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_ALIAS,
1880 (char *)fw_ddb_entry->iscsi_alias, buflen);
Mike Christie13483732011-12-01 21:38:41 -06001881}
1882
1883void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha,
1884 struct ddb_entry *ddb_entry)
1885{
1886 struct iscsi_cls_session *cls_sess;
1887 struct iscsi_cls_conn *cls_conn;
1888 uint32_t ddb_state;
1889 dma_addr_t fw_ddb_entry_dma;
1890 struct dev_db_entry *fw_ddb_entry;
1891
1892 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1893 &fw_ddb_entry_dma, GFP_KERNEL);
1894 if (!fw_ddb_entry) {
1895 ql4_printk(KERN_ERR, ha,
1896 "%s: Unable to allocate dma buffer\n", __func__);
1897 goto exit_session_conn_fwddb_param;
1898 }
1899
1900 if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry,
1901 fw_ddb_entry_dma, NULL, NULL, &ddb_state,
1902 NULL, NULL, NULL) == QLA_ERROR) {
1903 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
1904 "get_ddb_entry for fw_ddb_index %d\n",
1905 ha->host_no, __func__,
1906 ddb_entry->fw_ddb_index));
1907 goto exit_session_conn_fwddb_param;
1908 }
1909
1910 cls_sess = ddb_entry->sess;
1911
1912 cls_conn = ddb_entry->conn;
1913
1914 /* Update params */
1915 qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);
1916
1917exit_session_conn_fwddb_param:
1918 if (fw_ddb_entry)
1919 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1920 fw_ddb_entry, fw_ddb_entry_dma);
1921}
1922
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001923void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
1924 struct ddb_entry *ddb_entry)
1925{
1926 struct iscsi_cls_session *cls_sess;
1927 struct iscsi_cls_conn *cls_conn;
1928 struct iscsi_session *sess;
1929 struct iscsi_conn *conn;
1930 uint32_t ddb_state;
1931 dma_addr_t fw_ddb_entry_dma;
1932 struct dev_db_entry *fw_ddb_entry;
1933
1934 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1935 &fw_ddb_entry_dma, GFP_KERNEL);
1936 if (!fw_ddb_entry) {
1937 ql4_printk(KERN_ERR, ha,
1938 "%s: Unable to allocate dma buffer\n", __func__);
Mike Christie13483732011-12-01 21:38:41 -06001939 goto exit_session_conn_param;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001940 }
1941
1942 if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry,
1943 fw_ddb_entry_dma, NULL, NULL, &ddb_state,
1944 NULL, NULL, NULL) == QLA_ERROR) {
1945 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
1946 "get_ddb_entry for fw_ddb_index %d\n",
1947 ha->host_no, __func__,
1948 ddb_entry->fw_ddb_index));
Mike Christie13483732011-12-01 21:38:41 -06001949 goto exit_session_conn_param;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001950 }
1951
1952 cls_sess = ddb_entry->sess;
1953 sess = cls_sess->dd_data;
1954
1955 cls_conn = ddb_entry->conn;
1956 conn = cls_conn->dd_data;
1957
Mike Christie13483732011-12-01 21:38:41 -06001958 /* Update timers after login */
1959 ddb_entry->default_relogin_timeout =
Nilesh Javalic28eaac2011-12-18 21:40:44 -08001960 (le16_to_cpu(fw_ddb_entry->def_timeout) > LOGIN_TOV) &&
1961 (le16_to_cpu(fw_ddb_entry->def_timeout) < LOGIN_TOV * 10) ?
1962 le16_to_cpu(fw_ddb_entry->def_timeout) : LOGIN_TOV;
Mike Christie13483732011-12-01 21:38:41 -06001963 ddb_entry->default_time2wait =
1964 le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
1965
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001966 /* Update params */
Nilesh Javali376738a2012-02-27 03:08:52 -08001967 ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001968 conn->max_recv_dlength = BYTE_UNITS *
1969 le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
1970
1971 conn->max_xmit_dlength = BYTE_UNITS *
1972 le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len);
1973
1974 sess->initial_r2t_en =
1975 (BIT_10 & le16_to_cpu(fw_ddb_entry->iscsi_options));
1976
1977 sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t);
1978
1979 sess->imm_data_en = (BIT_11 & le16_to_cpu(fw_ddb_entry->iscsi_options));
1980
1981 sess->first_burst = BYTE_UNITS *
1982 le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len);
1983
1984 sess->max_burst = BYTE_UNITS *
1985 le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len);
1986
1987 sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
1988
1989 sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain);
1990
1991 sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
1992
1993 memcpy(sess->initiatorname, ha->name_string,
1994 min(sizeof(ha->name_string), sizeof(sess->initiatorname)));
Mike Christie13483732011-12-01 21:38:41 -06001995
Vikas Chaudhary6c1b8782012-01-19 03:06:54 -08001996 iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_ALIAS,
1997 (char *)fw_ddb_entry->iscsi_alias, 0);
1998
Mike Christie13483732011-12-01 21:38:41 -06001999exit_session_conn_param:
2000 if (fw_ddb_entry)
2001 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
2002 fw_ddb_entry, fw_ddb_entry_dma);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002003}
2004
David Somayajuluafaf5a22006-09-19 10:28:00 -07002005/*
2006 * Timer routines
2007 */
2008
2009static void qla4xxx_start_timer(struct scsi_qla_host *ha, void *func,
2010 unsigned long interval)
2011{
2012 DEBUG(printk("scsi: %s: Starting timer thread for adapter %d\n",
2013 __func__, ha->host->host_no));
2014 init_timer(&ha->timer);
2015 ha->timer.expires = jiffies + interval * HZ;
2016 ha->timer.data = (unsigned long)ha;
2017 ha->timer.function = (void (*)(unsigned long))func;
2018 add_timer(&ha->timer);
2019 ha->timer_active = 1;
2020}
2021
2022static void qla4xxx_stop_timer(struct scsi_qla_host *ha)
2023{
2024 del_timer_sync(&ha->timer);
2025 ha->timer_active = 0;
2026}
2027
2028/***
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002029 * qla4xxx_mark_device_missing - blocks the session
2030 * @cls_session: Pointer to the session to be blocked
David Somayajuluafaf5a22006-09-19 10:28:00 -07002031 * @ddb_entry: Pointer to device database entry
2032 *
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302033 * This routine marks a device missing and close connection.
David Somayajuluafaf5a22006-09-19 10:28:00 -07002034 **/
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002035void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002036{
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002037 iscsi_block_session(cls_session);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002038}
2039
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302040/**
2041 * qla4xxx_mark_all_devices_missing - mark all devices as missing.
2042 * @ha: Pointer to host adapter structure.
2043 *
2044 * This routine marks a device missing and resets the relogin retry count.
2045 **/
2046void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha)
2047{
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002048 iscsi_host_for_each_session(ha->host, qla4xxx_mark_device_missing);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302049}
2050
David Somayajuluafaf5a22006-09-19 10:28:00 -07002051static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
2052 struct ddb_entry *ddb_entry,
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -07002053 struct scsi_cmnd *cmd)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002054{
2055 struct srb *srb;
2056
2057 srb = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
2058 if (!srb)
2059 return srb;
2060
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302061 kref_init(&srb->srb_ref);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002062 srb->ha = ha;
2063 srb->ddb = ddb_entry;
2064 srb->cmd = cmd;
2065 srb->flags = 0;
Vikas Chaudhary53698872010-04-28 11:41:59 +05302066 CMD_SP(cmd) = (void *)srb;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002067
2068 return srb;
2069}
2070
2071static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb)
2072{
2073 struct scsi_cmnd *cmd = srb->cmd;
2074
2075 if (srb->flags & SRB_DMA_VALID) {
FUJITA Tomonori5f7186c2007-05-26 14:08:20 +09002076 scsi_dma_unmap(cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002077 srb->flags &= ~SRB_DMA_VALID;
2078 }
Vikas Chaudhary53698872010-04-28 11:41:59 +05302079 CMD_SP(cmd) = NULL;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002080}
2081
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302082void qla4xxx_srb_compl(struct kref *ref)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002083{
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302084 struct srb *srb = container_of(ref, struct srb, srb_ref);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002085 struct scsi_cmnd *cmd = srb->cmd;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302086 struct scsi_qla_host *ha = srb->ha;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002087
2088 qla4xxx_srb_free_dma(ha, srb);
2089
2090 mempool_free(srb, ha->srb_mempool);
2091
2092 cmd->scsi_done(cmd);
2093}
2094
2095/**
2096 * qla4xxx_queuecommand - scsi layer issues scsi command to driver.
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -07002097 * @host: scsi host
David Somayajuluafaf5a22006-09-19 10:28:00 -07002098 * @cmd: Pointer to Linux's SCSI command structure
David Somayajuluafaf5a22006-09-19 10:28:00 -07002099 *
2100 * Remarks:
2101 * This routine is invoked by Linux to send a SCSI command to the driver.
2102 * The mid-level driver tries to ensure that queuecommand never gets
2103 * invoked concurrently with itself or the interrupt handler (although
2104 * the interrupt handler may call this routine as part of request-
2105 * completion handling). Unfortunely, it sometimes calls the scheduler
2106 * in interrupt context which is a big NO! NO!.
2107 **/
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -07002108static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002109{
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -07002110 struct scsi_qla_host *ha = to_qla_host(host);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002111 struct ddb_entry *ddb_entry = cmd->device->hostdata;
Mike Christie7fb19212008-01-31 13:36:45 -06002112 struct iscsi_cls_session *sess = ddb_entry->sess;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002113 struct srb *srb;
2114 int rval;
2115
Lalit Chandivade2232be02010-07-30 14:38:47 +05302116 if (test_bit(AF_EEH_BUSY, &ha->flags)) {
2117 if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))
2118 cmd->result = DID_NO_CONNECT << 16;
2119 else
2120 cmd->result = DID_REQUEUE << 16;
2121 goto qc_fail_command;
2122 }
2123
Mike Christie7fb19212008-01-31 13:36:45 -06002124 if (!sess) {
2125 cmd->result = DID_IMM_RETRY << 16;
2126 goto qc_fail_command;
2127 }
2128
2129 rval = iscsi_session_chkready(sess);
2130 if (rval) {
2131 cmd->result = rval;
2132 goto qc_fail_command;
2133 }
2134
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302135 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
2136 test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
2137 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
2138 test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||
2139 test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||
2140 !test_bit(AF_ONLINE, &ha->flags) ||
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002141 !test_bit(AF_LINK_UP, &ha->flags) ||
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302142 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))
David C Somayajulu477ffb92007-01-22 12:26:11 -08002143 goto qc_host_busy;
2144
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -07002145 srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002146 if (!srb)
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -07002147 goto qc_host_busy;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002148
2149 rval = qla4xxx_send_command_to_isp(ha, srb);
2150 if (rval != QLA_SUCCESS)
2151 goto qc_host_busy_free_sp;
2152
David Somayajuluafaf5a22006-09-19 10:28:00 -07002153 return 0;
2154
2155qc_host_busy_free_sp:
2156 qla4xxx_srb_free_dma(ha, srb);
2157 mempool_free(srb, ha->srb_mempool);
2158
David Somayajuluafaf5a22006-09-19 10:28:00 -07002159qc_host_busy:
2160 return SCSI_MLQUEUE_HOST_BUSY;
2161
2162qc_fail_command:
Vikas Chaudhary8f0722c2011-05-17 23:17:10 -07002163 cmd->scsi_done(cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002164
2165 return 0;
2166}
2167
2168/**
2169 * qla4xxx_mem_free - frees memory allocated to adapter
2170 * @ha: Pointer to host adapter structure.
2171 *
2172 * Frees memory previously allocated by qla4xxx_mem_alloc
2173 **/
2174static void qla4xxx_mem_free(struct scsi_qla_host *ha)
2175{
2176 if (ha->queues)
2177 dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues,
2178 ha->queues_dma);
2179
2180 ha->queues_len = 0;
2181 ha->queues = NULL;
2182 ha->queues_dma = 0;
2183 ha->request_ring = NULL;
2184 ha->request_dma = 0;
2185 ha->response_ring = NULL;
2186 ha->response_dma = 0;
2187 ha->shadow_regs = NULL;
2188 ha->shadow_regs_dma = 0;
2189
2190 /* Free srb pool. */
2191 if (ha->srb_mempool)
2192 mempool_destroy(ha->srb_mempool);
2193
2194 ha->srb_mempool = NULL;
2195
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002196 if (ha->chap_dma_pool)
2197 dma_pool_destroy(ha->chap_dma_pool);
2198
Lalit Chandivade45494152011-10-07 16:55:42 -07002199 if (ha->chap_list)
2200 vfree(ha->chap_list);
2201 ha->chap_list = NULL;
2202
Mike Christie13483732011-12-01 21:38:41 -06002203 if (ha->fw_ddb_dma_pool)
2204 dma_pool_destroy(ha->fw_ddb_dma_pool);
2205
David Somayajuluafaf5a22006-09-19 10:28:00 -07002206 /* release io space registers */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302207 if (is_qla8022(ha)) {
2208 if (ha->nx_pcibase)
2209 iounmap(
2210 (struct device_reg_82xx __iomem *)ha->nx_pcibase);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302211 } else if (ha->reg)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002212 iounmap(ha->reg);
2213 pci_release_regions(ha->pdev);
2214}
2215
2216/**
2217 * qla4xxx_mem_alloc - allocates memory for use by adapter.
2218 * @ha: Pointer to host adapter structure
2219 *
2220 * Allocates DMA memory for request and response queues. Also allocates memory
2221 * for srbs.
2222 **/
2223static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
2224{
2225 unsigned long align;
2226
2227 /* Allocate contiguous block of DMA memory for queues. */
2228 ha->queues_len = ((REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +
2229 (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE) +
2230 sizeof(struct shadow_regs) +
2231 MEM_ALIGN_VALUE +
2232 (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
2233 ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len,
2234 &ha->queues_dma, GFP_KERNEL);
2235 if (ha->queues == NULL) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302236 ql4_printk(KERN_WARNING, ha,
2237 "Memory Allocation failed - queues.\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07002238
2239 goto mem_alloc_error_exit;
2240 }
2241 memset(ha->queues, 0, ha->queues_len);
2242
2243 /*
2244 * As per RISC alignment requirements -- the bus-address must be a
2245 * multiple of the request-ring size (in bytes).
2246 */
2247 align = 0;
2248 if ((unsigned long)ha->queues_dma & (MEM_ALIGN_VALUE - 1))
2249 align = MEM_ALIGN_VALUE - ((unsigned long)ha->queues_dma &
2250 (MEM_ALIGN_VALUE - 1));
2251
2252 /* Update request and response queue pointers. */
2253 ha->request_dma = ha->queues_dma + align;
2254 ha->request_ring = (struct queue_entry *) (ha->queues + align);
2255 ha->response_dma = ha->queues_dma + align +
2256 (REQUEST_QUEUE_DEPTH * QUEUE_SIZE);
2257 ha->response_ring = (struct queue_entry *) (ha->queues + align +
2258 (REQUEST_QUEUE_DEPTH *
2259 QUEUE_SIZE));
2260 ha->shadow_regs_dma = ha->queues_dma + align +
2261 (REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +
2262 (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE);
2263 ha->shadow_regs = (struct shadow_regs *) (ha->queues + align +
2264 (REQUEST_QUEUE_DEPTH *
2265 QUEUE_SIZE) +
2266 (RESPONSE_QUEUE_DEPTH *
2267 QUEUE_SIZE));
2268
2269 /* Allocate memory for srb pool. */
2270 ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab,
2271 mempool_free_slab, srb_cachep);
2272 if (ha->srb_mempool == NULL) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05302273 ql4_printk(KERN_WARNING, ha,
2274 "Memory Allocation failed - SRB Pool.\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07002275
2276 goto mem_alloc_error_exit;
2277 }
2278
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002279 ha->chap_dma_pool = dma_pool_create("ql4_chap", &ha->pdev->dev,
2280 CHAP_DMA_BLOCK_SIZE, 8, 0);
2281
2282 if (ha->chap_dma_pool == NULL) {
2283 ql4_printk(KERN_WARNING, ha,
2284 "%s: chap_dma_pool allocation failed..\n", __func__);
2285 goto mem_alloc_error_exit;
2286 }
2287
Mike Christie13483732011-12-01 21:38:41 -06002288 ha->fw_ddb_dma_pool = dma_pool_create("ql4_fw_ddb", &ha->pdev->dev,
2289 DDB_DMA_BLOCK_SIZE, 8, 0);
2290
2291 if (ha->fw_ddb_dma_pool == NULL) {
2292 ql4_printk(KERN_WARNING, ha,
2293 "%s: fw_ddb_dma_pool allocation failed..\n",
2294 __func__);
2295 goto mem_alloc_error_exit;
2296 }
2297
David Somayajuluafaf5a22006-09-19 10:28:00 -07002298 return QLA_SUCCESS;
2299
2300mem_alloc_error_exit:
2301 qla4xxx_mem_free(ha);
2302 return QLA_ERROR;
2303}
2304
2305/**
Mike Hernandez4f770832012-01-11 02:44:15 -08002306 * qla4_8xxx_check_temp - Check the ISP82XX temperature.
2307 * @ha: adapter block pointer.
2308 *
2309 * Note: The caller should not hold the idc lock.
2310 **/
2311static int qla4_8xxx_check_temp(struct scsi_qla_host *ha)
2312{
2313 uint32_t temp, temp_state, temp_val;
2314 int status = QLA_SUCCESS;
2315
2316 temp = qla4_8xxx_rd_32(ha, CRB_TEMP_STATE);
2317
2318 temp_state = qla82xx_get_temp_state(temp);
2319 temp_val = qla82xx_get_temp_val(temp);
2320
2321 if (temp_state == QLA82XX_TEMP_PANIC) {
2322 ql4_printk(KERN_WARNING, ha, "Device temperature %d degrees C"
2323 " exceeds maximum allowed. Hardware has been shut"
2324 " down.\n", temp_val);
2325 status = QLA_ERROR;
2326 } else if (temp_state == QLA82XX_TEMP_WARN) {
2327 if (ha->temperature == QLA82XX_TEMP_NORMAL)
2328 ql4_printk(KERN_WARNING, ha, "Device temperature %d"
2329 " degrees C exceeds operating range."
2330 " Immediate action needed.\n", temp_val);
2331 } else {
2332 if (ha->temperature == QLA82XX_TEMP_WARN)
2333 ql4_printk(KERN_INFO, ha, "Device temperature is"
2334 " now %d degrees C in normal range.\n",
2335 temp_val);
2336 }
2337 ha->temperature = temp_state;
2338 return status;
2339}
2340
2341/**
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302342 * qla4_8xxx_check_fw_alive - Check firmware health
2343 * @ha: Pointer to host adapter structure.
2344 *
2345 * Context: Interrupt
2346 **/
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002347static int qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha)
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302348{
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002349 uint32_t fw_heartbeat_counter;
2350 int status = QLA_SUCCESS;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302351
2352 fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
Lalit Chandivade2232be02010-07-30 14:38:47 +05302353 /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */
2354 if (fw_heartbeat_counter == 0xffffffff) {
2355 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen "
2356 "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n",
2357 ha->host_no, __func__));
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002358 return status;
Lalit Chandivade2232be02010-07-30 14:38:47 +05302359 }
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302360
2361 if (ha->fw_heartbeat_counter == fw_heartbeat_counter) {
2362 ha->seconds_since_last_heartbeat++;
2363 /* FW not alive after 2 seconds */
2364 if (ha->seconds_since_last_heartbeat == 2) {
2365 ha->seconds_since_last_heartbeat = 0;
Vikas Chaudhary68d92eb2011-05-17 23:17:05 -07002366
2367 ql4_printk(KERN_INFO, ha,
2368 "scsi(%ld): %s, Dumping hw/fw registers:\n "
2369 " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2:"
2370 " 0x%x,\n PEG_NET_0_PC: 0x%x, PEG_NET_1_PC:"
2371 " 0x%x,\n PEG_NET_2_PC: 0x%x, PEG_NET_3_PC:"
2372 " 0x%x,\n PEG_NET_4_PC: 0x%x\n",
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002373 ha->host_no, __func__,
2374 qla4_8xxx_rd_32(ha,
2375 QLA82XX_PEG_HALT_STATUS1),
Vikas Chaudhary68d92eb2011-05-17 23:17:05 -07002376 qla4_8xxx_rd_32(ha,
2377 QLA82XX_PEG_HALT_STATUS2),
2378 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_0 +
2379 0x3c),
2380 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_1 +
2381 0x3c),
2382 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_2 +
2383 0x3c),
2384 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_3 +
2385 0x3c),
2386 qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 +
2387 0x3c));
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002388 status = QLA_ERROR;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302389 }
Lalit Chandivade99457d72010-10-06 22:49:32 -07002390 } else
2391 ha->seconds_since_last_heartbeat = 0;
2392
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302393 ha->fw_heartbeat_counter = fw_heartbeat_counter;
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002394 return status;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302395}
2396
2397/**
2398 * qla4_8xxx_watchdog - Poll dev state
2399 * @ha: Pointer to host adapter structure.
2400 *
2401 * Context: Interrupt
2402 **/
2403void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
2404{
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002405 uint32_t dev_state, halt_status;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302406
2407 /* don't poll if reset is going on */
Lalit Chandivaded56a1f72010-12-02 22:12:45 -08002408 if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
2409 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
Vikas Chaudhary977f46a2011-05-17 23:17:08 -07002410 test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) {
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002411 dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
Mike Hernandez4f770832012-01-11 02:44:15 -08002412
2413 if (qla4_8xxx_check_temp(ha)) {
Giridhar Malavalie6bd0eb2012-01-11 02:44:16 -08002414 ql4_printk(KERN_INFO, ha, "disabling pause"
2415 " transmit on port 0 & 1.\n");
2416 qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
2417 CRB_NIU_XG_PAUSE_CTL_P0 |
2418 CRB_NIU_XG_PAUSE_CTL_P1);
Mike Hernandez4f770832012-01-11 02:44:15 -08002419 set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
2420 qla4xxx_wake_dpc(ha);
2421 } else if (dev_state == QLA82XX_DEV_NEED_RESET &&
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302422 !test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
Vikas Chaudhary3930b8c2010-12-02 22:12:47 -08002423 if (!ql4xdontresethba) {
2424 ql4_printk(KERN_INFO, ha, "%s: HW State: "
2425 "NEED RESET!\n", __func__);
2426 set_bit(DPC_RESET_HA, &ha->dpc_flags);
2427 qla4xxx_wake_dpc(ha);
Vikas Chaudhary3930b8c2010-12-02 22:12:47 -08002428 }
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302429 } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
2430 !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {
Vikas Chaudhary3930b8c2010-12-02 22:12:47 -08002431 ql4_printk(KERN_INFO, ha, "%s: HW State: NEED QUIES!\n",
2432 __func__);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302433 set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags);
2434 qla4xxx_wake_dpc(ha);
2435 } else {
2436 /* Check firmware health */
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002437 if (qla4_8xxx_check_fw_alive(ha)) {
Giridhar Malavalie6bd0eb2012-01-11 02:44:16 -08002438 ql4_printk(KERN_INFO, ha, "disabling pause"
2439 " transmit on port 0 & 1.\n");
2440 qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
2441 CRB_NIU_XG_PAUSE_CTL_P0 |
2442 CRB_NIU_XG_PAUSE_CTL_P1);
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002443 halt_status = qla4_8xxx_rd_32(ha,
2444 QLA82XX_PEG_HALT_STATUS1);
2445
Vikas Chaudhary46801ba2012-02-13 18:30:45 +05302446 if (QLA82XX_FWERROR_CODE(halt_status) == 0x67)
Nilesh Javali527c8b22012-01-11 02:44:17 -08002447 ql4_printk(KERN_ERR, ha, "%s:"
2448 " Firmware aborted with"
2449 " error code 0x00006700."
2450 " Device is being reset\n",
2451 __func__);
2452
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002453 /* Since we cannot change dev_state in interrupt
2454 * context, set appropriate DPC flag then wakeup
2455 * DPC */
2456 if (halt_status & HALT_STATUS_UNRECOVERABLE)
2457 set_bit(DPC_HA_UNRECOVERABLE,
2458 &ha->dpc_flags);
2459 else {
2460 ql4_printk(KERN_INFO, ha, "%s: detect "
2461 "abort needed!\n", __func__);
2462 set_bit(DPC_RESET_HA, &ha->dpc_flags);
2463 }
2464 qla4xxx_mailbox_premature_completion(ha);
2465 qla4xxx_wake_dpc(ha);
2466 }
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302467 }
2468 }
2469}
2470
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08002471static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
Mike Christie13483732011-12-01 21:38:41 -06002472{
2473 struct iscsi_session *sess;
2474 struct ddb_entry *ddb_entry;
2475 struct scsi_qla_host *ha;
2476
2477 sess = cls_sess->dd_data;
2478 ddb_entry = sess->dd_data;
2479 ha = ddb_entry->ha;
2480
2481 if (!(ddb_entry->ddb_type == FLASH_DDB))
2482 return;
2483
2484 if (adapter_up(ha) && !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
2485 !iscsi_is_session_online(cls_sess)) {
2486 if (atomic_read(&ddb_entry->retry_relogin_timer) !=
2487 INVALID_ENTRY) {
2488 if (atomic_read(&ddb_entry->retry_relogin_timer) ==
2489 0) {
2490 atomic_set(&ddb_entry->retry_relogin_timer,
2491 INVALID_ENTRY);
2492 set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
2493 set_bit(DF_RELOGIN, &ddb_entry->flags);
2494 DEBUG2(ql4_printk(KERN_INFO, ha,
2495 "%s: index [%d] login device\n",
2496 __func__, ddb_entry->fw_ddb_index));
2497 } else
2498 atomic_dec(&ddb_entry->retry_relogin_timer);
2499 }
2500 }
2501
2502 /* Wait for relogin to timeout */
2503 if (atomic_read(&ddb_entry->relogin_timer) &&
2504 (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) {
2505 /*
2506 * If the relogin times out and the device is
2507 * still NOT ONLINE then try and relogin again.
2508 */
2509 if (!iscsi_is_session_online(cls_sess)) {
2510 /* Reset retry relogin timer */
2511 atomic_inc(&ddb_entry->relogin_retry_count);
2512 DEBUG2(ql4_printk(KERN_INFO, ha,
2513 "%s: index[%d] relogin timed out-retrying"
2514 " relogin (%d), retry (%d)\n", __func__,
2515 ddb_entry->fw_ddb_index,
2516 atomic_read(&ddb_entry->relogin_retry_count),
2517 ddb_entry->default_time2wait + 4));
2518 set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
2519 atomic_set(&ddb_entry->retry_relogin_timer,
2520 ddb_entry->default_time2wait + 4);
2521 }
2522 }
2523}
2524
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302525/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07002526 * qla4xxx_timer - checks every second for work to do.
2527 * @ha: Pointer to host adapter structure.
2528 **/
2529static void qla4xxx_timer(struct scsi_qla_host *ha)
2530{
David Somayajuluafaf5a22006-09-19 10:28:00 -07002531 int start_dpc = 0;
Lalit Chandivade2232be02010-07-30 14:38:47 +05302532 uint16_t w;
2533
Mike Christie13483732011-12-01 21:38:41 -06002534 iscsi_host_for_each_session(ha->host, qla4xxx_check_relogin_flash_ddb);
2535
Lalit Chandivade2232be02010-07-30 14:38:47 +05302536 /* If we are in the middle of AER/EEH processing
2537 * skip any processing and reschedule the timer
2538 */
2539 if (test_bit(AF_EEH_BUSY, &ha->flags)) {
2540 mod_timer(&ha->timer, jiffies + HZ);
2541 return;
2542 }
2543
2544 /* Hardware read to trigger an EEH error during mailbox waits. */
2545 if (!pci_channel_offline(ha->pdev))
2546 pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002547
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302548 if (is_qla8022(ha)) {
2549 qla4_8xxx_watchdog(ha);
2550 }
2551
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302552 if (!is_qla8022(ha)) {
2553 /* Check for heartbeat interval. */
2554 if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE &&
2555 ha->heartbeat_interval != 0) {
2556 ha->seconds_since_last_heartbeat++;
2557 if (ha->seconds_since_last_heartbeat >
2558 ha->heartbeat_interval + 2)
2559 set_bit(DPC_RESET_HA, &ha->dpc_flags);
2560 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07002561 }
2562
Vikas Chaudharyff884432011-08-29 23:43:02 +05302563 /* Process any deferred work. */
2564 if (!list_empty(&ha->work_list))
2565 start_dpc++;
2566
David Somayajuluafaf5a22006-09-19 10:28:00 -07002567 /* Wakeup the dpc routine for this adapter, if needed. */
Lalit Chandivade1b468072011-05-17 23:17:09 -07002568 if (start_dpc ||
David Somayajuluafaf5a22006-09-19 10:28:00 -07002569 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
2570 test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) ||
2571 test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) ||
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302572 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||
David Somayajuluafaf5a22006-09-19 10:28:00 -07002573 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
2574 test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05302575 test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) ||
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302576 test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||
2577 test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||
Lalit Chandivade1b468072011-05-17 23:17:09 -07002578 test_bit(DPC_AEN, &ha->dpc_flags)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07002579 DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
2580 " - dpc flags = 0x%lx\n",
2581 ha->host_no, __func__, ha->dpc_flags));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302582 qla4xxx_wake_dpc(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002583 }
2584
2585 /* Reschedule timer thread to call us back in one second */
2586 mod_timer(&ha->timer, jiffies + HZ);
2587
2588 DEBUG2(ha->seconds_since_last_intr++);
2589}
2590
2591/**
2592 * qla4xxx_cmd_wait - waits for all outstanding commands to complete
2593 * @ha: Pointer to host adapter structure.
2594 *
2595 * This routine stalls the driver until all outstanding commands are returned.
2596 * Caller must release the Hardware Lock prior to calling this routine.
2597 **/
2598static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
2599{
2600 uint32_t index = 0;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002601 unsigned long flags;
2602 struct scsi_cmnd *cmd;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002603
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302604 unsigned long wtime = jiffies + (WAIT_CMD_TOV * HZ);
2605
2606 DEBUG2(ql4_printk(KERN_INFO, ha, "Wait up to %d seconds for cmds to "
2607 "complete\n", WAIT_CMD_TOV));
2608
2609 while (!time_after_eq(jiffies, wtime)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07002610 spin_lock_irqsave(&ha->hardware_lock, flags);
2611 /* Find a command that hasn't completed. */
2612 for (index = 0; index < ha->host->can_queue; index++) {
2613 cmd = scsi_host_find_tag(ha->host, index);
Mike Christiea1e00632010-10-26 05:45:30 -07002614 /*
2615 * We cannot just check if the index is valid,
2616 * becase if we are run from the scsi eh, then
2617 * the scsi/block layer is going to prevent
2618 * the tag from being released.
2619 */
2620 if (cmd != NULL && CMD_SP(cmd))
David Somayajuluafaf5a22006-09-19 10:28:00 -07002621 break;
2622 }
2623 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2624
2625 /* If No Commands are pending, wait is complete */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302626 if (index == ha->host->can_queue)
2627 return QLA_SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002628
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302629 msleep(1000);
2630 }
2631 /* If we timed out on waiting for commands to come back
2632 * return ERROR. */
2633 return QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002634}
2635
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302636int qla4xxx_hw_reset(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002637{
David Somayajuluafaf5a22006-09-19 10:28:00 -07002638 uint32_t ctrl_status;
David C Somayajulu477ffb92007-01-22 12:26:11 -08002639 unsigned long flags = 0;
2640
2641 DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));
David Somayajuluafaf5a22006-09-19 10:28:00 -07002642
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302643 if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS)
2644 return QLA_ERROR;
2645
David Somayajuluafaf5a22006-09-19 10:28:00 -07002646 spin_lock_irqsave(&ha->hardware_lock, flags);
2647
2648 /*
2649 * If the SCSI Reset Interrupt bit is set, clear it.
2650 * Otherwise, the Soft Reset won't work.
2651 */
2652 ctrl_status = readw(&ha->reg->ctrl_status);
2653 if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0)
2654 writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);
2655
2656 /* Issue Soft Reset */
2657 writel(set_rmask(CSR_SOFT_RESET), &ha->reg->ctrl_status);
2658 readl(&ha->reg->ctrl_status);
2659
2660 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302661 return QLA_SUCCESS;
David C Somayajulu477ffb92007-01-22 12:26:11 -08002662}
2663
2664/**
2665 * qla4xxx_soft_reset - performs soft reset.
2666 * @ha: Pointer to host adapter structure.
2667 **/
2668int qla4xxx_soft_reset(struct scsi_qla_host *ha)
2669{
2670 uint32_t max_wait_time;
2671 unsigned long flags = 0;
Vikas Chaudharyf931c532010-10-06 22:48:07 -07002672 int status;
David C Somayajulu477ffb92007-01-22 12:26:11 -08002673 uint32_t ctrl_status;
2674
Vikas Chaudharyf931c532010-10-06 22:48:07 -07002675 status = qla4xxx_hw_reset(ha);
2676 if (status != QLA_SUCCESS)
2677 return status;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002678
Vikas Chaudharyf931c532010-10-06 22:48:07 -07002679 status = QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002680 /* Wait until the Network Reset Intr bit is cleared */
2681 max_wait_time = RESET_INTR_TOV;
2682 do {
2683 spin_lock_irqsave(&ha->hardware_lock, flags);
2684 ctrl_status = readw(&ha->reg->ctrl_status);
2685 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2686
2687 if ((ctrl_status & CSR_NET_RESET_INTR) == 0)
2688 break;
2689
2690 msleep(1000);
2691 } while ((--max_wait_time));
2692
2693 if ((ctrl_status & CSR_NET_RESET_INTR) != 0) {
2694 DEBUG2(printk(KERN_WARNING
2695 "scsi%ld: Network Reset Intr not cleared by "
2696 "Network function, clearing it now!\n",
2697 ha->host_no));
2698 spin_lock_irqsave(&ha->hardware_lock, flags);
2699 writel(set_rmask(CSR_NET_RESET_INTR), &ha->reg->ctrl_status);
2700 readl(&ha->reg->ctrl_status);
2701 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2702 }
2703
2704 /* Wait until the firmware tells us the Soft Reset is done */
2705 max_wait_time = SOFT_RESET_TOV;
2706 do {
2707 spin_lock_irqsave(&ha->hardware_lock, flags);
2708 ctrl_status = readw(&ha->reg->ctrl_status);
2709 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2710
2711 if ((ctrl_status & CSR_SOFT_RESET) == 0) {
2712 status = QLA_SUCCESS;
2713 break;
2714 }
2715
2716 msleep(1000);
2717 } while ((--max_wait_time));
2718
2719 /*
2720 * Also, make sure that the SCSI Reset Interrupt bit has been cleared
2721 * after the soft reset has taken place.
2722 */
2723 spin_lock_irqsave(&ha->hardware_lock, flags);
2724 ctrl_status = readw(&ha->reg->ctrl_status);
2725 if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0) {
2726 writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);
2727 readl(&ha->reg->ctrl_status);
2728 }
2729 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2730
2731 /* If soft reset fails then most probably the bios on other
2732 * function is also enabled.
2733 * Since the initialization is sequential the other fn
2734 * wont be able to acknowledge the soft reset.
2735 * Issue a force soft reset to workaround this scenario.
2736 */
2737 if (max_wait_time == 0) {
2738 /* Issue Force Soft Reset */
2739 spin_lock_irqsave(&ha->hardware_lock, flags);
2740 writel(set_rmask(CSR_FORCE_SOFT_RESET), &ha->reg->ctrl_status);
2741 readl(&ha->reg->ctrl_status);
2742 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2743 /* Wait until the firmware tells us the Soft Reset is done */
2744 max_wait_time = SOFT_RESET_TOV;
2745 do {
2746 spin_lock_irqsave(&ha->hardware_lock, flags);
2747 ctrl_status = readw(&ha->reg->ctrl_status);
2748 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2749
2750 if ((ctrl_status & CSR_FORCE_SOFT_RESET) == 0) {
2751 status = QLA_SUCCESS;
2752 break;
2753 }
2754
2755 msleep(1000);
2756 } while ((--max_wait_time));
2757 }
2758
2759 return status;
2760}
2761
2762/**
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302763 * qla4xxx_abort_active_cmds - returns all outstanding i/o requests to O.S.
David Somayajuluafaf5a22006-09-19 10:28:00 -07002764 * @ha: Pointer to host adapter structure.
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302765 * @res: returned scsi status
David Somayajuluafaf5a22006-09-19 10:28:00 -07002766 *
2767 * This routine is called just prior to a HARD RESET to return all
2768 * outstanding commands back to the Operating System.
2769 * Caller should make sure that the following locks are released
2770 * before this calling routine: Hardware lock, and io_request_lock.
2771 **/
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302772static void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002773{
2774 struct srb *srb;
2775 int i;
2776 unsigned long flags;
2777
2778 spin_lock_irqsave(&ha->hardware_lock, flags);
2779 for (i = 0; i < ha->host->can_queue; i++) {
2780 srb = qla4xxx_del_from_active_array(ha, i);
2781 if (srb != NULL) {
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302782 srb->cmd->result = res;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05302783 kref_put(&srb->srb_ref, qla4xxx_srb_compl);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002784 }
2785 }
2786 spin_unlock_irqrestore(&ha->hardware_lock, flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002787}
2788
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302789void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha)
2790{
2791 clear_bit(AF_ONLINE, &ha->flags);
2792
2793 /* Disable the board */
2794 ql4_printk(KERN_INFO, ha, "Disabling the board\n");
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302795
2796 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
2797 qla4xxx_mark_all_devices_missing(ha);
2798 clear_bit(AF_INIT_DONE, &ha->flags);
2799}
2800
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002801static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session)
2802{
2803 struct iscsi_session *sess;
2804 struct ddb_entry *ddb_entry;
2805
2806 sess = cls_session->dd_data;
2807 ddb_entry = sess->dd_data;
2808 ddb_entry->fw_ddb_device_state = DDB_DS_SESSION_FAILED;
Mike Christie13483732011-12-01 21:38:41 -06002809
2810 if (ddb_entry->ddb_type == FLASH_DDB)
2811 iscsi_block_session(ddb_entry->sess);
2812 else
2813 iscsi_session_failure(cls_session->dd_data,
2814 ISCSI_ERR_CONN_FAILED);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002815}
2816
David Somayajuluafaf5a22006-09-19 10:28:00 -07002817/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07002818 * qla4xxx_recover_adapter - recovers adapter after a fatal error
2819 * @ha: Pointer to host adapter structure.
David Somayajuluafaf5a22006-09-19 10:28:00 -07002820 **/
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302821static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07002822{
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302823 int status = QLA_ERROR;
2824 uint8_t reset_chip = 0;
Sarang Radke8e0f3a62011-12-01 22:42:09 -08002825 uint32_t dev_state;
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002826 unsigned long wait;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002827
2828 /* Stall incoming I/O until we are done */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302829 scsi_block_requests(ha->host);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002830 clear_bit(AF_ONLINE, &ha->flags);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002831 clear_bit(AF_LINK_UP, &ha->flags);
Mike Christie50a29ae2008-03-04 13:26:53 -06002832
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302833 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__));
David Somayajuluafaf5a22006-09-19 10:28:00 -07002834
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302835 set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002836
Manish Rangankarb3a271a2011-07-25 13:48:53 -05002837 iscsi_host_for_each_session(ha->host, qla4xxx_fail_session);
2838
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302839 if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
2840 reset_chip = 1;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002841
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302842 /* For the DPC_RESET_HA_INTR case (ISP-4xxx specific)
2843 * do not reset adapter, jump to initialize_adapter */
2844 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
2845 status = QLA_SUCCESS;
2846 goto recover_ha_init_adapter;
David Somayajuluafaf5a22006-09-19 10:28:00 -07002847 }
2848
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302849 /* For the ISP-82xx adapter, issue a stop_firmware if invoked
2850 * from eh_host_reset or ioctl module */
2851 if (is_qla8022(ha) && !reset_chip &&
2852 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) {
2853
2854 DEBUG2(ql4_printk(KERN_INFO, ha,
2855 "scsi%ld: %s - Performing stop_firmware...\n",
2856 ha->host_no, __func__));
2857 status = ha->isp_ops->reset_firmware(ha);
2858 if (status == QLA_SUCCESS) {
Nilesh Javali2bd1e2b2010-10-06 22:49:20 -07002859 if (!test_bit(AF_FW_RECOVERY, &ha->flags))
2860 qla4xxx_cmd_wait(ha);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302861 ha->isp_ops->disable_intrs(ha);
2862 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
2863 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
2864 } else {
2865 /* If the stop_firmware fails then
2866 * reset the entire chip */
2867 reset_chip = 1;
2868 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
2869 set_bit(DPC_RESET_HA, &ha->dpc_flags);
2870 }
2871 }
2872
2873 /* Issue full chip reset if recovering from a catastrophic error,
2874 * or if stop_firmware fails for ISP-82xx.
2875 * This is the default case for ISP-4xxx */
2876 if (!is_qla8022(ha) || reset_chip) {
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002877 if (!is_qla8022(ha))
2878 goto chip_reset;
2879
2880 /* Check if 82XX firmware is alive or not
2881 * We may have arrived here from NEED_RESET
2882 * detection only */
2883 if (test_bit(AF_FW_RECOVERY, &ha->flags))
2884 goto chip_reset;
2885
2886 wait = jiffies + (FW_ALIVE_WAIT_TOV * HZ);
2887 while (time_before(jiffies, wait)) {
2888 if (qla4_8xxx_check_fw_alive(ha)) {
2889 qla4xxx_mailbox_premature_completion(ha);
2890 break;
2891 }
2892
2893 set_current_state(TASK_UNINTERRUPTIBLE);
2894 schedule_timeout(HZ);
2895 }
2896
Nilesh Javali2bd1e2b2010-10-06 22:49:20 -07002897 if (!test_bit(AF_FW_RECOVERY, &ha->flags))
2898 qla4xxx_cmd_wait(ha);
Shyam Sunder9ee91a32011-12-01 22:42:13 -08002899chip_reset:
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302900 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
2901 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
2902 DEBUG2(ql4_printk(KERN_INFO, ha,
2903 "scsi%ld: %s - Performing chip reset..\n",
2904 ha->host_no, __func__));
2905 status = ha->isp_ops->reset_chip(ha);
2906 }
2907
2908 /* Flush any pending ddb changed AENs */
2909 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
2910
2911recover_ha_init_adapter:
2912 /* Upon successful firmware/chip reset, re-initialize the adapter */
2913 if (status == QLA_SUCCESS) {
2914 /* For ISP-4xxx, force function 1 to always initialize
2915 * before function 3 to prevent both funcions from
2916 * stepping on top of the other */
2917 if (!is_qla8022(ha) && (ha->mac_index == 3))
2918 ssleep(6);
2919
2920 /* NOTE: AF_ONLINE flag set upon successful completion of
2921 * qla4xxx_initialize_adapter */
Mike Christie13483732011-12-01 21:38:41 -06002922 status = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302923 }
2924
2925 /* Retry failed adapter initialization, if necessary
2926 * Do not retry initialize_adapter for RESET_HA_INTR (ISP-4xxx specific)
2927 * case to prevent ping-pong resets between functions */
2928 if (!test_bit(AF_ONLINE, &ha->flags) &&
2929 !test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07002930 /* Adapter initialization failed, see if we can retry
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302931 * resetting the ha.
2932 * Since we don't want to block the DPC for too long
2933 * with multiple resets in the same thread,
2934 * utilize DPC to retry */
Sarang Radke8e0f3a62011-12-01 22:42:09 -08002935 if (is_qla8022(ha)) {
2936 qla4_8xxx_idc_lock(ha);
2937 dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
2938 qla4_8xxx_idc_unlock(ha);
2939 if (dev_state == QLA82XX_DEV_FAILED) {
2940 ql4_printk(KERN_INFO, ha, "%s: don't retry "
2941 "recover adapter. H/W is in Failed "
2942 "state\n", __func__);
2943 qla4xxx_dead_adapter_cleanup(ha);
2944 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
2945 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
2946 clear_bit(DPC_RESET_HA_FW_CONTEXT,
2947 &ha->dpc_flags);
2948 status = QLA_ERROR;
2949
2950 goto exit_recover;
2951 }
2952 }
2953
David Somayajuluafaf5a22006-09-19 10:28:00 -07002954 if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) {
2955 ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES;
2956 DEBUG2(printk("scsi%ld: recover adapter - retrying "
2957 "(%d) more times\n", ha->host_no,
2958 ha->retry_reset_ha_cnt));
2959 set_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
2960 status = QLA_ERROR;
2961 } else {
2962 if (ha->retry_reset_ha_cnt > 0) {
2963 /* Schedule another Reset HA--DPC will retry */
2964 ha->retry_reset_ha_cnt--;
2965 DEBUG2(printk("scsi%ld: recover adapter - "
2966 "retry remaining %d\n",
2967 ha->host_no,
2968 ha->retry_reset_ha_cnt));
2969 status = QLA_ERROR;
2970 }
2971
2972 if (ha->retry_reset_ha_cnt == 0) {
2973 /* Recover adapter retries have been exhausted.
2974 * Adapter DEAD */
2975 DEBUG2(printk("scsi%ld: recover adapter "
2976 "failed - board disabled\n",
2977 ha->host_no));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302978 qla4xxx_dead_adapter_cleanup(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002979 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
2980 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302981 clear_bit(DPC_RESET_HA_FW_CONTEXT,
David Somayajuluafaf5a22006-09-19 10:28:00 -07002982 &ha->dpc_flags);
2983 status = QLA_ERROR;
2984 }
2985 }
2986 } else {
2987 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302988 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002989 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
2990 }
2991
Sarang Radke8e0f3a62011-12-01 22:42:09 -08002992exit_recover:
David Somayajuluafaf5a22006-09-19 10:28:00 -07002993 ha->adapter_error_count++;
2994
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302995 if (test_bit(AF_ONLINE, &ha->flags))
2996 ha->isp_ops->enable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07002997
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05302998 scsi_unblock_requests(ha->host);
2999
3000 clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
3001 DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no,
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003002 status == QLA_ERROR ? "FAILED" : "SUCCEEDED"));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303003
David Somayajuluafaf5a22006-09-19 10:28:00 -07003004 return status;
3005}
3006
Manish Rangankarb3a271a2011-07-25 13:48:53 -05003007static void qla4xxx_relogin_devices(struct iscsi_cls_session *cls_session)
Vikas Chaudhary2d7924e2011-03-21 03:34:33 -07003008{
Manish Rangankarb3a271a2011-07-25 13:48:53 -05003009 struct iscsi_session *sess;
3010 struct ddb_entry *ddb_entry;
3011 struct scsi_qla_host *ha;
Vikas Chaudhary2d7924e2011-03-21 03:34:33 -07003012
Manish Rangankarb3a271a2011-07-25 13:48:53 -05003013 sess = cls_session->dd_data;
3014 ddb_entry = sess->dd_data;
3015 ha = ddb_entry->ha;
3016 if (!iscsi_is_session_online(cls_session)) {
3017 if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
3018 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
3019 " unblock session\n", ha->host_no, __func__,
3020 ddb_entry->fw_ddb_index);
3021 iscsi_unblock_session(ddb_entry->sess);
3022 } else {
3023 /* Trigger relogin */
Mike Christie13483732011-12-01 21:38:41 -06003024 if (ddb_entry->ddb_type == FLASH_DDB) {
3025 if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
3026 qla4xxx_arm_relogin_timer(ddb_entry);
3027 } else
3028 iscsi_session_failure(cls_session->dd_data,
3029 ISCSI_ERR_CONN_FAILED);
Vikas Chaudhary2d7924e2011-03-21 03:34:33 -07003030 }
3031 }
3032}
3033
Mike Christie13483732011-12-01 21:38:41 -06003034int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session)
3035{
3036 struct iscsi_session *sess;
3037 struct ddb_entry *ddb_entry;
3038 struct scsi_qla_host *ha;
3039
3040 sess = cls_session->dd_data;
3041 ddb_entry = sess->dd_data;
3042 ha = ddb_entry->ha;
3043 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
3044 " unblock session\n", ha->host_no, __func__,
3045 ddb_entry->fw_ddb_index);
3046
3047 iscsi_unblock_session(ddb_entry->sess);
3048
3049 /* Start scan target */
3050 if (test_bit(AF_ONLINE, &ha->flags)) {
3051 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
3052 " start scan\n", ha->host_no, __func__,
3053 ddb_entry->fw_ddb_index);
3054 scsi_queue_work(ha->host, &ddb_entry->sess->scan_work);
3055 }
3056 return QLA_SUCCESS;
3057}
3058
3059int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session)
3060{
3061 struct iscsi_session *sess;
3062 struct ddb_entry *ddb_entry;
3063 struct scsi_qla_host *ha;
3064
3065 sess = cls_session->dd_data;
3066 ddb_entry = sess->dd_data;
3067 ha = ddb_entry->ha;
3068 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
3069 " unblock user space session\n", ha->host_no, __func__,
3070 ddb_entry->fw_ddb_index);
3071 iscsi_conn_start(ddb_entry->conn);
3072 iscsi_conn_login_event(ddb_entry->conn,
3073 ISCSI_CONN_STATE_LOGGED_IN);
3074
3075 return QLA_SUCCESS;
3076}
3077
Manish Rangankarb3a271a2011-07-25 13:48:53 -05003078static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)
3079{
3080 iscsi_host_for_each_session(ha->host, qla4xxx_relogin_devices);
3081}
3082
Mike Christie13483732011-12-01 21:38:41 -06003083static void qla4xxx_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
3084{
3085 uint16_t relogin_timer;
3086 struct iscsi_session *sess;
3087 struct ddb_entry *ddb_entry;
3088 struct scsi_qla_host *ha;
3089
3090 sess = cls_sess->dd_data;
3091 ddb_entry = sess->dd_data;
3092 ha = ddb_entry->ha;
3093
3094 relogin_timer = max(ddb_entry->default_relogin_timeout,
3095 (uint16_t)RELOGIN_TOV);
3096 atomic_set(&ddb_entry->relogin_timer, relogin_timer);
3097
3098 DEBUG2(ql4_printk(KERN_INFO, ha,
3099 "scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no,
3100 ddb_entry->fw_ddb_index, relogin_timer));
3101
3102 qla4xxx_login_flash_ddb(cls_sess);
3103}
3104
3105static void qla4xxx_dpc_relogin(struct iscsi_cls_session *cls_sess)
3106{
3107 struct iscsi_session *sess;
3108 struct ddb_entry *ddb_entry;
3109 struct scsi_qla_host *ha;
3110
3111 sess = cls_sess->dd_data;
3112 ddb_entry = sess->dd_data;
3113 ha = ddb_entry->ha;
3114
3115 if (!(ddb_entry->ddb_type == FLASH_DDB))
3116 return;
3117
3118 if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) &&
3119 !iscsi_is_session_online(cls_sess)) {
3120 DEBUG2(ql4_printk(KERN_INFO, ha,
3121 "relogin issued\n"));
3122 qla4xxx_relogin_flash_ddb(cls_sess);
3123 }
3124}
3125
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303126void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
3127{
Lalit Chandivade1b468072011-05-17 23:17:09 -07003128 if (ha->dpc_thread)
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303129 queue_work(ha->dpc_thread, &ha->dpc_work);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303130}
3131
Vikas Chaudharyff884432011-08-29 23:43:02 +05303132static struct qla4_work_evt *
3133qla4xxx_alloc_work(struct scsi_qla_host *ha, uint32_t data_size,
3134 enum qla4_work_type type)
3135{
3136 struct qla4_work_evt *e;
3137 uint32_t size = sizeof(struct qla4_work_evt) + data_size;
3138
3139 e = kzalloc(size, GFP_ATOMIC);
3140 if (!e)
3141 return NULL;
3142
3143 INIT_LIST_HEAD(&e->list);
3144 e->type = type;
3145 return e;
3146}
3147
3148static void qla4xxx_post_work(struct scsi_qla_host *ha,
3149 struct qla4_work_evt *e)
3150{
3151 unsigned long flags;
3152
3153 spin_lock_irqsave(&ha->work_lock, flags);
3154 list_add_tail(&e->list, &ha->work_list);
3155 spin_unlock_irqrestore(&ha->work_lock, flags);
3156 qla4xxx_wake_dpc(ha);
3157}
3158
3159int qla4xxx_post_aen_work(struct scsi_qla_host *ha,
3160 enum iscsi_host_event_code aen_code,
3161 uint32_t data_size, uint8_t *data)
3162{
3163 struct qla4_work_evt *e;
3164
3165 e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_AEN);
3166 if (!e)
3167 return QLA_ERROR;
3168
3169 e->u.aen.code = aen_code;
3170 e->u.aen.data_size = data_size;
3171 memcpy(e->u.aen.data, data, data_size);
3172
3173 qla4xxx_post_work(ha, e);
3174
3175 return QLA_SUCCESS;
3176}
3177
Vikas Chaudharyc0b9d3f2012-02-13 18:30:49 +05303178int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha,
3179 uint32_t status, uint32_t pid,
3180 uint32_t data_size, uint8_t *data)
3181{
3182 struct qla4_work_evt *e;
3183
3184 e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_PING_STATUS);
3185 if (!e)
3186 return QLA_ERROR;
3187
3188 e->u.ping.status = status;
3189 e->u.ping.pid = pid;
3190 e->u.ping.data_size = data_size;
3191 memcpy(e->u.ping.data, data, data_size);
3192
3193 qla4xxx_post_work(ha, e);
3194
3195 return QLA_SUCCESS;
3196}
3197
Vikas Chaudharyff884432011-08-29 23:43:02 +05303198void qla4xxx_do_work(struct scsi_qla_host *ha)
3199{
3200 struct qla4_work_evt *e, *tmp;
3201 unsigned long flags;
3202 LIST_HEAD(work);
3203
3204 spin_lock_irqsave(&ha->work_lock, flags);
3205 list_splice_init(&ha->work_list, &work);
3206 spin_unlock_irqrestore(&ha->work_lock, flags);
3207
3208 list_for_each_entry_safe(e, tmp, &work, list) {
3209 list_del_init(&e->list);
3210
3211 switch (e->type) {
3212 case QLA4_EVENT_AEN:
3213 iscsi_post_host_event(ha->host_no,
3214 &qla4xxx_iscsi_transport,
3215 e->u.aen.code,
3216 e->u.aen.data_size,
3217 e->u.aen.data);
3218 break;
Vikas Chaudharyc0b9d3f2012-02-13 18:30:49 +05303219 case QLA4_EVENT_PING_STATUS:
3220 iscsi_ping_comp_event(ha->host_no,
3221 &qla4xxx_iscsi_transport,
3222 e->u.ping.status,
3223 e->u.ping.pid,
3224 e->u.ping.data_size,
3225 e->u.ping.data);
3226 break;
Vikas Chaudharyff884432011-08-29 23:43:02 +05303227 default:
3228 ql4_printk(KERN_WARNING, ha, "event type: 0x%x not "
3229 "supported", e->type);
3230 }
3231 kfree(e);
3232 }
3233}
3234
David Somayajuluafaf5a22006-09-19 10:28:00 -07003235/**
3236 * qla4xxx_do_dpc - dpc routine
3237 * @data: in our case pointer to adapter structure
3238 *
3239 * This routine is a task that is schedule by the interrupt handler
3240 * to perform the background processing for interrupts. We put it
3241 * on a task queue that is consumed whenever the scheduler runs; that's
3242 * so you can do anything (i.e. put the process to sleep etc). In fact,
3243 * the mid-level tries to sleep when it reaches the driver threshold
3244 * "host->can_queue". This can cause a panic if we were in our interrupt code.
3245 **/
David Howellsc4028952006-11-22 14:57:56 +00003246static void qla4xxx_do_dpc(struct work_struct *work)
David Somayajuluafaf5a22006-09-19 10:28:00 -07003247{
David Howellsc4028952006-11-22 14:57:56 +00003248 struct scsi_qla_host *ha =
3249 container_of(work, struct scsi_qla_host, dpc_work);
David C Somayajulu477ffb92007-01-22 12:26:11 -08003250 int status = QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -07003251
David C Somayajuluf26b9042006-11-15 16:41:09 -08003252 DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303253 "flags = 0x%08lx, dpc_flags = 0x%08lx\n",
3254 ha->host_no, __func__, ha->flags, ha->dpc_flags))
David Somayajuluafaf5a22006-09-19 10:28:00 -07003255
3256 /* Initialization not yet finished. Don't do anything yet. */
3257 if (!test_bit(AF_INIT_DONE, &ha->flags))
Lalit Chandivade1b468072011-05-17 23:17:09 -07003258 return;
David Somayajuluafaf5a22006-09-19 10:28:00 -07003259
Lalit Chandivade2232be02010-07-30 14:38:47 +05303260 if (test_bit(AF_EEH_BUSY, &ha->flags)) {
3261 DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n",
3262 ha->host_no, __func__, ha->flags));
Lalit Chandivade1b468072011-05-17 23:17:09 -07003263 return;
Lalit Chandivade2232be02010-07-30 14:38:47 +05303264 }
3265
Vikas Chaudharyff884432011-08-29 23:43:02 +05303266 /* post events to application */
3267 qla4xxx_do_work(ha);
3268
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303269 if (is_qla8022(ha)) {
3270 if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
3271 qla4_8xxx_idc_lock(ha);
3272 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
3273 QLA82XX_DEV_FAILED);
3274 qla4_8xxx_idc_unlock(ha);
3275 ql4_printk(KERN_INFO, ha, "HW State: FAILED\n");
3276 qla4_8xxx_device_state_handler(ha);
3277 }
3278 if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {
3279 qla4_8xxx_need_qsnt_handler(ha);
3280 }
3281 }
3282
3283 if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) &&
3284 (test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
David Somayajuluafaf5a22006-09-19 10:28:00 -07003285 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303286 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) {
3287 if (ql4xdontresethba) {
3288 DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
3289 ha->host_no, __func__));
3290 clear_bit(DPC_RESET_HA, &ha->dpc_flags);
3291 clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
3292 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
3293 goto dpc_post_reset_ha;
3294 }
3295 if (test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||
3296 test_bit(DPC_RESET_HA, &ha->dpc_flags))
3297 qla4xxx_recover_adapter(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07003298
David C Somayajulu477ffb92007-01-22 12:26:11 -08003299 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07003300 uint8_t wait_time = RESET_INTR_TOV;
David Somayajuluafaf5a22006-09-19 10:28:00 -07003301
David Somayajuluafaf5a22006-09-19 10:28:00 -07003302 while ((readw(&ha->reg->ctrl_status) &
3303 (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
3304 if (--wait_time == 0)
3305 break;
David Somayajuluafaf5a22006-09-19 10:28:00 -07003306 msleep(1000);
David Somayajuluafaf5a22006-09-19 10:28:00 -07003307 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07003308 if (wait_time == 0)
3309 DEBUG2(printk("scsi%ld: %s: SR|FSR "
3310 "bit not cleared-- resetting\n",
3311 ha->host_no, __func__));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303312 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
David C Somayajulu477ffb92007-01-22 12:26:11 -08003313 if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {
3314 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303315 status = qla4xxx_recover_adapter(ha);
David C Somayajulu477ffb92007-01-22 12:26:11 -08003316 }
3317 clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
3318 if (status == QLA_SUCCESS)
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303319 ha->isp_ops->enable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07003320 }
3321 }
3322
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303323dpc_post_reset_ha:
David Somayajuluafaf5a22006-09-19 10:28:00 -07003324 /* ---- process AEN? --- */
3325 if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
3326 qla4xxx_process_aen(ha, PROCESS_ALL_AENS);
3327
3328 /* ---- Get DHCP IP Address? --- */
3329 if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
3330 qla4xxx_get_dhcp_ip_address(ha);
3331
Mike Christie13483732011-12-01 21:38:41 -06003332 /* ---- relogin device? --- */
3333 if (adapter_up(ha) &&
3334 test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
3335 iscsi_host_for_each_session(ha->host, qla4xxx_dpc_relogin);
3336 }
3337
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05303338 /* ---- link change? --- */
3339 if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
3340 if (!test_bit(AF_LINK_UP, &ha->flags)) {
3341 /* ---- link down? --- */
Vikas Chaudhary2d7924e2011-03-21 03:34:33 -07003342 qla4xxx_mark_all_devices_missing(ha);
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05303343 } else {
3344 /* ---- link up? --- *
3345 * F/W will auto login to all devices ONLY ONCE after
3346 * link up during driver initialization and runtime
3347 * fatal error recovery. Therefore, the driver must
3348 * manually relogin to devices when recovering from
3349 * connection failures, logouts, expired KATO, etc. */
Mike Christie13483732011-12-01 21:38:41 -06003350 if (test_and_clear_bit(AF_BUILD_DDB_LIST, &ha->flags)) {
3351 qla4xxx_build_ddb_list(ha, ha->is_reset);
3352 iscsi_host_for_each_session(ha->host,
3353 qla4xxx_login_flash_ddb);
3354 } else
3355 qla4xxx_relogin_all_devices(ha);
Vikas Chaudhary065aa1b2010-04-28 11:38:11 +05303356 }
3357 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07003358}
3359
3360/**
3361 * qla4xxx_free_adapter - release the adapter
3362 * @ha: pointer to adapter structure
3363 **/
3364static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
3365{
Sarang Radke8a288962011-12-06 02:34:10 -08003366 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
David Somayajuluafaf5a22006-09-19 10:28:00 -07003367
3368 if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) {
3369 /* Turn-off interrupts on the card. */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303370 ha->isp_ops->disable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07003371 }
3372
David Somayajuluafaf5a22006-09-19 10:28:00 -07003373 /* Remove timer thread, if present */
3374 if (ha->timer_active)
3375 qla4xxx_stop_timer(ha);
3376
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303377 /* Kill the kernel thread for this host */
3378 if (ha->dpc_thread)
3379 destroy_workqueue(ha->dpc_thread);
3380
Manish Rangankarb3a271a2011-07-25 13:48:53 -05003381 /* Kill the kernel thread for this host */
3382 if (ha->task_wq)
3383 destroy_workqueue(ha->task_wq);
3384
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303385 /* Put firmware in known state */
3386 ha->isp_ops->reset_firmware(ha);
3387
3388 if (is_qla8022(ha)) {
3389 qla4_8xxx_idc_lock(ha);
3390 qla4_8xxx_clear_drv_active(ha);
3391 qla4_8xxx_idc_unlock(ha);
3392 }
3393
David Somayajuluafaf5a22006-09-19 10:28:00 -07003394 /* Detach interrupts */
3395 if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303396 qla4xxx_free_irqs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07003397
David C Somayajulubee4fe82007-05-23 18:03:32 -07003398 /* free extra memory */
3399 qla4xxx_mem_free(ha);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303400}
David C Somayajulubee4fe82007-05-23 18:03:32 -07003401
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303402int qla4_8xxx_iospace_config(struct scsi_qla_host *ha)
3403{
3404 int status = 0;
3405 uint8_t revision_id;
3406 unsigned long mem_base, mem_len, db_base, db_len;
3407 struct pci_dev *pdev = ha->pdev;
David Somayajuluafaf5a22006-09-19 10:28:00 -07003408
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303409 status = pci_request_regions(pdev, DRIVER_NAME);
3410 if (status) {
3411 printk(KERN_WARNING
3412 "scsi(%ld) Failed to reserve PIO regions (%s) "
3413 "status=%d\n", ha->host_no, pci_name(pdev), status);
3414 goto iospace_error_exit;
3415 }
3416
3417 pci_read_config_byte(pdev, PCI_REVISION_ID, &revision_id);
3418 DEBUG2(printk(KERN_INFO "%s: revision-id=%d\n",
3419 __func__, revision_id));
3420 ha->revision_id = revision_id;
3421
3422 /* remap phys address */
3423 mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
3424 mem_len = pci_resource_len(pdev, 0);
3425 DEBUG2(printk(KERN_INFO "%s: ioremap from %lx a size of %lx\n",
3426 __func__, mem_base, mem_len));
3427
3428 /* mapping of pcibase pointer */
3429 ha->nx_pcibase = (unsigned long)ioremap(mem_base, mem_len);
3430 if (!ha->nx_pcibase) {
3431 printk(KERN_ERR
3432 "cannot remap MMIO (%s), aborting\n", pci_name(pdev));
3433 pci_release_regions(ha->pdev);
3434 goto iospace_error_exit;
3435 }
3436
3437 /* Mapping of IO base pointer, door bell read and write pointer */
3438
3439 /* mapping of IO base pointer */
3440 ha->qla4_8xxx_reg =
3441 (struct device_reg_82xx __iomem *)((uint8_t *)ha->nx_pcibase +
3442 0xbc000 + (ha->pdev->devfn << 11));
3443
3444 db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */
3445 db_len = pci_resource_len(pdev, 4);
3446
Shyam Sundar2657c802010-10-06 22:50:29 -07003447 ha->nx_db_wr_ptr = (ha->pdev->devfn == 4 ? QLA82XX_CAM_RAM_DB1 :
3448 QLA82XX_CAM_RAM_DB2);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303449
Shyam Sundar2657c802010-10-06 22:50:29 -07003450 return 0;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303451iospace_error_exit:
3452 return -ENOMEM;
David Somayajuluafaf5a22006-09-19 10:28:00 -07003453}
3454
3455/***
3456 * qla4xxx_iospace_config - maps registers
3457 * @ha: pointer to adapter structure
3458 *
3459 * This routines maps HBA's registers from the pci address space
3460 * into the kernel virtual address space for memory mapped i/o.
3461 **/
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303462int qla4xxx_iospace_config(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07003463{
3464 unsigned long pio, pio_len, pio_flags;
3465 unsigned long mmio, mmio_len, mmio_flags;
3466
3467 pio = pci_resource_start(ha->pdev, 0);
3468 pio_len = pci_resource_len(ha->pdev, 0);
3469 pio_flags = pci_resource_flags(ha->pdev, 0);
3470 if (pio_flags & IORESOURCE_IO) {
3471 if (pio_len < MIN_IOBASE_LEN) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05303472 ql4_printk(KERN_WARNING, ha,
David Somayajuluafaf5a22006-09-19 10:28:00 -07003473 "Invalid PCI I/O region size\n");
3474 pio = 0;
3475 }
3476 } else {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05303477 ql4_printk(KERN_WARNING, ha, "region #0 not a PIO resource\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07003478 pio = 0;
3479 }
3480
3481 /* Use MMIO operations for all accesses. */
3482 mmio = pci_resource_start(ha->pdev, 1);
3483 mmio_len = pci_resource_len(ha->pdev, 1);
3484 mmio_flags = pci_resource_flags(ha->pdev, 1);
3485
3486 if (!(mmio_flags & IORESOURCE_MEM)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05303487 ql4_printk(KERN_ERR, ha,
3488 "region #0 not an MMIO resource, aborting\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07003489
3490 goto iospace_error_exit;
3491 }
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05303492
David Somayajuluafaf5a22006-09-19 10:28:00 -07003493 if (mmio_len < MIN_IOBASE_LEN) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05303494 ql4_printk(KERN_ERR, ha,
3495 "Invalid PCI mem region size, aborting\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07003496 goto iospace_error_exit;
3497 }
3498
3499 if (pci_request_regions(ha->pdev, DRIVER_NAME)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05303500 ql4_printk(KERN_WARNING, ha,
3501 "Failed to reserve PIO/MMIO regions\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07003502
3503 goto iospace_error_exit;
3504 }
3505
3506 ha->pio_address = pio;
3507 ha->pio_length = pio_len;
3508 ha->reg = ioremap(mmio, MIN_IOBASE_LEN);
3509 if (!ha->reg) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05303510 ql4_printk(KERN_ERR, ha,
3511 "cannot remap MMIO, aborting\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07003512
3513 goto iospace_error_exit;
3514 }
3515
3516 return 0;
3517
3518iospace_error_exit:
3519 return -ENOMEM;
3520}
3521
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05303522static struct isp_operations qla4xxx_isp_ops = {
3523 .iospace_config = qla4xxx_iospace_config,
3524 .pci_config = qla4xxx_pci_config,
3525 .disable_intrs = qla4xxx_disable_intrs,
3526 .enable_intrs = qla4xxx_enable_intrs,
3527 .start_firmware = qla4xxx_start_firmware,
3528 .intr_handler = qla4xxx_intr_handler,
3529 .interrupt_service_routine = qla4xxx_interrupt_service_routine,
3530 .reset_chip = qla4xxx_soft_reset,
3531 .reset_firmware = qla4xxx_hw_reset,
3532 .queue_iocb = qla4xxx_queue_iocb,
3533 .complete_iocb = qla4xxx_complete_iocb,
3534 .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out,
3535 .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in,
3536 .get_sys_info = qla4xxx_get_sys_info,
3537};
3538
3539static struct isp_operations qla4_8xxx_isp_ops = {
3540 .iospace_config = qla4_8xxx_iospace_config,
3541 .pci_config = qla4_8xxx_pci_config,
3542 .disable_intrs = qla4_8xxx_disable_intrs,
3543 .enable_intrs = qla4_8xxx_enable_intrs,
3544 .start_firmware = qla4_8xxx_load_risc,
3545 .intr_handler = qla4_8xxx_intr_handler,
3546 .interrupt_service_routine = qla4_8xxx_interrupt_service_routine,
3547 .reset_chip = qla4_8xxx_isp_reset,
3548 .reset_firmware = qla4_8xxx_stop_firmware,
3549 .queue_iocb = qla4_8xxx_queue_iocb,
3550 .complete_iocb = qla4_8xxx_complete_iocb,
3551 .rd_shdw_req_q_out = qla4_8xxx_rd_shdw_req_q_out,
3552 .rd_shdw_rsp_q_in = qla4_8xxx_rd_shdw_rsp_q_in,
3553 .get_sys_info = qla4_8xxx_get_sys_info,
3554};
3555
3556uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
3557{
3558 return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out);
3559}
3560
3561uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
3562{
3563 return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->req_q_out));
3564}
3565
3566uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
3567{
3568 return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in);
3569}
3570
3571uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
3572{
3573 return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in));
3574}
3575
Manish Rangankar2a991c22011-07-25 13:48:55 -05003576static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf)
3577{
3578 struct scsi_qla_host *ha = data;
3579 char *str = buf;
3580 int rc;
3581
3582 switch (type) {
3583 case ISCSI_BOOT_ETH_FLAGS:
3584 rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
3585 break;
3586 case ISCSI_BOOT_ETH_INDEX:
3587 rc = sprintf(str, "0\n");
3588 break;
3589 case ISCSI_BOOT_ETH_MAC:
3590 rc = sysfs_format_mac(str, ha->my_mac,
3591 MAC_ADDR_LEN);
3592 break;
3593 default:
3594 rc = -ENOSYS;
3595 break;
3596 }
3597 return rc;
3598}
3599
Al Viro587a1f12011-07-23 23:11:19 -04003600static umode_t qla4xxx_eth_get_attr_visibility(void *data, int type)
Manish Rangankar2a991c22011-07-25 13:48:55 -05003601{
3602 int rc;
3603
3604 switch (type) {
3605 case ISCSI_BOOT_ETH_FLAGS:
3606 case ISCSI_BOOT_ETH_MAC:
3607 case ISCSI_BOOT_ETH_INDEX:
3608 rc = S_IRUGO;
3609 break;
3610 default:
3611 rc = 0;
3612 break;
3613 }
3614 return rc;
3615}
3616
3617static ssize_t qla4xxx_show_boot_ini_info(void *data, int type, char *buf)
3618{
3619 struct scsi_qla_host *ha = data;
3620 char *str = buf;
3621 int rc;
3622
3623 switch (type) {
3624 case ISCSI_BOOT_INI_INITIATOR_NAME:
3625 rc = sprintf(str, "%s\n", ha->name_string);
3626 break;
3627 default:
3628 rc = -ENOSYS;
3629 break;
3630 }
3631 return rc;
3632}
3633
Al Viro587a1f12011-07-23 23:11:19 -04003634static umode_t qla4xxx_ini_get_attr_visibility(void *data, int type)
Manish Rangankar2a991c22011-07-25 13:48:55 -05003635{
3636 int rc;
3637
3638 switch (type) {
3639 case ISCSI_BOOT_INI_INITIATOR_NAME:
3640 rc = S_IRUGO;
3641 break;
3642 default:
3643 rc = 0;
3644 break;
3645 }
3646 return rc;
3647}
3648
3649static ssize_t
3650qla4xxx_show_boot_tgt_info(struct ql4_boot_session_info *boot_sess, int type,
3651 char *buf)
3652{
3653 struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];
3654 char *str = buf;
3655 int rc;
3656
3657 switch (type) {
3658 case ISCSI_BOOT_TGT_NAME:
3659 rc = sprintf(buf, "%s\n", (char *)&boot_sess->target_name);
3660 break;
3661 case ISCSI_BOOT_TGT_IP_ADDR:
3662 if (boot_sess->conn_list[0].dest_ipaddr.ip_type == 0x1)
3663 rc = sprintf(buf, "%pI4\n",
3664 &boot_conn->dest_ipaddr.ip_address);
3665 else
3666 rc = sprintf(str, "%pI6\n",
3667 &boot_conn->dest_ipaddr.ip_address);
3668 break;
3669 case ISCSI_BOOT_TGT_PORT:
3670 rc = sprintf(str, "%d\n", boot_conn->dest_port);
3671 break;
3672 case ISCSI_BOOT_TGT_CHAP_NAME:
3673 rc = sprintf(str, "%.*s\n",
3674 boot_conn->chap.target_chap_name_length,
3675 (char *)&boot_conn->chap.target_chap_name);
3676 break;
3677 case ISCSI_BOOT_TGT_CHAP_SECRET:
3678 rc = sprintf(str, "%.*s\n",
3679 boot_conn->chap.target_secret_length,
3680 (char *)&boot_conn->chap.target_secret);
3681 break;
3682 case ISCSI_BOOT_TGT_REV_CHAP_NAME:
3683 rc = sprintf(str, "%.*s\n",
3684 boot_conn->chap.intr_chap_name_length,
3685 (char *)&boot_conn->chap.intr_chap_name);
3686 break;
3687 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
3688 rc = sprintf(str, "%.*s\n",
3689 boot_conn->chap.intr_secret_length,
3690 (char *)&boot_conn->chap.intr_secret);
3691 break;
3692 case ISCSI_BOOT_TGT_FLAGS:
3693 rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
3694 break;
3695 case ISCSI_BOOT_TGT_NIC_ASSOC:
3696 rc = sprintf(str, "0\n");
3697 break;
3698 default:
3699 rc = -ENOSYS;
3700 break;
3701 }
3702 return rc;
3703}
3704
3705static ssize_t qla4xxx_show_boot_tgt_pri_info(void *data, int type, char *buf)
3706{
3707 struct scsi_qla_host *ha = data;
3708 struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_pri_sess);
3709
3710 return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);
3711}
3712
3713static ssize_t qla4xxx_show_boot_tgt_sec_info(void *data, int type, char *buf)
3714{
3715 struct scsi_qla_host *ha = data;
3716 struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_sec_sess);
3717
3718 return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);
3719}
3720
Al Viro587a1f12011-07-23 23:11:19 -04003721static umode_t qla4xxx_tgt_get_attr_visibility(void *data, int type)
Manish Rangankar2a991c22011-07-25 13:48:55 -05003722{
3723 int rc;
3724
3725 switch (type) {
3726 case ISCSI_BOOT_TGT_NAME:
3727 case ISCSI_BOOT_TGT_IP_ADDR:
3728 case ISCSI_BOOT_TGT_PORT:
3729 case ISCSI_BOOT_TGT_CHAP_NAME:
3730 case ISCSI_BOOT_TGT_CHAP_SECRET:
3731 case ISCSI_BOOT_TGT_REV_CHAP_NAME:
3732 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
3733 case ISCSI_BOOT_TGT_NIC_ASSOC:
3734 case ISCSI_BOOT_TGT_FLAGS:
3735 rc = S_IRUGO;
3736 break;
3737 default:
3738 rc = 0;
3739 break;
3740 }
3741 return rc;
3742}
3743
3744static void qla4xxx_boot_release(void *data)
3745{
3746 struct scsi_qla_host *ha = data;
3747
3748 scsi_host_put(ha->host);
3749}
3750
3751static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
3752{
3753 dma_addr_t buf_dma;
3754 uint32_t addr, pri_addr, sec_addr;
3755 uint32_t offset;
3756 uint16_t func_num;
3757 uint8_t val;
3758 uint8_t *buf = NULL;
3759 size_t size = 13 * sizeof(uint8_t);
3760 int ret = QLA_SUCCESS;
3761
3762 func_num = PCI_FUNC(ha->pdev->devfn);
3763
Manish Rangankar0d5b36b2011-10-07 16:55:51 -07003764 ql4_printk(KERN_INFO, ha, "%s: Get FW boot info for 0x%x func %d\n",
3765 __func__, ha->pdev->device, func_num);
Manish Rangankar2a991c22011-07-25 13:48:55 -05003766
Manish Rangankar0d5b36b2011-10-07 16:55:51 -07003767 if (is_qla40XX(ha)) {
Manish Rangankar2a991c22011-07-25 13:48:55 -05003768 if (func_num == 1) {
3769 addr = NVRAM_PORT0_BOOT_MODE;
3770 pri_addr = NVRAM_PORT0_BOOT_PRI_TGT;
3771 sec_addr = NVRAM_PORT0_BOOT_SEC_TGT;
3772 } else if (func_num == 3) {
3773 addr = NVRAM_PORT1_BOOT_MODE;
3774 pri_addr = NVRAM_PORT1_BOOT_PRI_TGT;
3775 sec_addr = NVRAM_PORT1_BOOT_SEC_TGT;
3776 } else {
3777 ret = QLA_ERROR;
3778 goto exit_boot_info;
3779 }
3780
3781 /* Check Boot Mode */
3782 val = rd_nvram_byte(ha, addr);
3783 if (!(val & 0x07)) {
Manish Rangankare8fb00e2012-02-13 18:30:43 +05303784 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Adapter boot "
3785 "options : 0x%x\n", __func__, val));
Manish Rangankar2a991c22011-07-25 13:48:55 -05003786 ret = QLA_ERROR;
3787 goto exit_boot_info;
3788 }
3789
3790 /* get primary valid target index */
3791 val = rd_nvram_byte(ha, pri_addr);
3792 if (val & BIT_7)
3793 ddb_index[0] = (val & 0x7f);
Manish Rangankar2a991c22011-07-25 13:48:55 -05003794
3795 /* get secondary valid target index */
3796 val = rd_nvram_byte(ha, sec_addr);
3797 if (val & BIT_7)
3798 ddb_index[1] = (val & 0x7f);
Manish Rangankar2a991c22011-07-25 13:48:55 -05003799
3800 } else if (is_qla8022(ha)) {
3801 buf = dma_alloc_coherent(&ha->pdev->dev, size,
3802 &buf_dma, GFP_KERNEL);
3803 if (!buf) {
3804 DEBUG2(ql4_printk(KERN_ERR, ha,
3805 "%s: Unable to allocate dma buffer\n",
3806 __func__));
3807 ret = QLA_ERROR;
3808 goto exit_boot_info;
3809 }
3810
3811 if (ha->port_num == 0)
3812 offset = BOOT_PARAM_OFFSET_PORT0;
3813 else if (ha->port_num == 1)
3814 offset = BOOT_PARAM_OFFSET_PORT1;
3815 else {
3816 ret = QLA_ERROR;
3817 goto exit_boot_info_free;
3818 }
3819 addr = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_iscsi_param * 4) +
3820 offset;
3821 if (qla4xxx_get_flash(ha, buf_dma, addr,
3822 13 * sizeof(uint8_t)) != QLA_SUCCESS) {
3823 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
3824 "failed\n", ha->host_no, __func__));
3825 ret = QLA_ERROR;
3826 goto exit_boot_info_free;
3827 }
3828 /* Check Boot Mode */
3829 if (!(buf[1] & 0x07)) {
Manish Rangankare8fb00e2012-02-13 18:30:43 +05303830 DEBUG2(ql4_printk(KERN_INFO, ha, "Firmware boot options"
3831 " : 0x%x\n", buf[1]));
Manish Rangankar2a991c22011-07-25 13:48:55 -05003832 ret = QLA_ERROR;
3833 goto exit_boot_info_free;
3834 }
3835
3836 /* get primary valid target index */
3837 if (buf[2] & BIT_7)
3838 ddb_index[0] = buf[2] & 0x7f;
Manish Rangankar2a991c22011-07-25 13:48:55 -05003839
3840 /* get secondary valid target index */
3841 if (buf[11] & BIT_7)
3842 ddb_index[1] = buf[11] & 0x7f;
Manish Rangankar2a991c22011-07-25 13:48:55 -05003843 } else {
3844 ret = QLA_ERROR;
3845 goto exit_boot_info;
3846 }
3847
3848 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary target ID %d, Secondary"
3849 " target ID %d\n", __func__, ddb_index[0],
3850 ddb_index[1]));
3851
3852exit_boot_info_free:
3853 dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma);
3854exit_boot_info:
Lalit Chandivade20e835b2012-02-13 18:30:42 +05303855 ha->pri_ddb_idx = ddb_index[0];
3856 ha->sec_ddb_idx = ddb_index[1];
Manish Rangankar2a991c22011-07-25 13:48:55 -05003857 return ret;
3858}
3859
Lalit Chandivade28deb452011-10-07 16:55:44 -07003860/**
3861 * qla4xxx_get_bidi_chap - Get a BIDI CHAP user and password
3862 * @ha: pointer to adapter structure
3863 * @username: CHAP username to be returned
3864 * @password: CHAP password to be returned
3865 *
3866 * If a boot entry has BIDI CHAP enabled then we need to set the BIDI CHAP
3867 * user and password in the sysfs entry in /sys/firmware/iscsi_boot#/.
3868 * So from the CHAP cache find the first BIDI CHAP entry and set it
3869 * to the boot record in sysfs.
3870 **/
3871static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username,
3872 char *password)
3873{
3874 int i, ret = -EINVAL;
3875 int max_chap_entries = 0;
3876 struct ql4_chap_table *chap_table;
3877
3878 if (is_qla8022(ha))
3879 max_chap_entries = (ha->hw.flt_chap_size / 2) /
3880 sizeof(struct ql4_chap_table);
3881 else
3882 max_chap_entries = MAX_CHAP_ENTRIES_40XX;
3883
3884 if (!ha->chap_list) {
3885 ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
3886 return ret;
3887 }
3888
3889 mutex_lock(&ha->chap_sem);
3890 for (i = 0; i < max_chap_entries; i++) {
3891 chap_table = (struct ql4_chap_table *)ha->chap_list + i;
3892 if (chap_table->cookie !=
3893 __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
3894 continue;
3895 }
3896
3897 if (chap_table->flags & BIT_7) /* local */
3898 continue;
3899
3900 if (!(chap_table->flags & BIT_6)) /* Not BIDI */
3901 continue;
3902
3903 strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
3904 strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
3905 ret = 0;
3906 break;
3907 }
3908 mutex_unlock(&ha->chap_sem);
3909
3910 return ret;
3911}
3912
3913
Manish Rangankar2a991c22011-07-25 13:48:55 -05003914static int qla4xxx_get_boot_target(struct scsi_qla_host *ha,
3915 struct ql4_boot_session_info *boot_sess,
3916 uint16_t ddb_index)
3917{
3918 struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];
3919 struct dev_db_entry *fw_ddb_entry;
3920 dma_addr_t fw_ddb_entry_dma;
3921 uint16_t idx;
3922 uint16_t options;
3923 int ret = QLA_SUCCESS;
3924
3925 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
3926 &fw_ddb_entry_dma, GFP_KERNEL);
3927 if (!fw_ddb_entry) {
3928 DEBUG2(ql4_printk(KERN_ERR, ha,
3929 "%s: Unable to allocate dma buffer.\n",
3930 __func__));
3931 ret = QLA_ERROR;
3932 return ret;
3933 }
3934
3935 if (qla4xxx_bootdb_by_index(ha, fw_ddb_entry,
3936 fw_ddb_entry_dma, ddb_index)) {
Manish Rangankare8fb00e2012-02-13 18:30:43 +05303937 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: No Flash DDB found at "
3938 "index [%d]\n", __func__, ddb_index));
Manish Rangankar2a991c22011-07-25 13:48:55 -05003939 ret = QLA_ERROR;
3940 goto exit_boot_target;
3941 }
3942
3943 /* Update target name and IP from DDB */
3944 memcpy(boot_sess->target_name, fw_ddb_entry->iscsi_name,
3945 min(sizeof(boot_sess->target_name),
3946 sizeof(fw_ddb_entry->iscsi_name)));
3947
3948 options = le16_to_cpu(fw_ddb_entry->options);
3949 if (options & DDB_OPT_IPV6_DEVICE) {
3950 memcpy(&boot_conn->dest_ipaddr.ip_address,
3951 &fw_ddb_entry->ip_addr[0], IPv6_ADDR_LEN);
3952 } else {
3953 boot_conn->dest_ipaddr.ip_type = 0x1;
3954 memcpy(&boot_conn->dest_ipaddr.ip_address,
3955 &fw_ddb_entry->ip_addr[0], IP_ADDR_LEN);
3956 }
3957
3958 boot_conn->dest_port = le16_to_cpu(fw_ddb_entry->port);
3959
3960 /* update chap information */
3961 idx = __le16_to_cpu(fw_ddb_entry->chap_tbl_idx);
3962
3963 if (BIT_7 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {
3964
3965 DEBUG2(ql4_printk(KERN_INFO, ha, "Setting chap\n"));
3966
3967 ret = qla4xxx_get_chap(ha, (char *)&boot_conn->chap.
3968 target_chap_name,
3969 (char *)&boot_conn->chap.target_secret,
3970 idx);
3971 if (ret) {
3972 ql4_printk(KERN_ERR, ha, "Failed to set chap\n");
3973 ret = QLA_ERROR;
3974 goto exit_boot_target;
3975 }
3976
3977 boot_conn->chap.target_chap_name_length = QL4_CHAP_MAX_NAME_LEN;
3978 boot_conn->chap.target_secret_length = QL4_CHAP_MAX_SECRET_LEN;
3979 }
3980
3981 if (BIT_4 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {
3982
3983 DEBUG2(ql4_printk(KERN_INFO, ha, "Setting BIDI chap\n"));
3984
Lalit Chandivade28deb452011-10-07 16:55:44 -07003985 ret = qla4xxx_get_bidi_chap(ha,
3986 (char *)&boot_conn->chap.intr_chap_name,
3987 (char *)&boot_conn->chap.intr_secret);
3988
Manish Rangankar2a991c22011-07-25 13:48:55 -05003989 if (ret) {
3990 ql4_printk(KERN_ERR, ha, "Failed to set BIDI chap\n");
3991 ret = QLA_ERROR;
3992 goto exit_boot_target;
3993 }
3994
3995 boot_conn->chap.intr_chap_name_length = QL4_CHAP_MAX_NAME_LEN;
3996 boot_conn->chap.intr_secret_length = QL4_CHAP_MAX_SECRET_LEN;
3997 }
3998
3999exit_boot_target:
4000 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
4001 fw_ddb_entry, fw_ddb_entry_dma);
4002 return ret;
4003}
4004
4005static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
4006{
4007 uint16_t ddb_index[2];
Lalit Chandivade8de5b952011-10-07 16:55:43 -07004008 int ret = QLA_ERROR;
4009 int rval;
Manish Rangankar2a991c22011-07-25 13:48:55 -05004010
4011 memset(ddb_index, 0, sizeof(ddb_index));
Lalit Chandivade8de5b952011-10-07 16:55:43 -07004012 ddb_index[0] = 0xffff;
4013 ddb_index[1] = 0xffff;
Manish Rangankar2a991c22011-07-25 13:48:55 -05004014 ret = get_fw_boot_info(ha, ddb_index);
4015 if (ret != QLA_SUCCESS) {
Manish Rangankare8fb00e2012-02-13 18:30:43 +05304016 DEBUG2(ql4_printk(KERN_INFO, ha,
4017 "%s: No boot target configured.\n", __func__));
Manish Rangankar2a991c22011-07-25 13:48:55 -05004018 return ret;
4019 }
4020
Mike Christie13483732011-12-01 21:38:41 -06004021 if (ql4xdisablesysfsboot)
4022 return QLA_SUCCESS;
4023
Lalit Chandivade8de5b952011-10-07 16:55:43 -07004024 if (ddb_index[0] == 0xffff)
4025 goto sec_target;
4026
4027 rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),
Manish Rangankar2a991c22011-07-25 13:48:55 -05004028 ddb_index[0]);
Lalit Chandivade8de5b952011-10-07 16:55:43 -07004029 if (rval != QLA_SUCCESS) {
Manish Rangankare8fb00e2012-02-13 18:30:43 +05304030 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary boot target not "
4031 "configured\n", __func__));
Lalit Chandivade8de5b952011-10-07 16:55:43 -07004032 } else
4033 ret = QLA_SUCCESS;
Manish Rangankar2a991c22011-07-25 13:48:55 -05004034
Lalit Chandivade8de5b952011-10-07 16:55:43 -07004035sec_target:
4036 if (ddb_index[1] == 0xffff)
4037 goto exit_get_boot_info;
4038
4039 rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),
Manish Rangankar2a991c22011-07-25 13:48:55 -05004040 ddb_index[1]);
Lalit Chandivade8de5b952011-10-07 16:55:43 -07004041 if (rval != QLA_SUCCESS) {
Manish Rangankare8fb00e2012-02-13 18:30:43 +05304042 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Secondary boot target not"
4043 " configured\n", __func__));
Lalit Chandivade8de5b952011-10-07 16:55:43 -07004044 } else
4045 ret = QLA_SUCCESS;
4046
4047exit_get_boot_info:
Manish Rangankar2a991c22011-07-25 13:48:55 -05004048 return ret;
4049}
4050
4051static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha)
4052{
4053 struct iscsi_boot_kobj *boot_kobj;
4054
4055 if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS)
Mike Christie13483732011-12-01 21:38:41 -06004056 return QLA_ERROR;
4057
4058 if (ql4xdisablesysfsboot) {
4059 ql4_printk(KERN_INFO, ha,
4060 "%s: syfsboot disabled - driver will trigger login"
4061 "and publish session for discovery .\n", __func__);
4062 return QLA_SUCCESS;
4063 }
4064
Manish Rangankar2a991c22011-07-25 13:48:55 -05004065
4066 ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no);
4067 if (!ha->boot_kset)
4068 goto kset_free;
4069
4070 if (!scsi_host_get(ha->host))
4071 goto kset_free;
4072 boot_kobj = iscsi_boot_create_target(ha->boot_kset, 0, ha,
4073 qla4xxx_show_boot_tgt_pri_info,
4074 qla4xxx_tgt_get_attr_visibility,
4075 qla4xxx_boot_release);
4076 if (!boot_kobj)
4077 goto put_host;
4078
4079 if (!scsi_host_get(ha->host))
4080 goto kset_free;
4081 boot_kobj = iscsi_boot_create_target(ha->boot_kset, 1, ha,
4082 qla4xxx_show_boot_tgt_sec_info,
4083 qla4xxx_tgt_get_attr_visibility,
4084 qla4xxx_boot_release);
4085 if (!boot_kobj)
4086 goto put_host;
4087
4088 if (!scsi_host_get(ha->host))
4089 goto kset_free;
4090 boot_kobj = iscsi_boot_create_initiator(ha->boot_kset, 0, ha,
4091 qla4xxx_show_boot_ini_info,
4092 qla4xxx_ini_get_attr_visibility,
4093 qla4xxx_boot_release);
4094 if (!boot_kobj)
4095 goto put_host;
4096
4097 if (!scsi_host_get(ha->host))
4098 goto kset_free;
4099 boot_kobj = iscsi_boot_create_ethernet(ha->boot_kset, 0, ha,
4100 qla4xxx_show_boot_eth_info,
4101 qla4xxx_eth_get_attr_visibility,
4102 qla4xxx_boot_release);
4103 if (!boot_kobj)
4104 goto put_host;
4105
Mike Christie13483732011-12-01 21:38:41 -06004106 return QLA_SUCCESS;
Manish Rangankar2a991c22011-07-25 13:48:55 -05004107
4108put_host:
4109 scsi_host_put(ha->host);
4110kset_free:
4111 iscsi_boot_destroy_kset(ha->boot_kset);
4112 return -ENOMEM;
4113}
4114
Lalit Chandivade45494152011-10-07 16:55:42 -07004115
4116/**
4117 * qla4xxx_create chap_list - Create CHAP list from FLASH
4118 * @ha: pointer to adapter structure
4119 *
4120 * Read flash and make a list of CHAP entries, during login when a CHAP entry
4121 * is received, it will be checked in this list. If entry exist then the CHAP
4122 * entry index is set in the DDB. If CHAP entry does not exist in this list
4123 * then a new entry is added in FLASH in CHAP table and the index obtained is
4124 * used in the DDB.
4125 **/
4126static void qla4xxx_create_chap_list(struct scsi_qla_host *ha)
4127{
4128 int rval = 0;
4129 uint8_t *chap_flash_data = NULL;
4130 uint32_t offset;
4131 dma_addr_t chap_dma;
4132 uint32_t chap_size = 0;
4133
4134 if (is_qla40XX(ha))
4135 chap_size = MAX_CHAP_ENTRIES_40XX *
4136 sizeof(struct ql4_chap_table);
4137 else /* Single region contains CHAP info for both
4138 * ports which is divided into half for each port.
4139 */
4140 chap_size = ha->hw.flt_chap_size / 2;
4141
4142 chap_flash_data = dma_alloc_coherent(&ha->pdev->dev, chap_size,
4143 &chap_dma, GFP_KERNEL);
4144 if (!chap_flash_data) {
4145 ql4_printk(KERN_ERR, ha, "No memory for chap_flash_data\n");
4146 return;
4147 }
4148 if (is_qla40XX(ha))
4149 offset = FLASH_CHAP_OFFSET;
4150 else {
4151 offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
4152 if (ha->port_num == 1)
4153 offset += chap_size;
4154 }
4155
4156 rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
4157 if (rval != QLA_SUCCESS)
4158 goto exit_chap_list;
4159
4160 if (ha->chap_list == NULL)
4161 ha->chap_list = vmalloc(chap_size);
4162 if (ha->chap_list == NULL) {
4163 ql4_printk(KERN_ERR, ha, "No memory for ha->chap_list\n");
4164 goto exit_chap_list;
4165 }
4166
4167 memcpy(ha->chap_list, chap_flash_data, chap_size);
4168
4169exit_chap_list:
4170 dma_free_coherent(&ha->pdev->dev, chap_size,
4171 chap_flash_data, chap_dma);
Lalit Chandivade45494152011-10-07 16:55:42 -07004172}
4173
Mike Christie13483732011-12-01 21:38:41 -06004174static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry,
4175 struct ql4_tuple_ddb *tddb)
4176{
4177 struct scsi_qla_host *ha;
4178 struct iscsi_cls_session *cls_sess;
4179 struct iscsi_cls_conn *cls_conn;
4180 struct iscsi_session *sess;
4181 struct iscsi_conn *conn;
4182
4183 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
4184 ha = ddb_entry->ha;
4185 cls_sess = ddb_entry->sess;
4186 sess = cls_sess->dd_data;
4187 cls_conn = ddb_entry->conn;
4188 conn = cls_conn->dd_data;
4189
4190 tddb->tpgt = sess->tpgt;
4191 tddb->port = conn->persistent_port;
4192 strncpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE);
4193 strncpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN);
4194}
4195
4196static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
4197 struct ql4_tuple_ddb *tddb)
4198{
4199 uint16_t options = 0;
4200
4201 tddb->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
4202 memcpy(&tddb->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
4203 min(sizeof(tddb->iscsi_name), sizeof(fw_ddb_entry->iscsi_name)));
4204
4205 options = le16_to_cpu(fw_ddb_entry->options);
4206 if (options & DDB_OPT_IPV6_DEVICE)
4207 sprintf(tddb->ip_addr, "%pI6", fw_ddb_entry->ip_addr);
4208 else
4209 sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr);
4210
4211 tddb->port = le16_to_cpu(fw_ddb_entry->port);
4212}
4213
4214static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,
4215 struct ql4_tuple_ddb *old_tddb,
4216 struct ql4_tuple_ddb *new_tddb)
4217{
4218 if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name))
4219 return QLA_ERROR;
4220
4221 if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr))
4222 return QLA_ERROR;
4223
4224 if (old_tddb->port != new_tddb->port)
4225 return QLA_ERROR;
4226
4227 DEBUG2(ql4_printk(KERN_INFO, ha,
4228 "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]",
4229 old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr,
4230 old_tddb->iscsi_name, new_tddb->port, new_tddb->tpgt,
4231 new_tddb->ip_addr, new_tddb->iscsi_name));
4232
4233 return QLA_SUCCESS;
4234}
4235
4236static int qla4xxx_is_session_exists(struct scsi_qla_host *ha,
4237 struct dev_db_entry *fw_ddb_entry)
4238{
4239 struct ddb_entry *ddb_entry;
4240 struct ql4_tuple_ddb *fw_tddb = NULL;
4241 struct ql4_tuple_ddb *tmp_tddb = NULL;
4242 int idx;
4243 int ret = QLA_ERROR;
4244
4245 fw_tddb = vzalloc(sizeof(*fw_tddb));
4246 if (!fw_tddb) {
4247 DEBUG2(ql4_printk(KERN_WARNING, ha,
4248 "Memory Allocation failed.\n"));
4249 ret = QLA_SUCCESS;
4250 goto exit_check;
4251 }
4252
4253 tmp_tddb = vzalloc(sizeof(*tmp_tddb));
4254 if (!tmp_tddb) {
4255 DEBUG2(ql4_printk(KERN_WARNING, ha,
4256 "Memory Allocation failed.\n"));
4257 ret = QLA_SUCCESS;
4258 goto exit_check;
4259 }
4260
4261 qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb);
4262
4263 for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {
4264 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
4265 if (ddb_entry == NULL)
4266 continue;
4267
4268 qla4xxx_get_param_ddb(ddb_entry, tmp_tddb);
4269 if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) {
4270 ret = QLA_SUCCESS; /* found */
4271 goto exit_check;
4272 }
4273 }
4274
4275exit_check:
4276 if (fw_tddb)
4277 vfree(fw_tddb);
4278 if (tmp_tddb)
4279 vfree(tmp_tddb);
4280 return ret;
4281}
4282
4283static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
4284 struct list_head *list_nt,
4285 struct dev_db_entry *fw_ddb_entry)
4286{
4287 struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;
4288 struct ql4_tuple_ddb *fw_tddb = NULL;
4289 struct ql4_tuple_ddb *tmp_tddb = NULL;
4290 int ret = QLA_ERROR;
4291
4292 fw_tddb = vzalloc(sizeof(*fw_tddb));
4293 if (!fw_tddb) {
4294 DEBUG2(ql4_printk(KERN_WARNING, ha,
4295 "Memory Allocation failed.\n"));
4296 ret = QLA_SUCCESS;
4297 goto exit_check;
4298 }
4299
4300 tmp_tddb = vzalloc(sizeof(*tmp_tddb));
4301 if (!tmp_tddb) {
4302 DEBUG2(ql4_printk(KERN_WARNING, ha,
4303 "Memory Allocation failed.\n"));
4304 ret = QLA_SUCCESS;
4305 goto exit_check;
4306 }
4307
4308 qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb);
4309
4310 list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
4311 qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb);
4312 if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) {
4313 ret = QLA_SUCCESS; /* found */
4314 goto exit_check;
4315 }
4316 }
4317
4318exit_check:
4319 if (fw_tddb)
4320 vfree(fw_tddb);
4321 if (tmp_tddb)
4322 vfree(tmp_tddb);
4323 return ret;
4324}
4325
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004326static void qla4xxx_free_ddb_list(struct list_head *list_ddb)
Mike Christie13483732011-12-01 21:38:41 -06004327{
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004328 struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;
Mike Christie13483732011-12-01 21:38:41 -06004329
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004330 list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
4331 list_del_init(&ddb_idx->list);
4332 vfree(ddb_idx);
Mike Christie13483732011-12-01 21:38:41 -06004333 }
Mike Christie13483732011-12-01 21:38:41 -06004334}
4335
4336static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
4337 struct dev_db_entry *fw_ddb_entry)
4338{
4339 struct iscsi_endpoint *ep;
4340 struct sockaddr_in *addr;
4341 struct sockaddr_in6 *addr6;
4342 struct sockaddr *dst_addr;
4343 char *ip;
4344
4345 /* TODO: need to destroy on unload iscsi_endpoint*/
4346 dst_addr = vmalloc(sizeof(*dst_addr));
4347 if (!dst_addr)
4348 return NULL;
4349
4350 if (fw_ddb_entry->options & DDB_OPT_IPV6_DEVICE) {
4351 dst_addr->sa_family = AF_INET6;
4352 addr6 = (struct sockaddr_in6 *)dst_addr;
4353 ip = (char *)&addr6->sin6_addr;
4354 memcpy(ip, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN);
4355 addr6->sin6_port = htons(le16_to_cpu(fw_ddb_entry->port));
4356
4357 } else {
4358 dst_addr->sa_family = AF_INET;
4359 addr = (struct sockaddr_in *)dst_addr;
4360 ip = (char *)&addr->sin_addr;
4361 memcpy(ip, fw_ddb_entry->ip_addr, IP_ADDR_LEN);
4362 addr->sin_port = htons(le16_to_cpu(fw_ddb_entry->port));
4363 }
4364
4365 ep = qla4xxx_ep_connect(ha->host, dst_addr, 0);
4366 vfree(dst_addr);
4367 return ep;
4368}
4369
4370static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)
4371{
4372 if (ql4xdisablesysfsboot)
4373 return QLA_SUCCESS;
4374 if (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx)
4375 return QLA_ERROR;
4376 return QLA_SUCCESS;
4377}
4378
4379static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
4380 struct ddb_entry *ddb_entry)
4381{
Nilesh Javalic28eaac2011-12-18 21:40:44 -08004382 uint16_t def_timeout;
4383
Mike Christie13483732011-12-01 21:38:41 -06004384 ddb_entry->ddb_type = FLASH_DDB;
4385 ddb_entry->fw_ddb_index = INVALID_ENTRY;
4386 ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
4387 ddb_entry->ha = ha;
4388 ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb;
4389 ddb_entry->ddb_change = qla4xxx_flash_ddb_change;
4390
4391 atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
4392 atomic_set(&ddb_entry->relogin_timer, 0);
4393 atomic_set(&ddb_entry->relogin_retry_count, 0);
Nilesh Javalic28eaac2011-12-18 21:40:44 -08004394 def_timeout = le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
Mike Christie13483732011-12-01 21:38:41 -06004395 ddb_entry->default_relogin_timeout =
Nilesh Javalic28eaac2011-12-18 21:40:44 -08004396 (def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ?
4397 def_timeout : LOGIN_TOV;
Mike Christie13483732011-12-01 21:38:41 -06004398 ddb_entry->default_time2wait =
4399 le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);
4400}
4401
4402static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
4403{
4404 uint32_t idx = 0;
4405 uint32_t ip_idx[IP_ADDR_COUNT] = {0, 1, 2, 3}; /* 4 IP interfaces */
4406 uint32_t sts[MBOX_REG_COUNT];
4407 uint32_t ip_state;
4408 unsigned long wtime;
4409 int ret;
4410
4411 wtime = jiffies + (HZ * IP_CONFIG_TOV);
4412 do {
4413 for (idx = 0; idx < IP_ADDR_COUNT; idx++) {
4414 if (ip_idx[idx] == -1)
4415 continue;
4416
4417 ret = qla4xxx_get_ip_state(ha, 0, ip_idx[idx], sts);
4418
4419 if (ret == QLA_ERROR) {
4420 ip_idx[idx] = -1;
4421 continue;
4422 }
4423
4424 ip_state = (sts[1] & IP_STATE_MASK) >> IP_STATE_SHIFT;
4425
4426 DEBUG2(ql4_printk(KERN_INFO, ha,
4427 "Waiting for IP state for idx = %d, state = 0x%x\n",
4428 ip_idx[idx], ip_state));
4429 if (ip_state == IP_ADDRSTATE_UNCONFIGURED ||
4430 ip_state == IP_ADDRSTATE_INVALID ||
4431 ip_state == IP_ADDRSTATE_PREFERRED ||
4432 ip_state == IP_ADDRSTATE_DEPRICATED ||
4433 ip_state == IP_ADDRSTATE_DISABLING)
4434 ip_idx[idx] = -1;
Mike Christie13483732011-12-01 21:38:41 -06004435 }
4436
4437 /* Break if all IP states checked */
4438 if ((ip_idx[0] == -1) &&
4439 (ip_idx[1] == -1) &&
4440 (ip_idx[2] == -1) &&
4441 (ip_idx[3] == -1))
4442 break;
4443 schedule_timeout_uninterruptible(HZ);
4444 } while (time_after(wtime, jiffies));
4445}
4446
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004447static void qla4xxx_build_st_list(struct scsi_qla_host *ha,
4448 struct list_head *list_st)
Mike Christie13483732011-12-01 21:38:41 -06004449{
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004450 struct qla_ddb_index *st_ddb_idx;
Mike Christie13483732011-12-01 21:38:41 -06004451 int max_ddbs;
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004452 int fw_idx_size;
4453 struct dev_db_entry *fw_ddb_entry;
4454 dma_addr_t fw_ddb_dma;
Mike Christie13483732011-12-01 21:38:41 -06004455 int ret;
4456 uint32_t idx = 0, next_idx = 0;
4457 uint32_t state = 0, conn_err = 0;
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004458 uint16_t conn_id = 0;
Mike Christie13483732011-12-01 21:38:41 -06004459
4460 fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
4461 &fw_ddb_dma);
4462 if (fw_ddb_entry == NULL) {
4463 DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004464 goto exit_st_list;
Mike Christie13483732011-12-01 21:38:41 -06004465 }
4466
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004467 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
4468 MAX_DEV_DB_ENTRIES;
Mike Christie13483732011-12-01 21:38:41 -06004469 fw_idx_size = sizeof(struct qla_ddb_index);
4470
4471 for (idx = 0; idx < max_ddbs; idx = next_idx) {
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004472 ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
4473 NULL, &next_idx, &state,
4474 &conn_err, NULL, &conn_id);
Mike Christie13483732011-12-01 21:38:41 -06004475 if (ret == QLA_ERROR)
4476 break;
4477
Lalit Chandivade981c9822012-02-13 18:30:41 +05304478 /* Ignore DDB if invalid state (unassigned) */
4479 if (state == DDB_DS_UNASSIGNED)
4480 goto continue_next_st;
4481
Mike Christie13483732011-12-01 21:38:41 -06004482 /* Check if ST, add to the list_st */
4483 if (strlen((char *) fw_ddb_entry->iscsi_name) != 0)
4484 goto continue_next_st;
4485
4486 st_ddb_idx = vzalloc(fw_idx_size);
4487 if (!st_ddb_idx)
4488 break;
4489
4490 st_ddb_idx->fw_ddb_idx = idx;
4491
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004492 list_add_tail(&st_ddb_idx->list, list_st);
Mike Christie13483732011-12-01 21:38:41 -06004493continue_next_st:
4494 if (next_idx == 0)
4495 break;
4496 }
4497
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004498exit_st_list:
4499 if (fw_ddb_entry)
4500 dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
4501}
4502
4503/**
4504 * qla4xxx_remove_failed_ddb - Remove inactive or failed ddb from list
4505 * @ha: pointer to adapter structure
4506 * @list_ddb: List from which failed ddb to be removed
4507 *
4508 * Iterate over the list of DDBs and find and remove DDBs that are either in
4509 * no connection active state or failed state
4510 **/
4511static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha,
4512 struct list_head *list_ddb)
4513{
4514 struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;
4515 uint32_t next_idx = 0;
4516 uint32_t state = 0, conn_err = 0;
4517 int ret;
4518
4519 list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
4520 ret = qla4xxx_get_fwddb_entry(ha, ddb_idx->fw_ddb_idx,
4521 NULL, 0, NULL, &next_idx, &state,
4522 &conn_err, NULL, NULL);
4523 if (ret == QLA_ERROR)
4524 continue;
4525
4526 if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
4527 state == DDB_DS_SESSION_FAILED) {
4528 list_del_init(&ddb_idx->list);
4529 vfree(ddb_idx);
4530 }
4531 }
4532}
4533
4534static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
4535 struct dev_db_entry *fw_ddb_entry,
4536 int is_reset)
4537{
4538 struct iscsi_cls_session *cls_sess;
4539 struct iscsi_session *sess;
4540 struct iscsi_cls_conn *cls_conn;
4541 struct iscsi_endpoint *ep;
4542 uint16_t cmds_max = 32;
4543 uint16_t conn_id = 0;
4544 uint32_t initial_cmdsn = 0;
4545 int ret = QLA_SUCCESS;
4546
4547 struct ddb_entry *ddb_entry = NULL;
4548
4549 /* Create session object, with INVALID_ENTRY,
4550 * the targer_id would get set when we issue the login
4551 */
4552 cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host,
4553 cmds_max, sizeof(struct ddb_entry),
4554 sizeof(struct ql4_task_data),
4555 initial_cmdsn, INVALID_ENTRY);
4556 if (!cls_sess) {
4557 ret = QLA_ERROR;
4558 goto exit_setup;
4559 }
4560
4561 /*
4562 * so calling module_put function to decrement the
4563 * reference count.
4564 **/
4565 module_put(qla4xxx_iscsi_transport.owner);
4566 sess = cls_sess->dd_data;
4567 ddb_entry = sess->dd_data;
4568 ddb_entry->sess = cls_sess;
4569
4570 cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
4571 memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
4572 sizeof(struct dev_db_entry));
4573
4574 qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
4575
4576 cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id);
4577
4578 if (!cls_conn) {
4579 ret = QLA_ERROR;
4580 goto exit_setup;
4581 }
4582
4583 ddb_entry->conn = cls_conn;
4584
4585 /* Setup ep, for displaying attributes in sysfs */
4586 ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
4587 if (ep) {
4588 ep->conn = cls_conn;
4589 cls_conn->ep = ep;
4590 } else {
4591 DEBUG2(ql4_printk(KERN_ERR, ha, "Unable to get ep\n"));
4592 ret = QLA_ERROR;
4593 goto exit_setup;
4594 }
4595
4596 /* Update sess/conn params */
4597 qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);
4598
4599 if (is_reset == RESET_ADAPTER) {
4600 iscsi_block_session(cls_sess);
4601 /* Use the relogin path to discover new devices
4602 * by short-circuting the logic of setting
4603 * timer to relogin - instead set the flags
4604 * to initiate login right away.
4605 */
4606 set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
4607 set_bit(DF_RELOGIN, &ddb_entry->flags);
4608 }
4609
4610exit_setup:
4611 return ret;
4612}
4613
4614static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,
4615 struct list_head *list_nt, int is_reset)
4616{
4617 struct dev_db_entry *fw_ddb_entry;
4618 dma_addr_t fw_ddb_dma;
4619 int max_ddbs;
4620 int fw_idx_size;
4621 int ret;
4622 uint32_t idx = 0, next_idx = 0;
4623 uint32_t state = 0, conn_err = 0;
4624 uint16_t conn_id = 0;
4625 struct qla_ddb_index *nt_ddb_idx;
4626
4627 fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
4628 &fw_ddb_dma);
4629 if (fw_ddb_entry == NULL) {
4630 DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
4631 goto exit_nt_list;
4632 }
4633 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
4634 MAX_DEV_DB_ENTRIES;
4635 fw_idx_size = sizeof(struct qla_ddb_index);
4636
4637 for (idx = 0; idx < max_ddbs; idx = next_idx) {
4638 ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
4639 NULL, &next_idx, &state,
4640 &conn_err, NULL, &conn_id);
4641 if (ret == QLA_ERROR)
4642 break;
4643
4644 if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
4645 goto continue_next_nt;
4646
4647 /* Check if NT, then add to list it */
4648 if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
4649 goto continue_next_nt;
4650
4651 if (!(state == DDB_DS_NO_CONNECTION_ACTIVE ||
4652 state == DDB_DS_SESSION_FAILED))
4653 goto continue_next_nt;
4654
4655 DEBUG2(ql4_printk(KERN_INFO, ha,
4656 "Adding DDB to session = 0x%x\n", idx));
4657 if (is_reset == INIT_ADAPTER) {
4658 nt_ddb_idx = vmalloc(fw_idx_size);
4659 if (!nt_ddb_idx)
4660 break;
4661
4662 nt_ddb_idx->fw_ddb_idx = idx;
4663
4664 memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
4665 sizeof(struct dev_db_entry));
4666
4667 if (qla4xxx_is_flash_ddb_exists(ha, list_nt,
4668 fw_ddb_entry) == QLA_SUCCESS) {
4669 vfree(nt_ddb_idx);
4670 goto continue_next_nt;
4671 }
4672 list_add_tail(&nt_ddb_idx->list, list_nt);
4673 } else if (is_reset == RESET_ADAPTER) {
4674 if (qla4xxx_is_session_exists(ha, fw_ddb_entry) ==
4675 QLA_SUCCESS)
4676 goto continue_next_nt;
4677 }
4678
4679 ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset);
4680 if (ret == QLA_ERROR)
4681 goto exit_nt_list;
4682
4683continue_next_nt:
4684 if (next_idx == 0)
4685 break;
4686 }
4687
4688exit_nt_list:
4689 if (fw_ddb_entry)
4690 dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
4691}
4692
4693/**
4694 * qla4xxx_build_ddb_list - Build ddb list and setup sessions
4695 * @ha: pointer to adapter structure
4696 * @is_reset: Is this init path or reset path
4697 *
4698 * Create a list of sendtargets (st) from firmware DDBs, issue send targets
4699 * using connection open, then create the list of normal targets (nt)
4700 * from firmware DDBs. Based on the list of nt setup session and connection
4701 * objects.
4702 **/
4703void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
4704{
4705 uint16_t tmo = 0;
4706 struct list_head list_st, list_nt;
4707 struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp;
4708 unsigned long wtime;
4709
4710 if (!test_bit(AF_LINK_UP, &ha->flags)) {
4711 set_bit(AF_BUILD_DDB_LIST, &ha->flags);
4712 ha->is_reset = is_reset;
4713 return;
4714 }
4715
4716 INIT_LIST_HEAD(&list_st);
4717 INIT_LIST_HEAD(&list_nt);
4718
4719 qla4xxx_build_st_list(ha, &list_st);
4720
Mike Christie13483732011-12-01 21:38:41 -06004721 /* Before issuing conn open mbox, ensure all IPs states are configured
4722 * Note, conn open fails if IPs are not configured
4723 */
4724 qla4xxx_wait_for_ip_configuration(ha);
4725
4726 /* Go thru the STs and fire the sendtargets by issuing conn open mbx */
4727 list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
4728 qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
4729 }
4730
4731 /* Wait to ensure all sendtargets are done for min 12 sec wait */
Nilesh Javalic28eaac2011-12-18 21:40:44 -08004732 tmo = ((ha->def_timeout > LOGIN_TOV) &&
4733 (ha->def_timeout < LOGIN_TOV * 10) ?
4734 ha->def_timeout : LOGIN_TOV);
4735
Mike Christie13483732011-12-01 21:38:41 -06004736 DEBUG2(ql4_printk(KERN_INFO, ha,
4737 "Default time to wait for build ddb %d\n", tmo));
4738
4739 wtime = jiffies + (HZ * tmo);
4740 do {
Nilesh Javalif1f2e602011-12-16 01:58:57 -08004741 if (list_empty(&list_st))
4742 break;
4743
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004744 qla4xxx_remove_failed_ddb(ha, &list_st);
Mike Christie13483732011-12-01 21:38:41 -06004745 schedule_timeout_uninterruptible(HZ / 10);
4746 } while (time_after(wtime, jiffies));
4747
4748 /* Free up the sendtargets list */
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004749 qla4xxx_free_ddb_list(&list_st);
Mike Christie13483732011-12-01 21:38:41 -06004750
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004751 qla4xxx_build_nt_list(ha, &list_nt, is_reset);
Mike Christie13483732011-12-01 21:38:41 -06004752
Lalit Chandivade4a4bc2e2011-12-16 01:58:55 -08004753 qla4xxx_free_ddb_list(&list_nt);
Mike Christie13483732011-12-01 21:38:41 -06004754
4755 qla4xxx_free_ddb_index(ha);
4756}
4757
David Somayajuluafaf5a22006-09-19 10:28:00 -07004758/**
4759 * qla4xxx_probe_adapter - callback function to probe HBA
4760 * @pdev: pointer to pci_dev structure
4761 * @pci_device_id: pointer to pci_device entry
4762 *
4763 * This routine will probe for Qlogic 4xxx iSCSI host adapters.
4764 * It returns zero if successful. It also initializes all data necessary for
4765 * the driver.
4766 **/
4767static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
4768 const struct pci_device_id *ent)
4769{
4770 int ret = -ENODEV, status;
4771 struct Scsi_Host *host;
4772 struct scsi_qla_host *ha;
David Somayajuluafaf5a22006-09-19 10:28:00 -07004773 uint8_t init_retry_count = 0;
4774 char buf[34];
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304775 struct qla4_8xxx_legacy_intr_set *nx_legacy_intr;
Prasanna Mumbaif9880e72011-03-21 03:34:26 -07004776 uint32_t dev_state;
David Somayajuluafaf5a22006-09-19 10:28:00 -07004777
4778 if (pci_enable_device(pdev))
4779 return -1;
4780
Manish Rangankarb3a271a2011-07-25 13:48:53 -05004781 host = iscsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha), 0);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004782 if (host == NULL) {
4783 printk(KERN_WARNING
4784 "qla4xxx: Couldn't allocate host from scsi layer!\n");
4785 goto probe_disable_device;
4786 }
4787
4788 /* Clear our data area */
Manish Rangankarb3a271a2011-07-25 13:48:53 -05004789 ha = to_qla_host(host);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004790 memset(ha, 0, sizeof(*ha));
4791
4792 /* Save the information from PCI BIOS. */
4793 ha->pdev = pdev;
4794 ha->host = host;
4795 ha->host_no = host->host_no;
4796
Lalit Chandivade2232be02010-07-30 14:38:47 +05304797 pci_enable_pcie_error_reporting(pdev);
4798
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304799 /* Setup Runtime configurable options */
4800 if (is_qla8022(ha)) {
4801 ha->isp_ops = &qla4_8xxx_isp_ops;
4802 rwlock_init(&ha->hw_lock);
4803 ha->qdr_sn_window = -1;
4804 ha->ddr_mn_window = -1;
4805 ha->curr_window = 255;
4806 ha->func_num = PCI_FUNC(ha->pdev->devfn);
4807 nx_legacy_intr = &legacy_intr[ha->func_num];
4808 ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;
4809 ha->nx_legacy_intr.tgt_status_reg =
4810 nx_legacy_intr->tgt_status_reg;
4811 ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;
4812 ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
4813 } else {
4814 ha->isp_ops = &qla4xxx_isp_ops;
4815 }
4816
Lalit Chandivade2232be02010-07-30 14:38:47 +05304817 /* Set EEH reset type to fundamental if required by hba */
4818 if (is_qla8022(ha))
4819 pdev->needs_freset = 1;
4820
David Somayajuluafaf5a22006-09-19 10:28:00 -07004821 /* Configure PCI I/O space. */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304822 ret = ha->isp_ops->iospace_config(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004823 if (ret)
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304824 goto probe_failed_ioconfig;
David Somayajuluafaf5a22006-09-19 10:28:00 -07004825
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05304826 ql4_printk(KERN_INFO, ha, "Found an ISP%04x, irq %d, iobase 0x%p\n",
David Somayajuluafaf5a22006-09-19 10:28:00 -07004827 pdev->device, pdev->irq, ha->reg);
4828
4829 qla4xxx_config_dma_addressing(ha);
4830
4831 /* Initialize lists and spinlocks. */
David Somayajuluafaf5a22006-09-19 10:28:00 -07004832 INIT_LIST_HEAD(&ha->free_srb_q);
4833
4834 mutex_init(&ha->mbox_sem);
Lalit Chandivade45494152011-10-07 16:55:42 -07004835 mutex_init(&ha->chap_sem);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304836 init_completion(&ha->mbx_intr_comp);
Vikas Chaudhary95d31262011-08-12 02:51:29 -07004837 init_completion(&ha->disable_acb_comp);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004838
4839 spin_lock_init(&ha->hardware_lock);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004840
Vikas Chaudharyff884432011-08-29 23:43:02 +05304841 /* Initialize work list */
4842 INIT_LIST_HEAD(&ha->work_list);
4843
David Somayajuluafaf5a22006-09-19 10:28:00 -07004844 /* Allocate dma buffers */
4845 if (qla4xxx_mem_alloc(ha)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05304846 ql4_printk(KERN_WARNING, ha,
4847 "[ERROR] Failed to allocate memory for adapter\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07004848
4849 ret = -ENOMEM;
4850 goto probe_failed;
4851 }
4852
Manish Rangankarb3a271a2011-07-25 13:48:53 -05004853 host->cmd_per_lun = 3;
4854 host->max_channel = 0;
4855 host->max_lun = MAX_LUNS - 1;
4856 host->max_id = MAX_TARGETS;
4857 host->max_cmd_len = IOCB_MAX_CDB_LEN;
4858 host->can_queue = MAX_SRBS ;
4859 host->transportt = qla4xxx_scsi_transport;
4860
4861 ret = scsi_init_shared_tag_map(host, MAX_SRBS);
4862 if (ret) {
4863 ql4_printk(KERN_WARNING, ha,
4864 "%s: scsi_init_shared_tag_map failed\n", __func__);
4865 goto probe_failed;
4866 }
4867
4868 pci_set_drvdata(pdev, ha);
4869
4870 ret = scsi_add_host(host, &pdev->dev);
4871 if (ret)
4872 goto probe_failed;
4873
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304874 if (is_qla8022(ha))
4875 (void) qla4_8xxx_get_flash_info(ha);
4876
David Somayajuluafaf5a22006-09-19 10:28:00 -07004877 /*
4878 * Initialize the Host adapter request/response queues and
4879 * firmware
4880 * NOTE: interrupts enabled upon successful completion
4881 */
Mike Christie13483732011-12-01 21:38:41 -06004882 status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304883 while ((!test_bit(AF_ONLINE, &ha->flags)) &&
4884 init_retry_count++ < MAX_INIT_RETRIES) {
Prasanna Mumbaif9880e72011-03-21 03:34:26 -07004885
4886 if (is_qla8022(ha)) {
4887 qla4_8xxx_idc_lock(ha);
4888 dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
4889 qla4_8xxx_idc_unlock(ha);
4890 if (dev_state == QLA82XX_DEV_FAILED) {
4891 ql4_printk(KERN_WARNING, ha, "%s: don't retry "
4892 "initialize adapter. H/W is in failed state\n",
4893 __func__);
4894 break;
4895 }
4896 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07004897 DEBUG2(printk("scsi: %s: retrying adapter initialization "
4898 "(%d)\n", __func__, init_retry_count));
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304899
4900 if (ha->isp_ops->reset_chip(ha) == QLA_ERROR)
4901 continue;
4902
Mike Christie13483732011-12-01 21:38:41 -06004903 status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004904 }
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304905
4906 if (!test_bit(AF_ONLINE, &ha->flags)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05304907 ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07004908
Lalit Chandivadefe998522010-12-02 22:12:36 -08004909 if (is_qla8022(ha) && ql4xdontresethba) {
4910 /* Put the device in failed state. */
4911 DEBUG2(printk(KERN_ERR "HW STATE: FAILED\n"));
4912 qla4_8xxx_idc_lock(ha);
4913 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
4914 QLA82XX_DEV_FAILED);
4915 qla4_8xxx_idc_unlock(ha);
4916 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07004917 ret = -ENODEV;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05004918 goto remove_host;
David Somayajuluafaf5a22006-09-19 10:28:00 -07004919 }
4920
David Somayajuluafaf5a22006-09-19 10:28:00 -07004921 /* Startup the kernel thread for this host adapter. */
4922 DEBUG2(printk("scsi: %s: Starting kernel thread for "
4923 "qla4xxx_dpc\n", __func__));
4924 sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no);
4925 ha->dpc_thread = create_singlethread_workqueue(buf);
4926 if (!ha->dpc_thread) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05304927 ql4_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n");
David Somayajuluafaf5a22006-09-19 10:28:00 -07004928 ret = -ENODEV;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05004929 goto remove_host;
David Somayajuluafaf5a22006-09-19 10:28:00 -07004930 }
David Howellsc4028952006-11-22 14:57:56 +00004931 INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004932
Manish Rangankarb3a271a2011-07-25 13:48:53 -05004933 sprintf(buf, "qla4xxx_%lu_task", ha->host_no);
4934 ha->task_wq = alloc_workqueue(buf, WQ_MEM_RECLAIM, 1);
4935 if (!ha->task_wq) {
4936 ql4_printk(KERN_WARNING, ha, "Unable to start task thread!\n");
4937 ret = -ENODEV;
4938 goto remove_host;
4939 }
4940
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304941 /* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc
4942 * (which is called indirectly by qla4xxx_initialize_adapter),
4943 * so that irqs will be registered after crbinit but before
4944 * mbx_intr_enable.
4945 */
4946 if (!is_qla8022(ha)) {
4947 ret = qla4xxx_request_irqs(ha);
4948 if (ret) {
4949 ql4_printk(KERN_WARNING, ha, "Failed to reserve "
4950 "interrupt %d already in use.\n", pdev->irq);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05004951 goto remove_host;
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304952 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07004953 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07004954
Lalit Chandivade2232be02010-07-30 14:38:47 +05304955 pci_save_state(ha->pdev);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304956 ha->isp_ops->enable_intrs(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004957
4958 /* Start timer thread. */
4959 qla4xxx_start_timer(ha, qla4xxx_timer, 1);
4960
4961 set_bit(AF_INIT_DONE, &ha->flags);
4962
David Somayajuluafaf5a22006-09-19 10:28:00 -07004963 printk(KERN_INFO
4964 " QLogic iSCSI HBA Driver version: %s\n"
4965 " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",
4966 qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),
4967 ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
4968 ha->patch_number, ha->build_number);
Vikas Chaudharyed1086e2011-07-25 13:48:41 -05004969
Manish Rangankar2a991c22011-07-25 13:48:55 -05004970 if (qla4xxx_setup_boot_info(ha))
4971 ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n",
4972 __func__);
4973
Mike Christie13483732011-12-01 21:38:41 -06004974 /* Perform the build ddb list and login to each */
4975 qla4xxx_build_ddb_list(ha, INIT_ADAPTER);
4976 iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb);
4977
4978 qla4xxx_create_chap_list(ha);
4979
Vikas Chaudharyed1086e2011-07-25 13:48:41 -05004980 qla4xxx_create_ifaces(ha);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004981 return 0;
4982
Manish Rangankarb3a271a2011-07-25 13:48:53 -05004983remove_host:
4984 scsi_remove_host(ha->host);
4985
David Somayajuluafaf5a22006-09-19 10:28:00 -07004986probe_failed:
4987 qla4xxx_free_adapter(ha);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05304988
4989probe_failed_ioconfig:
Lalit Chandivade2232be02010-07-30 14:38:47 +05304990 pci_disable_pcie_error_reporting(pdev);
David Somayajuluafaf5a22006-09-19 10:28:00 -07004991 scsi_host_put(ha->host);
4992
4993probe_disable_device:
4994 pci_disable_device(pdev);
4995
4996 return ret;
4997}
4998
4999/**
Karen Higgins7eece5a2011-03-21 03:34:29 -07005000 * qla4xxx_prevent_other_port_reinit - prevent other port from re-initialize
5001 * @ha: pointer to adapter structure
5002 *
5003 * Mark the other ISP-4xxx port to indicate that the driver is being removed,
5004 * so that the other port will not re-initialize while in the process of
5005 * removing the ha due to driver unload or hba hotplug.
5006 **/
5007static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha)
5008{
5009 struct scsi_qla_host *other_ha = NULL;
5010 struct pci_dev *other_pdev = NULL;
5011 int fn = ISP4XXX_PCI_FN_2;
5012
5013 /*iscsi function numbers for ISP4xxx is 1 and 3*/
5014 if (PCI_FUNC(ha->pdev->devfn) & BIT_1)
5015 fn = ISP4XXX_PCI_FN_1;
5016
5017 other_pdev =
5018 pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
5019 ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
5020 fn));
5021
5022 /* Get other_ha if other_pdev is valid and state is enable*/
5023 if (other_pdev) {
5024 if (atomic_read(&other_pdev->enable_cnt)) {
5025 other_ha = pci_get_drvdata(other_pdev);
5026 if (other_ha) {
5027 set_bit(AF_HA_REMOVAL, &other_ha->flags);
5028 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: "
5029 "Prevent %s reinit\n", __func__,
5030 dev_name(&other_ha->pdev->dev)));
5031 }
5032 }
5033 pci_dev_put(other_pdev);
5034 }
5035}
5036
Mike Christie13483732011-12-01 21:38:41 -06005037static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha)
5038{
5039 struct ddb_entry *ddb_entry;
5040 int options;
5041 int idx;
5042
5043 for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {
5044
5045 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
5046 if ((ddb_entry != NULL) &&
5047 (ddb_entry->ddb_type == FLASH_DDB)) {
5048
5049 options = LOGOUT_OPTION_CLOSE_SESSION;
5050 if (qla4xxx_session_logout_ddb(ha, ddb_entry, options)
5051 == QLA_ERROR)
5052 ql4_printk(KERN_ERR, ha, "%s: Logout failed\n",
5053 __func__);
5054
5055 qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
5056 /*
5057 * we have decremented the reference count of the driver
5058 * when we setup the session to have the driver unload
5059 * to be seamless without actually destroying the
5060 * session
5061 **/
5062 try_module_get(qla4xxx_iscsi_transport.owner);
5063 iscsi_destroy_endpoint(ddb_entry->conn->ep);
5064 qla4xxx_free_ddb(ha, ddb_entry);
5065 iscsi_session_teardown(ddb_entry->sess);
5066 }
5067 }
5068}
Karen Higgins7eece5a2011-03-21 03:34:29 -07005069/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07005070 * qla4xxx_remove_adapter - calback function to remove adapter.
5071 * @pci_dev: PCI device pointer
5072 **/
5073static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
5074{
5075 struct scsi_qla_host *ha;
5076
5077 ha = pci_get_drvdata(pdev);
5078
Karen Higgins7eece5a2011-03-21 03:34:29 -07005079 if (!is_qla8022(ha))
5080 qla4xxx_prevent_other_port_reinit(ha);
David C Somayajulubee4fe82007-05-23 18:03:32 -07005081
Vikas Chaudharyed1086e2011-07-25 13:48:41 -05005082 /* destroy iface from sysfs */
5083 qla4xxx_destroy_ifaces(ha);
5084
Mike Christie13483732011-12-01 21:38:41 -06005085 if ((!ql4xdisablesysfsboot) && ha->boot_kset)
Manish Rangankar2a991c22011-07-25 13:48:55 -05005086 iscsi_boot_destroy_kset(ha->boot_kset);
5087
Mike Christie13483732011-12-01 21:38:41 -06005088 qla4xxx_destroy_fw_ddb_session(ha);
5089
David Somayajuluafaf5a22006-09-19 10:28:00 -07005090 scsi_remove_host(ha->host);
5091
5092 qla4xxx_free_adapter(ha);
5093
5094 scsi_host_put(ha->host);
5095
Lalit Chandivade2232be02010-07-30 14:38:47 +05305096 pci_disable_pcie_error_reporting(pdev);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05305097 pci_disable_device(pdev);
David Somayajuluafaf5a22006-09-19 10:28:00 -07005098 pci_set_drvdata(pdev, NULL);
5099}
5100
5101/**
5102 * qla4xxx_config_dma_addressing() - Configure OS DMA addressing method.
5103 * @ha: HA context
5104 *
5105 * At exit, the @ha's flags.enable_64bit_addressing set to indicated
5106 * supported addressing method.
5107 */
Adrian Bunk47975472007-04-26 00:35:16 -07005108static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07005109{
5110 int retval;
5111
5112 /* Update our PCI device dma_mask for full 64 bit mask */
Yang Hongyang6a355282009-04-06 19:01:13 -07005113 if (pci_set_dma_mask(ha->pdev, DMA_BIT_MASK(64)) == 0) {
5114 if (pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07005115 dev_dbg(&ha->pdev->dev,
5116 "Failed to set 64 bit PCI consistent mask; "
5117 "using 32 bit.\n");
5118 retval = pci_set_consistent_dma_mask(ha->pdev,
Yang Hongyang284901a2009-04-06 19:01:15 -07005119 DMA_BIT_MASK(32));
David Somayajuluafaf5a22006-09-19 10:28:00 -07005120 }
5121 } else
Yang Hongyang284901a2009-04-06 19:01:15 -07005122 retval = pci_set_dma_mask(ha->pdev, DMA_BIT_MASK(32));
David Somayajuluafaf5a22006-09-19 10:28:00 -07005123}
5124
5125static int qla4xxx_slave_alloc(struct scsi_device *sdev)
5126{
Manish Rangankarb3a271a2011-07-25 13:48:53 -05005127 struct iscsi_cls_session *cls_sess;
5128 struct iscsi_session *sess;
5129 struct ddb_entry *ddb;
Vikas Chaudhary8bb40332011-03-21 03:34:31 -07005130 int queue_depth = QL4_DEF_QDEPTH;
David Somayajuluafaf5a22006-09-19 10:28:00 -07005131
Manish Rangankarb3a271a2011-07-25 13:48:53 -05005132 cls_sess = starget_to_session(sdev->sdev_target);
5133 sess = cls_sess->dd_data;
5134 ddb = sess->dd_data;
5135
David Somayajuluafaf5a22006-09-19 10:28:00 -07005136 sdev->hostdata = ddb;
5137 sdev->tagged_supported = 1;
Vikas Chaudhary8bb40332011-03-21 03:34:31 -07005138
5139 if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU)
5140 queue_depth = ql4xmaxqdepth;
5141
5142 scsi_activate_tcq(sdev, queue_depth);
David Somayajuluafaf5a22006-09-19 10:28:00 -07005143 return 0;
5144}
5145
5146static int qla4xxx_slave_configure(struct scsi_device *sdev)
5147{
5148 sdev->tagged_supported = 1;
5149 return 0;
5150}
5151
5152static void qla4xxx_slave_destroy(struct scsi_device *sdev)
5153{
5154 scsi_deactivate_tcq(sdev, 1);
5155}
5156
5157/**
5158 * qla4xxx_del_from_active_array - returns an active srb
5159 * @ha: Pointer to host adapter structure.
Anand Gadiyarfd589a82009-07-16 17:13:03 +02005160 * @index: index into the active_array
David Somayajuluafaf5a22006-09-19 10:28:00 -07005161 *
5162 * This routine removes and returns the srb at the specified index
5163 **/
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05305164struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
5165 uint32_t index)
David Somayajuluafaf5a22006-09-19 10:28:00 -07005166{
5167 struct srb *srb = NULL;
Vikas Chaudhary53698872010-04-28 11:41:59 +05305168 struct scsi_cmnd *cmd = NULL;
David Somayajuluafaf5a22006-09-19 10:28:00 -07005169
Vikas Chaudhary53698872010-04-28 11:41:59 +05305170 cmd = scsi_host_find_tag(ha->host, index);
5171 if (!cmd)
David Somayajuluafaf5a22006-09-19 10:28:00 -07005172 return srb;
5173
Vikas Chaudhary53698872010-04-28 11:41:59 +05305174 srb = (struct srb *)CMD_SP(cmd);
5175 if (!srb)
David Somayajuluafaf5a22006-09-19 10:28:00 -07005176 return srb;
5177
5178 /* update counters */
5179 if (srb->flags & SRB_DMA_VALID) {
5180 ha->req_q_count += srb->iocb_cnt;
5181 ha->iocb_cnt -= srb->iocb_cnt;
5182 if (srb->cmd)
Vikas Chaudhary53698872010-04-28 11:41:59 +05305183 srb->cmd->host_scribble =
5184 (unsigned char *)(unsigned long) MAX_SRBS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07005185 }
5186 return srb;
5187}
5188
5189/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07005190 * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305191 * @ha: Pointer to host adapter structure.
David Somayajuluafaf5a22006-09-19 10:28:00 -07005192 * @cmd: Scsi Command to wait on.
5193 *
5194 * This routine waits for the command to be returned by the Firmware
5195 * for some max time.
5196 **/
5197static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha,
5198 struct scsi_cmnd *cmd)
5199{
5200 int done = 0;
5201 struct srb *rp;
5202 uint32_t max_wait_time = EH_WAIT_CMD_TOV;
Lalit Chandivade2232be02010-07-30 14:38:47 +05305203 int ret = SUCCESS;
5204
5205 /* Dont wait on command if PCI error is being handled
5206 * by PCI AER driver
5207 */
5208 if (unlikely(pci_channel_offline(ha->pdev)) ||
5209 (test_bit(AF_EEH_BUSY, &ha->flags))) {
5210 ql4_printk(KERN_WARNING, ha, "scsi%ld: Return from %s\n",
5211 ha->host_no, __func__);
5212 return ret;
5213 }
David Somayajuluafaf5a22006-09-19 10:28:00 -07005214
5215 do {
5216 /* Checking to see if its returned to OS */
Vikas Chaudhary53698872010-04-28 11:41:59 +05305217 rp = (struct srb *) CMD_SP(cmd);
David Somayajuluafaf5a22006-09-19 10:28:00 -07005218 if (rp == NULL) {
5219 done++;
5220 break;
5221 }
5222
5223 msleep(2000);
5224 } while (max_wait_time--);
5225
5226 return done;
5227}
5228
5229/**
5230 * qla4xxx_wait_for_hba_online - waits for HBA to come online
5231 * @ha: Pointer to host adapter structure
5232 **/
5233static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
5234{
5235 unsigned long wait_online;
5236
Vikas Chaudharyf581a3f2010-10-06 22:47:48 -07005237 wait_online = jiffies + (HBA_ONLINE_TOV * HZ);
David Somayajuluafaf5a22006-09-19 10:28:00 -07005238 while (time_before(jiffies, wait_online)) {
5239
5240 if (adapter_up(ha))
5241 return QLA_SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07005242
5243 msleep(2000);
5244 }
5245
5246 return QLA_ERROR;
5247}
5248
5249/**
Mike Christiece545032008-02-29 18:25:20 -06005250 * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
Anand Gadiyarfd589a82009-07-16 17:13:03 +02005251 * @ha: pointer to HBA
David Somayajuluafaf5a22006-09-19 10:28:00 -07005252 * @t: target id
5253 * @l: lun id
5254 *
5255 * This function waits for all outstanding commands to a lun to complete. It
5256 * returns 0 if all pending commands are returned and 1 otherwise.
5257 **/
Mike Christiece545032008-02-29 18:25:20 -06005258static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
5259 struct scsi_target *stgt,
5260 struct scsi_device *sdev)
David Somayajuluafaf5a22006-09-19 10:28:00 -07005261{
5262 int cnt;
5263 int status = 0;
5264 struct scsi_cmnd *cmd;
5265
5266 /*
Mike Christiece545032008-02-29 18:25:20 -06005267 * Waiting for all commands for the designated target or dev
5268 * in the active array
David Somayajuluafaf5a22006-09-19 10:28:00 -07005269 */
5270 for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
5271 cmd = scsi_host_find_tag(ha->host, cnt);
Mike Christiece545032008-02-29 18:25:20 -06005272 if (cmd && stgt == scsi_target(cmd->device) &&
5273 (!sdev || sdev == cmd->device)) {
David Somayajuluafaf5a22006-09-19 10:28:00 -07005274 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
5275 status++;
5276 break;
5277 }
5278 }
5279 }
5280 return status;
5281}
5282
5283/**
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305284 * qla4xxx_eh_abort - callback for abort task.
5285 * @cmd: Pointer to Linux's SCSI command structure
5286 *
5287 * This routine is called by the Linux OS to abort the specified
5288 * command.
5289 **/
5290static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
5291{
5292 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
5293 unsigned int id = cmd->device->id;
5294 unsigned int lun = cmd->device->lun;
Mike Christie92b3e5b2010-10-06 22:51:17 -07005295 unsigned long flags;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305296 struct srb *srb = NULL;
5297 int ret = SUCCESS;
5298 int wait = 0;
5299
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05305300 ql4_printk(KERN_INFO, ha,
Christoph Hellwig5cd049a2011-04-04 09:42:14 -04005301 "scsi%ld:%d:%d: Abort command issued cmd=%p\n",
5302 ha->host_no, id, lun, cmd);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305303
Mike Christie92b3e5b2010-10-06 22:51:17 -07005304 spin_lock_irqsave(&ha->hardware_lock, flags);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305305 srb = (struct srb *) CMD_SP(cmd);
Mike Christie92b3e5b2010-10-06 22:51:17 -07005306 if (!srb) {
5307 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305308 return SUCCESS;
Mike Christie92b3e5b2010-10-06 22:51:17 -07005309 }
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305310 kref_get(&srb->srb_ref);
Mike Christie92b3e5b2010-10-06 22:51:17 -07005311 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305312
5313 if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) {
5314 DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx failed.\n",
5315 ha->host_no, id, lun));
5316 ret = FAILED;
5317 } else {
5318 DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx success.\n",
5319 ha->host_no, id, lun));
5320 wait = 1;
5321 }
5322
5323 kref_put(&srb->srb_ref, qla4xxx_srb_compl);
5324
5325 /* Wait for command to complete */
5326 if (wait) {
5327 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
5328 DEBUG2(printk("scsi%ld:%d:%d: Abort handler timed out\n",
5329 ha->host_no, id, lun));
5330 ret = FAILED;
5331 }
5332 }
5333
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05305334 ql4_printk(KERN_INFO, ha,
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305335 "scsi%ld:%d:%d: Abort command - %s\n",
Lucas De Marchi25985ed2011-03-30 22:57:33 -03005336 ha->host_no, id, lun, (ret == SUCCESS) ? "succeeded" : "failed");
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05305337
5338 return ret;
5339}
5340
5341/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07005342 * qla4xxx_eh_device_reset - callback for target reset.
5343 * @cmd: Pointer to Linux's SCSI command structure
5344 *
5345 * This routine is called by the Linux OS to reset all luns on the
5346 * specified target.
5347 **/
5348static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
5349{
5350 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
5351 struct ddb_entry *ddb_entry = cmd->device->hostdata;
David Somayajuluafaf5a22006-09-19 10:28:00 -07005352 int ret = FAILED, stat;
5353
Karen Higgins612f7342009-07-15 15:03:01 -05005354 if (!ddb_entry)
David Somayajuluafaf5a22006-09-19 10:28:00 -07005355 return ret;
5356
Mike Christiec01be6d2010-07-22 16:59:49 +05305357 ret = iscsi_block_scsi_eh(cmd);
5358 if (ret)
5359 return ret;
5360 ret = FAILED;
5361
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05305362 ql4_printk(KERN_INFO, ha,
David Somayajuluafaf5a22006-09-19 10:28:00 -07005363 "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no,
5364 cmd->device->channel, cmd->device->id, cmd->device->lun);
5365
5366 DEBUG2(printk(KERN_INFO
5367 "scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x,"
5368 "dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no,
Jens Axboe242f9dc2008-09-14 05:55:09 -07005369 cmd, jiffies, cmd->request->timeout / HZ,
David Somayajuluafaf5a22006-09-19 10:28:00 -07005370 ha->dpc_flags, cmd->result, cmd->allowed));
5371
5372 /* FIXME: wait for hba to go online */
5373 stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun);
5374 if (stat != QLA_SUCCESS) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05305375 ql4_printk(KERN_INFO, ha, "DEVICE RESET FAILED. %d\n", stat);
David Somayajuluafaf5a22006-09-19 10:28:00 -07005376 goto eh_dev_reset_done;
5377 }
5378
Mike Christiece545032008-02-29 18:25:20 -06005379 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
5380 cmd->device)) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05305381 ql4_printk(KERN_INFO, ha,
Mike Christiece545032008-02-29 18:25:20 -06005382 "DEVICE RESET FAILED - waiting for "
5383 "commands.\n");
5384 goto eh_dev_reset_done;
David Somayajuluafaf5a22006-09-19 10:28:00 -07005385 }
5386
David C Somayajulu9d562912008-03-19 11:23:03 -07005387 /* Send marker. */
5388 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
5389 MM_LUN_RESET) != QLA_SUCCESS)
5390 goto eh_dev_reset_done;
5391
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05305392 ql4_printk(KERN_INFO, ha,
David Somayajuluafaf5a22006-09-19 10:28:00 -07005393 "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
5394 ha->host_no, cmd->device->channel, cmd->device->id,
5395 cmd->device->lun);
5396
5397 ret = SUCCESS;
5398
5399eh_dev_reset_done:
5400
5401 return ret;
5402}
5403
5404/**
Mike Christiece545032008-02-29 18:25:20 -06005405 * qla4xxx_eh_target_reset - callback for target reset.
5406 * @cmd: Pointer to Linux's SCSI command structure
5407 *
5408 * This routine is called by the Linux OS to reset the target.
5409 **/
5410static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
5411{
5412 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
5413 struct ddb_entry *ddb_entry = cmd->device->hostdata;
Mike Christiec01be6d2010-07-22 16:59:49 +05305414 int stat, ret;
Mike Christiece545032008-02-29 18:25:20 -06005415
5416 if (!ddb_entry)
5417 return FAILED;
5418
Mike Christiec01be6d2010-07-22 16:59:49 +05305419 ret = iscsi_block_scsi_eh(cmd);
5420 if (ret)
5421 return ret;
5422
Mike Christiece545032008-02-29 18:25:20 -06005423 starget_printk(KERN_INFO, scsi_target(cmd->device),
5424 "WARM TARGET RESET ISSUED.\n");
5425
5426 DEBUG2(printk(KERN_INFO
5427 "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
5428 "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
Jens Axboe242f9dc2008-09-14 05:55:09 -07005429 ha->host_no, cmd, jiffies, cmd->request->timeout / HZ,
Mike Christiece545032008-02-29 18:25:20 -06005430 ha->dpc_flags, cmd->result, cmd->allowed));
5431
5432 stat = qla4xxx_reset_target(ha, ddb_entry);
5433 if (stat != QLA_SUCCESS) {
5434 starget_printk(KERN_INFO, scsi_target(cmd->device),
5435 "WARM TARGET RESET FAILED.\n");
5436 return FAILED;
5437 }
5438
Mike Christiece545032008-02-29 18:25:20 -06005439 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
5440 NULL)) {
5441 starget_printk(KERN_INFO, scsi_target(cmd->device),
5442 "WARM TARGET DEVICE RESET FAILED - "
5443 "waiting for commands.\n");
5444 return FAILED;
5445 }
5446
David C Somayajulu9d562912008-03-19 11:23:03 -07005447 /* Send marker. */
5448 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
5449 MM_TGT_WARM_RESET) != QLA_SUCCESS) {
5450 starget_printk(KERN_INFO, scsi_target(cmd->device),
5451 "WARM TARGET DEVICE RESET FAILED - "
5452 "marker iocb failed.\n");
5453 return FAILED;
5454 }
5455
Mike Christiece545032008-02-29 18:25:20 -06005456 starget_printk(KERN_INFO, scsi_target(cmd->device),
5457 "WARM TARGET RESET SUCCEEDED.\n");
5458 return SUCCESS;
5459}
5460
5461/**
Sarang Radke8a288962011-12-06 02:34:10 -08005462 * qla4xxx_is_eh_active - check if error handler is running
5463 * @shost: Pointer to SCSI Host struct
5464 *
5465 * This routine finds that if reset host is called in EH
5466 * scenario or from some application like sg_reset
5467 **/
5468static int qla4xxx_is_eh_active(struct Scsi_Host *shost)
5469{
5470 if (shost->shost_state == SHOST_RECOVERY)
5471 return 1;
5472 return 0;
5473}
5474
5475/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07005476 * qla4xxx_eh_host_reset - kernel callback
5477 * @cmd: Pointer to Linux's SCSI command structure
5478 *
5479 * This routine is invoked by the Linux kernel to perform fatal error
5480 * recovery on the specified adapter.
5481 **/
5482static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
5483{
5484 int return_status = FAILED;
5485 struct scsi_qla_host *ha;
5486
Manish Rangankarb3a271a2011-07-25 13:48:53 -05005487 ha = to_qla_host(cmd->device->host);
David Somayajuluafaf5a22006-09-19 10:28:00 -07005488
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05305489 if (ql4xdontresethba) {
5490 DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
5491 ha->host_no, __func__));
Sarang Radke8a288962011-12-06 02:34:10 -08005492
5493 /* Clear outstanding srb in queues */
5494 if (qla4xxx_is_eh_active(cmd->device->host))
5495 qla4xxx_abort_active_cmds(ha, DID_ABORT << 16);
5496
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05305497 return FAILED;
5498 }
5499
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05305500 ql4_printk(KERN_INFO, ha,
Karen Higginsdca05c42009-07-15 15:03:00 -05005501 "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no,
David Somayajuluafaf5a22006-09-19 10:28:00 -07005502 cmd->device->channel, cmd->device->id, cmd->device->lun);
5503
5504 if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) {
5505 DEBUG2(printk("scsi%ld:%d: %s: Unable to reset host. Adapter "
5506 "DEAD.\n", ha->host_no, cmd->device->channel,
5507 __func__));
5508
5509 return FAILED;
5510 }
5511
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05305512 if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
5513 if (is_qla8022(ha))
5514 set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
5515 else
5516 set_bit(DPC_RESET_HA, &ha->dpc_flags);
5517 }
Mike Christie50a29ae2008-03-04 13:26:53 -06005518
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05305519 if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS)
David Somayajuluafaf5a22006-09-19 10:28:00 -07005520 return_status = SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07005521
Vikas Chaudharyc2660df2010-07-10 14:51:02 +05305522 ql4_printk(KERN_INFO, ha, "HOST RESET %s.\n",
Lucas De Marchi25985ed2011-03-30 22:57:33 -03005523 return_status == FAILED ? "FAILED" : "SUCCEEDED");
David Somayajuluafaf5a22006-09-19 10:28:00 -07005524
5525 return return_status;
5526}
5527
Vikas Chaudhary95d31262011-08-12 02:51:29 -07005528static int qla4xxx_context_reset(struct scsi_qla_host *ha)
5529{
5530 uint32_t mbox_cmd[MBOX_REG_COUNT];
5531 uint32_t mbox_sts[MBOX_REG_COUNT];
5532 struct addr_ctrl_blk_def *acb = NULL;
5533 uint32_t acb_len = sizeof(struct addr_ctrl_blk_def);
5534 int rval = QLA_SUCCESS;
5535 dma_addr_t acb_dma;
5536
5537 acb = dma_alloc_coherent(&ha->pdev->dev,
5538 sizeof(struct addr_ctrl_blk_def),
5539 &acb_dma, GFP_KERNEL);
5540 if (!acb) {
5541 ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n",
5542 __func__);
5543 rval = -ENOMEM;
5544 goto exit_port_reset;
5545 }
5546
5547 memset(acb, 0, acb_len);
5548
5549 rval = qla4xxx_get_acb(ha, acb_dma, PRIMARI_ACB, acb_len);
5550 if (rval != QLA_SUCCESS) {
5551 rval = -EIO;
5552 goto exit_free_acb;
5553 }
5554
5555 rval = qla4xxx_disable_acb(ha);
5556 if (rval != QLA_SUCCESS) {
5557 rval = -EIO;
5558 goto exit_free_acb;
5559 }
5560
5561 wait_for_completion_timeout(&ha->disable_acb_comp,
5562 DISABLE_ACB_TOV * HZ);
5563
5564 rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma);
5565 if (rval != QLA_SUCCESS) {
5566 rval = -EIO;
5567 goto exit_free_acb;
5568 }
5569
5570exit_free_acb:
5571 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk_def),
5572 acb, acb_dma);
5573exit_port_reset:
5574 DEBUG2(ql4_printk(KERN_INFO, ha, "%s %s\n", __func__,
5575 rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED"));
5576 return rval;
5577}
5578
5579static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type)
5580{
5581 struct scsi_qla_host *ha = to_qla_host(shost);
5582 int rval = QLA_SUCCESS;
5583
5584 if (ql4xdontresethba) {
5585 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Don't Reset HBA\n",
5586 __func__));
5587 rval = -EPERM;
5588 goto exit_host_reset;
5589 }
5590
5591 rval = qla4xxx_wait_for_hba_online(ha);
5592 if (rval != QLA_SUCCESS) {
5593 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unable to reset host "
5594 "adapter\n", __func__));
5595 rval = -EIO;
5596 goto exit_host_reset;
5597 }
5598
5599 if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
5600 goto recover_adapter;
5601
5602 switch (reset_type) {
5603 case SCSI_ADAPTER_RESET:
5604 set_bit(DPC_RESET_HA, &ha->dpc_flags);
5605 break;
5606 case SCSI_FIRMWARE_RESET:
5607 if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
5608 if (is_qla8022(ha))
5609 /* set firmware context reset */
5610 set_bit(DPC_RESET_HA_FW_CONTEXT,
5611 &ha->dpc_flags);
5612 else {
5613 rval = qla4xxx_context_reset(ha);
5614 goto exit_host_reset;
5615 }
5616 }
5617 break;
5618 }
5619
5620recover_adapter:
5621 rval = qla4xxx_recover_adapter(ha);
5622 if (rval != QLA_SUCCESS) {
5623 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: recover adapter fail\n",
5624 __func__));
5625 rval = -EIO;
5626 }
5627
5628exit_host_reset:
5629 return rval;
5630}
5631
Lalit Chandivade2232be02010-07-30 14:38:47 +05305632/* PCI AER driver recovers from all correctable errors w/o
5633 * driver intervention. For uncorrectable errors PCI AER
5634 * driver calls the following device driver's callbacks
5635 *
5636 * - Fatal Errors - link_reset
5637 * - Non-Fatal Errors - driver's pci_error_detected() which
5638 * returns CAN_RECOVER, NEED_RESET or DISCONNECT.
5639 *
5640 * PCI AER driver calls
5641 * CAN_RECOVER - driver's pci_mmio_enabled(), mmio_enabled
5642 * returns RECOVERED or NEED_RESET if fw_hung
5643 * NEED_RESET - driver's slot_reset()
5644 * DISCONNECT - device is dead & cannot recover
5645 * RECOVERED - driver's pci_resume()
5646 */
5647static pci_ers_result_t
5648qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
5649{
5650 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
5651
5652 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: error detected:state %x\n",
5653 ha->host_no, __func__, state);
5654
5655 if (!is_aer_supported(ha))
5656 return PCI_ERS_RESULT_NONE;
5657
5658 switch (state) {
5659 case pci_channel_io_normal:
5660 clear_bit(AF_EEH_BUSY, &ha->flags);
5661 return PCI_ERS_RESULT_CAN_RECOVER;
5662 case pci_channel_io_frozen:
5663 set_bit(AF_EEH_BUSY, &ha->flags);
5664 qla4xxx_mailbox_premature_completion(ha);
5665 qla4xxx_free_irqs(ha);
5666 pci_disable_device(pdev);
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07005667 /* Return back all IOs */
5668 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
Lalit Chandivade2232be02010-07-30 14:38:47 +05305669 return PCI_ERS_RESULT_NEED_RESET;
5670 case pci_channel_io_perm_failure:
5671 set_bit(AF_EEH_BUSY, &ha->flags);
5672 set_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags);
5673 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
5674 return PCI_ERS_RESULT_DISCONNECT;
5675 }
5676 return PCI_ERS_RESULT_NEED_RESET;
5677}
5678
5679/**
5680 * qla4xxx_pci_mmio_enabled() gets called if
5681 * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER
5682 * and read/write to the device still works.
5683 **/
5684static pci_ers_result_t
5685qla4xxx_pci_mmio_enabled(struct pci_dev *pdev)
5686{
5687 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
5688
5689 if (!is_aer_supported(ha))
5690 return PCI_ERS_RESULT_NONE;
5691
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07005692 return PCI_ERS_RESULT_RECOVERED;
Lalit Chandivade2232be02010-07-30 14:38:47 +05305693}
5694
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07005695static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
Lalit Chandivade2232be02010-07-30 14:38:47 +05305696{
5697 uint32_t rval = QLA_ERROR;
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07005698 uint32_t ret = 0;
Lalit Chandivade2232be02010-07-30 14:38:47 +05305699 int fn;
5700 struct pci_dev *other_pdev = NULL;
5701
5702 ql4_printk(KERN_WARNING, ha, "scsi%ld: In %s\n", ha->host_no, __func__);
5703
5704 set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
5705
5706 if (test_bit(AF_ONLINE, &ha->flags)) {
5707 clear_bit(AF_ONLINE, &ha->flags);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05005708 clear_bit(AF_LINK_UP, &ha->flags);
5709 iscsi_host_for_each_session(ha->host, qla4xxx_fail_session);
Lalit Chandivade2232be02010-07-30 14:38:47 +05305710 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
Lalit Chandivade2232be02010-07-30 14:38:47 +05305711 }
5712
5713 fn = PCI_FUNC(ha->pdev->devfn);
5714 while (fn > 0) {
5715 fn--;
5716 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Finding PCI device at "
5717 "func %x\n", ha->host_no, __func__, fn);
5718 /* Get the pci device given the domain, bus,
5719 * slot/function number */
5720 other_pdev =
5721 pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
5722 ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
5723 fn));
5724
5725 if (!other_pdev)
5726 continue;
5727
5728 if (atomic_read(&other_pdev->enable_cnt)) {
5729 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Found PCI "
5730 "func in enabled state%x\n", ha->host_no,
5731 __func__, fn);
5732 pci_dev_put(other_pdev);
5733 break;
5734 }
5735 pci_dev_put(other_pdev);
5736 }
5737
5738 /* The first function on the card, the reset owner will
5739 * start & initialize the firmware. The other functions
5740 * on the card will reset the firmware context
5741 */
5742 if (!fn) {
5743 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn being reset "
5744 "0x%x is the owner\n", ha->host_no, __func__,
5745 ha->pdev->devfn);
5746
5747 qla4_8xxx_idc_lock(ha);
5748 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
5749 QLA82XX_DEV_COLD);
5750
5751 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION,
5752 QLA82XX_IDC_VERSION);
5753
5754 qla4_8xxx_idc_unlock(ha);
5755 clear_bit(AF_FW_RECOVERY, &ha->flags);
Mike Christie13483732011-12-01 21:38:41 -06005756 rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
Lalit Chandivade2232be02010-07-30 14:38:47 +05305757 qla4_8xxx_idc_lock(ha);
5758
5759 if (rval != QLA_SUCCESS) {
5760 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: "
5761 "FAILED\n", ha->host_no, __func__);
5762 qla4_8xxx_clear_drv_active(ha);
5763 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
5764 QLA82XX_DEV_FAILED);
5765 } else {
5766 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: "
5767 "READY\n", ha->host_no, __func__);
5768 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
5769 QLA82XX_DEV_READY);
5770 /* Clear driver state register */
5771 qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
5772 qla4_8xxx_set_drv_active(ha);
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07005773 ret = qla4xxx_request_irqs(ha);
5774 if (ret) {
5775 ql4_printk(KERN_WARNING, ha, "Failed to "
5776 "reserve interrupt %d already in use.\n",
5777 ha->pdev->irq);
5778 rval = QLA_ERROR;
5779 } else {
5780 ha->isp_ops->enable_intrs(ha);
5781 rval = QLA_SUCCESS;
5782 }
Lalit Chandivade2232be02010-07-30 14:38:47 +05305783 }
5784 qla4_8xxx_idc_unlock(ha);
5785 } else {
5786 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not "
5787 "the reset owner\n", ha->host_no, __func__,
5788 ha->pdev->devfn);
5789 if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
5790 QLA82XX_DEV_READY)) {
5791 clear_bit(AF_FW_RECOVERY, &ha->flags);
Mike Christie13483732011-12-01 21:38:41 -06005792 rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07005793 if (rval == QLA_SUCCESS) {
5794 ret = qla4xxx_request_irqs(ha);
5795 if (ret) {
5796 ql4_printk(KERN_WARNING, ha, "Failed to"
5797 " reserve interrupt %d already in"
5798 " use.\n", ha->pdev->irq);
5799 rval = QLA_ERROR;
5800 } else {
5801 ha->isp_ops->enable_intrs(ha);
5802 rval = QLA_SUCCESS;
5803 }
5804 }
Lalit Chandivade2232be02010-07-30 14:38:47 +05305805 qla4_8xxx_idc_lock(ha);
5806 qla4_8xxx_set_drv_active(ha);
5807 qla4_8xxx_idc_unlock(ha);
5808 }
5809 }
5810 clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
5811 return rval;
5812}
5813
5814static pci_ers_result_t
5815qla4xxx_pci_slot_reset(struct pci_dev *pdev)
5816{
5817 pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
5818 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
5819 int rc;
5820
5821 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: slot_reset\n",
5822 ha->host_no, __func__);
5823
5824 if (!is_aer_supported(ha))
5825 return PCI_ERS_RESULT_NONE;
5826
5827 /* Restore the saved state of PCIe device -
5828 * BAR registers, PCI Config space, PCIX, MSI,
5829 * IOV states
5830 */
5831 pci_restore_state(pdev);
5832
5833 /* pci_restore_state() clears the saved_state flag of the device
5834 * save restored state which resets saved_state flag
5835 */
5836 pci_save_state(pdev);
5837
5838 /* Initialize device or resume if in suspended state */
5839 rc = pci_enable_device(pdev);
5840 if (rc) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03005841 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Can't re-enable "
Lalit Chandivade2232be02010-07-30 14:38:47 +05305842 "device after reset\n", ha->host_no, __func__);
5843 goto exit_slot_reset;
5844 }
5845
Vikas Chaudhary7b3595d2010-10-06 22:50:56 -07005846 ha->isp_ops->disable_intrs(ha);
Lalit Chandivade2232be02010-07-30 14:38:47 +05305847
5848 if (is_qla8022(ha)) {
5849 if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) {
5850 ret = PCI_ERS_RESULT_RECOVERED;
5851 goto exit_slot_reset;
5852 } else
5853 goto exit_slot_reset;
5854 }
5855
5856exit_slot_reset:
5857 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Return=%x\n"
5858 "device after reset\n", ha->host_no, __func__, ret);
5859 return ret;
5860}
5861
5862static void
5863qla4xxx_pci_resume(struct pci_dev *pdev)
5864{
5865 struct scsi_qla_host *ha = pci_get_drvdata(pdev);
5866 int ret;
5867
5868 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: pci_resume\n",
5869 ha->host_no, __func__);
5870
5871 ret = qla4xxx_wait_for_hba_online(ha);
5872 if (ret != QLA_SUCCESS) {
5873 ql4_printk(KERN_ERR, ha, "scsi%ld: %s: the device failed to "
5874 "resume I/O from slot/link_reset\n", ha->host_no,
5875 __func__);
5876 }
5877
5878 pci_cleanup_aer_uncorrect_error_status(pdev);
5879 clear_bit(AF_EEH_BUSY, &ha->flags);
5880}
5881
5882static struct pci_error_handlers qla4xxx_err_handler = {
5883 .error_detected = qla4xxx_pci_error_detected,
5884 .mmio_enabled = qla4xxx_pci_mmio_enabled,
5885 .slot_reset = qla4xxx_pci_slot_reset,
5886 .resume = qla4xxx_pci_resume,
5887};
5888
David Somayajuluafaf5a22006-09-19 10:28:00 -07005889static struct pci_device_id qla4xxx_pci_tbl[] = {
5890 {
5891 .vendor = PCI_VENDOR_ID_QLOGIC,
5892 .device = PCI_DEVICE_ID_QLOGIC_ISP4010,
5893 .subvendor = PCI_ANY_ID,
5894 .subdevice = PCI_ANY_ID,
5895 },
5896 {
5897 .vendor = PCI_VENDOR_ID_QLOGIC,
5898 .device = PCI_DEVICE_ID_QLOGIC_ISP4022,
5899 .subvendor = PCI_ANY_ID,
5900 .subdevice = PCI_ANY_ID,
5901 },
David C Somayajulud9150582006-11-15 17:38:40 -08005902 {
5903 .vendor = PCI_VENDOR_ID_QLOGIC,
5904 .device = PCI_DEVICE_ID_QLOGIC_ISP4032,
5905 .subvendor = PCI_ANY_ID,
5906 .subdevice = PCI_ANY_ID,
5907 },
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05305908 {
5909 .vendor = PCI_VENDOR_ID_QLOGIC,
5910 .device = PCI_DEVICE_ID_QLOGIC_ISP8022,
5911 .subvendor = PCI_ANY_ID,
5912 .subdevice = PCI_ANY_ID,
5913 },
David Somayajuluafaf5a22006-09-19 10:28:00 -07005914 {0, 0},
5915};
5916MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl);
5917
Adrian Bunk47975472007-04-26 00:35:16 -07005918static struct pci_driver qla4xxx_pci_driver = {
David Somayajuluafaf5a22006-09-19 10:28:00 -07005919 .name = DRIVER_NAME,
5920 .id_table = qla4xxx_pci_tbl,
5921 .probe = qla4xxx_probe_adapter,
5922 .remove = qla4xxx_remove_adapter,
Lalit Chandivade2232be02010-07-30 14:38:47 +05305923 .err_handler = &qla4xxx_err_handler,
David Somayajuluafaf5a22006-09-19 10:28:00 -07005924};
5925
5926static int __init qla4xxx_module_init(void)
5927{
5928 int ret;
5929
5930 /* Allocate cache for SRBs. */
5931 srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0,
Paul Mundt20c2df82007-07-20 10:11:58 +09005932 SLAB_HWCACHE_ALIGN, NULL);
David Somayajuluafaf5a22006-09-19 10:28:00 -07005933 if (srb_cachep == NULL) {
5934 printk(KERN_ERR
5935 "%s: Unable to allocate SRB cache..."
5936 "Failing load!\n", DRIVER_NAME);
5937 ret = -ENOMEM;
5938 goto no_srp_cache;
5939 }
5940
5941 /* Derive version string. */
5942 strcpy(qla4xxx_version_str, QLA4XXX_DRIVER_VERSION);
Andrew Vasquez11010fe2006-10-06 09:54:59 -07005943 if (ql4xextended_error_logging)
David Somayajuluafaf5a22006-09-19 10:28:00 -07005944 strcat(qla4xxx_version_str, "-debug");
5945
5946 qla4xxx_scsi_transport =
5947 iscsi_register_transport(&qla4xxx_iscsi_transport);
5948 if (!qla4xxx_scsi_transport){
5949 ret = -ENODEV;
5950 goto release_srb_cache;
5951 }
5952
David Somayajuluafaf5a22006-09-19 10:28:00 -07005953 ret = pci_register_driver(&qla4xxx_pci_driver);
5954 if (ret)
5955 goto unregister_transport;
5956
5957 printk(KERN_INFO "QLogic iSCSI HBA Driver\n");
5958 return 0;
Doug Maxey5ae16db2006-10-05 23:50:07 -05005959
David Somayajuluafaf5a22006-09-19 10:28:00 -07005960unregister_transport:
5961 iscsi_unregister_transport(&qla4xxx_iscsi_transport);
5962release_srb_cache:
5963 kmem_cache_destroy(srb_cachep);
5964no_srp_cache:
5965 return ret;
5966}
5967
5968static void __exit qla4xxx_module_exit(void)
5969{
David Somayajuluafaf5a22006-09-19 10:28:00 -07005970 pci_unregister_driver(&qla4xxx_pci_driver);
5971 iscsi_unregister_transport(&qla4xxx_iscsi_transport);
5972 kmem_cache_destroy(srb_cachep);
5973}
5974
5975module_init(qla4xxx_module_init);
5976module_exit(qla4xxx_module_exit);
5977
5978MODULE_AUTHOR("QLogic Corporation");
5979MODULE_DESCRIPTION("QLogic iSCSI HBA Driver");
5980MODULE_LICENSE("GPL");
5981MODULE_VERSION(QLA4XXX_DRIVER_VERSION);