aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_init.c
diff options
context:
space:
mode:
authorVikas Chaudhary <vikas.chaudhary@qlogic.com>2010-04-28 02:07:07 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-05-02 15:38:19 -0400
commit2a49a78ed3c8d7c8319595270110c69f99c61a74 (patch)
tree14a771d774b25525aa1604e48004b6bc0415c104 /drivers/scsi/qla4xxx/ql4_init.c
parent3487d9e7c4727b3e587f61d2120e35e34f200faa (diff)
[SCSI] qla4xxx: added IPv6 support.
Signed-off-by: Karen Higgins <karen.higgins@qlogic.com> Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Signed-off-by: Ravi Anand <ravi.anand@qlogic.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_init.c')
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c218
1 files changed, 178 insertions, 40 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 92329a461c6..36ec02c49a1 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -189,6 +189,78 @@ static int qla4xxx_init_local_data(struct scsi_qla_host *ha)
189 return qla4xxx_get_firmware_status(ha); 189 return qla4xxx_get_firmware_status(ha);
190} 190}
191 191
192static uint8_t
193qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
194{
195 uint8_t ipv4_wait = 0;
196 uint8_t ipv6_wait = 0;
197 int8_t ip_address[IPv6_ADDR_LEN] = {0} ;
198
199 /* If both IPv4 & IPv6 are enabled, possibly only one
200 * IP address may be acquired, so check to see if we
201 * need to wait for another */
202 if (is_ipv4_enabled(ha) && is_ipv6_enabled(ha)) {
203 if (((ha->addl_fw_state & FW_ADDSTATE_DHCPv4_ENABLED) != 0) &&
204 ((ha->addl_fw_state &
205 FW_ADDSTATE_DHCPv4_LEASE_ACQUIRED) == 0)) {
206 ipv4_wait = 1;
207 }
208 if (((ha->ipv6_addl_options &
209 IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
210 ((ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING) ||
211 (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING) ||
212 (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING))) {
213
214 ipv6_wait = 1;
215
216 if ((ha->ipv6_link_local_state ==
217 IP_ADDRSTATE_PREFERRED) ||
218 (ha->ipv6_addr0_state == IP_ADDRSTATE_PREFERRED) ||
219 (ha->ipv6_addr1_state == IP_ADDRSTATE_PREFERRED)) {
220 DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
221 "Preferred IP configured."
222 " Don't wait!\n", ha->host_no,
223 __func__));
224 ipv6_wait = 0;
225 }
226 if (memcmp(&ha->ipv6_default_router_addr, ip_address,
227 IPv6_ADDR_LEN) == 0) {
228 DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
229 "No Router configured. "
230 "Don't wait!\n", ha->host_no,
231 __func__));
232 ipv6_wait = 0;
233 }
234 if ((ha->ipv6_default_router_state ==
235 IPV6_RTRSTATE_MANUAL) &&
236 (ha->ipv6_link_local_state ==
237 IP_ADDRSTATE_TENTATIVE) &&
238 (memcmp(&ha->ipv6_link_local_addr,
239 &ha->ipv6_default_router_addr, 4) == 0)) {
240 DEBUG2(printk("scsi%ld: %s: LinkLocal Router & "
241 "IP configured. Don't wait!\n",
242 ha->host_no, __func__));
243 ipv6_wait = 0;
244 }
245 }
246 if (ipv4_wait || ipv6_wait) {
247 DEBUG2(printk("scsi%ld: %s: Wait for additional "
248 "IP(s) \"", ha->host_no, __func__));
249 if (ipv4_wait)
250 DEBUG2(printk("IPv4 "));
251 if (ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING)
252 DEBUG2(printk("IPv6LinkLocal "));
253 if (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING)
254 DEBUG2(printk("IPv6Addr0 "));
255 if (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING)
256 DEBUG2(printk("IPv6Addr1 "));
257 DEBUG2(printk("\"\n"));
258 }
259 }
260
261 return ipv4_wait|ipv6_wait;
262}
263
192static int qla4xxx_fw_ready(struct scsi_qla_host *ha) 264static int qla4xxx_fw_ready(struct scsi_qla_host *ha)
193{ 265{
194 uint32_t timeout_count; 266 uint32_t timeout_count;
@@ -226,38 +298,80 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha)
226 continue; 298 continue;
227 } 299 }
228 300
301 if (ha->firmware_state & FW_STATE_WAIT_AUTOCONNECT) {
302 DEBUG2(printk(KERN_INFO "scsi%ld: %s: fwstate:"
303 "AUTOCONNECT in progress\n",
304 ha->host_no, __func__));
305 }
306
307 if (ha->firmware_state & FW_STATE_CONFIGURING_IP) {
308 DEBUG2(printk(KERN_INFO "scsi%ld: %s: fwstate:"
309 " CONFIGURING IP\n",
310 ha->host_no, __func__));
311 /*
312 * Check for link state after 15 secs and if link is
313 * still DOWN then, cable is unplugged. Ignore "DHCP
314 * in Progress/CONFIGURING IP" bit to check if firmware
315 * is in ready state or not after 15 secs.
316 * This is applicable for both 2.x & 3.x firmware
317 */
318 if (timeout_count <= (ADAPTER_INIT_TOV - 15)) {
319 if (ha->addl_fw_state & FW_ADDSTATE_LINK_UP) {
320 DEBUG2(printk(KERN_INFO "scsi%ld: %s:"
321 " LINK UP (Cable plugged)\n",
322 ha->host_no, __func__));
323 } else if (ha->firmware_state &
324 (FW_STATE_CONFIGURING_IP |
325 FW_STATE_READY)) {
326 DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
327 "LINK DOWN (Cable unplugged)\n",
328 ha->host_no, __func__));
329 ha->firmware_state = FW_STATE_READY;
330 }
331 }
332 }
333
229 if (ha->firmware_state == FW_STATE_READY) { 334 if (ha->firmware_state == FW_STATE_READY) {
230 DEBUG2(dev_info(&ha->pdev->dev, "Firmware Ready..\n")); 335 /* If DHCP IP Addr is available, retrieve it now. */
231 /* The firmware is ready to process SCSI commands. */ 336 if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR,
232 DEBUG2(dev_info(&ha->pdev->dev, 337 &ha->dpc_flags))
233 "scsi%ld: %s: MEDIA TYPE - %s\n", 338 qla4xxx_get_dhcp_ip_address(ha);
234 ha->host_no, 339
235 __func__, (ha->addl_fw_state & 340 if (!qla4xxx_wait_for_ip_config(ha) ||
236 FW_ADDSTATE_OPTICAL_MEDIA) 341 timeout_count == 1) {
237 != 0 ? "OPTICAL" : "COPPER")); 342 DEBUG2(dev_info(&ha->pdev->dev,
238 DEBUG2(dev_info(&ha->pdev->dev, 343 "Firmware Ready..\n"));
239 "scsi%ld: %s: DHCP STATE Enabled " 344 /* The firmware is ready to process SCSI
240 "%s\n", 345 commands. */
241 ha->host_no, __func__, 346 DEBUG2(dev_info(&ha->pdev->dev,
242 (ha->addl_fw_state & 347 "scsi%ld: %s: MEDIA TYPE"
243 FW_ADDSTATE_DHCP_ENABLED) != 0 ? 348 " - %s\n", ha->host_no,
244 "YES" : "NO")); 349 __func__, (ha->addl_fw_state &
245 DEBUG2(dev_info(&ha->pdev->dev, 350 FW_ADDSTATE_OPTICAL_MEDIA)
246 "scsi%ld: %s: LINK %s\n", 351 != 0 ? "OPTICAL" : "COPPER"));
247 ha->host_no, __func__, 352 DEBUG2(dev_info(&ha->pdev->dev,
248 (ha->addl_fw_state & 353 "scsi%ld: %s: DHCPv4 STATE"
249 FW_ADDSTATE_LINK_UP) != 0 ? 354 " Enabled %s\n", ha->host_no,
250 "UP" : "DOWN")); 355 __func__, (ha->addl_fw_state &
251 DEBUG2(dev_info(&ha->pdev->dev, 356 FW_ADDSTATE_DHCPv4_ENABLED) != 0 ?
252 "scsi%ld: %s: iSNS Service " 357 "YES" : "NO"));
253 "Started %s\n", 358 DEBUG2(dev_info(&ha->pdev->dev,
254 ha->host_no, __func__, 359 "scsi%ld: %s: LINK %s\n",
255 (ha->addl_fw_state & 360 ha->host_no, __func__,
256 FW_ADDSTATE_ISNS_SVC_ENABLED) != 0 ? 361 (ha->addl_fw_state &
257 "YES" : "NO")); 362 FW_ADDSTATE_LINK_UP) != 0 ?
258 363 "UP" : "DOWN"));
259 ready = 1; 364 DEBUG2(dev_info(&ha->pdev->dev,
260 break; 365 "scsi%ld: %s: iSNS Service "
366 "Started %s\n",
367 ha->host_no, __func__,
368 (ha->addl_fw_state &
369 FW_ADDSTATE_ISNS_SVC_ENABLED) != 0 ?
370 "YES" : "NO"));
371
372 ready = 1;
373 break;
374 }
261 } 375 }
262 DEBUG2(printk("scsi%ld: %s: waiting on fw, state=%x:%x - " 376 DEBUG2(printk("scsi%ld: %s: waiting on fw, state=%x:%x - "
263 "seconds expired= %d\n", ha->host_no, __func__, 377 "seconds expired= %d\n", ha->host_no, __func__,
@@ -272,15 +386,19 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha)
272 msleep(1000); 386 msleep(1000);
273 } /* end of for */ 387 } /* end of for */
274 388
275 if (timeout_count == 0) 389 if (timeout_count <= 0)
276 DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n", 390 DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n",
277 ha->host_no, __func__)); 391 ha->host_no, __func__));
278 392
279 if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS) { 393 if (ha->firmware_state & FW_STATE_CONFIGURING_IP) {
280 DEBUG2(printk("scsi%ld: %s: FW is reporting its waiting to" 394 DEBUG2(printk("scsi%ld: %s: FW initialized, but is reporting "
281 " grab an IP address from DHCP server\n", 395 "it's waiting to configure an IP address\n",
282 ha->host_no, __func__)); 396 ha->host_no, __func__));
283 ready = 1; 397 ready = 1;
398 } else if (ha->firmware_state & FW_STATE_WAIT_AUTOCONNECT) {
399 DEBUG2(printk("scsi%ld: %s: FW initialized, but "
400 "auto-discovery still in process\n",
401 ha->host_no, __func__));
284 } 402 }
285 403
286 return ready; 404 return ready;
@@ -419,6 +537,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
419 } 537 }
420 538
421 status = QLA_SUCCESS; 539 status = QLA_SUCCESS;
540 ddb_entry->options = le16_to_cpu(fw_ddb_entry->options);
422 ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid); 541 ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid);
423 ddb_entry->task_mgmt_timeout = 542 ddb_entry->task_mgmt_timeout =
424 le16_to_cpu(fw_ddb_entry->def_timeout); 543 le16_to_cpu(fw_ddb_entry->def_timeout);
@@ -442,11 +561,30 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
442 memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0], 561 memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0],
443 min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr))); 562 min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr)));
444 563
564 ddb_entry->iscsi_max_burst_len = fw_ddb_entry->iscsi_max_burst_len;
565 ddb_entry->iscsi_max_outsnd_r2t = fw_ddb_entry->iscsi_max_outsnd_r2t;
566 ddb_entry->iscsi_first_burst_len = fw_ddb_entry->iscsi_first_burst_len;
567 ddb_entry->iscsi_max_rcv_data_seg_len =
568 fw_ddb_entry->iscsi_max_rcv_data_seg_len;
569 ddb_entry->iscsi_max_snd_data_seg_len =
570 fw_ddb_entry->iscsi_max_snd_data_seg_len;
571
572 if (ddb_entry->options & DDB_OPT_IPV6_DEVICE) {
573 memcpy(&ddb_entry->remote_ipv6_addr,
574 fw_ddb_entry->ip_addr,
575 min(sizeof(ddb_entry->remote_ipv6_addr),
576 sizeof(fw_ddb_entry->ip_addr)));
577 memcpy(&ddb_entry->link_local_ipv6_addr,
578 fw_ddb_entry->link_local_ipv6_addr,
579 min(sizeof(ddb_entry->link_local_ipv6_addr),
580 sizeof(fw_ddb_entry->link_local_ipv6_addr)));
581 }
582
445 DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n", 583 DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n",
446 ha->host_no, __func__, fw_ddb_index, 584 ha->host_no, __func__, fw_ddb_index,
447 ddb_entry->fw_ddb_device_state, status)); 585 ddb_entry->fw_ddb_device_state, status));
448 586
449 exit_update_ddb: 587exit_update_ddb:
450 if (fw_ddb_entry) 588 if (fw_ddb_entry)
451 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 589 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
452 fw_ddb_entry, fw_ddb_entry_dma); 590 fw_ddb_entry, fw_ddb_entry_dma);
@@ -1166,7 +1304,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
1166 * the ddb_list and wait for DHCP lease acquired aen to come in 1304 * the ddb_list and wait for DHCP lease acquired aen to come in
1167 * followed by 0x8014 aen" to trigger the tgt discovery process. 1305 * followed by 0x8014 aen" to trigger the tgt discovery process.
1168 */ 1306 */
1169 if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS) 1307 if (ha->firmware_state & FW_STATE_CONFIGURING_IP)
1170 goto exit_init_online; 1308 goto exit_init_online;
1171 1309
1172 /* Skip device discovery if ip and subnet is zero */ 1310 /* Skip device discovery if ip and subnet is zero */