]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/qla2xxx/qla_init.c
Merge by hand (conflicts between pending drivers and kfree cleanups)
[linux-2.6-omap-h63xx.git] / drivers / scsi / qla2xxx / qla_init.c
index fbb6feee40cfeb1921ead1abd59a1a970b57a9a7..72d9090df3dff8e8863204183b938c854392ce38 100644 (file)
@@ -1,20 +1,8 @@
 /*
- *                  QLOGIC LINUX SOFTWARE
- *
- * QLogic ISP2x00 device driver for Linux 2.6.x
- * Copyright (C) 2003-2005 QLogic Corporation
- * (www.qlogic.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c)  2003-2005 QLogic Corporation
  *
+ * See LICENSE.qla2xxx for copyright and licensing details.
  */
 #include "qla_def.h"
 
@@ -1372,7 +1360,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
        nvram_t         *nv = (nvram_t *)ha->request_ring;
        uint8_t         *ptr = (uint8_t *)ha->request_ring;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
-       uint8_t         timer_mode;
 
        rval = QLA_SUCCESS;
 
@@ -1650,22 +1637,26 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
 
                ha->flags.process_response_queue = 1;
        } else {
-               /* Enable ZIO -- Support mode 5 only. */
-               timer_mode = icb->add_firmware_options[0] &
-                   (BIT_3 | BIT_2 | BIT_1 | BIT_0);
+               /* Enable ZIO. */
+               if (!ha->flags.init_done) {
+                       ha->zio_mode = icb->add_firmware_options[0] &
+                           (BIT_3 | BIT_2 | BIT_1 | BIT_0);
+                       ha->zio_timer = icb->interrupt_delay_timer ?
+                           icb->interrupt_delay_timer: 2;
+               }
                icb->add_firmware_options[0] &=
                    ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
-               if (ql2xenablezio)
-                       timer_mode = BIT_2 | BIT_0;
-               if (timer_mode == (BIT_2 | BIT_0)) {
-                       DEBUG2(printk("scsi(%ld): ZIO enabled; timer delay "
-                           "(%d).\n", ha->host_no, ql2xintrdelaytimer));
+               ha->flags.process_response_queue = 0;
+               if (ha->zio_mode != QLA_ZIO_DISABLED) {
+                       DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer "
+                           "delay (%d us).\n", ha->host_no, ha->zio_mode,
+                           ha->zio_timer * 100));
                        qla_printk(KERN_INFO, ha,
-                           "ZIO enabled; timer delay (%d).\n",
-                           ql2xintrdelaytimer);
+                           "ZIO mode %d enabled; timer delay (%d us).\n",
+                           ha->zio_mode, ha->zio_timer * 100);
 
-                       icb->add_firmware_options[0] |= timer_mode;
-                       icb->interrupt_delay_timer = ql2xintrdelaytimer;
+                       icb->add_firmware_options[0] |= (uint8_t)ha->zio_mode;
+                       icb->interrupt_delay_timer = (uint8_t)ha->zio_timer;
                        ha->flags.process_response_queue = 1;
                }
        }
@@ -1677,6 +1668,24 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
        return (rval);
 }
 
+static void
+qla2x00_rport_add(void *data)
+{
+       fc_port_t *fcport = data;
+
+       qla2x00_reg_remote_port(fcport->ha, fcport);
+}
+
+static void
+qla2x00_rport_del(void *data)
+{
+       fc_port_t *fcport = data;
+
+       if (fcport->rport)
+               fc_remote_port_delete(fcport->rport);
+       fcport->rport = NULL;
+}
+
 /**
  * qla2x00_alloc_fcport() - Allocate a generic fcport.
  * @ha: HA context
@@ -1702,6 +1711,8 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
        atomic_set(&fcport->state, FCS_UNCONFIGURED);
        fcport->flags = FCF_RLC_SUPPORT;
        fcport->supported_classes = FC_COS_UNSPECIFIED;
+       INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport);
+       INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport);
 
        return (fcport);
 }
@@ -1966,8 +1977,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
        }
 
 cleanup_allocation:
-       if (new_fcport)
-               kfree(new_fcport);
+       kfree(new_fcport);
 
        if (rval != QLA_SUCCESS) {
                DEBUG2(printk("scsi(%ld): Configure local loop error exit: "
@@ -2065,8 +2075,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
        struct fc_rport *rport;
 
        if (fcport->rport) {
-               fc_remote_port_unblock(fcport->rport);
-               return;
+               fc_remote_port_delete(fcport->rport);
+               fcport->rport = NULL;
        }
 
        rport_ids.node_name = wwn_to_u64(fcport->node_name);
@@ -2080,7 +2090,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
                    "Unable to allocate fc remote port!\n");
                return;
        }
-       rport->dd_data = fcport;
+       *((fc_port_t **)rport->dd_data) = fcport;
        rport->supported_classes = fcport->supported_classes;
 
        rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
@@ -2337,8 +2347,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
        /* Allocate temporary fcport for any new fcports discovered. */
        new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);
        if (new_fcport == NULL) {
-               if (swl)
-                       kfree(swl);
+               kfree(swl);
                return (QLA_MEMORY_ALLOC_FAILED);
        }
        new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
@@ -2474,19 +2483,15 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
                nxt_d_id.b24 = new_fcport->d_id.b24;
                new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);
                if (new_fcport == NULL) {
-                       if (swl)
-                               kfree(swl);
+                       kfree(swl);
                        return (QLA_MEMORY_ALLOC_FAILED);
                }
                new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
                new_fcport->d_id.b24 = nxt_d_id.b24;
        }
 
-       if (swl)
-               kfree(swl);
-
-       if (new_fcport)
-               kfree(new_fcport);
+       kfree(swl);
+       kfree(new_fcport);
 
        if (!list_empty(new_fcports))
                ha->device_flags |= DFLG_FABRIC_DEVICES;
@@ -2858,7 +2863,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
                            fcport->d_id.b.domain, fcport->d_id.b.area,
                            fcport->d_id.b.al_pa);
                        fcport->loop_id = FC_NO_LOOP_ID;
-                       atomic_set(&fcport->state, FCS_DEVICE_DEAD);
+                       fcport->login_retry = 0;
 
                        rval = 3;
                        break;
@@ -3442,6 +3447,30 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
        if (ql2xloginretrycount)
                ha->login_retry_count = ql2xloginretrycount;
 
+       /* Enable ZIO. */
+       if (!ha->flags.init_done) {
+               ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
+                   (BIT_3 | BIT_2 | BIT_1 | BIT_0);
+               ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
+                   le16_to_cpu(icb->interrupt_delay_timer): 2;
+       }
+       icb->firmware_options_2 &= __constant_cpu_to_le32(
+           ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
+       ha->flags.process_response_queue = 0;
+       if (ha->zio_mode != QLA_ZIO_DISABLED) {
+               DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
+                   "(%d us).\n", ha->host_no, ha->zio_mode,
+                   ha->zio_timer * 100));
+               qla_printk(KERN_INFO, ha,
+                   "ZIO mode %d enabled; timer delay (%d us).\n",
+                   ha->zio_mode, ha->zio_timer * 100);
+
+               icb->firmware_options_2 |= cpu_to_le32(
+                   (uint32_t)ha->zio_mode);
+               icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
+               ha->flags.process_response_queue = 1;
+       }
+
        if (rval) {
                DEBUG2_3(printk(KERN_WARNING
                    "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));