Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2011-10-10 15:36:42 +0200
committerHannes Reinecke <hare@suse.de>2011-10-10 15:36:42 +0200
commit8eb35dee8059a62a84e68ff41a3cde925edd2235 (patch)
tree0716ab90d2596c7f1fc8fbcb5221e1996959555d
parent7b0cfb32078832d8a41757d893e8022acfc88cdd (diff)
- patches.drivers/qla4xxx-Add-new-FLT-firmware-region.patch:rpm-3.0.6-0.7
qla4xxx: Add new FLT firmware region (bnc#723008). - patches.drivers/qla4xxx-Clear-DDB-map-index-on-the-basis-of-AEN.patch: qla4xxx: Clear DDB map index on the basis of AEN (bnc#723008). - patches.drivers/qla4xxx-Do-not-add-duplicate-CHAP-entry-in-FLASH.patch: qla4xxx: Do not add duplicate CHAP entry in FLASH (bnc#723008). - patches.drivers/qla4xxx-Fix-bidirectional-CHAP.patch: qla4xxx: Fix bidirectional CHAP (bnc#723008). - patches.drivers/qla4xxx-Fix-exporting-boot-targets-to-sysfs.patch: qla4xxx: Fix exporting boot targets to sysfs (bnc#723008). - patches.drivers/qla4xxx-Fix-getting-BIDI-CHAP-for-boot-targets.patch: qla4xxx: Fix getting BIDI CHAP for boot targets (bnc#723008). - patches.drivers/qla4xxx-Fixed-active-session-re-open-issue.patch: qla4xxx: Fixed active session re-open issue (bnc#723008). - patches.drivers/qla4xxx-Fixed-device-blocked-issue-on-link-up-down.patch: qla4xxx: Fixed device blocked issue on link up-down (bnc#723008). - patches.drivers/qla4xxx-Fixed-session-destroy-issue-on-link-up-down.patch: qla4xxx: Fixed session destroy issue on link up-down (bnc#723008). - patches.drivers/qla4xxx-Fixed-target-discovery-failed-issue.patch: qla4xxx: Fixed target discovery failed issue (bnc#723008). - patches.drivers/qla4xxx-Free-Device-Database-DDB-reserved-by-FW.patch: qla4xxx: Free Device Database (DDB) reserved by FW (bnc#723008). - patches.drivers/qla4xxx-Update-driver-version-to-5.02.00-k8.patch: qla4xxx: Update driver version to 5.02.00-k8 (bnc#723008). - patches.drivers/qla4xxx-Update-license.patch: qla4xxx: Update license (bnc#723008). - patches.drivers/qla4xxx-updated-device-id-check-for-BFS.patch: qla4xxx: updated device id check for BFS (bnc#723008). suse-commit: a38998ed2678584f93f624cab5bd9ec121dd146a
-rw-r--r--Documentation/scsi/00-INDEX2
-rw-r--r--Documentation/scsi/LICENSE.qla4xxx310
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h13
-rw-r--r--drivers/scsi/qla4xxx/ql4_fw.h6
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c70
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c140
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c8
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c207
-rw-r--r--drivers/scsi/qla4xxx/ql4_version.h2
10 files changed, 683 insertions, 77 deletions
diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX
index c2e18e109858..b48ded55b555 100644
--- a/Documentation/scsi/00-INDEX
+++ b/Documentation/scsi/00-INDEX
@@ -28,6 +28,8 @@ LICENSE.FlashPoint
- Licence of the Flashpoint driver
LICENSE.qla2xxx
- License for QLogic Linux Fibre Channel HBA Driver firmware.
+LICENSE.qla4xxx
+ - License for QLogic Linux iSCSI HBA Driver.
Mylex.txt
- info on driver for Mylex adapters
NinjaSCSI.txt
diff --git a/Documentation/scsi/LICENSE.qla4xxx b/Documentation/scsi/LICENSE.qla4xxx
new file mode 100644
index 000000000000..494980e40491
--- /dev/null
+++ b/Documentation/scsi/LICENSE.qla4xxx
@@ -0,0 +1,310 @@
+Copyright (c) 2003-2011 QLogic Corporation
+QLogic Linux iSCSI HBA Driver
+
+This program includes a device driver for Linux 3.x.
+You may modify and redistribute the device driver code under the
+GNU General Public License (a copy of which is attached hereto as
+Exhibit A) published by the Free Software Foundation (version 2).
+
+REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
+THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
+CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
+OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
+TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
+ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
+COMBINATION WITH THIS PROGRAM.
+
+
+EXHIBIT A
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index d2f7cd64d066..ace637bf254e 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -279,7 +279,8 @@ struct ql82xx_hw_data {
uint32_t flt_region_fw;
uint32_t flt_iscsi_param;
- uint32_t reserved;
+ uint32_t flt_region_chap;
+ uint32_t flt_chap_size;
};
struct qla4_8xxx_legacy_intr_set {
@@ -351,6 +352,8 @@ struct ipaddress_config {
#define QL4_CHAP_MAX_NAME_LEN 256
#define QL4_CHAP_MAX_SECRET_LEN 100
+#define LOCAL_CHAP 0
+#define BIDI_CHAP 1
struct ql4_chap_format {
u8 intr_chap_name[QL4_CHAP_MAX_NAME_LEN];
@@ -607,6 +610,8 @@ struct scsi_qla_host {
#define QLFLASH_READING 1
#define QLFLASH_WRITING 2
struct dma_pool *chap_dma_pool;
+ uint8_t *chap_list; /* CHAP table cache */
+ struct mutex chap_sem;
#define CHAP_DMA_BLOCK_SIZE 512
struct workqueue_struct *task_wq;
unsigned long ddb_idx_map[MAX_DDB_ENTRIES / BITS_PER_LONG];
@@ -626,6 +631,7 @@ struct ql4_task_data {
dma_addr_t data_dma;
void *req_buffer;
dma_addr_t req_dma;
+ uint32_t req_len;
void *resp_buffer;
dma_addr_t resp_dma;
uint32_t resp_len;
@@ -669,6 +675,11 @@ static inline int is_qla4032(struct scsi_qla_host *ha)
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032;
}
+static inline int is_qla40XX(struct scsi_qla_host *ha)
+{
+ return is_qla4032(ha) || is_qla4022(ha) || is_qla4010(ha);
+}
+
static inline int is_qla8022(struct scsi_qla_host *ha)
{
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022;
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 0e24c7ad7e1c..cbd5a20dbbd1 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -251,6 +251,8 @@ union external_hw_config_reg {
#define FA_BOOT_CODE_ADDR_82 0x20000
#define FA_RISC_CODE_ADDR_82 0x40000
#define FA_GOLD_RISC_CODE_ADDR_82 0x80000
+#define FA_FLASH_ISCSI_CHAP 0x540000
+#define FA_FLASH_CHAP_SIZE 0xC0000
/* Flash Description Table */
struct qla_fdt_layout {
@@ -306,9 +308,11 @@ struct qla_flt_header {
#define FLT_REG_FLT 0x1c
#define FLT_REG_BOOTLOAD_82 0x72
#define FLT_REG_FW_82 0x74
+#define FLT_REG_FW_82_1 0x97
#define FLT_REG_GOLD_FW_82 0x75
#define FLT_REG_BOOT_CODE_82 0x78
#define FLT_REG_ISCSI_PARAM 0x65
+#define FLT_REG_ISCSI_CHAP 0x63
struct qla_flt_region {
uint32_t code;
@@ -680,6 +684,8 @@ struct addr_ctrl_blk_def {
#define MAX_CHAP_ENTRIES_40XX 128
#define MAX_CHAP_ENTRIES_82XX 1024
+#define MAX_RESRV_CHAP_IDX 3
+#define FLASH_CHAP_OFFSET 0x06000000
struct ql4_chap_table {
uint16_t link;
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index b0bffe15c287..3075fbaef553 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -765,6 +765,44 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha)
}
return status;
}
+/**
+ * qla4xxx_free_ddb_index - Free DDBs reserved by firmware
+ * @ha: pointer to adapter structure
+ *
+ * Since firmware is not running in autoconnect mode the DDB indices should
+ * be freed so that when login happens from user space there are free DDB
+ * indices available.
+ **/
+static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
+{
+ int max_ddbs;
+ int ret;
+ uint32_t idx = 0, next_idx = 0;
+ uint32_t state = 0, conn_err = 0;
+
+ max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES :
+ MAX_DEV_DB_ENTRIES;
+
+ for (idx = 0; idx < max_ddbs; idx = next_idx) {
+ ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL,
+ &next_idx, &state, &conn_err,
+ NULL, NULL);
+ if (ret == QLA_ERROR)
+ continue;
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
+ state == DDB_DS_SESSION_FAILED) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Freeing DDB index = 0x%x\n", idx));
+ ret = qla4xxx_clear_ddb_entry(ha, idx);
+ if (ret == QLA_ERROR)
+ ql4_printk(KERN_ERR, ha,
+ "Unable to clear DDB index = "
+ "0x%x\n", idx);
+ }
+ if (next_idx == 0)
+ break;
+ }
+}
/**
@@ -802,6 +840,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha)
if (status == QLA_ERROR)
goto exit_init_hba;
+ qla4xxx_free_ddb_index(ha);
+
set_bit(AF_ONLINE, &ha->flags);
exit_init_hba:
if (is_qla8022(ha) && (status == QLA_ERROR)) {
@@ -840,6 +880,10 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
if (ddb_entry == NULL) {
ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
__func__, fw_ddb_index);
+
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE)
+ clear_bit(fw_ddb_index, ha->ddb_idx_map);
+
goto exit_ddb_event;
}
@@ -856,6 +900,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
switch (state) {
case DDB_DS_SESSION_ACTIVE:
case DDB_DS_DISCOVERY:
+ iscsi_conn_start(ddb_entry->conn);
iscsi_conn_login_event(ddb_entry->conn,
ISCSI_CONN_STATE_LOGGED_IN);
qla4xxx_update_session_conn_param(ha, ddb_entry);
@@ -870,7 +915,8 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
}
break;
case DDB_DS_SESSION_ACTIVE:
- if (state == DDB_DS_SESSION_FAILED) {
+ switch (state) {
+ case DDB_DS_SESSION_FAILED:
/*
* iscsi_session failure will cause userspace to
* stop the connection which in turn would block the
@@ -879,6 +925,28 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
iscsi_session_failure(ddb_entry->sess->dd_data,
ISCSI_ERR_CONN_FAILED);
status = QLA_SUCCESS;
+ break;
+ case DDB_DS_NO_CONNECTION_ACTIVE:
+ clear_bit(fw_ddb_index, ha->ddb_idx_map);
+ status = QLA_SUCCESS;
+ break;
+ }
+ break;
+ case DDB_DS_SESSION_FAILED:
+ switch (state) {
+ case DDB_DS_SESSION_ACTIVE:
+ case DDB_DS_DISCOVERY:
+ iscsi_conn_start(ddb_entry->conn);
+ iscsi_conn_login_event(ddb_entry->conn,
+ ISCSI_CONN_STATE_LOGGED_IN);
+ qla4xxx_update_session_conn_param(ha, ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ case DDB_DS_SESSION_FAILED:
+ iscsi_session_failure(ddb_entry->sess->dd_data,
+ ISCSI_ERR_CONN_FAILED);
+ status = QLA_SUCCESS;
+ break;
}
break;
default:
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index ad40a613bcf1..410669351906 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -407,7 +407,7 @@ int qla4xxx_send_passthru0(struct iscsi_task *task)
passthru_iocb->timeout = cpu_to_le16(PT_DEFAULT_TIMEOUT);
/* Setup the out & in DSDs */
- if (task->data_count) {
+ if (task_data->req_len) {
memcpy((uint8_t *)task_data->req_buffer +
sizeof(struct iscsi_hdr), task->data, task->data_count);
ctrl_flags |= PT_FLAG_SEND_BUFFER;
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index de733a777803..4c2b84870392 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -872,7 +872,6 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
uint32_t max_event_log_entries;
uint8_t i;
-
memset(&mbox_cmd, 0, sizeof(mbox_cmd));
memset(&mbox_sts, 0, sizeof(mbox_cmd));
@@ -1305,7 +1304,7 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
{
int ret = 0;
int rval = QLA_ERROR;
- uint32_t offset = 0;
+ uint32_t offset = 0, chap_size;
struct ql4_chap_table *chap_table;
dma_addr_t chap_dma;
@@ -1315,12 +1314,22 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
goto exit_get_chap;
}
- memset(chap_table, 0, sizeof(struct ql4_chap_table));
-
- offset = 0x06000000 | (idx * sizeof(struct ql4_chap_table));
+ chap_size = sizeof(struct ql4_chap_table);
+ memset(chap_table, 0, chap_size);
+
+ if (is_qla40XX(ha))
+ offset = FLASH_CHAP_OFFSET | (idx * chap_size);
+ else {
+ offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
+ /* flt_chap_size is CHAP table size for both ports
+ * so divide it by 2 to calculate the offset for second port
+ */
+ if (ha->port_num == 1)
+ offset += (ha->hw.flt_chap_size / 2);
+ offset += (idx * chap_size);
+ }
- rval = qla4xxx_get_flash(ha, chap_dma, offset,
- sizeof(struct ql4_chap_table));
+ rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
if (rval != QLA_SUCCESS) {
ret = -EINVAL;
goto exit_get_chap;
@@ -1367,10 +1376,16 @@ static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN);
strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN);
chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
- offset = 0x06000000 | (idx * sizeof(struct ql4_chap_table));
+ offset = FLASH_CHAP_OFFSET | (idx * sizeof(struct ql4_chap_table));
rval = qla4xxx_set_flash(ha, chap_dma, offset,
sizeof(struct ql4_chap_table),
FLASH_OPT_RMW_COMMIT);
+
+ if (rval == QLA_SUCCESS && ha->chap_list) {
+ /* Update ha chap_list cache */
+ memcpy((struct ql4_chap_table *)ha->chap_list + idx,
+ chap_table, sizeof(struct ql4_chap_table));
+ }
dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
if (rval != QLA_SUCCESS)
ret = -EINVAL;
@@ -1379,6 +1394,83 @@ exit_set_chap:
return ret;
}
+/**
+ * qla4xxx_get_chap_index - Get chap index given username and secret
+ * @ha: pointer to adapter structure
+ * @username: CHAP username to be searched
+ * @password: CHAP password to be searched
+ * @bidi: Is this a BIDI CHAP
+ * @chap_index: CHAP index to be returned
+ *
+ * Match the username and password in the chap_list, return the index if a
+ * match is found. If a match is not found then add the entry in FLASH and
+ * return the index at which entry is written in the FLASH.
+ **/
+static int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
+ char *password, int bidi, uint16_t *chap_index)
+{
+ int i, rval;
+ int free_index = -1;
+ int found_index = 0;
+ int max_chap_entries = 0;
+ struct ql4_chap_table *chap_table;
+
+ if (is_qla8022(ha))
+ max_chap_entries = (ha->hw.flt_chap_size / 2) /
+ sizeof(struct ql4_chap_table);
+ else
+ max_chap_entries = MAX_CHAP_ENTRIES_40XX;
+
+ if (!ha->chap_list) {
+ ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
+ return QLA_ERROR;
+ }
+
+ mutex_lock(&ha->chap_sem);
+ for (i = 0; i < max_chap_entries; i++) {
+ chap_table = (struct ql4_chap_table *)ha->chap_list + i;
+ if (chap_table->cookie !=
+ __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ if (i > MAX_RESRV_CHAP_IDX && free_index == -1)
+ free_index = i;
+ continue;
+ }
+ if (bidi) {
+ if (chap_table->flags & BIT_7)
+ continue;
+ } else {
+ if (chap_table->flags & BIT_6)
+ continue;
+ }
+ if (!strncmp(chap_table->secret, password,
+ MAX_CHAP_SECRET_LEN) &&
+ !strncmp(chap_table->name, username,
+ MAX_CHAP_NAME_LEN)) {
+ *chap_index = i;
+ found_index = 1;
+ break;
+ }
+ }
+
+ /* If chap entry is not present and a free index is available then
+ * write the entry in flash
+ */
+ if (!found_index && free_index != -1) {
+ rval = qla4xxx_set_chap(ha, username, password,
+ free_index, bidi);
+ if (!rval) {
+ *chap_index = free_index;
+ found_index = 1;
+ }
+ }
+
+ mutex_unlock(&ha->chap_sem);
+
+ if (found_index)
+ return QLA_SUCCESS;
+ return QLA_ERROR;
+}
+
int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
uint16_t fw_ddb_index,
uint16_t connection_id,
@@ -1491,7 +1583,6 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
uint16_t iscsi_opts = 0;
uint32_t options = 0;
uint16_t idx;
- int max_chap_entries = 0;
fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
&fw_ddb_entry_dma, GFP_KERNEL);
@@ -1560,25 +1651,14 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
goto exit_set_param;
}
- if (is_qla8022(ha))
- max_chap_entries = MAX_CHAP_ENTRIES_82XX;
- else
- max_chap_entries = MAX_CHAP_ENTRIES_40XX;
/* CHAP */
if (sess->username != NULL && sess->password != NULL) {
if (strlen(sess->username) && strlen(sess->password)) {
iscsi_opts |= BIT_7;
- idx = ddb_entry->fw_ddb_index * 2;
- if (idx > max_chap_entries) {
- ql4_printk(KERN_ERR, ha,
- "%s: Invalid ddb or chap index\n",
- __func__);
- rval = -EINVAL;
- goto exit_set_param;
- }
- rval = qla4xxx_set_chap(ha, sess->username,
- sess->password, idx, 0);
+ rval = qla4xxx_get_chap_index(ha, sess->username,
+ sess->password,
+ LOCAL_CHAP, &idx);
if (rval)
goto exit_set_param;
@@ -1590,16 +1670,10 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
/* Check if BIDI CHAP */
if (strlen(sess->username_in) && strlen(sess->password_in)) {
iscsi_opts |= BIT_4;
- idx = (ddb_entry->fw_ddb_index * 2) + 1;
- if (idx > max_chap_entries) {
- ql4_printk(KERN_ERR, ha,
- "%s: Invalid ddb or bidi chap "
- "index\n", __func__);
- rval = -EINVAL;
- goto exit_set_param;
- }
- rval = qla4xxx_set_chap(ha, sess->username_in,
- sess->password_in, idx, 0);
+
+ rval = qla4xxx_get_chap_index(ha, sess->username_in,
+ sess->password_in,
+ BIDI_CHAP, &idx);
if (rval)
goto exit_set_param;
}
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index a539e1761f65..f484ff438199 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -2015,6 +2015,7 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
hw->flt_region_boot = start;
break;
case FLT_REG_FW_82:
+ case FLT_REG_FW_82_1:
hw->flt_region_fw = start;
break;
case FLT_REG_BOOTLOAD_82:
@@ -2023,6 +2024,10 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
case FLT_REG_ISCSI_PARAM:
hw->flt_iscsi_param = start;
break;
+ case FLT_REG_ISCSI_CHAP:
+ hw->flt_region_chap = start;
+ hw->flt_chap_size = le32_to_cpu(region->size);
+ break;
}
}
goto done;
@@ -2035,6 +2040,9 @@ no_flash_data:
hw->flt_region_boot = FA_BOOT_CODE_ADDR_82;
hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82;
hw->flt_region_fw = FA_RISC_CODE_ADDR_82;
+ hw->flt_region_chap = FA_FLASH_ISCSI_CHAP;
+ hw->flt_chap_size = FA_FLASH_CHAP_SIZE;
+
done:
DEBUG2(ql4_printk(KERN_INFO, ha, "FLT[%s]: flt=0x%x fdt=0x%x "
"boot=0x%x bootload=0x%x fw=0x%x\n", loc, hw->flt_region_flt,
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 9f7ef0d55d1a..8fef0d92ebbc 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -997,6 +997,7 @@ qla4xxx_session_create(struct iscsi_endpoint *ep,
qla_ep = ep->dd_data;
dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
ha = to_qla_host(qla_ep->host);
+
get_ddb_index:
ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES);
@@ -1056,6 +1057,8 @@ static void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess)
ddb_entry = sess->dd_data;
ha = ddb_entry->ha;
+ qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
+
spin_lock_irqsave(&ha->hardware_lock, flags);
qla4xxx_free_ddb(ha, ddb_entry);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1132,8 +1135,12 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)
*/
if (mbx_sts)
if (ddb_entry->fw_ddb_device_state ==
- DDB_DS_SESSION_ACTIVE)
+ DDB_DS_SESSION_ACTIVE) {
+ iscsi_conn_start(ddb_entry->conn);
+ iscsi_conn_login_event(ddb_entry->conn,
+ ISCSI_CONN_STATE_LOGGED_IN);
goto exit_set_param;
+ }
ql4_printk(KERN_ERR, ha, "%s: Failed set param for index[%d]\n",
__func__, ddb_entry->fw_ddb_index);
@@ -1148,10 +1155,13 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)
goto exit_conn_start;
}
- ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
+ if (ddb_entry->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE)
+ ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
+
+ DEBUG2(printk(KERN_INFO "%s: DDB state [%d]\n", __func__,
+ ddb_entry->fw_ddb_device_state));
exit_set_param:
- iscsi_conn_start(cls_conn);
ret = 0;
exit_conn_start:
@@ -1176,14 +1186,6 @@ static void qla4xxx_conn_destroy(struct iscsi_cls_conn *cls_conn)
options = LOGOUT_OPTION_CLOSE_SESSION;
if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR)
ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__);
- else
- qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
-
- /*
- * Clear the DDB bit so that next login can use the bit
- * if FW is not clearing the DDB entry then set DDB will fail anyways
- */
- clear_bit(ddb_entry->fw_ddb_index, ha->ddb_idx_map);
}
static void qla4xxx_task_work(struct work_struct *wdata)
@@ -1263,7 +1265,7 @@ static int qla4xxx_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",
__func__, task->conn->max_recv_dlength, hdr_len));
- task_data->resp_len = task->conn->max_recv_dlength;
+ task_data->resp_len = task->conn->max_recv_dlength + hdr_len;
task_data->resp_buffer = dma_alloc_coherent(&ha->pdev->dev,
task_data->resp_len,
&task_data->resp_dma,
@@ -1271,8 +1273,9 @@ static int qla4xxx_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
if (!task_data->resp_buffer)
goto exit_alloc_pdu;
+ task_data->req_len = task->data_count + hdr_len;
task_data->req_buffer = dma_alloc_coherent(&ha->pdev->dev,
- task->data_count + hdr_len,
+ task_data->req_len,
&task_data->req_dma,
GFP_ATOMIC);
if (!task_data->req_buffer)
@@ -1290,7 +1293,7 @@ exit_alloc_pdu:
task_data->resp_buffer, task_data->resp_dma);
if (task_data->req_buffer)
- dma_free_coherent(&ha->pdev->dev, task->data_count + hdr_len,
+ dma_free_coherent(&ha->pdev->dev, task_data->req_len,
task_data->req_buffer, task_data->req_dma);
return -ENOMEM;
}
@@ -1319,7 +1322,7 @@ static void qla4xxx_task_cleanup(struct iscsi_task *task)
dma_free_coherent(&ha->pdev->dev, task_data->resp_len,
task_data->resp_buffer, task_data->resp_dma);
- dma_free_coherent(&ha->pdev->dev, task->data_count + hdr_len,
+ dma_free_coherent(&ha->pdev->dev, task_data->req_len,
task_data->req_buffer, task_data->req_dma);
return;
}
@@ -1598,6 +1601,10 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha)
if (ha->chap_dma_pool)
dma_pool_destroy(ha->chap_dma_pool);
+ if (ha->chap_list)
+ vfree(ha->chap_list);
+ ha->chap_list = NULL;
+
/* release io space registers */
if (is_qla8022(ha)) {
if (ha->nx_pcibase)
@@ -2768,12 +2775,10 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
func_num = PCI_FUNC(ha->pdev->devfn);
- DEBUG2(ql4_printk(KERN_INFO, ha,
- "%s: Get FW boot info for 0x%x func %d\n", __func__,
- (is_qla4032(ha) ? PCI_DEVICE_ID_QLOGIC_ISP4032 :
- PCI_DEVICE_ID_QLOGIC_ISP8022), func_num));
+ ql4_printk(KERN_INFO, ha, "%s: Get FW boot info for 0x%x func %d\n",
+ __func__, ha->pdev->device, func_num);
- if (is_qla4032(ha)) {
+ if (is_qla40XX(ha)) {
if (func_num == 1) {
addr = NVRAM_PORT0_BOOT_MODE;
pri_addr = NVRAM_PORT0_BOOT_PRI_TGT;
@@ -2801,15 +2806,11 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
val = rd_nvram_byte(ha, pri_addr);
if (val & BIT_7)
ddb_index[0] = (val & 0x7f);
- else
- ddb_index[0] = 0;
/* get secondary valid target index */
val = rd_nvram_byte(ha, sec_addr);
if (val & BIT_7)
ddb_index[1] = (val & 0x7f);
- else
- ddb_index[1] = 1;
} else if (is_qla8022(ha)) {
buf = dma_alloc_coherent(&ha->pdev->dev, size,
@@ -2851,15 +2852,10 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
/* get primary valid target index */
if (buf[2] & BIT_7)
ddb_index[0] = buf[2] & 0x7f;
- else
- ddb_index[0] = 0;
/* get secondary valid target index */
if (buf[11] & BIT_7)
ddb_index[1] = buf[11] & 0x7f;
- else
- ddb_index[1] = 1;
-
} else {
ret = QLA_ERROR;
goto exit_boot_info;
@@ -2875,6 +2871,60 @@ exit_boot_info:
return ret;
}
+/**
+ * qla4xxx_get_bidi_chap - Get a BIDI CHAP user and password
+ * @ha: pointer to adapter structure
+ * @username: CHAP username to be returned
+ * @password: CHAP password to be returned
+ *
+ * If a boot entry has BIDI CHAP enabled then we need to set the BIDI CHAP
+ * user and password in the sysfs entry in /sys/firmware/iscsi_boot#/.
+ * So from the CHAP cache find the first BIDI CHAP entry and set it
+ * to the boot record in sysfs.
+ **/
+static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username,
+ char *password)
+{
+ int i, ret = -EINVAL;
+ int max_chap_entries = 0;
+ struct ql4_chap_table *chap_table;
+
+ if (is_qla8022(ha))
+ max_chap_entries = (ha->hw.flt_chap_size / 2) /
+ sizeof(struct ql4_chap_table);
+ else
+ max_chap_entries = MAX_CHAP_ENTRIES_40XX;
+
+ if (!ha->chap_list) {
+ ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
+ return ret;
+ }
+
+ mutex_lock(&ha->chap_sem);
+ for (i = 0; i < max_chap_entries; i++) {
+ chap_table = (struct ql4_chap_table *)ha->chap_list + i;
+ if (chap_table->cookie !=
+ __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ continue;
+ }
+
+ if (chap_table->flags & BIT_7) /* local */
+ continue;
+
+ if (!(chap_table->flags & BIT_6)) /* Not BIDI */
+ continue;
+
+ strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+ strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+ ret = 0;
+ break;
+ }
+ mutex_unlock(&ha->chap_sem);
+
+ return ret;
+}
+
+
static int qla4xxx_get_boot_target(struct scsi_qla_host *ha,
struct ql4_boot_session_info *boot_sess,
uint16_t ddb_index)
@@ -2946,10 +2996,10 @@ static int qla4xxx_get_boot_target(struct scsi_qla_host *ha,
DEBUG2(ql4_printk(KERN_INFO, ha, "Setting BIDI chap\n"));
- ret = qla4xxx_get_chap(ha, (char *)&boot_conn->chap.
- intr_chap_name,
- (char *)&boot_conn->chap.intr_secret,
- (idx + 1));
+ ret = qla4xxx_get_bidi_chap(ha,
+ (char *)&boot_conn->chap.intr_chap_name,
+ (char *)&boot_conn->chap.intr_secret);
+
if (ret) {
ql4_printk(KERN_ERR, ha, "Failed to set BIDI chap\n");
ret = QLA_ERROR;
@@ -2969,9 +3019,12 @@ exit_boot_target:
static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
{
uint16_t ddb_index[2];
- int ret = QLA_SUCCESS;
+ int ret = QLA_ERROR;
+ int rval;
memset(ddb_index, 0, sizeof(ddb_index));
+ ddb_index[0] = 0xffff;
+ ddb_index[1] = 0xffff;
ret = get_fw_boot_info(ha, ddb_index);
if (ret != QLA_SUCCESS) {
DEBUG2(ql4_printk(KERN_ERR, ha,
@@ -2979,19 +3032,30 @@ static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
return ret;
}
- ret = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),
+ if (ddb_index[0] == 0xffff)
+ goto sec_target;
+
+ rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),
ddb_index[0]);
- if (ret != QLA_SUCCESS) {
+ if (rval != QLA_SUCCESS) {
DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
"primary target\n", __func__));
- }
+ } else
+ ret = QLA_SUCCESS;
+
+sec_target:
+ if (ddb_index[1] == 0xffff)
+ goto exit_get_boot_info;
- ret = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),
+ rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),
ddb_index[1]);
- if (ret != QLA_SUCCESS) {
+ if (rval != QLA_SUCCESS) {
DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
"secondary target\n", __func__));
- }
+ } else
+ ret = QLA_SUCCESS;
+
+exit_get_boot_info:
return ret;
}
@@ -3051,6 +3115,66 @@ kset_free:
return -ENOMEM;
}
+
+/**
+ * qla4xxx_create chap_list - Create CHAP list from FLASH
+ * @ha: pointer to adapter structure
+ *
+ * Read flash and make a list of CHAP entries, during login when a CHAP entry
+ * is received, it will be checked in this list. If entry exist then the CHAP
+ * entry index is set in the DDB. If CHAP entry does not exist in this list
+ * then a new entry is added in FLASH in CHAP table and the index obtained is
+ * used in the DDB.
+ **/
+static void qla4xxx_create_chap_list(struct scsi_qla_host *ha)
+{
+ int rval = 0;
+ uint8_t *chap_flash_data = NULL;
+ uint32_t offset;
+ dma_addr_t chap_dma;
+ uint32_t chap_size = 0;
+
+ if (is_qla40XX(ha))
+ chap_size = MAX_CHAP_ENTRIES_40XX *
+ sizeof(struct ql4_chap_table);
+ else /* Single region contains CHAP info for both
+ * ports which is divided into half for each port.
+ */
+ chap_size = ha->hw.flt_chap_size / 2;
+
+ chap_flash_data = dma_alloc_coherent(&ha->pdev->dev, chap_size,
+ &chap_dma, GFP_KERNEL);
+ if (!chap_flash_data) {
+ ql4_printk(KERN_ERR, ha, "No memory for chap_flash_data\n");
+ return;
+ }
+ if (is_qla40XX(ha))
+ offset = FLASH_CHAP_OFFSET;
+ else {
+ offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
+ if (ha->port_num == 1)
+ offset += chap_size;
+ }
+
+ rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
+ if (rval != QLA_SUCCESS)
+ goto exit_chap_list;
+
+ if (ha->chap_list == NULL)
+ ha->chap_list = vmalloc(chap_size);
+ if (ha->chap_list == NULL) {
+ ql4_printk(KERN_ERR, ha, "No memory for ha->chap_list\n");
+ goto exit_chap_list;
+ }
+
+ memcpy(ha->chap_list, chap_flash_data, chap_size);
+
+exit_chap_list:
+ dma_free_coherent(&ha->pdev->dev, chap_size,
+ chap_flash_data, chap_dma);
+ return;
+}
+
/**
* qla4xxx_probe_adapter - callback function to probe HBA
* @pdev: pointer to pci_dev structure
@@ -3128,6 +3252,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
INIT_LIST_HEAD(&ha->free_srb_q);
mutex_init(&ha->mbox_sem);
+ mutex_init(&ha->chap_sem);
init_completion(&ha->mbx_intr_comp);
init_completion(&ha->disable_acb_comp);
@@ -3259,6 +3384,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
ha->patch_number, ha->build_number);
+ qla4xxx_create_chap_list(ha);
+
if (qla4xxx_setup_boot_info(ha))
ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n",
__func__);
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 610492877253..c15347d3f532 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
* See LICENSE.qla4xxx for copyright and licensing details.
*/
-#define QLA4XXX_DRIVER_VERSION "5.02.00-k7"
+#define QLA4XXX_DRIVER_VERSION "5.02.00-k8"