Browse Source

Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (222 commits)
  [SCSI] zfcp: Remove flag ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP
  [SCSI] zfcp: Activate fc4s attributes for zfcp in FC transport class
  [SCSI] zfcp: Block scsi_eh thread for rport state BLOCKED
  [SCSI] zfcp: Update FSF error reporting
  [SCSI] zfcp: Improve ELS ADISC handling
  [SCSI] zfcp: Simplify handling of ct and els requests
  [SCSI] zfcp: Remove ZFCP_DID_MASK
  [SCSI] zfcp: Move WKA port to zfcp FC code
  [SCSI] zfcp: Use common code definitions for FC CT structs
  [SCSI] zfcp: Use common code definitions for FC ELS structs
  [SCSI] zfcp: Update FCP protocol related code
  [SCSI] zfcp: Dont fail SCSI commands when transitioning to blocked fc_rport
  [SCSI] zfcp: Assign scheduled work to driver queue
  [SCSI] zfcp: Remove STATUS_COMMON_REMOVE flag as it is not required anymore
  [SCSI] zfcp: Implement module unloading
  [SCSI] zfcp: Merge trace code for fsf requests in one function
  [SCSI] zfcp: Access ports and units with container_of in sysfs code
  [SCSI] zfcp: Remove suspend callback
  [SCSI] zfcp: Remove global config_mutex
  [SCSI] zfcp: Replace local reference counting with common kref
  ...
Linus Torvalds 15 years ago
parent
commit
382f51fe2f
100 changed files with 5144 additions and 2468 deletions
  1. 8 0
      Documentation/ABI/stable/sysfs-driver-qla2xxx
  2. 62 0
      Documentation/scsi/ChangeLog.megaraid_sas
  3. 15 0
      MAINTAINERS
  4. 6 1
      drivers/ata/libata-scsi.c
  5. 1 1
      drivers/ata/sata_nv.c
  6. 1 0
      drivers/infiniband/ulp/iser/iscsi_iser.c
  7. 4 4
      drivers/md/dm-mpath.c
  8. 2 2
      drivers/message/fusion/mptbase.h
  9. 1 4
      drivers/message/fusion/mptctl.c
  10. 88 7
      drivers/message/fusion/mptscsih.c
  11. 2 1
      drivers/message/fusion/mptscsih.h
  12. 193 195
      drivers/s390/scsi/zfcp_aux.c
  13. 82 97
      drivers/s390/scsi/zfcp_ccw.c
  14. 10 16
      drivers/s390/scsi/zfcp_cfdc.c
  15. 63 71
      drivers/s390/scsi/zfcp_dbf.c
  16. 4 6
      drivers/s390/scsi/zfcp_dbf.h
  17. 8 315
      drivers/s390/scsi/zfcp_def.h
  18. 74 64
      drivers/s390/scsi/zfcp_erp.c
  19. 21 17
      drivers/s390/scsi/zfcp_ext.h
  20. 288 388
      drivers/s390/scsi/zfcp_fc.c
  21. 260 0
      drivers/s390/scsi/zfcp_fc.h
  22. 135 232
      drivers/s390/scsi/zfcp_fsf.c
  23. 29 24
      drivers/s390/scsi/zfcp_fsf.h
  24. 78 78
      drivers/s390/scsi/zfcp_scsi.c
  25. 143 107
      drivers/s390/scsi/zfcp_sysfs.c
  26. 5 1
      drivers/scsi/3w-9xxx.c
  27. 1924 0
      drivers/scsi/3w-sas.c
  28. 396 0
      drivers/scsi/3w-sas.h
  29. 5 1
      drivers/scsi/3w-xxxx.c
  30. 5 2
      drivers/scsi/53c700.c
  31. 28 1
      drivers/scsi/Kconfig
  32. 3 0
      drivers/scsi/Makefile
  33. 5 1
      drivers/scsi/aacraid/linit.c
  34. 4 1
      drivers/scsi/arcmsr/arcmsr_hba.c
  35. 9 15
      drivers/scsi/be2iscsi/be.h
  36. 234 29
      drivers/scsi/be2iscsi/be_cmds.c
  37. 31 6
      drivers/scsi/be2iscsi/be_cmds.h
  38. 13 10
      drivers/scsi/be2iscsi/be_iscsi.c
  39. 473 171
      drivers/scsi/be2iscsi/be_main.c
  40. 28 21
      drivers/scsi/be2iscsi/be_main.h
  41. 52 17
      drivers/scsi/be2iscsi/be_mgmt.c
  42. 7 1
      drivers/scsi/be2iscsi/be_mgmt.h
  43. 5 5
      drivers/scsi/bfa/bfa_cb_ioim_macros.h
  44. 1 1
      drivers/scsi/bfa/bfa_cee.c
  45. 2 2
      drivers/scsi/bfa/bfa_csdebug.c
  46. 2 2
      drivers/scsi/bfa/bfa_fcpim.c
  47. 2 2
      drivers/scsi/bfa/bfa_fcpim_priv.h
  48. 28 31
      drivers/scsi/bfa/bfa_fcport.c
  49. 5 6
      drivers/scsi/bfa/bfa_fcs_lport.c
  50. 4 4
      drivers/scsi/bfa/bfa_fcxp.c
  51. 1 1
      drivers/scsi/bfa/bfa_intr.c
  52. 10 8
      drivers/scsi/bfa/bfa_intr_priv.h
  53. 5 5
      drivers/scsi/bfa/bfa_ioc.c
  54. 6 6
      drivers/scsi/bfa/bfa_ioc.h
  55. 4 4
      drivers/scsi/bfa/bfa_iocfc.c
  56. 4 4
      drivers/scsi/bfa/bfa_iocfc.h
  57. 2 2
      drivers/scsi/bfa/bfa_ioim.c
  58. 3 3
      drivers/scsi/bfa/bfa_itnim.c
  59. 2 2
      drivers/scsi/bfa/bfa_log.c
  60. 2 2
      drivers/scsi/bfa/bfa_port_priv.h
  61. 3 3
      drivers/scsi/bfa/bfa_rport.c
  62. 5 4
      drivers/scsi/bfa/bfa_tskim.c
  63. 1 1
      drivers/scsi/bfa/bfa_uf.c
  64. 3 3
      drivers/scsi/bfa/bfad.c
  65. 4 4
      drivers/scsi/bfa/bfad_fwimg.c
  66. 1 1
      drivers/scsi/bfa/bfad_im.c
  67. 1 1
      drivers/scsi/bfa/bfad_im_compat.h
  68. 1 2
      drivers/scsi/bfa/bfad_intr.c
  69. 9 9
      drivers/scsi/bfa/fabric.c
  70. 95 95
      drivers/scsi/bfa/fcbuild.c
  71. 3 3
      drivers/scsi/bfa/fcbuild.h
  72. 3 4
      drivers/scsi/bfa/fcpim.c
  73. 1 1
      drivers/scsi/bfa/fcs.h
  74. 4 4
      drivers/scsi/bfa/fdmi.c
  75. 1 1
      drivers/scsi/bfa/include/aen/bfa_aen.h
  76. 5 5
      drivers/scsi/bfa/include/bfa.h
  77. 4 4
      drivers/scsi/bfa/include/bfa_svc.h
  78. 6 6
      drivers/scsi/bfa/include/bfi/bfi.h
  79. 1 1
      drivers/scsi/bfa/include/bfi/bfi_ioc.h
  80. 2 2
      drivers/scsi/bfa/include/bfi/bfi_lps.h
  81. 4 4
      drivers/scsi/bfa/include/bfi/bfi_rport.h
  82. 3 3
      drivers/scsi/bfa/include/cs/bfa_checksum.h
  83. 3 3
      drivers/scsi/bfa/include/cs/bfa_sm.h
  84. 1 1
      drivers/scsi/bfa/include/cs/bfa_trc.h
  85. 1 1
      drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h
  86. 9 8
      drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h
  87. 5 5
      drivers/scsi/bfa/include/protocol/ct.h
  88. 11 11
      drivers/scsi/bfa/include/protocol/fc.h
  89. 12 221
      drivers/scsi/bfa/loop.c
  90. 7 8
      drivers/scsi/bfa/lport_api.c
  91. 2 3
      drivers/scsi/bfa/ns.c
  92. 1 1
      drivers/scsi/bfa/plog.c
  93. 13 15
      drivers/scsi/bfa/rport_ftrs.c
  94. 1 1
      drivers/scsi/bfa/vfapi.c
  95. 10 10
      drivers/scsi/bfa/vport.c
  96. 0 1
      drivers/scsi/bnx2i/bnx2i.h
  97. 2 8
      drivers/scsi/bnx2i/bnx2i_iscsi.c
  98. 1 0
      drivers/scsi/constants.c
  99. 1 1
      drivers/scsi/cxgb3i/cxgb3i_iscsi.c
  100. 16 12
      drivers/scsi/device_handler/scsi_dh.c

+ 8 - 0
Documentation/ABI/stable/sysfs-driver-qla2xxx

@@ -0,0 +1,8 @@
+What:		/sys/bus/pci/drivers/qla2xxx/.../devices/*
+Date:		September 2009
+Contact:	QLogic Linux Driver <linux-driver@qlogic.com>
+Description:	qla2xxx-udev.sh currently looks for uevent CHANGE events to
+		signal a firmware-dump has been generated by the driver and is
+		ready for retrieval.
+Users:		qla2xxx-udev.sh.  Proposed changes should be mailed to
+		linux-driver@qlogic.com

+ 62 - 0
Documentation/scsi/ChangeLog.megaraid_sas

@@ -1,3 +1,65 @@
+1 Release Date    : Tues.  July 28, 2009 10:12:45 PST 2009 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Bo Yang
+
+2 Current Version : 00.00.04.12
+3 Older Version   : 00.00.04.10
+
+1.	Change the AEN sys PD update from scsi_scan to
+	scsi_add_device and scsi_remove_device.
+2.	Takeoff the debug print-out in aen_polling routine.
+
+1 Release Date    : Thur.  July 02, 2009 10:12:45 PST 2009 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Bo Yang
+
+2 Current Version : 00.00.04.10
+3 Older Version   : 00.00.04.08
+
+1.	Add the 3 mins timeout during the controller initialize.
+2.	Add the fix for 64bit sense date errors.
+
+1 Release Date    : Tues. May 05, 2009 10:12:45 PST 2009 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Bo Yang
+
+2 Current Version : 00.00.04.08
+3 Older Version   : 00.00.04.06
+
+1.	Add the fix of pending in FW after deleted the logic drives.
+2.	Add the fix of deallocating memory after get pdlist.
+
+1 Release Date    : Tues. March 26, 2009 10:12:45 PST 2009 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Bo Yang
+
+2 Current Version : 00.00.04.06
+3 Older Version   : 00.00.04.04
+
+1.	Add the fix of the driver cmd empty fix of the driver cmd empty.
+2.	Add the fix of the driver MSM AEN CMD cause the system slow.
+
+1 Release Date    : Tues. March 03, 2009 10:12:45 PST 2009 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Bo Yang
+
+2 Current Version : 00.00.04.04
+3 Older Version   : 00.00.04.01
+
+1.	Add the Tape drive fix to the driver: If the command is for
+	the tape device, set the pthru timeout to the os layer timeout value.
+
+2.	Add Poll_wait mechanism to Gen-2 Linux driv.
+		In the aen handler, driver needs to wakeup poll handler similar to
+		the way it raises SIGIO.
+
+3.	Add new controller new SAS2 support to the driver.
+
+4.	Report the unconfigured PD (system PD) to OS.
+
+5.	Add the IEEE SGL support to the driver
+
+6.	Reasign the Application cmds to SAS2 controller
 
 1 Release Date    : Thur.July. 24 11:41:51 PST 2008 -
                        (emaild-id:megaraidlinux@lsi.com)

+ 15 - 0
MAINTAINERS

@@ -4196,6 +4196,13 @@ W:	http://www.pmc-sierra.com/
 S:	Supported
 F:	drivers/scsi/pmcraid.*
 
+PMC SIERRA PM8001 DRIVER
+M:	jack_wang@usish.com
+M:	lindar_liu@usish.com
+L:	linux-scsi@vger.kernel.org
+S:	Supported
+F:	drivers/scsi/pm8001/
+
 POSIX CLOCKS and TIMERS
 M:	Thomas Gleixner <tglx@linutronix.de>
 S:	Supported
@@ -5772,6 +5779,14 @@ L:	netdev@vger.kernel.org
 S:	Maintained
 F:	drivers/net/vmxnet3/
 
+VMware PVSCSI driver
+M:	Alok Kataria <akataria@vmware.com>
+M:	VMware PV-Drivers <pv-drivers@vmware.com>
+L:	linux-scsi@vger.kernel.org
+S:	Maintained
+F:	drivers/scsi/vmw_pvscsi.c
+F:	drivers/scsi/vmw_pvscsi.h
+
 VOLTAGE AND CURRENT REGULATOR FRAMEWORK
 M:	Liam Girdwood <lrg@slimlogic.co.uk>
 M:	Mark Brown <broonie@opensource.wolfsonmicro.com>

+ 6 - 1
drivers/ata/libata-scsi.c

@@ -1208,6 +1208,7 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
  *	ata_scsi_change_queue_depth - SCSI callback for queue depth config
  *	@sdev: SCSI device to configure queue depth for
  *	@queue_depth: new queue depth
+ *	@reason: calling context
  *
  *	This is libata standard hostt->change_queue_depth callback.
  *	SCSI will call into this callback when user tries to set queue
@@ -1219,12 +1220,16 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
  *	RETURNS:
  *	Newly configured queue depth.
  */
-int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				int reason)
 {
 	struct ata_port *ap = ata_shost_to_port(sdev->host);
 	struct ata_device *dev;
 	unsigned long flags;
 
+	if (reason != SCSI_QDEPTH_DEFAULT)
+		return -EOPNOTSUPP;
+
 	if (queue_depth < 1 || queue_depth == sdev->queue_depth)
 		return sdev->queue_depth;
 

+ 1 - 1
drivers/ata/sata_nv.c

@@ -1975,7 +1975,7 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)
 	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
 	if (strncmp(model_num, "Maxtor", 6) == 0) {
-		ata_scsi_change_queue_depth(sdev, 1);
+		ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT);
 		ata_dev_printk(dev, KERN_NOTICE,
 			"Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth);
 	}

+ 1 - 0
drivers/infiniband/ulp/iser/iscsi_iser.c

@@ -625,6 +625,7 @@ static struct iscsi_transport iscsi_iser_transport = {
 				  ISCSI_USERNAME | ISCSI_PASSWORD |
 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
 				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
 				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
 	.host_param_mask	= ISCSI_HOST_HWADDRESS |

+ 4 - 4
drivers/md/dm-mpath.c

@@ -1116,8 +1116,9 @@ static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath)
 	return limit_reached;
 }
 
-static void pg_init_done(struct dm_path *path, int errors)
+static void pg_init_done(void *data, int errors)
 {
+	struct dm_path *path = data;
 	struct pgpath *pgpath = path_to_pgpath(path);
 	struct priority_group *pg = pgpath->pg;
 	struct multipath *m = pg->m;
@@ -1183,12 +1184,11 @@ static void pg_init_done(struct dm_path *path, int errors)
 
 static void activate_path(struct work_struct *work)
 {
-	int ret;
 	struct pgpath *pgpath =
 		container_of(work, struct pgpath, activate_path);
 
-	ret = scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev));
-	pg_init_done(&pgpath->path, ret);
+	scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev),
+				pg_init_done, &pgpath->path);
 }
 
 /*

+ 2 - 2
drivers/message/fusion/mptbase.h

@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2008 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.04.12"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.12"
+#define MPT_LINUX_VERSION_COMMON	"3.04.13"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.13"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \

+ 1 - 4
drivers/message/fusion/mptctl.c

@@ -621,11 +621,8 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	 */
 	iocnumX = khdr.iocnum & 0xFF;
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
-	    (iocp == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnumX);
+	    (iocp == NULL))
 		return -ENODEV;
-	}
 
 	if (!iocp->active) {
 		printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - Controller disabled.\n",

+ 88 - 7
drivers/message/fusion/mptscsih.c

@@ -792,11 +792,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			 *  precedence!
 			 */
 			sc->result = (DID_OK << 16) | scsi_status;
-			if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
-				/* Have already saved the status and sense data
+			if (!(scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
+
+				/*
+				 * For an Errata on LSI53C1030
+				 * When the length of request data
+				 * and transfer data are different
+				 * with result of command (READ or VERIFY),
+				 * DID_SOFT_ERROR is set.
 				 */
-				;
-			} else {
+				if (ioc->bus_type == SPI) {
+					if (pScsiReq->CDB[0] == READ_6  ||
+					    pScsiReq->CDB[0] == READ_10 ||
+					    pScsiReq->CDB[0] == READ_12 ||
+					    pScsiReq->CDB[0] == READ_16 ||
+					    pScsiReq->CDB[0] == VERIFY  ||
+					    pScsiReq->CDB[0] == VERIFY_16) {
+						if (scsi_bufflen(sc) !=
+							xfer_cnt) {
+							sc->result =
+							DID_SOFT_ERROR << 16;
+						    printk(KERN_WARNING "Errata"
+						    "on LSI53C1030 occurred."
+						    "sc->req_bufflen=0x%02x,"
+						    "xfer_cnt=0x%02x\n",
+						    scsi_bufflen(sc),
+						    xfer_cnt);
+						}
+					}
+				}
+
 				if (xfer_cnt < sc->underflow) {
 					if (scsi_status == SAM_STAT_BUSY)
 						sc->result = SAM_STAT_BUSY;
@@ -835,7 +860,58 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			sc->result = (DID_OK << 16) | scsi_status;
 			if (scsi_state == 0) {
 				;
-			} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
+			} else if (scsi_state &
+			    MPI_SCSI_STATE_AUTOSENSE_VALID) {
+
+				/*
+				 * For potential trouble on LSI53C1030.
+				 * (date:2007.xx.)
+				 * It is checked whether the length of
+				 * request data is equal to
+				 * the length of transfer and residual.
+				 * MEDIUM_ERROR is set by incorrect data.
+				 */
+				if ((ioc->bus_type == SPI) &&
+					(sc->sense_buffer[2] & 0x20)) {
+					u32	 difftransfer;
+					difftransfer =
+					sc->sense_buffer[3] << 24 |
+					sc->sense_buffer[4] << 16 |
+					sc->sense_buffer[5] << 8 |
+					sc->sense_buffer[6];
+					if (((sc->sense_buffer[3] & 0x80) ==
+						0x80) && (scsi_bufflen(sc)
+						!= xfer_cnt)) {
+						sc->sense_buffer[2] =
+						    MEDIUM_ERROR;
+						sc->sense_buffer[12] = 0xff;
+						sc->sense_buffer[13] = 0xff;
+						printk(KERN_WARNING"Errata"
+						"on LSI53C1030 occurred."
+						"sc->req_bufflen=0x%02x,"
+						"xfer_cnt=0x%02x\n" ,
+						scsi_bufflen(sc),
+						xfer_cnt);
+					}
+					if (((sc->sense_buffer[3] & 0x80)
+						!= 0x80) &&
+						(scsi_bufflen(sc) !=
+						xfer_cnt + difftransfer)) {
+						sc->sense_buffer[2] =
+							MEDIUM_ERROR;
+						sc->sense_buffer[12] = 0xff;
+						sc->sense_buffer[13] = 0xff;
+						printk(KERN_WARNING
+						"Errata on LSI53C1030 occurred"
+						"sc->req_bufflen=0x%02x,"
+						" xfer_cnt=0x%02x,"
+						"difftransfer=0x%02x\n",
+						scsi_bufflen(sc),
+						xfer_cnt,
+						difftransfer);
+					}
+				}
+
 				/*
 				 * If running against circa 200003dd 909 MPT f/w,
 				 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
@@ -2275,11 +2351,12 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
  *	mptscsih_change_queue_depth - This function will set a devices queue depth
  *	@sdev: per scsi_device pointer
  *	@qdepth: requested queue depth
+ *	@reason: calling context
  *
  *	Adding support for new 'change_queue_depth' api.
 */
 int
-mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
 {
 	MPT_SCSI_HOST		*hd = shost_priv(sdev->host);
 	VirtTarget 		*vtarget;
@@ -2291,6 +2368,9 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
 
+	if (reason != SCSI_QDEPTH_DEFAULT)
+		return -EOPNOTSUPP;
+
 	if (ioc->bus_type == SPI) {
 		if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
 			max_depth = 1;
@@ -2357,7 +2437,8 @@ mptscsih_slave_configure(struct scsi_device *sdev)
 		    ioc->name, vtarget->negoFlags, vtarget->maxOffset,
 		    vtarget->minSyncFactor));
 
-	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
+	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH,
+				    SCSI_QDEPTH_DEFAULT);
 	dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 		"tagged %d, simple %d, ordered %d\n",
 		ioc->name,sdev->tagged_supported, sdev->simple_tags,

+ 2 - 1
drivers/message/fusion/mptscsih.h

@@ -128,7 +128,8 @@ extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_F
 extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
-extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
+extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth,
+				       int reason);
 extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
 extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
 extern struct device_attribute *mptscsih_host_attrs[];

+ 193 - 195
drivers/s390/scsi/zfcp_aux.c

@@ -31,6 +31,7 @@
 #include <linux/miscdevice.h>
 #include <linux/seq_file.h>
 #include "zfcp_ext.h"
+#include "zfcp_fc.h"
 
 #define ZFCP_BUS_ID_SIZE	20
 
@@ -80,48 +81,40 @@ int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
 
 static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
 {
-	struct ccw_device *ccwdev;
+	struct ccw_device *cdev;
 	struct zfcp_adapter *adapter;
 	struct zfcp_port *port;
 	struct zfcp_unit *unit;
 
-	ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
-	if (!ccwdev)
+	cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
+	if (!cdev)
 		return;
 
-	if (ccw_device_set_online(ccwdev))
-		goto out_ccwdev;
+	if (ccw_device_set_online(cdev))
+		goto out_ccw_device;
 
-	mutex_lock(&zfcp_data.config_mutex);
-	adapter = dev_get_drvdata(&ccwdev->dev);
+	adapter = zfcp_ccw_adapter_by_cdev(cdev);
 	if (!adapter)
-		goto out_unlock;
-	zfcp_adapter_get(adapter);
+		goto out_ccw_device;
 
 	port = zfcp_get_port_by_wwpn(adapter, wwpn);
 	if (!port)
 		goto out_port;
 
-	zfcp_port_get(port);
 	unit = zfcp_unit_enqueue(port, lun);
 	if (IS_ERR(unit))
 		goto out_unit;
-	mutex_unlock(&zfcp_data.config_mutex);
 
 	zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
 	zfcp_erp_wait(adapter);
 	flush_work(&unit->scsi_work);
 
-	mutex_lock(&zfcp_data.config_mutex);
-	zfcp_unit_put(unit);
 out_unit:
-	zfcp_port_put(port);
+	put_device(&port->sysfs_device);
 out_port:
-	zfcp_adapter_put(adapter);
-out_unlock:
-	mutex_unlock(&zfcp_data.config_mutex);
-out_ccwdev:
-	put_device(&ccwdev->dev);
+	zfcp_ccw_adapter_put(adapter);
+out_ccw_device:
+	put_device(&cdev->dev);
 	return;
 }
 
@@ -167,7 +160,7 @@ static int __init zfcp_module_init(void)
 	int retval = -ENOMEM;
 
 	zfcp_data.gpn_ft_cache = zfcp_cache_hw_align("zfcp_gpn",
-					sizeof(struct ct_iu_gpn_ft_req));
+					sizeof(struct zfcp_fc_gpn_ft_req));
 	if (!zfcp_data.gpn_ft_cache)
 		goto out;
 
@@ -182,12 +175,14 @@ static int __init zfcp_module_init(void)
 		goto out_sr_cache;
 
 	zfcp_data.gid_pn_cache = zfcp_cache_hw_align("zfcp_gid",
-					sizeof(struct zfcp_gid_pn_data));
+					sizeof(struct zfcp_fc_gid_pn));
 	if (!zfcp_data.gid_pn_cache)
 		goto out_gid_cache;
 
-	mutex_init(&zfcp_data.config_mutex);
-	rwlock_init(&zfcp_data.config_lock);
+	zfcp_data.adisc_cache = zfcp_cache_hw_align("zfcp_adisc",
+					sizeof(struct zfcp_fc_els_adisc));
+	if (!zfcp_data.adisc_cache)
+		goto out_adisc_cache;
 
 	zfcp_data.scsi_transport_template =
 		fc_attach_transport(&zfcp_transport_functions);
@@ -200,7 +195,7 @@ static int __init zfcp_module_init(void)
 		goto out_misc;
 	}
 
-	retval = zfcp_ccw_register();
+	retval = ccw_driver_register(&zfcp_ccw_driver);
 	if (retval) {
 		pr_err("The zfcp device driver could not register with "
 		       "the common I/O layer\n");
@@ -216,6 +211,8 @@ out_ccw_register:
 out_misc:
 	fc_release_transport(zfcp_data.scsi_transport_template);
 out_transport:
+	kmem_cache_destroy(zfcp_data.adisc_cache);
+out_adisc_cache:
 	kmem_cache_destroy(zfcp_data.gid_pn_cache);
 out_gid_cache:
 	kmem_cache_destroy(zfcp_data.sr_buffer_cache);
@@ -229,6 +226,20 @@ out:
 
 module_init(zfcp_module_init);
 
+static void __exit zfcp_module_exit(void)
+{
+	ccw_driver_unregister(&zfcp_ccw_driver);
+	misc_deregister(&zfcp_cfdc_misc);
+	fc_release_transport(zfcp_data.scsi_transport_template);
+	kmem_cache_destroy(zfcp_data.adisc_cache);
+	kmem_cache_destroy(zfcp_data.gid_pn_cache);
+	kmem_cache_destroy(zfcp_data.sr_buffer_cache);
+	kmem_cache_destroy(zfcp_data.qtcb_cache);
+	kmem_cache_destroy(zfcp_data.gpn_ft_cache);
+}
+
+module_exit(zfcp_module_exit);
+
 /**
  * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN
  * @port: pointer to port to search for unit
@@ -238,12 +249,18 @@ module_init(zfcp_module_init);
  */
 struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
 {
+	unsigned long flags;
 	struct zfcp_unit *unit;
 
-	list_for_each_entry(unit, &port->unit_list_head, list)
-		if ((unit->fcp_lun == fcp_lun) &&
-		    !(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_REMOVE))
-		    return unit;
+	read_lock_irqsave(&port->unit_list_lock, flags);
+	list_for_each_entry(unit, &port->unit_list, list)
+		if (unit->fcp_lun == fcp_lun) {
+			if (!get_device(&unit->sysfs_device))
+				unit = NULL;
+			read_unlock_irqrestore(&port->unit_list_lock, flags);
+			return unit;
+		}
+	read_unlock_irqrestore(&port->unit_list_lock, flags);
 	return NULL;
 }
 
@@ -257,18 +274,35 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
 struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
 					u64 wwpn)
 {
+	unsigned long flags;
 	struct zfcp_port *port;
 
-	list_for_each_entry(port, &adapter->port_list_head, list)
-		if ((port->wwpn == wwpn) &&
-		    !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE))
+	read_lock_irqsave(&adapter->port_list_lock, flags);
+	list_for_each_entry(port, &adapter->port_list, list)
+		if (port->wwpn == wwpn) {
+			if (!get_device(&port->sysfs_device))
+				port = NULL;
+			read_unlock_irqrestore(&adapter->port_list_lock, flags);
 			return port;
+		}
+	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 	return NULL;
 }
 
-static void zfcp_sysfs_unit_release(struct device *dev)
+/**
+ * zfcp_unit_release - dequeue unit
+ * @dev: pointer to device
+ *
+ * waits until all work is done on unit and removes it then from the unit->list
+ * of the associated port.
+ */
+static void zfcp_unit_release(struct device *dev)
 {
-	kfree(container_of(dev, struct zfcp_unit, sysfs_device));
+	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit,
+					      sysfs_device);
+
+	put_device(&unit->port->sysfs_device);
+	kfree(unit);
 }
 
 /**
@@ -276,43 +310,40 @@ static void zfcp_sysfs_unit_release(struct device *dev)
  * @port: pointer to port where unit is added
  * @fcp_lun: FCP LUN of unit to be enqueued
  * Returns: pointer to enqueued unit on success, ERR_PTR on error
- * Locks: config_mutex must be held to serialize changes to the unit list
  *
  * Sets up some unit internal structures and creates sysfs entry.
  */
 struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
 {
 	struct zfcp_unit *unit;
+	int retval = -ENOMEM;
 
-	read_lock_irq(&zfcp_data.config_lock);
-	if (zfcp_get_unit_by_lun(port, fcp_lun)) {
-		read_unlock_irq(&zfcp_data.config_lock);
-		return ERR_PTR(-EINVAL);
+	get_device(&port->sysfs_device);
+
+	unit = zfcp_get_unit_by_lun(port, fcp_lun);
+	if (unit) {
+		put_device(&unit->sysfs_device);
+		retval = -EEXIST;
+		goto err_out;
 	}
-	read_unlock_irq(&zfcp_data.config_lock);
 
 	unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
 	if (!unit)
-		return ERR_PTR(-ENOMEM);
-
-	atomic_set(&unit->refcount, 0);
-	init_waitqueue_head(&unit->remove_wq);
-	INIT_WORK(&unit->scsi_work, zfcp_scsi_scan);
+		goto err_out;
 
 	unit->port = port;
 	unit->fcp_lun = fcp_lun;
+	unit->sysfs_device.parent = &port->sysfs_device;
+	unit->sysfs_device.release = zfcp_unit_release;
 
 	if (dev_set_name(&unit->sysfs_device, "0x%016llx",
 			 (unsigned long long) fcp_lun)) {
 		kfree(unit);
-		return ERR_PTR(-ENOMEM);
+		goto err_out;
 	}
-	unit->sysfs_device.parent = &port->sysfs_device;
-	unit->sysfs_device.release = zfcp_sysfs_unit_release;
-	dev_set_drvdata(&unit->sysfs_device, unit);
+	retval = -EINVAL;
 
-	/* mark unit unusable as long as sysfs registration is not complete */
-	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
+	INIT_WORK(&unit->scsi_work, zfcp_scsi_scan);
 
 	spin_lock_init(&unit->latencies.lock);
 	unit->latencies.write.channel.min = 0xFFFFFFFF;
@@ -324,50 +355,30 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
 
 	if (device_register(&unit->sysfs_device)) {
 		put_device(&unit->sysfs_device);
-		return ERR_PTR(-EINVAL);
+		goto err_out;
 	}
 
 	if (sysfs_create_group(&unit->sysfs_device.kobj,
-			       &zfcp_sysfs_unit_attrs)) {
-		device_unregister(&unit->sysfs_device);
-		return ERR_PTR(-EINVAL);
-	}
+			       &zfcp_sysfs_unit_attrs))
+		goto err_out_put;
 
-	zfcp_unit_get(unit);
+	write_lock_irq(&port->unit_list_lock);
+	list_add_tail(&unit->list, &port->unit_list);
+	write_unlock_irq(&port->unit_list_lock);
 
-	write_lock_irq(&zfcp_data.config_lock);
-	list_add_tail(&unit->list, &port->unit_list_head);
-	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
 	atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
 
-	write_unlock_irq(&zfcp_data.config_lock);
-
-	zfcp_port_get(port);
-
 	return unit;
-}
 
-/**
- * zfcp_unit_dequeue - dequeue unit
- * @unit: pointer to zfcp_unit
- *
- * waits until all work is done on unit and removes it then from the unit->list
- * of the associated port.
- */
-void zfcp_unit_dequeue(struct zfcp_unit *unit)
-{
-	wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0);
-	write_lock_irq(&zfcp_data.config_lock);
-	list_del(&unit->list);
-	write_unlock_irq(&zfcp_data.config_lock);
-	zfcp_port_put(unit->port);
-	sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs);
+err_out_put:
 	device_unregister(&unit->sysfs_device);
+err_out:
+	put_device(&port->sysfs_device);
+	return ERR_PTR(retval);
 }
 
 static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
 {
-	/* must only be called with zfcp_data.config_mutex taken */
 	adapter->pool.erp_req =
 		mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
 	if (!adapter->pool.erp_req)
@@ -405,9 +416,9 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
 	if (!adapter->pool.status_read_data)
 		return -ENOMEM;
 
-	adapter->pool.gid_pn_data =
+	adapter->pool.gid_pn =
 		mempool_create_slab_pool(1, zfcp_data.gid_pn_cache);
-	if (!adapter->pool.gid_pn_data)
+	if (!adapter->pool.gid_pn)
 		return -ENOMEM;
 
 	return 0;
@@ -415,7 +426,6 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
 
 static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
 {
-	/* zfcp_data.config_mutex must be held */
 	if (adapter->pool.erp_req)
 		mempool_destroy(adapter->pool.erp_req);
 	if (adapter->pool.scsi_req)
@@ -428,8 +438,8 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
 		mempool_destroy(adapter->pool.status_read_req);
 	if (adapter->pool.status_read_data)
 		mempool_destroy(adapter->pool.status_read_data);
-	if (adapter->pool.gid_pn_data)
-		mempool_destroy(adapter->pool.gid_pn_data);
+	if (adapter->pool.gid_pn)
+		mempool_destroy(adapter->pool.gid_pn);
 }
 
 /**
@@ -497,53 +507,56 @@ static void zfcp_destroy_adapter_work_queue(struct zfcp_adapter *adapter)
  * zfcp_adapter_enqueue - enqueue a new adapter to the list
  * @ccw_device: pointer to the struct cc_device
  *
- * Returns:	0             if a new adapter was successfully enqueued
- *		-ENOMEM       if alloc failed
+ * Returns:	struct zfcp_adapter*
  * Enqueues an adapter at the end of the adapter list in the driver data.
  * All adapter internal structures are set up.
  * Proc-fs entries are also created.
- * locks: config_mutex must be held to serialize changes to the adapter list
  */
-int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
+struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 {
 	struct zfcp_adapter *adapter;
 
-	/*
-	 * Note: It is safe to release the list_lock, as any list changes
-	 * are protected by the config_mutex, which must be held to get here
-	 */
+	if (!get_device(&ccw_device->dev))
+		return ERR_PTR(-ENODEV);
 
 	adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL);
-	if (!adapter)
-		return -ENOMEM;
+	if (!adapter) {
+		put_device(&ccw_device->dev);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	kref_init(&adapter->ref);
 
 	ccw_device->handler = NULL;
 	adapter->ccw_device = ccw_device;
-	atomic_set(&adapter->refcount, 0);
+
+	INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
+	INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
 
 	if (zfcp_qdio_setup(adapter))
-		goto qdio_failed;
+		goto failed;
 
 	if (zfcp_allocate_low_mem_buffers(adapter))
-		goto low_mem_buffers_failed;
+		goto failed;
 
 	if (zfcp_reqlist_alloc(adapter))
-		goto low_mem_buffers_failed;
+		goto failed;
 
 	if (zfcp_dbf_adapter_register(adapter))
-		goto debug_register_failed;
+		goto failed;
 
 	if (zfcp_setup_adapter_work_queue(adapter))
-		goto work_queue_failed;
+		goto failed;
 
 	if (zfcp_fc_gs_setup(adapter))
-		goto generic_services_failed;
+		goto failed;
+
+	rwlock_init(&adapter->port_list_lock);
+	INIT_LIST_HEAD(&adapter->port_list);
 
-	init_waitqueue_head(&adapter->remove_wq);
 	init_waitqueue_head(&adapter->erp_ready_wq);
 	init_waitqueue_head(&adapter->erp_done_wqh);
 
-	INIT_LIST_HEAD(&adapter->port_list_head);
 	INIT_LIST_HEAD(&adapter->erp_ready_head);
 	INIT_LIST_HEAD(&adapter->erp_running_head);
 
@@ -553,83 +566,85 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 	rwlock_init(&adapter->abort_lock);
 
 	if (zfcp_erp_thread_setup(adapter))
-		goto erp_thread_failed;
-
-	INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
-	INIT_WORK(&adapter->scan_work, _zfcp_fc_scan_ports_later);
+		goto failed;
 
 	adapter->service_level.seq_print = zfcp_print_sl;
 
-	/* mark adapter unusable as long as sysfs registration is not complete */
-	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
-
 	dev_set_drvdata(&ccw_device->dev, adapter);
 
 	if (sysfs_create_group(&ccw_device->dev.kobj,
 			       &zfcp_sysfs_adapter_attrs))
-		goto sysfs_failed;
-
-	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
+		goto failed;
 
 	if (!zfcp_adapter_scsi_register(adapter))
-		return 0;
+		return adapter;
 
-sysfs_failed:
-	zfcp_erp_thread_kill(adapter);
-erp_thread_failed:
-	zfcp_fc_gs_destroy(adapter);
-generic_services_failed:
+failed:
+	zfcp_adapter_unregister(adapter);
+	return ERR_PTR(-ENOMEM);
+}
+
+void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
+{
+	struct ccw_device *cdev = adapter->ccw_device;
+
+	cancel_work_sync(&adapter->scan_work);
+	cancel_work_sync(&adapter->stat_work);
 	zfcp_destroy_adapter_work_queue(adapter);
-work_queue_failed:
+
+	zfcp_fc_wka_ports_force_offline(adapter->gs);
+	zfcp_adapter_scsi_unregister(adapter);
+	sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs);
+
+	zfcp_erp_thread_kill(adapter);
 	zfcp_dbf_adapter_unregister(adapter->dbf);
-debug_register_failed:
-	dev_set_drvdata(&ccw_device->dev, NULL);
-	kfree(adapter->req_list);
-low_mem_buffers_failed:
-	zfcp_free_low_mem_buffers(adapter);
-qdio_failed:
 	zfcp_qdio_destroy(adapter->qdio);
-	kfree(adapter);
-	return -ENOMEM;
+
+	zfcp_ccw_adapter_put(adapter); /* final put to release */
 }
 
 /**
- * zfcp_adapter_dequeue - remove the adapter from the resource list
- * @adapter: pointer to struct zfcp_adapter which should be removed
+ * zfcp_adapter_release - remove the adapter from the resource list
+ * @ref: pointer to struct kref
  * locks:	adapter list write lock is assumed to be held by caller
  */
-void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
+void zfcp_adapter_release(struct kref *ref)
 {
-	int retval = 0;
-	unsigned long flags;
+	struct zfcp_adapter *adapter = container_of(ref, struct zfcp_adapter,
+						    ref);
+	struct ccw_device *cdev = adapter->ccw_device;
 
-	cancel_work_sync(&adapter->stat_work);
-	zfcp_fc_wka_ports_force_offline(adapter->gs);
-	sysfs_remove_group(&adapter->ccw_device->dev.kobj,
-			   &zfcp_sysfs_adapter_attrs);
 	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
-	/* sanity check: no pending FSF requests */
-	spin_lock_irqsave(&adapter->req_list_lock, flags);
-	retval = zfcp_reqlist_isempty(adapter);
-	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
-	if (!retval)
-		return;
-
 	zfcp_fc_gs_destroy(adapter);
-	zfcp_erp_thread_kill(adapter);
-	zfcp_destroy_adapter_work_queue(adapter);
-	zfcp_dbf_adapter_unregister(adapter->dbf);
 	zfcp_free_low_mem_buffers(adapter);
-	zfcp_qdio_destroy(adapter->qdio);
 	kfree(adapter->req_list);
 	kfree(adapter->fc_stats);
 	kfree(adapter->stats_reset_data);
 	kfree(adapter);
+	put_device(&cdev->dev);
 }
 
-static void zfcp_sysfs_port_release(struct device *dev)
+/**
+ * zfcp_device_unregister - remove port, unit from system
+ * @dev: reference to device which is to be removed
+ * @grp: related reference to attribute group
+ *
+ * Helper function to unregister port, unit from system
+ */
+void zfcp_device_unregister(struct device *dev,
+			    const struct attribute_group *grp)
 {
-	kfree(container_of(dev, struct zfcp_port, sysfs_device));
+	sysfs_remove_group(&dev->kobj, grp);
+	device_unregister(dev);
+}
+
+static void zfcp_port_release(struct device *dev)
+{
+	struct zfcp_port *port = container_of(dev, struct zfcp_port,
+					      sysfs_device);
+
+	zfcp_ccw_adapter_put(port->adapter);
+	kfree(port);
 }
 
 /**
@@ -639,7 +654,6 @@ static void zfcp_sysfs_port_release(struct device *dev)
  * @status: initial status for the port
  * @d_id: destination id of the remote port to be enqueued
  * Returns: pointer to enqueued port on success, ERR_PTR on error
- * Locks: config_mutex must be held to serialize changes to the port list
  *
  * All port internal structures are set up and the sysfs entry is generated.
  * d_id is used to enqueue ports with a well known address like the Directory
@@ -649,20 +663,24 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
 				     u32 status, u32 d_id)
 {
 	struct zfcp_port *port;
+	int retval = -ENOMEM;
 
-	read_lock_irq(&zfcp_data.config_lock);
-	if (zfcp_get_port_by_wwpn(adapter, wwpn)) {
-		read_unlock_irq(&zfcp_data.config_lock);
-		return ERR_PTR(-EINVAL);
+	kref_get(&adapter->ref);
+
+	port = zfcp_get_port_by_wwpn(adapter, wwpn);
+	if (port) {
+		put_device(&port->sysfs_device);
+		retval = -EEXIST;
+		goto err_out;
 	}
-	read_unlock_irq(&zfcp_data.config_lock);
 
 	port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
 	if (!port)
-		return ERR_PTR(-ENOMEM);
+		goto err_out;
+
+	rwlock_init(&port->unit_list_lock);
+	INIT_LIST_HEAD(&port->unit_list);
 
-	init_waitqueue_head(&port->remove_wq);
-	INIT_LIST_HEAD(&port->unit_list_head);
 	INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
 	INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
 	INIT_WORK(&port->rport_work, zfcp_scsi_rport_work);
@@ -671,58 +689,38 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
 	port->d_id = d_id;
 	port->wwpn = wwpn;
 	port->rport_task = RPORT_NONE;
-
-	/* mark port unusable as long as sysfs registration is not complete */
-	atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
-	atomic_set(&port->refcount, 0);
+	port->sysfs_device.parent = &adapter->ccw_device->dev;
+	port->sysfs_device.release = zfcp_port_release;
 
 	if (dev_set_name(&port->sysfs_device, "0x%016llx",
 			 (unsigned long long)wwpn)) {
 		kfree(port);
-		return ERR_PTR(-ENOMEM);
+		goto err_out;
 	}
-	port->sysfs_device.parent = &adapter->ccw_device->dev;
-	port->sysfs_device.release = zfcp_sysfs_port_release;
-	dev_set_drvdata(&port->sysfs_device, port);
+	retval = -EINVAL;
 
 	if (device_register(&port->sysfs_device)) {
 		put_device(&port->sysfs_device);
-		return ERR_PTR(-EINVAL);
+		goto err_out;
 	}
 
 	if (sysfs_create_group(&port->sysfs_device.kobj,
-			       &zfcp_sysfs_port_attrs)) {
-		device_unregister(&port->sysfs_device);
-		return ERR_PTR(-EINVAL);
-	}
+			       &zfcp_sysfs_port_attrs))
+		goto err_out_put;
 
-	zfcp_port_get(port);
+	write_lock_irq(&adapter->port_list_lock);
+	list_add_tail(&port->list, &adapter->port_list);
+	write_unlock_irq(&adapter->port_list_lock);
 
-	write_lock_irq(&zfcp_data.config_lock);
-	list_add_tail(&port->list, &adapter->port_list_head);
-	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
-	atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
+	atomic_set_mask(status | ZFCP_STATUS_COMMON_RUNNING, &port->status);
 
-	write_unlock_irq(&zfcp_data.config_lock);
-
-	zfcp_adapter_get(adapter);
 	return port;
-}
 
-/**
- * zfcp_port_dequeue - dequeues a port from the port list of the adapter
- * @port: pointer to struct zfcp_port which should be removed
- */
-void zfcp_port_dequeue(struct zfcp_port *port)
-{
-	write_lock_irq(&zfcp_data.config_lock);
-	list_del(&port->list);
-	write_unlock_irq(&zfcp_data.config_lock);
-	wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
-	cancel_work_sync(&port->rport_work); /* usually not necessary */
-	zfcp_adapter_put(port->adapter);
-	sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
+err_out_put:
 	device_unregister(&port->sysfs_device);
+err_out:
+	zfcp_ccw_adapter_put(adapter);
+	return ERR_PTR(retval);
 }
 
 /**

+ 82 - 97
drivers/s390/scsi/zfcp_ccw.c

@@ -13,28 +13,34 @@
 
 #define ZFCP_MODEL_PRIV 0x4
 
-static int zfcp_ccw_suspend(struct ccw_device *cdev)
+static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock);
 
+struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *cdev)
 {
-	struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
-
-	if (!adapter)
-		return 0;
-
-	mutex_lock(&zfcp_data.config_mutex);
+	struct zfcp_adapter *adapter;
+	unsigned long flags;
 
-	zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL);
-	zfcp_erp_wait(adapter);
+	spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);
+	adapter = dev_get_drvdata(&cdev->dev);
+	if (adapter)
+		kref_get(&adapter->ref);
+	spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
+	return adapter;
+}
 
-	mutex_unlock(&zfcp_data.config_mutex);
+void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
+{
+	unsigned long flags;
 
-	return 0;
+	spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);
+	kref_put(&adapter->ref, zfcp_adapter_release);
+	spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
 }
 
 static int zfcp_ccw_activate(struct ccw_device *cdev)
 
 {
-	struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
 
 	if (!adapter)
 		return 0;
@@ -46,6 +52,8 @@ static int zfcp_ccw_activate(struct ccw_device *cdev)
 	zfcp_erp_wait(adapter);
 	flush_work(&adapter->scan_work);
 
+	zfcp_ccw_adapter_put(adapter);
+
 	return 0;
 }
 
@@ -67,28 +75,28 @@ int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter)
 
 /**
  * zfcp_ccw_probe - probe function of zfcp driver
- * @ccw_device: pointer to belonging ccw device
+ * @cdev: pointer to belonging ccw device
  *
  * This function gets called by the common i/o layer for each FCP
  * device found on the current system. This is only a stub to make cio
  * work: To only allocate adapter resources for devices actually used,
  * the allocation is deferred to the first call to ccw_set_online.
  */
-static int zfcp_ccw_probe(struct ccw_device *ccw_device)
+static int zfcp_ccw_probe(struct ccw_device *cdev)
 {
 	return 0;
 }
 
 /**
  * zfcp_ccw_remove - remove function of zfcp driver
- * @ccw_device: pointer to belonging ccw device
+ * @cdev: pointer to belonging ccw device
  *
  * This function gets called by the common i/o layer and removes an adapter
  * from the system. Task of this function is to get rid of all units and
  * ports that belong to this adapter. And in addition all resources of this
  * adapter will be freed too.
  */
-static void zfcp_ccw_remove(struct ccw_device *ccw_device)
+static void zfcp_ccw_remove(struct ccw_device *cdev)
 {
 	struct zfcp_adapter *adapter;
 	struct zfcp_port *port, *p;
@@ -96,49 +104,37 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
 	LIST_HEAD(unit_remove_lh);
 	LIST_HEAD(port_remove_lh);
 
-	ccw_device_set_offline(ccw_device);
+	ccw_device_set_offline(cdev);
 
-	mutex_lock(&zfcp_data.config_mutex);
-	adapter = dev_get_drvdata(&ccw_device->dev);
+	adapter = zfcp_ccw_adapter_by_cdev(cdev);
 	if (!adapter)
-		goto out;
-	mutex_unlock(&zfcp_data.config_mutex);
+		return;
 
-	cancel_work_sync(&adapter->scan_work);
-
-	mutex_lock(&zfcp_data.config_mutex);
-
-	/* this also removes the scsi devices, so call it first */
-	zfcp_adapter_scsi_unregister(adapter);
-
-	write_lock_irq(&zfcp_data.config_lock);
-	list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
-		list_for_each_entry_safe(unit, u, &port->unit_list_head, list) {
+	write_lock_irq(&adapter->port_list_lock);
+	list_for_each_entry_safe(port, p, &adapter->port_list, list) {
+		write_lock(&port->unit_list_lock);
+		list_for_each_entry_safe(unit, u, &port->unit_list, list)
 			list_move(&unit->list, &unit_remove_lh);
-			atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
-					&unit->status);
-		}
+		write_unlock(&port->unit_list_lock);
 		list_move(&port->list, &port_remove_lh);
-		atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
 	}
-	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
-	write_unlock_irq(&zfcp_data.config_lock);
+	write_unlock_irq(&adapter->port_list_lock);
+	zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */
 
-	list_for_each_entry_safe(port, p, &port_remove_lh, list) {
-		list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
-			zfcp_unit_dequeue(unit);
-		zfcp_port_dequeue(port);
-	}
-	wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
-	zfcp_adapter_dequeue(adapter);
+	list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
+		zfcp_device_unregister(&unit->sysfs_device,
+				       &zfcp_sysfs_unit_attrs);
 
-out:
-	mutex_unlock(&zfcp_data.config_mutex);
+	list_for_each_entry_safe(port, p, &port_remove_lh, list)
+		zfcp_device_unregister(&port->sysfs_device,
+				       &zfcp_sysfs_port_attrs);
+
+	zfcp_adapter_unregister(adapter);
 }
 
 /**
  * zfcp_ccw_set_online - set_online function of zfcp driver
- * @ccw_device: pointer to belonging ccw device
+ * @cdev: pointer to belonging ccw device
  *
  * This function gets called by the common i/o layer and sets an
  * adapter into state online.  The first call will allocate all
@@ -149,23 +145,20 @@ out:
  * the SCSI stack, that the QDIO queues will be set up and that the
  * adapter will be opened.
  */
-static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
+static int zfcp_ccw_set_online(struct ccw_device *cdev)
 {
-	struct zfcp_adapter *adapter;
-	int ret = 0;
-
-	mutex_lock(&zfcp_data.config_mutex);
-	adapter = dev_get_drvdata(&ccw_device->dev);
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
 
 	if (!adapter) {
-		ret = zfcp_adapter_enqueue(ccw_device);
-		if (ret) {
-			dev_err(&ccw_device->dev,
+		adapter = zfcp_adapter_enqueue(cdev);
+
+		if (IS_ERR(adapter)) {
+			dev_err(&cdev->dev,
 				"Setting up data structures for the "
 				"FCP adapter failed\n");
-			goto out;
+			return PTR_ERR(adapter);
 		}
-		adapter = dev_get_drvdata(&ccw_device->dev);
+		kref_get(&adapter->ref);
 	}
 
 	/* initialize request counter */
@@ -177,58 +170,61 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 				"ccsonl2", NULL);
 	zfcp_erp_wait(adapter);
-out:
-	mutex_unlock(&zfcp_data.config_mutex);
-	if (!ret)
-		flush_work(&adapter->scan_work);
-	return ret;
+
+	flush_work(&adapter->scan_work);
+
+	zfcp_ccw_adapter_put(adapter);
+	return 0;
 }
 
 /**
  * zfcp_ccw_set_offline - set_offline function of zfcp driver
- * @ccw_device: pointer to belonging ccw device
+ * @cdev: pointer to belonging ccw device
  *
  * This function gets called by the common i/o layer and sets an adapter
  * into state offline.
  */
-static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
+static int zfcp_ccw_set_offline(struct ccw_device *cdev)
 {
-	struct zfcp_adapter *adapter;
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
+
+	if (!adapter)
+		return 0;
 
-	mutex_lock(&zfcp_data.config_mutex);
-	adapter = dev_get_drvdata(&ccw_device->dev);
 	zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
 	zfcp_erp_wait(adapter);
-	mutex_unlock(&zfcp_data.config_mutex);
+
+	zfcp_ccw_adapter_put(adapter);
 	return 0;
 }
 
 /**
  * zfcp_ccw_notify - ccw notify function
- * @ccw_device: pointer to belonging ccw device
+ * @cdev: pointer to belonging ccw device
  * @event: indicates if adapter was detached or attached
  *
  * This function gets called by the common i/o layer if an adapter has gone
  * or reappeared.
  */
-static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
+static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
 {
-	struct zfcp_adapter *adapter = dev_get_drvdata(&ccw_device->dev);
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
+
+	if (!adapter)
+		return 1;
 
 	switch (event) {
 	case CIO_GONE:
-		dev_warn(&adapter->ccw_device->dev,
-			 "The FCP device has been detached\n");
+		dev_warn(&cdev->dev, "The FCP device has been detached\n");
 		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL);
 		break;
 	case CIO_NO_PATH:
-		dev_warn(&adapter->ccw_device->dev,
+		dev_warn(&cdev->dev,
 			 "The CHPID for the FCP device is offline\n");
 		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL);
 		break;
 	case CIO_OPER:
-		dev_info(&adapter->ccw_device->dev,
-			 "The FCP device is operational again\n");
+		dev_info(&cdev->dev, "The FCP device is operational again\n");
 		zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL,
 					       ZFCP_STATUS_COMMON_RUNNING,
 					       ZFCP_SET);
@@ -236,11 +232,13 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
 					"ccnoti4", NULL);
 		break;
 	case CIO_BOXED:
-		dev_warn(&adapter->ccw_device->dev, "The FCP device "
-			 "did not respond within the specified time\n");
+		dev_warn(&cdev->dev, "The FCP device did not respond within "
+				     "the specified time\n");
 		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL);
 		break;
 	}
+
+	zfcp_ccw_adapter_put(adapter);
 	return 1;
 }
 
@@ -250,18 +248,16 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
  */
 static void zfcp_ccw_shutdown(struct ccw_device *cdev)
 {
-	struct zfcp_adapter *adapter;
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
 
-	mutex_lock(&zfcp_data.config_mutex);
-	adapter = dev_get_drvdata(&cdev->dev);
 	if (!adapter)
-		goto out;
+		return;
 
 	zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
 	zfcp_erp_wait(adapter);
 	zfcp_erp_thread_kill(adapter);
-out:
-	mutex_unlock(&zfcp_data.config_mutex);
+
+	zfcp_ccw_adapter_put(adapter);
 }
 
 struct ccw_driver zfcp_ccw_driver = {
@@ -274,18 +270,7 @@ struct ccw_driver zfcp_ccw_driver = {
 	.set_offline = zfcp_ccw_set_offline,
 	.notify      = zfcp_ccw_notify,
 	.shutdown    = zfcp_ccw_shutdown,
-	.freeze      = zfcp_ccw_suspend,
+	.freeze      = zfcp_ccw_set_offline,
 	.thaw	     = zfcp_ccw_activate,
 	.restore     = zfcp_ccw_activate,
 };
-
-/**
- * zfcp_ccw_register - ccw register function
- *
- * Registers the driver at the common i/o layer. This function will be called
- * at module load time/system start.
- */
-int __init zfcp_ccw_register(void)
-{
-	return ccw_driver_register(&zfcp_ccw_driver);
-}

+ 10 - 16
drivers/s390/scsi/zfcp_cfdc.c

@@ -86,22 +86,17 @@ static int zfcp_cfdc_copy_to_user(void __user  *user_buffer,
 static struct zfcp_adapter *zfcp_cfdc_get_adapter(u32 devno)
 {
 	char busid[9];
-	struct ccw_device *ccwdev;
-	struct zfcp_adapter *adapter = NULL;
+	struct ccw_device *cdev;
+	struct zfcp_adapter *adapter;
 
 	snprintf(busid, sizeof(busid), "0.0.%04x", devno);
-	ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
-	if (!ccwdev)
-		goto out;
-
-	adapter = dev_get_drvdata(&ccwdev->dev);
-	if (!adapter)
-		goto out_put;
-
-	zfcp_adapter_get(adapter);
-out_put:
-	put_device(&ccwdev->dev);
-out:
+	cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
+	if (!cdev)
+		return NULL;
+
+	adapter = zfcp_ccw_adapter_by_cdev(cdev);
+
+	put_device(&cdev->dev);
 	return adapter;
 }
 
@@ -212,7 +207,6 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
 		retval = -ENXIO;
 		goto free_buffer;
 	}
-	zfcp_adapter_get(adapter);
 
 	retval = zfcp_cfdc_sg_setup(data->command, fsf_cfdc->sg,
 				    data_user->control_file);
@@ -245,7 +239,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
  free_sg:
 	zfcp_sg_free_table(fsf_cfdc->sg, ZFCP_CFDC_PAGES);
  adapter_put:
-	zfcp_adapter_put(adapter);
+	zfcp_ccw_adapter_put(adapter);
  free_buffer:
 	kfree(data);
  no_mem_sense:

+ 63 - 71
drivers/s390/scsi/zfcp_dbf.c

@@ -13,6 +13,7 @@
 #include <asm/debug.h>
 #include "zfcp_dbf.h"
 #include "zfcp_ext.h"
+#include "zfcp_fc.h"
 
 static u32 dbfsize = 4;
 
@@ -177,8 +178,7 @@ void _zfcp_dbf_hba_fsf_response(const char *tag2, int level,
 
 	case FSF_QTCB_SEND_ELS:
 		send_els = (struct zfcp_send_els *)fsf_req->data;
-		response->u.els.d_id = qtcb->bottom.support.d_id;
-		response->u.els.ls_code = send_els->ls_code >> 24;
+		response->u.els.d_id = ntoh24(qtcb->bottom.support.d_id);
 		break;
 
 	case FSF_QTCB_ABORT_FCP_CMND:
@@ -348,7 +348,6 @@ static void zfcp_dbf_hba_view_response(char **p,
 
 	case FSF_QTCB_SEND_ELS:
 		zfcp_dbf_out(p, "d_id", "0x%06x", r->u.els.d_id);
-		zfcp_dbf_out(p, "ls_code", "0x%02x", r->u.els.ls_code);
 		break;
 
 	case FSF_QTCB_ABORT_FCP_CMND:
@@ -677,14 +676,14 @@ void zfcp_dbf_rec_action(char *id2, struct zfcp_erp_action *erp_action)
 /**
  * zfcp_dbf_san_ct_request - trace event for issued CT request
  * @fsf_req: request containing issued CT data
+ * @d_id: destination id where ct request is sent to
  */
-void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req)
+void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req, u32 d_id)
 {
-	struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
-	struct zfcp_wka_port *wka_port = ct->wka_port;
-	struct zfcp_adapter *adapter = wka_port->adapter;
+	struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data;
+	struct zfcp_adapter *adapter = fsf_req->adapter;
 	struct zfcp_dbf *dbf = adapter->dbf;
-	struct ct_hdr *hdr = sg_virt(ct->req);
+	struct fc_ct_hdr *hdr = sg_virt(ct->req);
 	struct zfcp_dbf_san_record *r = &dbf->san_buf;
 	struct zfcp_dbf_san_record_ct_request *oct = &r->u.ct_req;
 	int level = 3;
@@ -695,19 +694,18 @@ void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req)
 	strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE);
 	r->fsf_reqid = fsf_req->req_id;
 	r->fsf_seqno = fsf_req->seq_no;
-	r->s_id = fc_host_port_id(adapter->scsi_host);
-	r->d_id = wka_port->d_id;
-	oct->cmd_req_code = hdr->cmd_rsp_code;
-	oct->revision = hdr->revision;
-	oct->gs_type = hdr->gs_type;
-	oct->gs_subtype = hdr->gs_subtype;
-	oct->options = hdr->options;
-	oct->max_res_size = hdr->max_res_size;
-	oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr),
+	oct->d_id = d_id;
+	oct->cmd_req_code = hdr->ct_cmd;
+	oct->revision = hdr->ct_rev;
+	oct->gs_type = hdr->ct_fs_type;
+	oct->gs_subtype = hdr->ct_fs_subtype;
+	oct->options = hdr->ct_options;
+	oct->max_res_size = hdr->ct_mr_size;
+	oct->len = min((int)ct->req->length - (int)sizeof(struct fc_ct_hdr),
 		       ZFCP_DBF_SAN_MAX_PAYLOAD);
 	debug_event(dbf->san, level, r, sizeof(*r));
 	zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level,
-			 (void *)hdr + sizeof(struct ct_hdr), oct->len);
+			 (void *)hdr + sizeof(struct fc_ct_hdr), oct->len);
 	spin_unlock_irqrestore(&dbf->san_lock, flags);
 }
 
@@ -717,10 +715,9 @@ void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req)
  */
 void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req)
 {
-	struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
-	struct zfcp_wka_port *wka_port = ct->wka_port;
-	struct zfcp_adapter *adapter = wka_port->adapter;
-	struct ct_hdr *hdr = sg_virt(ct->resp);
+	struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data;
+	struct zfcp_adapter *adapter = fsf_req->adapter;
+	struct fc_ct_hdr *hdr = sg_virt(ct->resp);
 	struct zfcp_dbf *dbf = adapter->dbf;
 	struct zfcp_dbf_san_record *r = &dbf->san_buf;
 	struct zfcp_dbf_san_record_ct_response *rct = &r->u.ct_resp;
@@ -732,25 +729,23 @@ void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req)
 	strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE);
 	r->fsf_reqid = fsf_req->req_id;
 	r->fsf_seqno = fsf_req->seq_no;
-	r->s_id = wka_port->d_id;
-	r->d_id = fc_host_port_id(adapter->scsi_host);
-	rct->cmd_rsp_code = hdr->cmd_rsp_code;
-	rct->revision = hdr->revision;
-	rct->reason_code = hdr->reason_code;
-	rct->expl = hdr->reason_code_expl;
-	rct->vendor_unique = hdr->vendor_unique;
-	rct->max_res_size = hdr->max_res_size;
-	rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
+	rct->cmd_rsp_code = hdr->ct_cmd;
+	rct->revision = hdr->ct_rev;
+	rct->reason_code = hdr->ct_reason;
+	rct->expl = hdr->ct_explan;
+	rct->vendor_unique = hdr->ct_vendor;
+	rct->max_res_size = hdr->ct_mr_size;
+	rct->len = min((int)ct->resp->length - (int)sizeof(struct fc_ct_hdr),
 		       ZFCP_DBF_SAN_MAX_PAYLOAD);
 	debug_event(dbf->san, level, r, sizeof(*r));
 	zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level,
-			 (void *)hdr + sizeof(struct ct_hdr), rct->len);
+			 (void *)hdr + sizeof(struct fc_ct_hdr), rct->len);
 	spin_unlock_irqrestore(&dbf->san_lock, flags);
 }
 
 static void zfcp_dbf_san_els(const char *tag, int level,
-			     struct zfcp_fsf_req *fsf_req, u32 s_id, u32 d_id,
-			     u8 ls_code, void *buffer, int buflen)
+			     struct zfcp_fsf_req *fsf_req, u32 d_id,
+			     void *buffer, int buflen)
 {
 	struct zfcp_adapter *adapter = fsf_req->adapter;
 	struct zfcp_dbf *dbf = adapter->dbf;
@@ -762,9 +757,7 @@ static void zfcp_dbf_san_els(const char *tag, int level,
 	strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
 	rec->fsf_reqid = fsf_req->req_id;
 	rec->fsf_seqno = fsf_req->seq_no;
-	rec->s_id = s_id;
-	rec->d_id = d_id;
-	rec->u.els.ls_code = ls_code;
+	rec->u.els.d_id = d_id;
 	debug_event(dbf->san, level, rec, sizeof(*rec));
 	zfcp_dbf_hexdump(dbf->san, rec, sizeof(*rec), level,
 			 buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD));
@@ -777,12 +770,11 @@ static void zfcp_dbf_san_els(const char *tag, int level,
  */
 void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req)
 {
-	struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+	struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data;
+	u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id);
 
-	zfcp_dbf_san_els("oels", 2, fsf_req,
-			       fc_host_port_id(els->adapter->scsi_host),
-			       els->d_id, *(u8 *) sg_virt(els->req),
-			       sg_virt(els->req), els->req->length);
+	zfcp_dbf_san_els("oels", 2, fsf_req, d_id,
+			 sg_virt(els->req), els->req->length);
 }
 
 /**
@@ -791,12 +783,11 @@ void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req)
  */
 void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req)
 {
-	struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+	struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data;
+	u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id);
 
-	zfcp_dbf_san_els("rels", 2, fsf_req, els->d_id,
-			       fc_host_port_id(els->adapter->scsi_host),
-			       *(u8 *)sg_virt(els->req), sg_virt(els->resp),
-			       els->resp->length);
+	zfcp_dbf_san_els("rels", 2, fsf_req, d_id,
+			       sg_virt(els->resp), els->resp->length);
 }
 
 /**
@@ -805,16 +796,13 @@ void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req)
  */
 void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *fsf_req)
 {
-	struct zfcp_adapter *adapter = fsf_req->adapter;
 	struct fsf_status_read_buffer *buf =
 			(struct fsf_status_read_buffer *)fsf_req->data;
 	int length = (int)buf->length -
 		     (int)((void *)&buf->payload - (void *)buf);
 
-	zfcp_dbf_san_els("iels", 1, fsf_req, buf->d_id,
-			       fc_host_port_id(adapter->scsi_host),
-			       buf->payload.data[0], (void *)buf->payload.data,
-			       length);
+	zfcp_dbf_san_els("iels", 1, fsf_req, ntoh24(buf->d_id),
+			       (void *)buf->payload.data, length);
 }
 
 static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view,
@@ -829,11 +817,10 @@ static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view,
 	zfcp_dbf_tag(&p, "tag", r->tag);
 	zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
 	zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
-	zfcp_dbf_out(&p, "s_id", "0x%06x", r->s_id);
-	zfcp_dbf_out(&p, "d_id", "0x%06x", r->d_id);
 
 	if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
 		struct zfcp_dbf_san_record_ct_request *ct = &r->u.ct_req;
+		zfcp_dbf_out(&p, "d_id", "0x%06x", ct->d_id);
 		zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code);
 		zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
 		zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type);
@@ -852,7 +839,7 @@ static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view,
 		   strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
 		   strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
 		struct zfcp_dbf_san_record_els *els = &r->u.els;
-		zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code);
+		zfcp_dbf_out(&p, "d_id", "0x%06x", els->d_id);
 	}
 	return p - out_buf;
 }
@@ -870,8 +857,9 @@ void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
 	struct zfcp_dbf_scsi_record *rec = &dbf->scsi_buf;
 	struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
 	unsigned long flags;
-	struct fcp_rsp_iu *fcp_rsp;
-	char *fcp_rsp_info = NULL, *fcp_sns_info = NULL;
+	struct fcp_resp_with_ext *fcp_rsp;
+	struct fcp_resp_rsp_info *fcp_rsp_info = NULL;
+	char *fcp_sns_info = NULL;
 	int offset = 0, buflen = 0;
 
 	spin_lock_irqsave(&dbf->scsi_lock, flags);
@@ -895,20 +883,22 @@ void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
 				rec->scsi_allowed = scsi_cmnd->allowed;
 			}
 			if (fsf_req != NULL) {
-				fcp_rsp = (struct fcp_rsp_iu *)
-				    &(fsf_req->qtcb->bottom.io.fcp_rsp);
-				fcp_rsp_info = (unsigned char *) &fcp_rsp[1];
-				fcp_sns_info =
-				    zfcp_get_fcp_sns_info_ptr(fcp_rsp);
-
-				rec->rsp_validity = fcp_rsp->validity.value;
-				rec->rsp_scsi_status = fcp_rsp->scsi_status;
-				rec->rsp_resid = fcp_rsp->fcp_resid;
-				if (fcp_rsp->validity.bits.fcp_rsp_len_valid)
-					rec->rsp_code = *(fcp_rsp_info + 3);
-				if (fcp_rsp->validity.bits.fcp_sns_len_valid) {
-					buflen = min((int)fcp_rsp->fcp_sns_len,
-						     ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
+				fcp_rsp = (struct fcp_resp_with_ext *)
+					&(fsf_req->qtcb->bottom.io.fcp_rsp);
+				fcp_rsp_info = (struct fcp_resp_rsp_info *)
+					&fcp_rsp[1];
+				fcp_sns_info = (char *) &fcp_rsp[1];
+				if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL)
+					fcp_sns_info += fcp_rsp->ext.fr_sns_len;
+
+				rec->rsp_validity = fcp_rsp->resp.fr_flags;
+				rec->rsp_scsi_status = fcp_rsp->resp.fr_status;
+				rec->rsp_resid = fcp_rsp->ext.fr_resid;
+				if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL)
+					rec->rsp_code = fcp_rsp_info->rsp_code;
+				if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) {
+					buflen = min(fcp_rsp->ext.fr_sns_len,
+					   (u32)ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
 					rec->sns_info_len = buflen;
 					memcpy(rec->sns_info, fcp_sns_info,
 					       min(buflen,
@@ -1067,6 +1057,8 @@ err_out:
  */
 void zfcp_dbf_adapter_unregister(struct zfcp_dbf *dbf)
 {
+	if (!dbf)
+		return;
 	debug_unregister(dbf->scsi);
 	debug_unregister(dbf->san);
 	debug_unregister(dbf->hba);

+ 4 - 6
drivers/s390/scsi/zfcp_dbf.h

@@ -22,6 +22,7 @@
 #ifndef ZFCP_DBF_H
 #define ZFCP_DBF_H
 
+#include <scsi/fc/fc_fcp.h>
 #include "zfcp_ext.h"
 #include "zfcp_fsf.h"
 #include "zfcp_def.h"
@@ -122,7 +123,6 @@ struct zfcp_dbf_hba_record_response {
 		} unit;
 		struct {
 			u32 d_id;
-			u8 ls_code;
 		} els;
 	} u;
 } __attribute__ ((packed));
@@ -166,6 +166,7 @@ struct zfcp_dbf_san_record_ct_request {
 	u8 options;
 	u16 max_res_size;
 	u32 len;
+	u32 d_id;
 } __attribute__ ((packed));
 
 struct zfcp_dbf_san_record_ct_response {
@@ -179,16 +180,13 @@ struct zfcp_dbf_san_record_ct_response {
 } __attribute__ ((packed));
 
 struct zfcp_dbf_san_record_els {
-	u8 ls_code;
-	u32 len;
+	u32 d_id;
 } __attribute__ ((packed));
 
 struct zfcp_dbf_san_record {
 	u8 tag[ZFCP_DBF_TAG_SIZE];
 	u64 fsf_reqid;
 	u32 fsf_seqno;
-	u32 s_id;
-	u32 d_id;
 	union {
 		struct zfcp_dbf_san_record_ct_request ct_req;
 		struct zfcp_dbf_san_record_ct_response ct_resp;
@@ -343,7 +341,7 @@ static inline
 void zfcp_dbf_scsi_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
 			    struct scsi_cmnd *scsi_cmnd)
 {
-	zfcp_dbf_scsi(flag == FCP_TARGET_RESET ? "trst" : "lrst", tag, 1,
+	zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1,
 			    unit->port->adapter->dbf, scsi_cmnd, NULL, 0);
 }
 

+ 8 - 315
drivers/s390/scsi/zfcp_def.h

@@ -71,131 +71,6 @@
 /* timeout value for "default timer" for fsf requests */
 #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ)
 
-/*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
-
-/* task attribute values in FCP-2 FCP_CMND IU */
-#define SIMPLE_Q	0
-#define HEAD_OF_Q	1
-#define ORDERED_Q	2
-#define ACA_Q		4
-#define UNTAGGED	5
-
-/* task management flags in FCP-2 FCP_CMND IU */
-#define FCP_CLEAR_ACA		0x40
-#define FCP_TARGET_RESET	0x20
-#define FCP_LOGICAL_UNIT_RESET	0x10
-#define FCP_CLEAR_TASK_SET	0x04
-#define FCP_ABORT_TASK_SET	0x02
-
-#define FCP_CDB_LENGTH		16
-
-#define ZFCP_DID_MASK           0x00FFFFFF
-
-/* FCP(-2) FCP_CMND IU */
-struct fcp_cmnd_iu {
-	u64 fcp_lun;	   /* FCP logical unit number */
-	u8  crn;	           /* command reference number */
-	u8  reserved0:5;	   /* reserved */
-	u8  task_attribute:3;	   /* task attribute */
-	u8  task_management_flags; /* task management flags */
-	u8  add_fcp_cdb_length:6;  /* additional FCP_CDB length */
-	u8  rddata:1;              /* read data */
-	u8  wddata:1;              /* write data */
-	u8  fcp_cdb[FCP_CDB_LENGTH];
-} __attribute__((packed));
-
-/* FCP(-2) FCP_RSP IU */
-struct fcp_rsp_iu {
-	u8  reserved0[10];
-	union {
-		struct {
-			u8 reserved1:3;
-			u8 fcp_conf_req:1;
-			u8 fcp_resid_under:1;
-			u8 fcp_resid_over:1;
-			u8 fcp_sns_len_valid:1;
-			u8 fcp_rsp_len_valid:1;
-		} bits;
-		u8 value;
-	} validity;
-	u8  scsi_status;
-	u32 fcp_resid;
-	u32 fcp_sns_len;
-	u32 fcp_rsp_len;
-} __attribute__((packed));
-
-
-#define RSP_CODE_GOOD		 0
-#define RSP_CODE_LENGTH_MISMATCH 1
-#define RSP_CODE_FIELD_INVALID	 2
-#define RSP_CODE_RO_MISMATCH	 3
-#define RSP_CODE_TASKMAN_UNSUPP	 4
-#define RSP_CODE_TASKMAN_FAILED	 5
-
-/* see fc-fs */
-#define LS_RSCN  0x61
-#define LS_LOGO  0x05
-#define LS_PLOGI 0x03
-
-struct fcp_rscn_head {
-        u8  command;
-        u8  page_length; /* always 0x04 */
-        u16 payload_len;
-} __attribute__((packed));
-
-struct fcp_rscn_element {
-        u8  reserved:2;
-        u8  event_qual:4;
-        u8  addr_format:2;
-        u32 nport_did:24;
-} __attribute__((packed));
-
-/* see fc-ph */
-struct fcp_logo {
-        u32 command;
-        u32 nport_did;
-	u64 nport_wwpn;
-} __attribute__((packed));
-
-/*
- * FC-FS stuff
- */
-#define R_A_TOV				10 /* seconds */
-
-#define ZFCP_LS_RLS			0x0f
-#define ZFCP_LS_ADISC			0x52
-#define ZFCP_LS_RPS			0x56
-#define ZFCP_LS_RSCN			0x61
-#define ZFCP_LS_RNID			0x78
-
-struct zfcp_ls_adisc {
-	u8		code;
-	u8		field[3];
-	u32		hard_nport_id;
-	u64		wwpn;
-	u64		wwnn;
-	u32		nport_id;
-} __attribute__ ((packed));
-
-/*
- * FC-GS-2 stuff
- */
-#define ZFCP_CT_REVISION		0x01
-#define ZFCP_CT_DIRECTORY_SERVICE	0xFC
-#define ZFCP_CT_NAME_SERVER		0x02
-#define ZFCP_CT_SYNCHRONOUS		0x00
-#define ZFCP_CT_SCSI_FCP		0x08
-#define ZFCP_CT_UNABLE_TO_PERFORM_CMD	0x09
-#define ZFCP_CT_GID_PN			0x0121
-#define ZFCP_CT_GPN_FT			0x0172
-#define ZFCP_CT_ACCEPT			0x8002
-#define ZFCP_CT_REJECT			0x8001
-
-/*
- * FC-GS-4 stuff
- */
-#define ZFCP_CT_TIMEOUT			(3 * R_A_TOV)
-
 /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
 
 /*
@@ -205,7 +80,6 @@ struct zfcp_ls_adisc {
 #define ZFCP_COMMON_FLAGS			0xfff00000
 
 /* common status bits */
-#define ZFCP_STATUS_COMMON_REMOVE		0x80000000
 #define ZFCP_STATUS_COMMON_RUNNING		0x40000000
 #define ZFCP_STATUS_COMMON_ERP_FAILED		0x20000000
 #define ZFCP_STATUS_COMMON_UNBLOCKED		0x10000000
@@ -222,21 +96,10 @@ struct zfcp_ls_adisc {
 #define ZFCP_STATUS_ADAPTER_ERP_PENDING		0x00000100
 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED	0x00000200
 
-/* FC-PH/FC-GS well-known address identifiers for generic services */
-#define ZFCP_DID_WKA				0xFFFFF0
-
 /* remote port status */
 #define ZFCP_STATUS_PORT_PHYS_OPEN		0x00000001
 #define ZFCP_STATUS_PORT_LINK_TEST		0x00000002
 
-/* well known address (WKA) port status*/
-enum zfcp_wka_status {
-	ZFCP_WKA_PORT_OFFLINE,
-	ZFCP_WKA_PORT_CLOSING,
-	ZFCP_WKA_PORT_OPENING,
-	ZFCP_WKA_PORT_ONLINE,
-};
-
 /* logical unit status */
 #define ZFCP_STATUS_UNIT_SHARED			0x00000004
 #define ZFCP_STATUS_UNIT_READONLY		0x00000008
@@ -247,10 +110,7 @@ enum zfcp_wka_status {
 #define ZFCP_STATUS_FSFREQ_CLEANUP		0x00000010
 #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED	0x00000040
 #define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED       0x00000080
-#define ZFCP_STATUS_FSFREQ_ABORTED              0x00000100
 #define ZFCP_STATUS_FSFREQ_TMFUNCFAILED         0x00000200
-#define ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP        0x00000400
-#define ZFCP_STATUS_FSFREQ_RETRY                0x00000800
 #define ZFCP_STATUS_FSFREQ_DISMISSED            0x00001000
 
 /************************* STRUCTURE DEFINITIONS *****************************/
@@ -265,125 +125,10 @@ struct zfcp_adapter_mempool {
 	mempool_t *scsi_abort;
 	mempool_t *status_read_req;
 	mempool_t *status_read_data;
-	mempool_t *gid_pn_data;
+	mempool_t *gid_pn;
 	mempool_t *qtcb_pool;
 };
 
-/*
- * header for CT_IU
- */
-struct ct_hdr {
-	u8 revision;		// 0x01
-	u8 in_id[3];		// 0x00
-	u8 gs_type;		// 0xFC	Directory Service
-	u8 gs_subtype;		// 0x02	Name Server
-	u8 options;		// 0x00 single bidirectional exchange
-	u8 reserved0;
-	u16 cmd_rsp_code;	// 0x0121 GID_PN, or 0x0100 GA_NXT
-	u16 max_res_size;	// <= (4096 - 16) / 4
-	u8 reserved1;
-	u8 reason_code;
-	u8 reason_code_expl;
-	u8 vendor_unique;
-} __attribute__ ((packed));
-
-/* nameserver request CT_IU -- for requests where
- * a port name is required */
-struct ct_iu_gid_pn_req {
-	struct ct_hdr header;
-	u64 wwpn;
-} __attribute__ ((packed));
-
-/* FS_ACC IU and data unit for GID_PN nameserver request */
-struct ct_iu_gid_pn_resp {
-	struct ct_hdr header;
-	u32 d_id;
-} __attribute__ ((packed));
-
-struct ct_iu_gpn_ft_req {
-	struct ct_hdr header;
-	u8 flags;
-	u8 domain_id_scope;
-	u8 area_id_scope;
-	u8 fc4_type;
-} __attribute__ ((packed));
-
-
-/**
- * struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct
- * @wka_port: port where the request is sent to
- * @req: scatter-gather list for request
- * @resp: scatter-gather list for response
- * @handler: handler function (called for response to the request)
- * @handler_data: data passed to handler function
- * @completion: completion for synchronization purposes
- * @status: used to pass error status to calling function
- */
-struct zfcp_send_ct {
-	struct zfcp_wka_port *wka_port;
-	struct scatterlist *req;
-	struct scatterlist *resp;
-	void (*handler)(unsigned long);
-	unsigned long handler_data;
-	struct completion *completion;
-	int status;
-};
-
-/* used for name server requests in error recovery */
-struct zfcp_gid_pn_data {
-	struct zfcp_send_ct ct;
-	struct scatterlist req;
-	struct scatterlist resp;
-	struct ct_iu_gid_pn_req ct_iu_req;
-	struct ct_iu_gid_pn_resp ct_iu_resp;
-        struct zfcp_port *port;
-};
-
-/**
- * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
- * @adapter: adapter where request is sent from
- * @port: port where ELS is destinated (port reference count has to be increased)
- * @d_id: destiniation id of port where request is sent to
- * @req: scatter-gather list for request
- * @resp: scatter-gather list for response
- * @handler: handler function (called for response to the request)
- * @handler_data: data passed to handler function
- * @completion: completion for synchronization purposes
- * @ls_code: hex code of ELS command
- * @status: used to pass error status to calling function
- */
-struct zfcp_send_els {
-	struct zfcp_adapter *adapter;
-	struct zfcp_port *port;
-	u32 d_id;
-	struct scatterlist *req;
-	struct scatterlist *resp;
-	void (*handler)(unsigned long);
-	unsigned long handler_data;
-	struct completion *completion;
-	int ls_code;
-	int status;
-};
-
-struct zfcp_wka_port {
-	struct zfcp_adapter	*adapter;
-	wait_queue_head_t	completion_wq;
-	enum zfcp_wka_status	status;
-	atomic_t		refcount;
-	u32			d_id;
-	u32			handle;
-	struct mutex		mutex;
-	struct delayed_work	work;
-};
-
-struct zfcp_wka_ports {
-	struct zfcp_wka_port ms; 	/* management service */
-	struct zfcp_wka_port ts; 	/* time service */
-	struct zfcp_wka_port ds; 	/* directory service */
-	struct zfcp_wka_port as; 	/* alias service */
-	struct zfcp_wka_port ks; 	/* key distribution service */
-};
-
 struct zfcp_qdio_queue {
 	struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q];
 	u8		   first;	/* index of next free bfr in queue */
@@ -446,9 +191,7 @@ struct zfcp_qdio {
 };
 
 struct zfcp_adapter {
-	atomic_t                refcount;          /* reference count */
-	wait_queue_head_t	remove_wq;         /* can be used to wait for
-						      refcount drop to zero */
+	struct kref		ref;
 	u64			peer_wwnn;	   /* P2P peer WWNN */
 	u64			peer_wwpn;	   /* P2P peer WWPN */
 	u32			peer_d_id;	   /* P2P peer D_ID */
@@ -461,7 +204,8 @@ struct zfcp_adapter {
         u32			hardware_version;  /* of FCP channel */
 	u16			timer_ticks;       /* time int for a tick */
 	struct Scsi_Host	*scsi_host;	   /* Pointer to mid-layer */
-	struct list_head	port_list_head;	   /* remote port list */
+	struct list_head	port_list;	   /* remote port list */
+	rwlock_t		port_list_lock;    /* port list lock */
 	unsigned long		req_no;		   /* unique FSF req number */
 	struct list_head	*req_list;	   /* list of pending reqs */
 	spinlock_t		req_list_lock;	   /* request list lock */
@@ -485,7 +229,7 @@ struct zfcp_adapter {
 	u32			erp_low_mem_count; /* nr of erp actions waiting
 						      for memory */
 	struct task_struct	*erp_thread;
-	struct zfcp_wka_ports	*gs;		   /* generic services */
+	struct zfcp_fc_wka_ports *gs;		   /* generic services */
 	struct zfcp_dbf		*dbf;		   /* debug traces */
 	struct zfcp_adapter_mempool	pool;      /* Adapter memory pools */
 	struct fc_host_statistics *fc_stats;
@@ -500,11 +244,9 @@ struct zfcp_port {
 	struct device          sysfs_device;   /* sysfs device */
 	struct fc_rport        *rport;         /* rport of fc transport class */
 	struct list_head       list;	       /* list of remote ports */
-	atomic_t               refcount;       /* reference count */
-	wait_queue_head_t      remove_wq;      /* can be used to wait for
-						  refcount drop to zero */
 	struct zfcp_adapter    *adapter;       /* adapter used to access port */
-	struct list_head       unit_list_head; /* head of logical unit list */
+	struct list_head	unit_list;	/* head of logical unit list */
+	rwlock_t		unit_list_lock; /* unit list lock */
 	atomic_t	       status;	       /* status of this remote port */
 	u64		       wwnn;	       /* WWNN if known */
 	u64		       wwpn;	       /* WWPN */
@@ -523,9 +265,6 @@ struct zfcp_port {
 struct zfcp_unit {
 	struct device          sysfs_device;   /* sysfs device */
 	struct list_head       list;	       /* list of logical units */
-	atomic_t               refcount;       /* reference count */
-	wait_queue_head_t      remove_wq;      /* can be used to wait for
-						  refcount drop to zero */
 	struct zfcp_port       *port;	       /* remote port of unit */
 	atomic_t	       status;	       /* status of this logical unit */
 	u64		       fcp_lun;	       /* own FCP_LUN */
@@ -601,14 +340,11 @@ struct zfcp_fsf_req {
 struct zfcp_data {
 	struct scsi_host_template scsi_host_template;
 	struct scsi_transport_template *scsi_transport_template;
-	rwlock_t                config_lock;        /* serialises changes
-						       to adapter/port/unit
-						       lists */
-	struct mutex		config_mutex;
 	struct kmem_cache	*gpn_ft_cache;
 	struct kmem_cache	*qtcb_cache;
 	struct kmem_cache	*sr_buffer_cache;
 	struct kmem_cache	*gid_pn_cache;
+	struct kmem_cache	*adisc_cache;
 };
 
 /********************** ZFCP SPECIFIC DEFINES ********************************/
@@ -657,47 +393,4 @@ zfcp_reqlist_find_safe(struct zfcp_adapter *adapter, struct zfcp_fsf_req *req)
 	return NULL;
 }
 
-/*
- *  functions needed for reference/usage counting
- */
-
-static inline void
-zfcp_unit_get(struct zfcp_unit *unit)
-{
-	atomic_inc(&unit->refcount);
-}
-
-static inline void
-zfcp_unit_put(struct zfcp_unit *unit)
-{
-	if (atomic_dec_return(&unit->refcount) == 0)
-		wake_up(&unit->remove_wq);
-}
-
-static inline void
-zfcp_port_get(struct zfcp_port *port)
-{
-	atomic_inc(&port->refcount);
-}
-
-static inline void
-zfcp_port_put(struct zfcp_port *port)
-{
-	if (atomic_dec_return(&port->refcount) == 0)
-		wake_up(&port->remove_wq);
-}
-
-static inline void
-zfcp_adapter_get(struct zfcp_adapter *adapter)
-{
-	atomic_inc(&adapter->refcount);
-}
-
-static inline void
-zfcp_adapter_put(struct zfcp_adapter *adapter)
-{
-	if (atomic_dec_return(&adapter->refcount) == 0)
-		wake_up(&adapter->remove_wq);
-}
-
 #endif /* ZFCP_DEF_H */

+ 74 - 64
drivers/s390/scsi/zfcp_erp.c

@@ -99,9 +99,12 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 
 	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
 		zfcp_erp_action_dismiss(&port->erp_action);
-	else
-		list_for_each_entry(unit, &port->unit_list_head, list)
-		    zfcp_erp_action_dismiss_unit(unit);
+	else {
+		read_lock(&port->unit_list_lock);
+		list_for_each_entry(unit, &port->unit_list, list)
+			zfcp_erp_action_dismiss_unit(unit);
+		read_unlock(&port->unit_list_lock);
+	}
 }
 
 static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
@@ -110,9 +113,12 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
 
 	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
 		zfcp_erp_action_dismiss(&adapter->erp_action);
-	else
-		list_for_each_entry(port, &adapter->port_list_head, list)
+	else {
+		read_lock(&adapter->port_list_lock);
+		list_for_each_entry(port, &adapter->port_list, list)
 		    zfcp_erp_action_dismiss_port(port);
+		read_unlock(&adapter->port_list_lock);
+	}
 }
 
 static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
@@ -168,7 +174,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
 
 	switch (need) {
 	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		zfcp_unit_get(unit);
+		if (!get_device(&unit->sysfs_device))
+			return NULL;
 		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status);
 		erp_action = &unit->erp_action;
 		if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING))
@@ -177,7 +184,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
-		zfcp_port_get(port);
+		if (!get_device(&port->sysfs_device))
+			return NULL;
 		zfcp_erp_action_dismiss_port(port);
 		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
 		erp_action = &port->erp_action;
@@ -186,7 +194,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
-		zfcp_adapter_get(adapter);
+		kref_get(&adapter->ref);
 		zfcp_erp_action_dismiss_adapter(adapter);
 		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
 		erp_action = &adapter->erp_action;
@@ -264,11 +272,16 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear,
 {
 	unsigned long flags;
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	write_lock(&adapter->erp_lock);
-	_zfcp_erp_adapter_reopen(adapter, clear, id, ref);
-	write_unlock(&adapter->erp_lock);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	zfcp_erp_adapter_block(adapter, clear);
+	zfcp_scsi_schedule_rports_block(adapter);
+
+	write_lock_irqsave(&adapter->erp_lock, flags);
+	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+		zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
+	else
+		zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
+					NULL, NULL, id, ref);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
 /**
@@ -345,11 +358,9 @@ void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id,
 	unsigned long flags;
 	struct zfcp_adapter *adapter = port->adapter;
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	write_lock(&adapter->erp_lock);
+	write_lock_irqsave(&adapter->erp_lock, flags);
 	_zfcp_erp_port_forced_reopen(port, clear, id, ref);
-	write_unlock(&adapter->erp_lock);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
 static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id,
@@ -377,15 +388,13 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id,
  */
 int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref)
 {
-	unsigned long flags;
 	int retval;
+	unsigned long flags;
 	struct zfcp_adapter *adapter = port->adapter;
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	write_lock(&adapter->erp_lock);
+	write_lock_irqsave(&adapter->erp_lock, flags);
 	retval = _zfcp_erp_port_reopen(port, clear, id, ref);
-	write_unlock(&adapter->erp_lock);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
 
 	return retval;
 }
@@ -424,11 +433,9 @@ void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
 	struct zfcp_port *port = unit->port;
 	struct zfcp_adapter *adapter = port->adapter;
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	write_lock(&adapter->erp_lock);
+	write_lock_irqsave(&adapter->erp_lock, flags);
 	_zfcp_erp_unit_reopen(unit, clear, id, ref);
-	write_unlock(&adapter->erp_lock);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
 static int status_change_set(unsigned long mask, atomic_t *status)
@@ -540,8 +547,10 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
 {
 	struct zfcp_port *port;
 
-	list_for_each_entry(port, &adapter->port_list_head, list)
+	read_lock(&adapter->port_list_lock);
+	list_for_each_entry(port, &adapter->port_list, list)
 		_zfcp_erp_port_reopen(port, clear, id, ref);
+	read_unlock(&adapter->port_list_lock);
 }
 
 static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
@@ -549,8 +558,10 @@ static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
 {
 	struct zfcp_unit *unit;
 
-	list_for_each_entry(unit, &port->unit_list_head, list)
+	read_lock(&port->unit_list_lock);
+	list_for_each_entry(unit, &port->unit_list, list)
 		_zfcp_erp_unit_reopen(unit, clear, id, ref);
+	read_unlock(&port->unit_list_lock);
 }
 
 static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
@@ -590,16 +601,14 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
 {
 	unsigned long flags;
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	read_lock(&adapter->erp_lock);
+	read_lock_irqsave(&adapter->erp_lock, flags);
 	if (list_empty(&adapter->erp_ready_head) &&
 	    list_empty(&adapter->erp_running_head)) {
 			atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
 					  &adapter->status);
 			wake_up(&adapter->erp_done_wqh);
 	}
-	read_unlock(&adapter->erp_lock);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	read_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
 static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act)
@@ -1170,28 +1179,28 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
 	switch (act->action) {
 	case ZFCP_ERP_ACTION_REOPEN_UNIT:
 		if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
-			zfcp_unit_get(unit);
+			get_device(&unit->sysfs_device);
 			if (scsi_queue_work(unit->port->adapter->scsi_host,
 					    &unit->scsi_work) <= 0)
-				zfcp_unit_put(unit);
+				put_device(&unit->sysfs_device);
 		}
-		zfcp_unit_put(unit);
+		put_device(&unit->sysfs_device);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
 		if (result == ZFCP_ERP_SUCCEEDED)
 			zfcp_scsi_schedule_rport_register(port);
-		zfcp_port_put(port);
+		put_device(&port->sysfs_device);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
 		if (result == ZFCP_ERP_SUCCEEDED) {
 			register_service_level(&adapter->service_level);
-			schedule_work(&adapter->scan_work);
+			queue_work(adapter->work_queue, &adapter->scan_work);
 		} else
 			unregister_service_level(&adapter->service_level);
-		zfcp_adapter_put(adapter);
+		kref_put(&adapter->ref, zfcp_adapter_release);
 		break;
 	}
 }
@@ -1214,12 +1223,12 @@ static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
 static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
 {
 	int retval;
-	struct zfcp_adapter *adapter = erp_action->adapter;
 	unsigned long flags;
+	struct zfcp_adapter *adapter = erp_action->adapter;
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	write_lock(&adapter->erp_lock);
+	kref_get(&adapter->ref);
 
+	write_lock_irqsave(&adapter->erp_lock, flags);
 	zfcp_erp_strategy_check_fsfreq(erp_action);
 
 	if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
@@ -1231,11 +1240,9 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
 	zfcp_erp_action_to_running(erp_action);
 
 	/* no lock to allow for blocking operations */
-	write_unlock(&adapter->erp_lock);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
 	retval = zfcp_erp_strategy_do_action(erp_action);
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	write_lock(&adapter->erp_lock);
+	write_lock_irqsave(&adapter->erp_lock, flags);
 
 	if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
 		retval = ZFCP_ERP_CONTINUES;
@@ -1273,12 +1280,12 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
 		zfcp_erp_strategy_followup_failed(erp_action);
 
  unlock:
-	write_unlock(&adapter->erp_lock);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
 
 	if (retval != ZFCP_ERP_CONTINUES)
 		zfcp_erp_action_cleanup(erp_action, retval);
 
+	kref_put(&adapter->ref, zfcp_adapter_release);
 	return retval;
 }
 
@@ -1415,6 +1422,7 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
 				    void *ref, u32 mask, int set_or_clear)
 {
 	struct zfcp_port *port;
+	unsigned long flags;
 	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
 
 	if (set_or_clear == ZFCP_SET) {
@@ -1429,10 +1437,13 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
 			atomic_set(&adapter->erp_counter, 0);
 	}
 
-	if (common_mask)
-		list_for_each_entry(port, &adapter->port_list_head, list)
+	if (common_mask) {
+		read_lock_irqsave(&adapter->port_list_lock, flags);
+		list_for_each_entry(port, &adapter->port_list, list)
 			zfcp_erp_modify_port_status(port, id, ref, common_mask,
 						    set_or_clear);
+		read_unlock_irqrestore(&adapter->port_list_lock, flags);
+	}
 }
 
 /**
@@ -1449,6 +1460,7 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
 				 u32 mask, int set_or_clear)
 {
 	struct zfcp_unit *unit;
+	unsigned long flags;
 	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
 
 	if (set_or_clear == ZFCP_SET) {
@@ -1463,10 +1475,13 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
 			atomic_set(&port->erp_counter, 0);
 	}
 
-	if (common_mask)
-		list_for_each_entry(unit, &port->unit_list_head, list)
+	if (common_mask) {
+		read_lock_irqsave(&port->unit_list_lock, flags);
+		list_for_each_entry(unit, &port->unit_list, list)
 			zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
 						    set_or_clear);
+		read_unlock_irqrestore(&port->unit_list_lock, flags);
+	}
 }
 
 /**
@@ -1502,12 +1517,8 @@ void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref,
  */
 void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref)
 {
-	unsigned long flags;
-
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
 	zfcp_erp_modify_port_status(port, id, ref,
 				    ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
 }
 
@@ -1535,13 +1546,9 @@ void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref)
  */
 void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref)
 {
-	unsigned long flags;
-
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
 	zfcp_erp_modify_port_status(port, id, ref,
 				    ZFCP_STATUS_COMMON_ERP_FAILED |
 				    ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 }
 
 /**
@@ -1574,12 +1581,15 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id,
 					 void *ref)
 {
 	struct zfcp_unit *unit;
+	unsigned long flags;
 	int status = atomic_read(&port->status);
 
 	if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
 			ZFCP_STATUS_COMMON_ACCESS_BOXED))) {
-		list_for_each_entry(unit, &port->unit_list_head, list)
+		read_lock_irqsave(&port->unit_list_lock, flags);
+		list_for_each_entry(unit, &port->unit_list, list)
 				    zfcp_erp_unit_access_changed(unit, id, ref);
+		read_unlock_irqrestore(&port->unit_list_lock, flags);
 		return;
 	}
 
@@ -1595,14 +1605,14 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id,
 void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id,
 				     void *ref)
 {
-	struct zfcp_port *port;
 	unsigned long flags;
+	struct zfcp_port *port;
 
 	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
 		return;
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	list_for_each_entry(port, &adapter->port_list_head, list)
+	read_lock_irqsave(&adapter->port_list_lock, flags);
+	list_for_each_entry(port, &adapter->port_list, list)
 		zfcp_erp_port_access_changed(port, id, ref);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 }

+ 21 - 17
drivers/s390/scsi/zfcp_ext.h

@@ -9,26 +9,31 @@
 #ifndef ZFCP_EXT_H
 #define ZFCP_EXT_H
 
+#include <linux/types.h>
+#include <scsi/fc/fc_els.h>
 #include "zfcp_def.h"
+#include "zfcp_fc.h"
 
 /* zfcp_aux.c */
 extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64);
 extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64);
-extern int zfcp_adapter_enqueue(struct ccw_device *);
-extern void zfcp_adapter_dequeue(struct zfcp_adapter *);
+extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
 extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
 					   u32);
-extern void zfcp_port_dequeue(struct zfcp_port *);
 extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
-extern void zfcp_unit_dequeue(struct zfcp_unit *);
 extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
 extern void zfcp_sg_free_table(struct scatterlist *, int);
 extern int zfcp_sg_setup_table(struct scatterlist *, int);
+extern void zfcp_device_unregister(struct device *,
+				   const struct attribute_group *);
+extern void zfcp_adapter_release(struct kref *);
+extern void zfcp_adapter_unregister(struct zfcp_adapter *);
 
 /* zfcp_ccw.c */
-extern int zfcp_ccw_register(void);
 extern int zfcp_ccw_priv_sch(struct zfcp_adapter *);
 extern struct ccw_driver zfcp_ccw_driver;
+extern struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *);
+extern void zfcp_ccw_adapter_put(struct zfcp_adapter *);
 
 /* zfcp_cfdc.c */
 extern struct miscdevice zfcp_cfdc_misc;
@@ -51,7 +56,7 @@ extern void _zfcp_dbf_hba_fsf_unsol(const char *, int level, struct zfcp_dbf *,
 					  struct fsf_status_read_buffer *);
 extern void zfcp_dbf_hba_qdio(struct zfcp_dbf *, unsigned int, int, int);
 extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
-extern void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *, u32);
 extern void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *);
 extern void zfcp_dbf_san_els_request(struct zfcp_fsf_req *);
 extern void zfcp_dbf_san_els_response(struct zfcp_fsf_req *);
@@ -92,24 +97,22 @@ extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *,
 extern void zfcp_erp_timeout_handler(unsigned long);
 
 /* zfcp_fc.c */
-extern int zfcp_fc_scan_ports(struct zfcp_adapter *);
-extern void _zfcp_fc_scan_ports_later(struct work_struct *);
+extern void zfcp_fc_scan_ports(struct work_struct *);
 extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
 extern void zfcp_fc_port_did_lookup(struct work_struct *);
 extern void zfcp_fc_trigger_did_lookup(struct zfcp_port *);
-extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
+extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fc_els_flogi *);
 extern void zfcp_fc_test_link(struct zfcp_port *);
 extern void zfcp_fc_link_test_work(struct work_struct *);
-extern void zfcp_fc_wka_ports_force_offline(struct zfcp_wka_ports *);
+extern void zfcp_fc_wka_ports_force_offline(struct zfcp_fc_wka_ports *);
 extern int zfcp_fc_gs_setup(struct zfcp_adapter *);
 extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
-extern int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *);
-extern int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *);
+extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
 
 /* zfcp_fsf.c */
 extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
-extern int zfcp_fsf_open_wka_port(struct zfcp_wka_port *);
-extern int zfcp_fsf_close_wka_port(struct zfcp_wka_port *);
+extern int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *);
+extern int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *);
 extern int zfcp_fsf_close_port(struct zfcp_erp_action *);
 extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *);
 extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
@@ -125,8 +128,10 @@ extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *,
 extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
 extern int zfcp_fsf_status_read(struct zfcp_qdio *);
 extern int zfcp_status_read_refill(struct zfcp_adapter *adapter);
-extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *);
-extern int zfcp_fsf_send_els(struct zfcp_send_els *);
+extern int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *, struct zfcp_fsf_ct_els *,
+			    mempool_t *);
+extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32,
+			     struct zfcp_fsf_ct_els *);
 extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
 					  struct scsi_cmnd *);
 extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
@@ -153,7 +158,6 @@ extern void zfcp_qdio_close(struct zfcp_qdio *);
 extern struct zfcp_data zfcp_data;
 extern int zfcp_adapter_scsi_register(struct zfcp_adapter *);
 extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
-extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
 extern struct fc_function_template zfcp_transport_functions;
 extern void zfcp_scsi_rport_work(struct work_struct *);
 extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);

File diff suppressed because it is too large
+ 288 - 388
drivers/s390/scsi/zfcp_fc.c


+ 260 - 0
drivers/s390/scsi/zfcp_fc.h

@@ -0,0 +1,260 @@
+/*
+ * zfcp device driver
+ *
+ * Fibre Channel related definitions and inline functions for the zfcp
+ * device driver
+ *
+ * Copyright IBM Corporation 2009
+ */
+
+#ifndef ZFCP_FC_H
+#define ZFCP_FC_H
+
+#include <scsi/fc/fc_els.h>
+#include <scsi/fc/fc_fcp.h>
+#include <scsi/fc/fc_ns.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_tcq.h>
+#include "zfcp_fsf.h"
+
+#define ZFCP_FC_CT_SIZE_PAGE	  (PAGE_SIZE - sizeof(struct fc_ct_hdr))
+#define ZFCP_FC_GPN_FT_ENT_PAGE	  (ZFCP_FC_CT_SIZE_PAGE \
+					/ sizeof(struct fc_gpn_ft_resp))
+#define ZFCP_FC_GPN_FT_NUM_BUFS	  4 /* memory pages */
+
+#define ZFCP_FC_GPN_FT_MAX_SIZE	  (ZFCP_FC_GPN_FT_NUM_BUFS * PAGE_SIZE \
+					- sizeof(struct fc_ct_hdr))
+#define ZFCP_FC_GPN_FT_MAX_ENT	  (ZFCP_FC_GPN_FT_NUM_BUFS * \
+					(ZFCP_FC_GPN_FT_ENT_PAGE + 1))
+
+/**
+ * struct zfcp_fc_gid_pn_req - container for ct header plus gid_pn request
+ * @ct_hdr: FC GS common transport header
+ * @gid_pn: GID_PN request
+ */
+struct zfcp_fc_gid_pn_req {
+	struct fc_ct_hdr	ct_hdr;
+	struct fc_ns_gid_pn	gid_pn;
+} __packed;
+
+/**
+ * struct zfcp_fc_gid_pn_resp - container for ct header plus gid_pn response
+ * @ct_hdr: FC GS common transport header
+ * @gid_pn: GID_PN response
+ */
+struct zfcp_fc_gid_pn_resp {
+	struct fc_ct_hdr	ct_hdr;
+	struct fc_gid_pn_resp	gid_pn;
+} __packed;
+
+/**
+ * struct zfcp_fc_gid_pn - everything required in zfcp for gid_pn request
+ * @ct: data passed to zfcp_fsf for issuing fsf request
+ * @sg_req: scatterlist entry for request data
+ * @sg_resp: scatterlist entry for response data
+ * @gid_pn_req: GID_PN request data
+ * @gid_pn_resp: GID_PN response data
+ */
+struct zfcp_fc_gid_pn {
+	struct zfcp_fsf_ct_els ct;
+	struct scatterlist sg_req;
+	struct scatterlist sg_resp;
+	struct zfcp_fc_gid_pn_req gid_pn_req;
+	struct zfcp_fc_gid_pn_resp gid_pn_resp;
+	struct zfcp_port *port;
+};
+
+/**
+ * struct zfcp_fc_gpn_ft - container for ct header plus gpn_ft request
+ * @ct_hdr: FC GS common transport header
+ * @gpn_ft: GPN_FT request
+ */
+struct zfcp_fc_gpn_ft_req {
+	struct fc_ct_hdr	ct_hdr;
+	struct fc_ns_gid_ft	gpn_ft;
+} __packed;
+
+/**
+ * struct zfcp_fc_gpn_ft_resp - container for ct header plus gpn_ft response
+ * @ct_hdr: FC GS common transport header
+ * @gpn_ft: Array of gpn_ft response data to fill one memory page
+ */
+struct zfcp_fc_gpn_ft_resp {
+	struct fc_ct_hdr	ct_hdr;
+	struct fc_gpn_ft_resp	gpn_ft[ZFCP_FC_GPN_FT_ENT_PAGE];
+} __packed;
+
+/**
+ * struct zfcp_fc_gpn_ft - zfcp data for gpn_ft request
+ * @ct: data passed to zfcp_fsf for issuing fsf request
+ * @sg_req: scatter list entry for gpn_ft request
+ * @sg_resp: scatter list entries for gpn_ft responses (per memory page)
+ */
+struct zfcp_fc_gpn_ft {
+	struct zfcp_fsf_ct_els ct;
+	struct scatterlist sg_req;
+	struct scatterlist sg_resp[ZFCP_FC_GPN_FT_NUM_BUFS];
+};
+
+/**
+ * struct zfcp_fc_els_adisc - everything required in zfcp for issuing ELS ADISC
+ * @els: data required for issuing els fsf command
+ * @req: scatterlist entry for ELS ADISC request
+ * @resp: scatterlist entry for ELS ADISC response
+ * @adisc_req: ELS ADISC request data
+ * @adisc_resp: ELS ADISC response data
+ */
+struct zfcp_fc_els_adisc {
+	struct zfcp_fsf_ct_els els;
+	struct scatterlist req;
+	struct scatterlist resp;
+	struct fc_els_adisc adisc_req;
+	struct fc_els_adisc adisc_resp;
+};
+
+/**
+ * enum zfcp_fc_wka_status - FC WKA port status in zfcp
+ * @ZFCP_FC_WKA_PORT_OFFLINE: Port is closed and not in use
+ * @ZFCP_FC_WKA_PORT_CLOSING: The FSF "close port" request is pending
+ * @ZFCP_FC_WKA_PORT_OPENING: The FSF "open port" request is pending
+ * @ZFCP_FC_WKA_PORT_ONLINE: The port is open and the port handle is valid
+ */
+enum zfcp_fc_wka_status {
+	ZFCP_FC_WKA_PORT_OFFLINE,
+	ZFCP_FC_WKA_PORT_CLOSING,
+	ZFCP_FC_WKA_PORT_OPENING,
+	ZFCP_FC_WKA_PORT_ONLINE,
+};
+
+/**
+ * struct zfcp_fc_wka_port - representation of well-known-address (WKA) FC port
+ * @adapter: Pointer to adapter structure this WKA port belongs to
+ * @completion_wq: Wait for completion of open/close command
+ * @status: Current status of WKA port
+ * @refcount: Reference count to keep port open as long as it is in use
+ * @d_id: FC destination id or well-known-address
+ * @handle: FSF handle for the open WKA port
+ * @mutex: Mutex used during opening/closing state changes
+ * @work: For delaying the closing of the WKA port
+ */
+struct zfcp_fc_wka_port {
+	struct zfcp_adapter	*adapter;
+	wait_queue_head_t	completion_wq;
+	enum zfcp_fc_wka_status	status;
+	atomic_t		refcount;
+	u32			d_id;
+	u32			handle;
+	struct mutex		mutex;
+	struct delayed_work	work;
+};
+
+/**
+ * struct zfcp_fc_wka_ports - Data structures for FC generic services
+ * @ms: FC Management service
+ * @ts: FC time service
+ * @ds: FC directory service
+ * @as: FC alias service
+ */
+struct zfcp_fc_wka_ports {
+	struct zfcp_fc_wka_port ms;
+	struct zfcp_fc_wka_port ts;
+	struct zfcp_fc_wka_port ds;
+	struct zfcp_fc_wka_port as;
+};
+
+/**
+ * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd
+ * @fcp: fcp_cmnd to setup
+ * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB
+ */
+static inline
+void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi)
+{
+	char tag[2];
+
+	int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
+
+	if (scsi_populate_tag_msg(scsi, tag)) {
+		switch (tag[0]) {
+		case MSG_ORDERED_TAG:
+			fcp->fc_pri_ta |= FCP_PTA_ORDERED;
+			break;
+		case MSG_SIMPLE_TAG:
+			fcp->fc_pri_ta |= FCP_PTA_SIMPLE;
+			break;
+		};
+	} else
+		fcp->fc_pri_ta = FCP_PTA_SIMPLE;
+
+	if (scsi->sc_data_direction == DMA_FROM_DEVICE)
+		fcp->fc_flags |= FCP_CFL_RDDATA;
+	if (scsi->sc_data_direction == DMA_TO_DEVICE)
+		fcp->fc_flags |= FCP_CFL_WRDATA;
+
+	memcpy(fcp->fc_cdb, scsi->cmnd, scsi->cmd_len);
+
+	fcp->fc_dl = scsi_bufflen(scsi);
+}
+
+/**
+ * zfcp_fc_fcp_tm - setup FCP command as task management command
+ * @fcp: fcp_cmnd to setup
+ * @dev: scsi_device where to send the task management command
+ * @tm: task management flags to setup tm command
+ */
+static inline
+void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags)
+{
+	int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun);
+	fcp->fc_tm_flags |= tm_flags;
+}
+
+/**
+ * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly
+ * @fcp_rsp: FCP RSP IU to evaluate
+ * @scsi: SCSI command where to update status and sense buffer
+ */
+static inline
+void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp,
+			  struct scsi_cmnd *scsi)
+{
+	struct fcp_resp_rsp_info *rsp_info;
+	char *sense;
+	u32 sense_len, resid;
+	u8 rsp_flags;
+
+	set_msg_byte(scsi, COMMAND_COMPLETE);
+	scsi->result |= fcp_rsp->resp.fr_status;
+
+	rsp_flags = fcp_rsp->resp.fr_flags;
+
+	if (unlikely(rsp_flags & FCP_RSP_LEN_VAL)) {
+		rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
+		if (rsp_info->rsp_code == FCP_TMF_CMPL)
+			set_host_byte(scsi, DID_OK);
+		else {
+			set_host_byte(scsi, DID_ERROR);
+			return;
+		}
+	}
+
+	if (unlikely(rsp_flags & FCP_SNS_LEN_VAL)) {
+		sense = (char *) &fcp_rsp[1];
+		if (rsp_flags & FCP_RSP_LEN_VAL)
+			sense += fcp_rsp->ext.fr_sns_len;
+		sense_len = min(fcp_rsp->ext.fr_sns_len,
+				(u32) SCSI_SENSE_BUFFERSIZE);
+		memcpy(scsi->sense_buffer, sense, sense_len);
+	}
+
+	if (unlikely(rsp_flags & FCP_RESID_UNDER)) {
+		resid = fcp_rsp->ext.fr_resid;
+		scsi_set_resid(scsi, resid);
+		if (scsi_bufflen(scsi) - resid < scsi->underflow &&
+		     !(rsp_flags & FCP_SNS_LEN_VAL) &&
+		     fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
+			set_host_byte(scsi, DID_ERROR);
+	}
+}
+
+#endif

+ 135 - 232
drivers/s390/scsi/zfcp_fsf.c

@@ -10,7 +10,9 @@
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/blktrace_api.h>
+#include <scsi/fc/fc_els.h>
 #include "zfcp_ext.h"
+#include "zfcp_fc.h"
 #include "zfcp_dbf.h"
 
 static void zfcp_fsf_request_timeout_handler(unsigned long data)
@@ -122,36 +124,32 @@ void zfcp_fsf_req_free(struct zfcp_fsf_req *req)
 
 static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
 {
+	unsigned long flags;
 	struct fsf_status_read_buffer *sr_buf = req->data;
 	struct zfcp_adapter *adapter = req->adapter;
 	struct zfcp_port *port;
-	int d_id = sr_buf->d_id & ZFCP_DID_MASK;
-	unsigned long flags;
+	int d_id = ntoh24(sr_buf->d_id);
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	list_for_each_entry(port, &adapter->port_list_head, list)
+	read_lock_irqsave(&adapter->port_list_lock, flags);
+	list_for_each_entry(port, &adapter->port_list, list)
 		if (port->d_id == d_id) {
-			read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 			zfcp_erp_port_reopen(port, 0, "fssrpc1", req);
-			return;
+			break;
 		}
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 }
 
 static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
 					 struct fsf_link_down_info *link_down)
 {
 	struct zfcp_adapter *adapter = req->adapter;
-	unsigned long flags;
 
 	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
 		return;
 
 	atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
 	zfcp_scsi_schedule_rports_block(adapter);
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 
 	if (!link_down)
 		goto out;
@@ -291,7 +289,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
 			zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
 							req);
 		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
-			schedule_work(&adapter->scan_work);
+			queue_work(adapter->work_queue, &adapter->scan_work);
 		break;
 	case FSF_STATUS_READ_CFDC_UPDATED:
 		zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
@@ -317,7 +315,6 @@ static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
 	case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 		return;
 	case FSF_SQ_COMMAND_ABORTED:
-		req->status |= ZFCP_STATUS_FSFREQ_ABORTED;
 		break;
 	case FSF_SQ_NO_RECOM:
 		dev_err(&req->adapter->ccw_device->dev,
@@ -358,8 +355,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
 	zfcp_dbf_hba_fsf_response(req);
 
 	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-			ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		return;
 	}
 
@@ -377,7 +373,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
 	case FSF_PROT_ERROR_STATE:
 	case FSF_PROT_SEQ_NUMB_ERROR:
 		zfcp_erp_adapter_reopen(adapter, 0, "fspse_2", req);
-		req->status |= ZFCP_STATUS_FSFREQ_RETRY;
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PROT_UNSUPP_QTCB_TYPE:
 		dev_err(&adapter->ccw_device->dev,
@@ -480,20 +476,27 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
 
 static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
 {
-	struct fsf_qtcb_bottom_config *bottom;
+	struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
 	struct zfcp_adapter *adapter = req->adapter;
 	struct Scsi_Host *shost = adapter->scsi_host;
+	struct fc_els_flogi *nsp, *plogi;
 
-	bottom = &req->qtcb->bottom.config;
+	/* adjust pointers for missing command code */
+	nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param
+					- sizeof(u32));
+	plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload
+					- sizeof(u32));
 
 	if (req->data)
 		memcpy(req->data, bottom, sizeof(*bottom));
 
-	fc_host_node_name(shost) = bottom->nport_serv_param.wwnn;
-	fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
-	fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
+	fc_host_port_name(shost) = nsp->fl_wwpn;
+	fc_host_node_name(shost) = nsp->fl_wwnn;
+	fc_host_port_id(shost) = ntoh24(bottom->s_id);
 	fc_host_speed(shost) = bottom->fc_link_speed;
 	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
+	fc_host_supported_fc4s(shost)[2] = 1; /* FCP */
+	fc_host_active_fc4s(shost)[2] = 1; /* FCP */
 
 	adapter->hydra_version = bottom->adapter_type;
 	adapter->timer_ticks = bottom->timer_interval;
@@ -503,9 +506,9 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
 
 	switch (bottom->fc_topology) {
 	case FSF_TOPO_P2P:
-		adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
-		adapter->peer_wwpn = bottom->plogi_payload.wwpn;
-		adapter->peer_wwnn = bottom->plogi_payload.wwnn;
+		adapter->peer_d_id = ntoh24(bottom->peer_d_id);
+		adapter->peer_wwpn = plogi->fl_wwpn;
+		adapter->peer_wwnn = plogi->fl_wwnn;
 		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
 		break;
 	case FSF_TOPO_FABRIC:
@@ -881,13 +884,11 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
 		break;
 	case FSF_PORT_BOXED:
 		zfcp_erp_port_boxed(unit->port, "fsafch3", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-			       ZFCP_STATUS_FSFREQ_RETRY;
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_BOXED:
 		zfcp_erp_unit_boxed(unit, "fsafch4", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-			       ZFCP_STATUS_FSFREQ_RETRY;
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                 break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (fsq->word[0]) {
@@ -958,10 +959,10 @@ out:
 static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
 {
 	struct zfcp_adapter *adapter = req->adapter;
-	struct zfcp_send_ct *send_ct = req->data;
+	struct zfcp_fsf_ct_els *ct = req->data;
 	struct fsf_qtcb_header *header = &req->qtcb->header;
 
-	send_ct->status = -EINVAL;
+	ct->status = -EINVAL;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		goto skip_fsfstatus;
@@ -969,7 +970,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
 	switch (header->fsf_status) {
         case FSF_GOOD:
 		zfcp_dbf_san_ct_response(req);
-		send_ct->status = 0;
+		ct->status = 0;
 		break;
         case FSF_SERVICE_CLASS_NOT_SUPPORTED:
 		zfcp_fsf_class_not_supp(req);
@@ -985,8 +986,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
 	case FSF_ACCESS_DENIED:
 		break;
         case FSF_PORT_BOXED:
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-			       ZFCP_STATUS_FSFREQ_RETRY;
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PORT_HANDLE_NOT_VALID:
 		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req);
@@ -1001,8 +1001,8 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
 	}
 
 skip_fsfstatus:
-	if (send_ct->handler)
-		send_ct->handler(send_ct->handler_data);
+	if (ct->handler)
+		ct->handler(ct->handler_data);
 }
 
 static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale,
@@ -1071,15 +1071,17 @@ static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
 				 int max_sbals)
 {
 	int ret;
+	unsigned int fcp_chan_timeout;
 
 	ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp, max_sbals);
 	if (ret)
 		return ret;
 
 	/* common settings for ct/gs and els requests */
+	fcp_chan_timeout = 2 * FC_DEF_R_A_TOV / 1000;
 	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
-	req->qtcb->bottom.support.timeout = 2 * R_A_TOV;
-	zfcp_fsf_start_timer(req, (2 * R_A_TOV + 10) * HZ);
+	req->qtcb->bottom.support.timeout = fcp_chan_timeout;
+	zfcp_fsf_start_timer(req, (fcp_chan_timeout + 10) * HZ);
 
 	return 0;
 }
@@ -1089,9 +1091,9 @@ static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
  * @ct: pointer to struct zfcp_send_ct with data for request
  * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req
  */
-int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool)
+int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
+		     struct zfcp_fsf_ct_els *ct, mempool_t *pool)
 {
-	struct zfcp_wka_port *wka_port = ct->wka_port;
 	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
 	struct zfcp_fsf_req *req;
 	int ret = -EIO;
@@ -1117,7 +1119,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool)
 	req->qtcb->header.port_handle = wka_port->handle;
 	req->data = ct;
 
-	zfcp_dbf_san_ct_request(req);
+	zfcp_dbf_san_ct_request(req, wka_port->d_id);
 
 	ret = zfcp_fsf_req_send(req);
 	if (ret)
@@ -1134,7 +1136,7 @@ out:
 
 static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
 {
-	struct zfcp_send_els *send_els = req->data;
+	struct zfcp_fsf_ct_els *send_els = req->data;
 	struct zfcp_port *port = send_els->port;
 	struct fsf_qtcb_header *header = &req->qtcb->header;
 
@@ -1154,9 +1156,6 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (header->fsf_status_qual.word[0]){
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			if (port && (send_els->ls_code != ZFCP_LS_ADISC))
-				zfcp_fc_test_link(port);
-			/*fall through */
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 		case FSF_SQ_RETRY_IF_POSSIBLE:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1188,10 +1187,11 @@ skip_fsfstatus:
  * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
  * @els: pointer to struct zfcp_send_els with data for the command
  */
-int zfcp_fsf_send_els(struct zfcp_send_els *els)
+int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
+		      struct zfcp_fsf_ct_els *els)
 {
 	struct zfcp_fsf_req *req;
-	struct zfcp_qdio *qdio = els->adapter->qdio;
+	struct zfcp_qdio *qdio = adapter->qdio;
 	int ret = -EIO;
 
 	spin_lock_bh(&qdio->req_q_lock);
@@ -1211,7 +1211,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
 	if (ret)
 		goto failed_send;
 
-	req->qtcb->bottom.support.d_id = els->d_id;
+	hton24(req->qtcb->bottom.support.d_id, d_id);
 	req->handler = zfcp_fsf_send_els_handler;
 	req->data = els;
 
@@ -1422,7 +1422,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
 {
 	struct zfcp_port *port = req->data;
 	struct fsf_qtcb_header *header = &req->qtcb->header;
-	struct fsf_plogi *plogi;
+	struct fc_els_flogi *plogi;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		goto out;
@@ -1472,23 +1472,10 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
 		 * another GID_PN straight after a port has been opened.
 		 * Alternately, an ADISC/PDISC ELS should suffice, as well.
 		 */
-		plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
+		plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els;
 		if (req->qtcb->bottom.support.els1_length >=
-		    FSF_PLOGI_MIN_LEN) {
-			if (plogi->serv_param.wwpn != port->wwpn) {
-				port->d_id = 0;
-				dev_warn(&port->adapter->ccw_device->dev,
-					 "A port opened with WWPN 0x%016Lx "
-					 "returned data that identifies it as "
-					 "WWPN 0x%016Lx\n",
-					 (unsigned long long) port->wwpn,
-					 (unsigned long long)
-					  plogi->serv_param.wwpn);
-			} else {
-				port->wwnn = plogi->serv_param.wwnn;
+		    FSF_PLOGI_MIN_LEN)
 				zfcp_fc_plogi_evaluate(port, plogi);
-			}
-		}
 		break;
 	case FSF_UNKNOWN_OP_SUBTYPE:
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1496,7 +1483,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
 	}
 
 out:
-	zfcp_port_put(port);
+	put_device(&port->sysfs_device);
 }
 
 /**
@@ -1530,18 +1517,18 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
         sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
 	req->handler = zfcp_fsf_open_port_handler;
-	req->qtcb->bottom.support.d_id = port->d_id;
+	hton24(req->qtcb->bottom.support.d_id, port->d_id);
 	req->data = port;
 	req->erp_action = erp_action;
 	erp_action->fsf_req = req;
-	zfcp_port_get(port);
+	get_device(&port->sysfs_device);
 
 	zfcp_fsf_start_erp_timer(req);
 	retval = zfcp_fsf_req_send(req);
 	if (retval) {
 		zfcp_fsf_req_free(req);
 		erp_action->fsf_req = NULL;
-		zfcp_port_put(port);
+		put_device(&port->sysfs_device);
 	}
 out:
 	spin_unlock_bh(&qdio->req_q_lock);
@@ -1618,11 +1605,11 @@ out:
 
 static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
 {
-	struct zfcp_wka_port *wka_port = req->data;
+	struct zfcp_fc_wka_port *wka_port = req->data;
 	struct fsf_qtcb_header *header = &req->qtcb->header;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
-		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
 		goto out;
 	}
 
@@ -1635,13 +1622,13 @@ static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		/* fall through */
 	case FSF_ACCESS_DENIED:
-		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
 		break;
 	case FSF_GOOD:
 		wka_port->handle = header->port_handle;
 		/* fall through */
 	case FSF_PORT_ALREADY_OPEN:
-		wka_port->status = ZFCP_WKA_PORT_ONLINE;
+		wka_port->status = ZFCP_FC_WKA_PORT_ONLINE;
 	}
 out:
 	wake_up(&wka_port->completion_wq);
@@ -1649,10 +1636,10 @@ out:
 
 /**
  * zfcp_fsf_open_wka_port - create and send open wka-port request
- * @wka_port: pointer to struct zfcp_wka_port
+ * @wka_port: pointer to struct zfcp_fc_wka_port
  * Returns: 0 on success, error otherwise
  */
-int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
+int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
 {
 	struct qdio_buffer_element *sbale;
 	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
@@ -1677,7 +1664,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
 	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
 	req->handler = zfcp_fsf_open_wka_port_handler;
-	req->qtcb->bottom.support.d_id = wka_port->d_id;
+	hton24(req->qtcb->bottom.support.d_id, wka_port->d_id);
 	req->data = wka_port;
 
 	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
@@ -1691,23 +1678,23 @@ out:
 
 static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
 {
-	struct zfcp_wka_port *wka_port = req->data;
+	struct zfcp_fc_wka_port *wka_port = req->data;
 
 	if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req);
 	}
 
-	wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+	wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
 	wake_up(&wka_port->completion_wq);
 }
 
 /**
  * zfcp_fsf_close_wka_port - create and send close wka port request
- * @erp_action: pointer to struct zfcp_erp_action
+ * @wka_port: WKA port to open
  * Returns: 0 on success, error otherwise
  */
-int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
+int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
 {
 	struct qdio_buffer_element *sbale;
 	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
@@ -1765,13 +1752,13 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
 		/* can't use generic zfcp_erp_modify_port_status because
 		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
 		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
-		list_for_each_entry(unit, &port->unit_list_head, list)
+		read_lock(&port->unit_list_lock);
+		list_for_each_entry(unit, &port->unit_list, list)
 			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
 					  &unit->status);
+		read_unlock(&port->unit_list_lock);
 		zfcp_erp_port_boxed(port, "fscpph2", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-			       ZFCP_STATUS_FSFREQ_RETRY;
-
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (header->fsf_status_qual.word[0]) {
@@ -1787,9 +1774,11 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
 		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
 		 */
 		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
-		list_for_each_entry(unit, &port->unit_list_head, list)
+		read_lock(&port->unit_list_lock);
+		list_for_each_entry(unit, &port->unit_list, list)
 			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
 					  &unit->status);
+		read_unlock(&port->unit_list_lock);
 		break;
 	}
 }
@@ -1873,8 +1862,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
 		break;
 	case FSF_PORT_BOXED:
 		zfcp_erp_port_boxed(unit->port, "fsouh_2", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-			       ZFCP_STATUS_FSFREQ_RETRY;
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_SHARING_VIOLATION:
 		if (header->fsf_status_qual.word[0])
@@ -2036,8 +2024,7 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
 		break;
 	case FSF_PORT_BOXED:
 		zfcp_erp_port_boxed(unit->port, "fscuh_3", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-			       ZFCP_STATUS_FSFREQ_RETRY;
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (req->qtcb->header.fsf_status_qual.word[0]) {
@@ -2109,72 +2096,57 @@ static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
 	lat_rec->max = max(lat_rec->max, lat);
 }
 
-static void zfcp_fsf_req_latency(struct zfcp_fsf_req *req)
+static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
 {
-	struct fsf_qual_latency_info *lat_inf;
-	struct latency_cont *lat;
+	struct fsf_qual_latency_info *lat_in;
+	struct latency_cont *lat = NULL;
 	struct zfcp_unit *unit = req->unit;
+	struct zfcp_blk_drv_data blktrc;
+	int ticks = req->adapter->timer_ticks;
 
-	lat_inf = &req->qtcb->prefix.prot_status_qual.latency_info;
-
-	switch (req->qtcb->bottom.io.data_direction) {
-	case FSF_DATADIR_READ:
-		lat = &unit->latencies.read;
-		break;
-	case FSF_DATADIR_WRITE:
-		lat = &unit->latencies.write;
-		break;
-	case FSF_DATADIR_CMND:
-		lat = &unit->latencies.cmd;
-		break;
-	default:
-		return;
-	}
+	lat_in = &req->qtcb->prefix.prot_status_qual.latency_info;
 
-	spin_lock(&unit->latencies.lock);
-	zfcp_fsf_update_lat(&lat->channel, lat_inf->channel_lat);
-	zfcp_fsf_update_lat(&lat->fabric, lat_inf->fabric_lat);
-	lat->counter++;
-	spin_unlock(&unit->latencies.lock);
-}
-
-#ifdef CONFIG_BLK_DEV_IO_TRACE
-static void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
-{
-	struct fsf_qual_latency_info *lat_inf;
-	struct scsi_cmnd *scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
-	struct request *req = scsi_cmnd->request;
-	struct zfcp_blk_drv_data trace;
-	int ticks = fsf_req->adapter->timer_ticks;
+	blktrc.flags = 0;
+	blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
+	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
+		blktrc.flags |= ZFCP_BLK_REQ_ERROR;
+	blktrc.inb_usage = req->queue_req.qdio_inb_usage;
+	blktrc.outb_usage = req->queue_req.qdio_outb_usage;
+
+	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
+		blktrc.flags |= ZFCP_BLK_LAT_VALID;
+		blktrc.channel_lat = lat_in->channel_lat * ticks;
+		blktrc.fabric_lat = lat_in->fabric_lat * ticks;
+
+		switch (req->qtcb->bottom.io.data_direction) {
+		case FSF_DATADIR_READ:
+			lat = &unit->latencies.read;
+			break;
+		case FSF_DATADIR_WRITE:
+			lat = &unit->latencies.write;
+			break;
+		case FSF_DATADIR_CMND:
+			lat = &unit->latencies.cmd;
+			break;
+		}
 
-	trace.flags = 0;
-	trace.magic = ZFCP_BLK_DRV_DATA_MAGIC;
-	if (fsf_req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
-		trace.flags |= ZFCP_BLK_LAT_VALID;
-		lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
-		trace.channel_lat = lat_inf->channel_lat * ticks;
-		trace.fabric_lat = lat_inf->fabric_lat * ticks;
+		if (lat) {
+			spin_lock(&unit->latencies.lock);
+			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
+			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
+			lat->counter++;
+			spin_unlock(&unit->latencies.lock);
+		}
 	}
-	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
-		trace.flags |= ZFCP_BLK_REQ_ERROR;
-	trace.inb_usage = fsf_req->queue_req.qdio_inb_usage;
-	trace.outb_usage = fsf_req->queue_req.qdio_outb_usage;
 
-	blk_add_driver_data(req->q, req, &trace, sizeof(trace));
-}
-#else
-static inline void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
-{
+	blk_add_driver_data(scsi->request->q, scsi->request, &blktrc,
+			    sizeof(blktrc));
 }
-#endif
 
 static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
 {
 	struct scsi_cmnd *scpnt;
-	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
-	    &(req->qtcb->bottom.io.fcp_rsp);
-	u32 sns_len;
-	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
+	struct fcp_resp_with_ext *fcp_rsp;
 	unsigned long flags;
 
 	read_lock_irqsave(&req->adapter->abort_lock, flags);
@@ -2185,50 +2157,16 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
 		return;
 	}
 
-	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) {
-		set_host_byte(scpnt, DID_SOFT_ERROR);
-		goto skip_fsfstatus;
-	}
-
 	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
-		set_host_byte(scpnt, DID_ERROR);
+		set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED);
 		goto skip_fsfstatus;
 	}
 
-	set_msg_byte(scpnt, COMMAND_COMPLETE);
-
-	scpnt->result |= fcp_rsp_iu->scsi_status;
+	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
+	zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt);
 
-	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA)
-		zfcp_fsf_req_latency(req);
-
-	zfcp_fsf_trace_latency(req);
-
-	if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
-		if (fcp_rsp_info[3] == RSP_CODE_GOOD)
-			set_host_byte(scpnt, DID_OK);
-		else {
-			set_host_byte(scpnt, DID_ERROR);
-			goto skip_fsfstatus;
-		}
-	}
-
-	if (unlikely(fcp_rsp_iu->validity.bits.fcp_sns_len_valid)) {
-		sns_len = FSF_FCP_RSP_SIZE - sizeof(struct fcp_rsp_iu) +
-			  fcp_rsp_iu->fcp_rsp_len;
-		sns_len = min(sns_len, (u32) SCSI_SENSE_BUFFERSIZE);
-		sns_len = min(sns_len, fcp_rsp_iu->fcp_sns_len);
-
-		memcpy(scpnt->sense_buffer,
-		       zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len);
-	}
+	zfcp_fsf_req_trace(req, scpnt);
 
-	if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) {
-		scsi_set_resid(scpnt, fcp_rsp_iu->fcp_resid);
-		if (scsi_bufflen(scpnt) - scsi_get_resid(scpnt) <
-		    scpnt->underflow)
-			set_host_byte(scpnt, DID_ERROR);
-	}
 skip_fsfstatus:
 	if (scpnt->result != 0)
 		zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req);
@@ -2250,11 +2188,13 @@ skip_fsfstatus:
 
 static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
 {
-	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
-	    &(req->qtcb->bottom.io.fcp_rsp);
-	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
+	struct fcp_resp_with_ext *fcp_rsp;
+	struct fcp_resp_rsp_info *rsp_info;
+
+	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
+	rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
 
-	if ((fcp_rsp_info[3] != RSP_CODE_GOOD) ||
+	if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
 	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
 		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
 }
@@ -2314,13 +2254,11 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
 		break;
 	case FSF_PORT_BOXED:
 		zfcp_erp_port_boxed(unit->port, "fssfch5", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-			       ZFCP_STATUS_FSFREQ_RETRY;
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_BOXED:
 		zfcp_erp_unit_boxed(unit, "fssfch6", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-			       ZFCP_STATUS_FSFREQ_RETRY;
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		if (header->fsf_status_qual.word[0] ==
@@ -2335,24 +2273,10 @@ skip_fsfstatus:
 	else {
 		zfcp_fsf_send_fcp_command_task_handler(req);
 		req->unit = NULL;
-		zfcp_unit_put(unit);
+		put_device(&unit->sysfs_device);
 	}
 }
 
-static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl)
-{
-	u32 *fcp_dl_ptr;
-
-	/*
-	 * fcp_dl_addr = start address of fcp_cmnd structure +
-	 * size of fixed part + size of dynamically sized add_dcp_cdb field
-	 * SEE FCP-2 documentation
-	 */
-	fcp_dl_ptr = (u32 *) ((unsigned char *) &fcp_cmd[1] +
-			(fcp_cmd->add_fcp_cdb_length << 2));
-	*fcp_dl_ptr = fcp_dl;
-}
-
 /**
  * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
  * @unit: unit where command is sent to
@@ -2362,7 +2286,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
 				   struct scsi_cmnd *scsi_cmnd)
 {
 	struct zfcp_fsf_req *req;
-	struct fcp_cmnd_iu *fcp_cmnd_iu;
+	struct fcp_cmnd *fcp_cmnd;
 	unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
 	int real_bytes, retval = -EIO;
 	struct zfcp_adapter *adapter = unit->port->adapter;
@@ -2387,23 +2311,21 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
 	}
 
 	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-	zfcp_unit_get(unit);
+	get_device(&unit->sysfs_device);
 	req->unit = unit;
 	req->data = scsi_cmnd;
 	req->handler = zfcp_fsf_send_fcp_command_handler;
 	req->qtcb->header.lun_handle = unit->handle;
 	req->qtcb->header.port_handle = unit->port->handle;
 	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
+	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
 
 	scsi_cmnd->host_scribble = (unsigned char *) req->req_id;
 
-	fcp_cmnd_iu = (struct fcp_cmnd_iu *) &(req->qtcb->bottom.io.fcp_cmnd);
-	fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
 	/*
 	 * set depending on data direction:
 	 *      data direction bits in SBALE (SB Type)
 	 *      data direction bits in QTCB
-	 *      data direction bits in FCP_CMND IU
 	 */
 	switch (scsi_cmnd->sc_data_direction) {
 	case DMA_NONE:
@@ -2411,32 +2333,17 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
 		break;
 	case DMA_FROM_DEVICE:
 		req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
-		fcp_cmnd_iu->rddata = 1;
 		break;
 	case DMA_TO_DEVICE:
 		req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
 		sbtype = SBAL_FLAGS0_TYPE_WRITE;
-		fcp_cmnd_iu->wddata = 1;
 		break;
 	case DMA_BIDIRECTIONAL:
 		goto failed_scsi_cmnd;
 	}
 
-	if (likely((scsi_cmnd->device->simple_tags) ||
-		   ((atomic_read(&unit->status) & ZFCP_STATUS_UNIT_READONLY) &&
-		    (atomic_read(&unit->status) & ZFCP_STATUS_UNIT_SHARED))))
-		fcp_cmnd_iu->task_attribute = SIMPLE_Q;
-	else
-		fcp_cmnd_iu->task_attribute = UNTAGGED;
-
-	if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH))
-		fcp_cmnd_iu->add_fcp_cdb_length =
-			(scsi_cmnd->cmd_len - FCP_CDB_LENGTH) >> 2;
-
-	memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
-
-	req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
-		fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32);
+	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
+	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
 
 	real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype,
 					     scsi_sglist(scsi_cmnd),
@@ -2454,8 +2361,6 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
 		goto failed_scsi_cmnd;
 	}
 
-	zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes);
-
 	retval = zfcp_fsf_req_send(req);
 	if (unlikely(retval))
 		goto failed_scsi_cmnd;
@@ -2463,7 +2368,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
 	goto out;
 
 failed_scsi_cmnd:
-	zfcp_unit_put(unit);
+	put_device(&unit->sysfs_device);
 	zfcp_fsf_req_free(req);
 	scsi_cmnd->host_scribble = NULL;
 out:
@@ -2481,7 +2386,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
 {
 	struct qdio_buffer_element *sbale;
 	struct zfcp_fsf_req *req = NULL;
-	struct fcp_cmnd_iu *fcp_cmnd_iu;
+	struct fcp_cmnd *fcp_cmnd;
 	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
 
 	if (unlikely(!(atomic_read(&unit->status) &
@@ -2507,16 +2412,14 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
 	req->qtcb->header.port_handle = unit->port->handle;
 	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
 	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
-	req->qtcb->bottom.io.fcp_cmnd_length = 	sizeof(struct fcp_cmnd_iu) +
-						sizeof(u32);
+	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
 
 	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
 	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
 	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
-	fcp_cmnd_iu = (struct fcp_cmnd_iu *) &req->qtcb->bottom.io.fcp_cmnd;
-	fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
-	fcp_cmnd_iu->task_management_flags = tm_flags;
+	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
+	zfcp_fc_fcp_tm(fcp_cmnd, unit->device, tm_flags);
 
 	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
 	if (!zfcp_fsf_req_send(req))

+ 29 - 24
drivers/s390/scsi/zfcp_fsf.h

@@ -11,6 +11,7 @@
 
 #include <linux/pfn.h>
 #include <linux/scatterlist.h>
+#include <scsi/libfc.h>
 
 #define FSF_QTCB_CURRENT_VERSION		0x00000001
 
@@ -228,7 +229,8 @@ struct fsf_status_read_buffer {
 	u32 length;
 	u32 res1;
 	struct fsf_queue_designator queue_designator;
-	u32 d_id;
+	u8 res2;
+	u8 d_id[3];
 	u32 class;
 	u64 fcp_lun;
 	u8  res3[24];
@@ -309,22 +311,7 @@ struct fsf_qtcb_header {
 	u8  res4[16];
 } __attribute__ ((packed));
 
-struct fsf_nport_serv_param {
-	u8  common_serv_param[16];
-	u64 wwpn;
-	u64 wwnn;
-	u8  class1_serv_param[16];
-	u8  class2_serv_param[16];
-	u8  class3_serv_param[16];
-	u8  class4_serv_param[16];
-	u8  vendor_version_level[16];
-} __attribute__ ((packed));
-
 #define FSF_PLOGI_MIN_LEN	112
-struct fsf_plogi {
-	u32    code;
-	struct fsf_nport_serv_param serv_param;
-} __attribute__ ((packed));
 
 #define FSF_FCP_CMND_SIZE	288
 #define FSF_FCP_RSP_SIZE	128
@@ -342,8 +329,8 @@ struct fsf_qtcb_bottom_io {
 
 struct fsf_qtcb_bottom_support {
 	u32 operation_subtype;
-	u8  res1[12];
-	u32 d_id;
+	u8  res1[13];
+	u8 d_id[3];
 	u32 option;
 	u64 fcp_lun;
 	u64 res2;
@@ -372,18 +359,18 @@ struct fsf_qtcb_bottom_config {
 	u32 fc_topology;
 	u32 fc_link_speed;
 	u32 adapter_type;
-	u32 peer_d_id;
+	u8 res0;
+	u8 peer_d_id[3];
 	u8 res1[2];
 	u16 timer_interval;
-	u8 res2[8];
-	u32 s_id;
-	struct fsf_nport_serv_param nport_serv_param;
-	u8 reserved_nport_serv_param[16];
+	u8 res2[9];
+	u8 s_id[3];
+	u8 nport_serv_param[128];
 	u8 res3[8];
 	u32 adapter_ports;
 	u32 hardware_version;
 	u8 serial_number[32];
-	struct fsf_nport_serv_param plogi_payload;
+	u8 plogi_payload[112];
 	struct fsf_statistics_info stat_info;
 	u8 res4[112];
 } __attribute__ ((packed));
@@ -450,4 +437,22 @@ struct zfcp_blk_drv_data {
 	u64 fabric_lat;
 } __attribute__ ((packed));
 
+/**
+ * struct zfcp_fsf_ct_els - zfcp data for ct or els request
+ * @req: scatter-gather list for request
+ * @resp: scatter-gather list for response
+ * @handler: handler function (called for response to the request)
+ * @handler_data: data passed to handler function
+ * @port: Optional pointer to port for zfcp internal ELS (only test link ADISC)
+ * @status: used to pass error status to calling function
+ */
+struct zfcp_fsf_ct_els {
+	struct scatterlist *req;
+	struct scatterlist *resp;
+	void (*handler)(void *);
+	void *handler_data;
+	struct zfcp_port *port;
+	int status;
+};
+
 #endif				/* FSF_H */

+ 78 - 78
drivers/s390/scsi/zfcp_scsi.c

@@ -9,29 +9,33 @@
 #define KMSG_COMPONENT "zfcp"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/types.h>
+#include <scsi/fc/fc_fcp.h>
 #include <asm/atomic.h>
 #include "zfcp_ext.h"
 #include "zfcp_dbf.h"
+#include "zfcp_fc.h"
 
 static unsigned int default_depth = 32;
 module_param_named(queue_depth, default_depth, uint, 0600);
 MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices");
 
-/* Find start of Sense Information in FCP response unit*/
-char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu)
+static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
+					int reason)
 {
-	char *fcp_sns_info_ptr;
-
-	fcp_sns_info_ptr = (unsigned char *) &fcp_rsp_iu[1];
-	if (fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)
-		fcp_sns_info_ptr += fcp_rsp_iu->fcp_rsp_len;
-
-	return fcp_sns_info_ptr;
-}
-
-static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth)
-{
-	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+	switch (reason) {
+	case SCSI_QDEPTH_DEFAULT:
+		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+		break;
+	case SCSI_QDEPTH_QFULL:
+		scsi_track_queue_full(sdev, depth);
+		break;
+	case SCSI_QDEPTH_RAMP_UP:
+		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
 	return sdev->queue_depth;
 }
 
@@ -39,7 +43,7 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
 {
 	struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
 	unit->device = NULL;
-	zfcp_unit_put(unit);
+	put_device(&unit->sysfs_device);
 }
 
 static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
@@ -99,12 +103,26 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 	}
 
 	status = atomic_read(&unit->status);
-	if (unlikely((status & ZFCP_STATUS_COMMON_ERP_FAILED) ||
-		     !(status & ZFCP_STATUS_COMMON_RUNNING))) {
+	if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) &&
+		     !(atomic_read(&unit->port->status) &
+		       ZFCP_STATUS_COMMON_ERP_FAILED)) {
+		/* only unit access denied, but port is good
+		 * not covered by FC transport, have to fail here */
 		zfcp_scsi_command_fail(scpnt, DID_ERROR);
 		return 0;
 	}
 
+	if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
+		/* This could be either
+		 * open unit pending: this is temporary, will result in
+		 * 	open unit or ERP_FAILED, so retry command
+		 * call to rport_delete pending: mimic retry from
+		 * 	fc_remote_port_chkready until rport is BLOCKED
+		 */
+		zfcp_scsi_command_fail(scpnt, DID_IMM_RETRY);
+		return 0;
+	}
+
 	ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
 	if (unlikely(ret == -EBUSY))
 		return SCSI_MLQUEUE_DEVICE_BUSY;
@@ -115,49 +133,44 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 }
 
 static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter,
-					  int channel, unsigned int id,
-					  unsigned int lun)
+					  unsigned int id, u64 lun)
 {
+	unsigned long flags;
 	struct zfcp_port *port;
-	struct zfcp_unit *unit;
-	int scsi_lun;
+	struct zfcp_unit *unit = NULL;
 
-	list_for_each_entry(port, &adapter->port_list_head, list) {
+	read_lock_irqsave(&adapter->port_list_lock, flags);
+	list_for_each_entry(port, &adapter->port_list, list) {
 		if (!port->rport || (id != port->rport->scsi_target_id))
 			continue;
-		list_for_each_entry(unit, &port->unit_list_head, list) {
-			scsi_lun = scsilun_to_int(
-				(struct scsi_lun *)&unit->fcp_lun);
-			if (lun == scsi_lun)
-				return unit;
-		}
+		unit = zfcp_get_unit_by_lun(port, lun);
+		if (unit)
+			break;
 	}
+	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-	return NULL;
+	return unit;
 }
 
 static int zfcp_scsi_slave_alloc(struct scsi_device *sdp)
 {
 	struct zfcp_adapter *adapter;
 	struct zfcp_unit *unit;
-	unsigned long flags;
-	int retval = -ENXIO;
+	u64 lun;
 
 	adapter = (struct zfcp_adapter *) sdp->host->hostdata[0];
 	if (!adapter)
 		goto out;
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun);
+	int_to_scsilun(sdp->lun, (struct scsi_lun *)&lun);
+	unit = zfcp_unit_lookup(adapter, sdp->id, lun);
 	if (unit) {
 		sdp->hostdata = unit;
 		unit->device = sdp;
-		zfcp_unit_get(unit);
-		retval = 0;
+		return 0;
 	}
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 out:
-	return retval;
+	return -ENXIO;
 }
 
 static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
@@ -196,6 +209,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 			break;
 
 		zfcp_erp_wait(adapter);
+		fc_block_scsi_eh(scpnt);
 		if (!(atomic_read(&adapter->status) &
 		      ZFCP_STATUS_COMMON_RUNNING)) {
 			zfcp_dbf_scsi_abort("nres", adapter->dbf, scpnt, NULL,
@@ -235,6 +249,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 			break;
 
 		zfcp_erp_wait(adapter);
+		fc_block_scsi_eh(scpnt);
 		if (!(atomic_read(&adapter->status) &
 		      ZFCP_STATUS_COMMON_RUNNING)) {
 			zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt);
@@ -249,9 +264,6 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
 		zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt);
 		retval = FAILED;
-	} else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) {
-		zfcp_dbf_scsi_devreset("nsup", tm_flags, unit, scpnt);
-		retval = FAILED;
 	} else
 		zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt);
 
@@ -261,12 +273,12 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 
 static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
 {
-	return zfcp_task_mgmt_function(scpnt, FCP_LOGICAL_UNIT_RESET);
+	return zfcp_task_mgmt_function(scpnt, FCP_TMF_LUN_RESET);
 }
 
 static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
 {
-	return zfcp_task_mgmt_function(scpnt, FCP_TARGET_RESET);
+	return zfcp_task_mgmt_function(scpnt, FCP_TMF_TGT_RESET);
 }
 
 static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
@@ -276,6 +288,7 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 
 	zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
 	zfcp_erp_wait(adapter);
+	fc_block_scsi_eh(scpnt);
 
 	return SUCCESS;
 }
@@ -303,7 +316,7 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
 	adapter->scsi_host->max_lun = 1;
 	adapter->scsi_host->max_channel = 0;
 	adapter->scsi_host->unique_id = dev_id.devno;
-	adapter->scsi_host->max_cmd_len = 255;
+	adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
 	adapter->scsi_host->transportt = zfcp_data.scsi_transport_template;
 
 	adapter->scsi_host->hostdata[0] = (unsigned long) adapter;
@@ -325,12 +338,11 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
 	if (!shost)
 		return;
 
-	read_lock_irq(&zfcp_data.config_lock);
-	list_for_each_entry(port, &adapter->port_list_head, list)
-		if (port->rport)
-			port->rport = NULL;
+	read_lock_irq(&adapter->port_list_lock);
+	list_for_each_entry(port, &adapter->port_list, list)
+		port->rport = NULL;
+	read_unlock_irq(&adapter->port_list_lock);
 
-	read_unlock_irq(&zfcp_data.config_lock);
 	fc_remove_host(shost);
 	scsi_remove_host(shost);
 	scsi_host_put(shost);
@@ -348,7 +360,7 @@ zfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
 		fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);
 		if (!fc_stats)
 			return NULL;
-		adapter->fc_stats = fc_stats; /* freed in adater_dequeue */
+		adapter->fc_stats = fc_stats; /* freed in adapter_release */
 	}
 	memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));
 	return adapter->fc_stats;
@@ -464,7 +476,7 @@ static void zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
 		adapter->stats_reset = jiffies/HZ;
 		kfree(adapter->stats_reset_data);
 		adapter->stats_reset_data = data; /* finally freed in
-						     adapter_dequeue */
+						     adapter_release */
 	}
 }
 
@@ -495,7 +507,7 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
  * @rport: The FC rport where to teminate I/O
  *
  * Abort all pending SCSI commands for a port by closing the
- * port. Using a reopen for avoids a conflict with a shutdown
+ * port. Using a reopen avoiding a conflict with a shutdown
  * overwriting a reopen.
  */
 static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
@@ -505,15 +517,11 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
 	struct zfcp_adapter *adapter =
 		(struct zfcp_adapter *)shost->hostdata[0];
 
-	write_lock_irq(&zfcp_data.config_lock);
 	port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
-	if (port)
-		zfcp_port_get(port);
-	write_unlock_irq(&zfcp_data.config_lock);
 
 	if (port) {
 		zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
-		zfcp_port_put(port);
+		put_device(&port->sysfs_device);
 	}
 }
 
@@ -555,31 +563,34 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port)
 
 void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
 {
-	zfcp_port_get(port);
+	get_device(&port->sysfs_device);
 	port->rport_task = RPORT_ADD;
 
 	if (!queue_work(port->adapter->work_queue, &port->rport_work))
-		zfcp_port_put(port);
+		put_device(&port->sysfs_device);
 }
 
 void zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
 {
-	zfcp_port_get(port);
+	get_device(&port->sysfs_device);
 	port->rport_task = RPORT_DEL;
 
 	if (port->rport && queue_work(port->adapter->work_queue,
 				      &port->rport_work))
 		return;
 
-	zfcp_port_put(port);
+	put_device(&port->sysfs_device);
 }
 
 void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
 {
+	unsigned long flags;
 	struct zfcp_port *port;
 
-	list_for_each_entry(port, &adapter->port_list_head, list)
+	read_lock_irqsave(&adapter->port_list_lock, flags);
+	list_for_each_entry(port, &adapter->port_list, list)
 		zfcp_scsi_schedule_rport_block(port);
+	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 }
 
 void zfcp_scsi_rport_work(struct work_struct *work)
@@ -597,7 +608,7 @@ void zfcp_scsi_rport_work(struct work_struct *work)
 		}
 	}
 
-	zfcp_port_put(port);
+	put_device(&port->sysfs_device);
 }
 
 
@@ -615,21 +626,7 @@ void zfcp_scsi_scan(struct work_struct *work)
 				 scsilun_to_int((struct scsi_lun *)
 						&unit->fcp_lun), 0);
 
-	zfcp_unit_put(unit);
-}
-
-static int zfcp_execute_fc_job(struct fc_bsg_job *job)
-{
-	switch (job->request->msgcode) {
-	case FC_BSG_RPT_ELS:
-	case FC_BSG_HST_ELS_NOLOGIN:
-		return zfcp_fc_execute_els_fc_job(job);
-	case FC_BSG_RPT_CT:
-	case FC_BSG_HST_CT:
-		return zfcp_fc_execute_ct_fc_job(job);
-	default:
-		return -EINVAL;
-	}
+	put_device(&unit->sysfs_device);
 }
 
 struct fc_function_template zfcp_transport_functions = {
@@ -643,6 +640,7 @@ struct fc_function_template zfcp_transport_functions = {
 	.show_host_port_name = 1,
 	.show_host_permanent_port_name = 1,
 	.show_host_supported_classes = 1,
+	.show_host_supported_fc4s = 1,
 	.show_host_supported_speeds = 1,
 	.show_host_maxframe_size = 1,
 	.show_host_serial_number = 1,
@@ -652,13 +650,15 @@ struct fc_function_template zfcp_transport_functions = {
 	.get_host_port_state = zfcp_get_host_port_state,
 	.terminate_rport_io = zfcp_scsi_terminate_rport_io,
 	.show_host_port_state = 1,
-	.bsg_request = zfcp_execute_fc_job,
+	.show_host_active_fc4s = 1,
+	.bsg_request = zfcp_fc_exec_bsg_job,
 	/* no functions registered for following dynamic attributes but
 	   directly set by LLDD */
 	.show_host_port_type = 1,
 	.show_host_speed = 1,
 	.show_host_port_id = 1,
 	.disable_target_scan = 1,
+	.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
 };
 
 struct zfcp_data zfcp_data = {

+ 143 - 107
drivers/s390/scsi/zfcp_sysfs.c

@@ -3,7 +3,7 @@
  *
  * sysfs attributes.
  *
- * Copyright IBM Corporation 2008
+ * Copyright IBM Corporation 2008, 2009
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -19,30 +19,44 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev,	       \
 						   struct device_attribute *at,\
 						   char *buf)		       \
 {									       \
-	struct _feat_def *_feat = dev_get_drvdata(dev);			       \
+	struct _feat_def *_feat = container_of(dev, struct _feat_def,	       \
+					       sysfs_device);		       \
 									       \
 	return sprintf(buf, _format, _value);				       \
 }									       \
 static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO,				       \
 		     zfcp_sysfs_##_feat##_##_name##_show, NULL);
 
-ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n",
-		 atomic_read(&adapter->status));
-ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n",
-		 (unsigned long long) adapter->peer_wwnn);
-ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n",
-		 (unsigned long long) adapter->peer_wwpn);
-ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n",
-		 adapter->peer_d_id);
-ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n",
-		 adapter->hydra_version);
-ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, lic_version, "0x%08x\n",
-		 adapter->fsf_lic_version);
-ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, hardware_version, "0x%08x\n",
-		 adapter->hardware_version);
-ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, in_recovery, "%d\n",
-		 (atomic_read(&adapter->status) &
-		  ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
+#define ZFCP_DEFINE_A_ATTR(_name, _format, _value)			     \
+static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev,	     \
+						 struct device_attribute *at,\
+						 char *buf)		     \
+{									     \
+	struct ccw_device *cdev = to_ccwdev(dev);			     \
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);	     \
+	int i;								     \
+									     \
+	if (!adapter)							     \
+		return -ENODEV;						     \
+									     \
+	i = sprintf(buf, _format, _value);				     \
+	zfcp_ccw_adapter_put(adapter);					     \
+	return i;							     \
+}									     \
+static ZFCP_DEV_ATTR(adapter, _name, S_IRUGO,				     \
+		     zfcp_sysfs_adapter_##_name##_show, NULL);
+
+ZFCP_DEFINE_A_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
+ZFCP_DEFINE_A_ATTR(peer_wwnn, "0x%016llx\n",
+		   (unsigned long long) adapter->peer_wwnn);
+ZFCP_DEFINE_A_ATTR(peer_wwpn, "0x%016llx\n",
+		   (unsigned long long) adapter->peer_wwpn);
+ZFCP_DEFINE_A_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
+ZFCP_DEFINE_A_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
+ZFCP_DEFINE_A_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
+ZFCP_DEFINE_A_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version);
+ZFCP_DEFINE_A_ATTR(in_recovery, "%d\n", (atomic_read(&adapter->status) &
+					 ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
 
 ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
 		 atomic_read(&port->status));
@@ -73,7 +87,8 @@ static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev,	       \
 						struct device_attribute *attr, \
 						char *buf)		       \
 {									       \
-	struct _feat_def *_feat = dev_get_drvdata(dev);			       \
+	struct _feat_def *_feat = container_of(dev, struct _feat_def,	       \
+					       sysfs_device);		       \
 									       \
 	if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED)       \
 		return sprintf(buf, "1\n");				       \
@@ -84,15 +99,13 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev,	       \
 						 struct device_attribute *attr,\
 						 const char *buf, size_t count)\
 {									       \
-	struct _feat_def *_feat = dev_get_drvdata(dev);			       \
+	struct _feat_def *_feat = container_of(dev, struct _feat_def,	       \
+					       sysfs_device);		       \
 	unsigned long val;						       \
 	int retval = 0;							       \
 									       \
-	mutex_lock(&zfcp_data.config_mutex);				       \
-	if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) {	       \
-		retval = -EBUSY;					       \
-		goto out;						       \
-	}								       \
+	if (!(_feat && get_device(&_feat->sysfs_device)))		       \
+		return -EBUSY;						       \
 									       \
 	if (strict_strtoul(buf, 0, &val) || val != 0) {			       \
 		retval = -EINVAL;					       \
@@ -105,29 +118,82 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev,	       \
 				  _reopen_id, NULL);			       \
 	zfcp_erp_wait(_adapter);					       \
 out:									       \
-	mutex_unlock(&zfcp_data.config_mutex);				       \
+	put_device(&_feat->sysfs_device);				       \
 	return retval ? retval : (ssize_t) count;			       \
 }									       \
 static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO,			       \
 		     zfcp_sysfs_##_feat##_failed_show,			       \
 		     zfcp_sysfs_##_feat##_failed_store);
 
-ZFCP_SYSFS_FAILED(zfcp_adapter, adapter, adapter, "syafai1", "syafai2");
 ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
 ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
 
+static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	struct ccw_device *cdev = to_ccwdev(dev);
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
+	int i;
+
+	if (!adapter)
+		return -ENODEV;
+
+	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+		i = sprintf(buf, "1\n");
+	else
+		i = sprintf(buf, "0\n");
+
+	zfcp_ccw_adapter_put(adapter);
+	return i;
+}
+
+static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev,
+					       struct device_attribute *attr,
+					       const char *buf, size_t count)
+{
+	struct ccw_device *cdev = to_ccwdev(dev);
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
+	unsigned long val;
+	int retval = 0;
+
+	if (!adapter)
+		return -ENODEV;
+
+	if (strict_strtoul(buf, 0, &val) || val != 0) {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL,
+				       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
+				"syafai2", NULL);
+	zfcp_erp_wait(adapter);
+out:
+	zfcp_ccw_adapter_put(adapter);
+	return retval ? retval : (ssize_t) count;
+}
+static ZFCP_DEV_ATTR(adapter, failed, S_IWUSR | S_IRUGO,
+		     zfcp_sysfs_adapter_failed_show,
+		     zfcp_sysfs_adapter_failed_store);
+
 static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
 					    struct device_attribute *attr,
 					    const char *buf, size_t count)
 {
-	struct zfcp_adapter *adapter = dev_get_drvdata(dev);
-	int ret;
+	struct ccw_device *cdev = to_ccwdev(dev);
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
 
-	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE)
-		return -EBUSY;
+	if (!adapter)
+		return -ENODEV;
 
-	ret = zfcp_fc_scan_ports(adapter);
-	return ret ? ret : (ssize_t) count;
+	/* sync the user-space- with the kernel-invocation of scan_work */
+	queue_work(adapter->work_queue, &adapter->scan_work);
+	flush_work(&adapter->scan_work);
+	zfcp_ccw_adapter_put(adapter);
+
+	return (ssize_t) count;
 }
 static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
 		     zfcp_sysfs_port_rescan_store);
@@ -136,44 +202,34 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
 					    struct device_attribute *attr,
 					    const char *buf, size_t count)
 {
-	struct zfcp_adapter *adapter = dev_get_drvdata(dev);
+	struct ccw_device *cdev = to_ccwdev(dev);
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
 	struct zfcp_port *port;
 	u64 wwpn;
-	int retval = 0;
-	LIST_HEAD(port_remove_lh);
+	int retval = -EINVAL;
 
-	mutex_lock(&zfcp_data.config_mutex);
-	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
-		retval = -EBUSY;
-		goto out;
-	}
+	if (!adapter)
+		return -ENODEV;
 
-	if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) {
-		retval = -EINVAL;
+	if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn))
 		goto out;
-	}
 
-	write_lock_irq(&zfcp_data.config_lock);
 	port = zfcp_get_port_by_wwpn(adapter, wwpn);
-	if (port && (atomic_read(&port->refcount) == 0)) {
-		zfcp_port_get(port);
-		atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
-		list_move(&port->list, &port_remove_lh);
-	} else
-		port = NULL;
-	write_unlock_irq(&zfcp_data.config_lock);
-
-	if (!port) {
-		retval = -ENXIO;
+	if (!port)
 		goto out;
-	}
+	else
+		retval = 0;
+
+	write_lock_irq(&adapter->port_list_lock);
+	list_del(&port->list);
+	write_unlock_irq(&adapter->port_list_lock);
+
+	put_device(&port->sysfs_device);
 
 	zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL);
-	zfcp_erp_wait(adapter);
-	zfcp_port_put(port);
-	zfcp_port_dequeue(port);
+	zfcp_device_unregister(&port->sysfs_device, &zfcp_sysfs_port_attrs);
  out:
-	mutex_unlock(&zfcp_data.config_mutex);
+	zfcp_ccw_adapter_put(adapter);
 	return retval ? retval : (ssize_t) count;
 }
 static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
@@ -202,16 +258,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
 					 struct device_attribute *attr,
 					 const char *buf, size_t count)
 {
-	struct zfcp_port *port = dev_get_drvdata(dev);
+	struct zfcp_port *port = container_of(dev, struct zfcp_port,
+					      sysfs_device);
 	struct zfcp_unit *unit;
 	u64 fcp_lun;
 	int retval = -EINVAL;
 
-	mutex_lock(&zfcp_data.config_mutex);
-	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
-		retval = -EBUSY;
-		goto out;
-	}
+	if (!(port && get_device(&port->sysfs_device)))
+		return -EBUSY;
 
 	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
 		goto out;
@@ -219,15 +273,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
 	unit = zfcp_unit_enqueue(port, fcp_lun);
 	if (IS_ERR(unit))
 		goto out;
-
-	retval = 0;
+	else
+		retval = 0;
 
 	zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
 	zfcp_erp_wait(unit->port->adapter);
 	flush_work(&unit->scsi_work);
-	zfcp_unit_put(unit);
 out:
-	mutex_unlock(&zfcp_data.config_mutex);
+	put_device(&port->sysfs_device);
 	return retval ? retval : (ssize_t) count;
 }
 static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
@@ -236,54 +289,37 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
 					    struct device_attribute *attr,
 					    const char *buf, size_t count)
 {
-	struct zfcp_port *port = dev_get_drvdata(dev);
+	struct zfcp_port *port = container_of(dev, struct zfcp_port,
+					      sysfs_device);
 	struct zfcp_unit *unit;
 	u64 fcp_lun;
-	int retval = 0;
-	LIST_HEAD(unit_remove_lh);
+	int retval = -EINVAL;
 
-	mutex_lock(&zfcp_data.config_mutex);
-	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
-		retval = -EBUSY;
-		goto out;
-	}
+	if (!(port && get_device(&port->sysfs_device)))
+		return -EBUSY;
 
-	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) {
-		retval = -EINVAL;
+	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
 		goto out;
-	}
 
-	write_lock_irq(&zfcp_data.config_lock);
 	unit = zfcp_get_unit_by_lun(port, fcp_lun);
-	if (unit) {
-		write_unlock_irq(&zfcp_data.config_lock);
-		/* wait for possible timeout during SCSI probe */
-		flush_work(&unit->scsi_work);
-		write_lock_irq(&zfcp_data.config_lock);
-
-		if (atomic_read(&unit->refcount) == 0) {
-			zfcp_unit_get(unit);
-			atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
-					&unit->status);
-			list_move(&unit->list, &unit_remove_lh);
-		} else {
-			unit = NULL;
-		}
-	}
+	if (!unit)
+		goto out;
+	else
+		retval = 0;
 
-	write_unlock_irq(&zfcp_data.config_lock);
+	/* wait for possible timeout during SCSI probe */
+	flush_work(&unit->scsi_work);
 
-	if (!unit) {
-		retval = -ENXIO;
-		goto out;
-	}
+	write_lock_irq(&port->unit_list_lock);
+	list_del(&unit->list);
+	write_unlock_irq(&port->unit_list_lock);
+
+	put_device(&unit->sysfs_device);
 
 	zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
-	zfcp_erp_wait(unit->port->adapter);
-	zfcp_unit_put(unit);
-	zfcp_unit_dequeue(unit);
+	zfcp_device_unregister(&unit->sysfs_device, &zfcp_sysfs_unit_attrs);
 out:
-	mutex_unlock(&zfcp_data.config_mutex);
+	put_device(&port->sysfs_device);
 	return retval ? retval : (ssize_t) count;
 }
 static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);

+ 5 - 1
drivers/scsi/3w-9xxx.c

@@ -186,8 +186,12 @@ static ssize_t twa_show_stats(struct device *dev,
 } /* End twa_show_stats() */
 
 /* This function will set a devices queue depth */
-static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				  int reason)
 {
+	if (reason != SCSI_QDEPTH_DEFAULT)
+		return -EOPNOTSUPP;
+
 	if (queue_depth > TW_Q_LENGTH-2)
 		queue_depth = TW_Q_LENGTH-2;
 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);

+ 1924 - 0
drivers/scsi/3w-sas.c

@@ -0,0 +1,1924 @@
+/*
+   3w-sas.c -- LSI 3ware SAS/SATA-RAID Controller device driver for Linux.
+
+   Written By: Adam Radford <linuxraid@lsi.com>
+
+   Copyright (C) 2009 LSI Corporation.
+
+   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; version 2 of the License.
+
+   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.
+
+   NO WARRANTY
+   THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+   LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+   solely responsible for determining the appropriateness of using and
+   distributing the Program and assumes all risks associated with its
+   exercise of rights under this Agreement, including but not limited to
+   the risks and costs of program errors, damage to or loss of data,
+   programs or equipment, and unavailability or interruption of operations.
+
+   DISCLAIMER OF LIABILITY
+   NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+   HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+   Controllers supported by this driver:
+
+   LSI 3ware 9750 6Gb/s SAS/SATA-RAID
+
+   Bugs/Comments/Suggestions should be mailed to:
+   linuxraid@lsi.com
+
+   For more information, goto:
+   http://www.lsi.com
+
+   History
+   -------
+   3.26.02.000 - Initial driver release.
+*/
+
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/mutex.h>
+#include <linux/smp_lock.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_cmnd.h>
+#include "3w-sas.h"
+
+/* Globals */
+#define TW_DRIVER_VERSION "3.26.02.000"
+static TW_Device_Extension *twl_device_extension_list[TW_MAX_SLOT];
+static unsigned int twl_device_extension_count;
+static int twl_major = -1;
+extern struct timezone sys_tz;
+
+/* Module parameters */
+MODULE_AUTHOR ("LSI");
+MODULE_DESCRIPTION ("LSI 3ware SAS/SATA-RAID Linux Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(TW_DRIVER_VERSION);
+
+static int use_msi;
+module_param(use_msi, int, S_IRUGO);
+MODULE_PARM_DESC(use_msi, "Use Message Signaled Interrupts. Default: 0");
+
+/* Function prototypes */
+static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset);
+
+/* Functions */
+
+/* This function returns AENs through sysfs */
+static ssize_t twl_sysfs_aen_read(struct kobject *kobj,
+				  struct bin_attribute *bin_attr,
+				  char *outbuf, loff_t offset, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct Scsi_Host *shost = class_to_shost(dev);
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)shost->hostdata;
+	unsigned long flags = 0;
+	ssize_t ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	spin_lock_irqsave(tw_dev->host->host_lock, flags);
+	ret = memory_read_from_buffer(outbuf, count, &offset, tw_dev->event_queue[0], sizeof(TW_Event) * TW_Q_LENGTH);
+	spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+
+	return ret;
+} /* End twl_sysfs_aen_read() */
+
+/* aen_read sysfs attribute initializer */
+static struct bin_attribute twl_sysfs_aen_read_attr = {
+	.attr = {
+		.name = "3ware_aen_read",
+		.mode = S_IRUSR,
+	}, 
+	.size = 0,
+	.read = twl_sysfs_aen_read
+};
+
+/* This function returns driver compatibility info through sysfs */
+static ssize_t twl_sysfs_compat_info(struct kobject *kobj,
+				     struct bin_attribute *bin_attr,
+				     char *outbuf, loff_t offset, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct Scsi_Host *shost = class_to_shost(dev);
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)shost->hostdata;
+	unsigned long flags = 0;
+	ssize_t ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	spin_lock_irqsave(tw_dev->host->host_lock, flags);
+	ret = memory_read_from_buffer(outbuf, count, &offset, &tw_dev->tw_compat_info, sizeof(TW_Compatibility_Info));
+	spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+
+	return ret;
+} /* End twl_sysfs_compat_info() */
+
+/* compat_info sysfs attribute initializer */
+static struct bin_attribute twl_sysfs_compat_info_attr = {
+	.attr = {
+		.name = "3ware_compat_info",
+		.mode = S_IRUSR,
+	}, 
+	.size = 0,
+	.read = twl_sysfs_compat_info
+};
+
+/* Show some statistics about the card */
+static ssize_t twl_show_stats(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host *host = class_to_shost(dev);
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+	unsigned long flags = 0;
+	ssize_t len;
+
+	spin_lock_irqsave(tw_dev->host->host_lock, flags);
+	len = snprintf(buf, PAGE_SIZE, "3w-sas Driver version: %s\n"
+		       "Current commands posted:   %4d\n"
+		       "Max commands posted:       %4d\n"
+		       "Last sgl length:           %4d\n"
+		       "Max sgl length:            %4d\n"
+		       "Last sector count:         %4d\n"
+		       "Max sector count:          %4d\n"
+		       "SCSI Host Resets:          %4d\n"
+		       "AEN's:                     %4d\n", 
+		       TW_DRIVER_VERSION,
+		       tw_dev->posted_request_count,
+		       tw_dev->max_posted_request_count,
+		       tw_dev->sgl_entries,
+		       tw_dev->max_sgl_entries,
+		       tw_dev->sector_count,
+		       tw_dev->max_sector_count,
+		       tw_dev->num_resets,
+		       tw_dev->aen_count);
+	spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+	return len;
+} /* End twl_show_stats() */
+
+/* This function will set a devices queue depth */
+static int twl_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				  int reason)
+{
+	if (reason != SCSI_QDEPTH_DEFAULT)
+		return -EOPNOTSUPP;
+
+	if (queue_depth > TW_Q_LENGTH-2)
+		queue_depth = TW_Q_LENGTH-2;
+	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+	return queue_depth;
+} /* End twl_change_queue_depth() */
+
+/* stats sysfs attribute initializer */
+static struct device_attribute twl_host_stats_attr = {
+	.attr = {
+		.name = 	"3ware_stats",
+		.mode =		S_IRUGO,
+	},
+	.show = twl_show_stats
+};
+
+/* Host attributes initializer */
+static struct device_attribute *twl_host_attrs[] = {
+	&twl_host_stats_attr,
+	NULL,
+};
+
+/* This function will look up an AEN severity string */
+static char *twl_aen_severity_lookup(unsigned char severity_code)
+{
+	char *retval = NULL;
+
+	if ((severity_code < (unsigned char) TW_AEN_SEVERITY_ERROR) ||
+	    (severity_code > (unsigned char) TW_AEN_SEVERITY_DEBUG))
+		goto out;
+
+	retval = twl_aen_severity_table[severity_code];
+out:
+	return retval;
+} /* End twl_aen_severity_lookup() */
+
+/* This function will queue an event */
+static void twl_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header)
+{
+	u32 local_time;
+	struct timeval time;
+	TW_Event *event;
+	unsigned short aen;
+	char host[16];
+	char *error_str;
+
+	tw_dev->aen_count++;
+
+	/* Fill out event info */
+	event = tw_dev->event_queue[tw_dev->error_index];
+
+	host[0] = '\0';
+	if (tw_dev->host)
+		sprintf(host, " scsi%d:", tw_dev->host->host_no);
+
+	aen = le16_to_cpu(header->status_block.error);
+	memset(event, 0, sizeof(TW_Event));
+
+	event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
+	do_gettimeofday(&time);
+	local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60));
+	event->time_stamp_sec = local_time;
+	event->aen_code = aen;
+	event->retrieved = TW_AEN_NOT_RETRIEVED;
+	event->sequence_id = tw_dev->error_sequence_id;
+	tw_dev->error_sequence_id++;
+
+	/* Check for embedded error string */
+	error_str = &(header->err_specific_desc[strlen(header->err_specific_desc)+1]);
+
+	header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
+	event->parameter_len = strlen(header->err_specific_desc);
+	memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len + 1 + strlen(error_str));
+	if (event->severity != TW_AEN_SEVERITY_DEBUG)
+		printk(KERN_WARNING "3w-sas:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n",
+		       host,
+		       twl_aen_severity_lookup(TW_SEV_OUT(header->status_block.severity__reserved)),
+		       TW_MESSAGE_SOURCE_CONTROLLER_EVENT, aen, error_str,
+		       header->err_specific_desc);
+	else
+		tw_dev->aen_count--;
+
+	tw_dev->error_index = (tw_dev->error_index + 1 ) % TW_Q_LENGTH;
+} /* End twl_aen_queue_event() */
+
+/* This function will attempt to post a command packet to the board */
+static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
+{
+	dma_addr_t command_que_value;
+
+	command_que_value = tw_dev->command_packet_phys[request_id];
+	command_que_value += TW_COMMAND_OFFSET;
+
+	/* First write upper 4 bytes */
+	writel((u32)((u64)command_que_value >> 32), TWL_HIBQPH_REG_ADDR(tw_dev));
+	/* Then the lower 4 bytes */
+	writel((u32)(command_que_value | TWL_PULL_MODE), TWL_HIBQPL_REG_ADDR(tw_dev));
+
+	tw_dev->state[request_id] = TW_S_POSTED;
+	tw_dev->posted_request_count++;
+	if (tw_dev->posted_request_count > tw_dev->max_posted_request_count)
+		tw_dev->max_posted_request_count = tw_dev->posted_request_count;
+
+	return 0;
+} /* End twl_post_command_packet() */
+
+/* This function will perform a pci-dma mapping for a scatter gather list */
+static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
+{
+	int use_sg;
+	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+
+	use_sg = scsi_dma_map(cmd);
+	if (!use_sg)
+		return 0;
+	else if (use_sg < 0) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list");
+		return 0;
+	}
+
+	cmd->SCp.phase = TW_PHASE_SGLIST;
+	cmd->SCp.have_data_in = use_sg;
+
+	return use_sg;
+} /* End twl_map_scsi_sg_data() */
+
+/* This function hands scsi cdb's to the firmware */
+static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg)
+{
+	TW_Command_Full *full_command_packet;
+	TW_Command_Apache *command_packet;
+	int i, sg_count;
+	struct scsi_cmnd *srb = NULL;
+	struct scatterlist *sglist = NULL, *sg;
+	int retval = 1;
+
+	if (tw_dev->srb[request_id]) {
+		srb = tw_dev->srb[request_id];
+		if (scsi_sglist(srb))
+			sglist = scsi_sglist(srb);
+	}
+
+	/* Initialize command packet */
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	full_command_packet->header.header_desc.size_header = 128;
+	full_command_packet->header.status_block.error = 0;
+	full_command_packet->header.status_block.severity__reserved = 0;
+
+	command_packet = &full_command_packet->command.newcommand;
+	command_packet->status = 0;
+	command_packet->opcode__reserved = TW_OPRES_IN(0, TW_OP_EXECUTE_SCSI);
+
+	/* We forced 16 byte cdb use earlier */
+	if (!cdb)
+		memcpy(command_packet->cdb, srb->cmnd, TW_MAX_CDB_LEN);
+	else
+		memcpy(command_packet->cdb, cdb, TW_MAX_CDB_LEN);
+
+	if (srb) {
+		command_packet->unit = srb->device->id;
+		command_packet->request_id__lunl =
+			cpu_to_le16(TW_REQ_LUN_IN(srb->device->lun, request_id));
+	} else {
+		command_packet->request_id__lunl =
+			cpu_to_le16(TW_REQ_LUN_IN(0, request_id));
+		command_packet->unit = 0;
+	}
+
+	command_packet->sgl_offset = 16;
+
+	if (!sglistarg) {
+		/* Map sglist from scsi layer to cmd packet */
+		if (scsi_sg_count(srb)) {
+			sg_count = twl_map_scsi_sg_data(tw_dev, request_id);
+			if (sg_count == 0)
+				goto out;
+
+			scsi_for_each_sg(srb, sg, sg_count, i) {
+				command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(sg));
+				command_packet->sg_list[i].length = TW_CPU_TO_SGL(sg_dma_len(sg));
+			}
+			command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), scsi_sg_count(tw_dev->srb[request_id])));
+		}
+	} else {
+		/* Internal cdb post */
+		for (i = 0; i < use_sg; i++) {
+			command_packet->sg_list[i].address = TW_CPU_TO_SGL(sglistarg[i].address);
+			command_packet->sg_list[i].length = TW_CPU_TO_SGL(sglistarg[i].length);
+		}
+		command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN(0, use_sg));
+	}
+
+	/* Update some stats */
+	if (srb) {
+		tw_dev->sector_count = scsi_bufflen(srb) / 512;
+		if (tw_dev->sector_count > tw_dev->max_sector_count)
+			tw_dev->max_sector_count = tw_dev->sector_count;
+		tw_dev->sgl_entries = scsi_sg_count(srb);
+		if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
+			tw_dev->max_sgl_entries = tw_dev->sgl_entries;
+	}
+
+	/* Now post the command to the board */
+	retval = twl_post_command_packet(tw_dev, request_id);
+
+out:
+	return retval;
+} /* End twl_scsiop_execute_scsi() */
+
+/* This function will read the aen queue from the isr */
+static int twl_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
+{
+	char cdb[TW_MAX_CDB_LEN];
+	TW_SG_Entry_ISO sglist[1];
+	TW_Command_Full *full_command_packet;
+	int retval = 1;
+
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+
+	/* Initialize cdb */
+	memset(&cdb, 0, TW_MAX_CDB_LEN);
+	cdb[0] = REQUEST_SENSE; /* opcode */
+	cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
+
+	/* Initialize sglist */
+	memset(&sglist, 0, sizeof(TW_SG_Entry_ISO));
+	sglist[0].length = TW_SECTOR_SIZE;
+	sglist[0].address = tw_dev->generic_buffer_phys[request_id];
+
+	/* Mark internal command */
+	tw_dev->srb[request_id] = NULL;
+
+	/* Now post the command packet */
+	if (twl_scsiop_execute_scsi(tw_dev, request_id, cdb, 1, sglist)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2, "Post failed while reading AEN queue");
+		goto out;
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twl_aen_read_queue() */
+
+/* This function will sync firmware time with the host time */
+static void twl_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
+{
+	u32 schedulertime;
+	struct timeval utc;
+	TW_Command_Full *full_command_packet;
+	TW_Command *command_packet;
+	TW_Param_Apache *param;
+	u32 local_time;
+
+	/* Fill out the command packet */
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+	command_packet = &full_command_packet->command.oldcommand;
+	command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
+	command_packet->request_id = request_id;
+	command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
+	command_packet->byte8_offset.param.sgl[0].length = TW_CPU_TO_SGL(TW_SECTOR_SIZE);
+	command_packet->size = TW_COMMAND_SIZE;
+	command_packet->byte6_offset.parameter_count = cpu_to_le16(1);
+
+	/* Setup the param */
+	param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
+	memset(param, 0, TW_SECTOR_SIZE);
+	param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* Controller time keep table */
+	param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */
+	param->parameter_size_bytes = cpu_to_le16(4);
+
+	/* Convert system time in UTC to local time seconds since last 
+           Sunday 12:00AM */
+	do_gettimeofday(&utc);
+	local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
+	schedulertime = local_time - (3 * 86400);
+	schedulertime = cpu_to_le32(schedulertime % 604800);
+
+	memcpy(param->data, &schedulertime, sizeof(u32));
+
+	/* Mark internal command */
+	tw_dev->srb[request_id] = NULL;
+
+	/* Now post the command */
+	twl_post_command_packet(tw_dev, request_id);
+} /* End twl_aen_sync_time() */
+
+/* This function will assign an available request id */
+static void twl_get_request_id(TW_Device_Extension *tw_dev, int *request_id)
+{
+	*request_id = tw_dev->free_queue[tw_dev->free_head];
+	tw_dev->free_head = (tw_dev->free_head + 1) % TW_Q_LENGTH;
+	tw_dev->state[*request_id] = TW_S_STARTED;
+} /* End twl_get_request_id() */
+
+/* This function will free a request id */
+static void twl_free_request_id(TW_Device_Extension *tw_dev, int request_id)
+{
+	tw_dev->free_queue[tw_dev->free_tail] = request_id;
+	tw_dev->state[request_id] = TW_S_FINISHED;
+	tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH;
+} /* End twl_free_request_id() */
+
+/* This function will complete an aen request from the isr */
+static int twl_aen_complete(TW_Device_Extension *tw_dev, int request_id)
+{
+	TW_Command_Full *full_command_packet;
+	TW_Command *command_packet;
+	TW_Command_Apache_Header *header;
+	unsigned short aen;
+	int retval = 1;
+
+	header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
+	tw_dev->posted_request_count--;
+	aen = le16_to_cpu(header->status_block.error);
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	command_packet = &full_command_packet->command.oldcommand;
+
+	/* First check for internal completion of set param for time sync */
+	if (TW_OP_OUT(command_packet->opcode__sgloffset) == TW_OP_SET_PARAM) {
+		/* Keep reading the queue in case there are more aen's */
+		if (twl_aen_read_queue(tw_dev, request_id))
+			goto out2;
+	        else {
+			retval = 0;
+			goto out;
+		}
+	}
+
+	switch (aen) {
+	case TW_AEN_QUEUE_EMPTY:
+		/* Quit reading the queue if this is the last one */
+		break;
+	case TW_AEN_SYNC_TIME_WITH_HOST:
+		twl_aen_sync_time(tw_dev, request_id);
+		retval = 0;
+		goto out;
+	default:
+		twl_aen_queue_event(tw_dev, header);
+
+		/* If there are more aen's, keep reading the queue */
+		if (twl_aen_read_queue(tw_dev, request_id))
+			goto out2;
+		else {
+			retval = 0;
+			goto out;
+		}
+	}
+	retval = 0;
+out2:
+	tw_dev->state[request_id] = TW_S_COMPLETED;
+	twl_free_request_id(tw_dev, request_id);
+	clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
+out:
+	return retval;
+} /* End twl_aen_complete() */
+
+/* This function will poll for a response */
+static int twl_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
+{
+	unsigned long before;
+	dma_addr_t mfa;
+	u32 regh, regl;
+	u32 response;
+	int retval = 1;
+	int found = 0;
+
+	before = jiffies;
+
+	while (!found) {
+		if (sizeof(dma_addr_t) > 4) {
+			regh = readl(TWL_HOBQPH_REG_ADDR(tw_dev));
+			regl = readl(TWL_HOBQPL_REG_ADDR(tw_dev));
+			mfa = ((u64)regh << 32) | regl;
+		} else
+			mfa = readl(TWL_HOBQPL_REG_ADDR(tw_dev));
+
+		response = (u32)mfa;
+
+		if (TW_RESID_OUT(response) == request_id)
+			found = 1;
+
+		if (time_after(jiffies, before + HZ * seconds))
+			goto out;
+
+		msleep(50);
+	}
+	retval = 0;
+out: 
+	return retval;
+} /* End twl_poll_response() */
+
+/* This function will drain the aen queue */
+static int twl_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
+{
+	int request_id = 0;
+	char cdb[TW_MAX_CDB_LEN];
+	TW_SG_Entry_ISO sglist[1];
+	int finished = 0, count = 0;
+	TW_Command_Full *full_command_packet;
+	TW_Command_Apache_Header *header;
+	unsigned short aen;
+	int first_reset = 0, queue = 0, retval = 1;
+
+	if (no_check_reset)
+		first_reset = 0;
+	else
+		first_reset = 1;
+
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+
+	/* Initialize cdb */
+	memset(&cdb, 0, TW_MAX_CDB_LEN);
+	cdb[0] = REQUEST_SENSE; /* opcode */
+	cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
+
+	/* Initialize sglist */
+	memset(&sglist, 0, sizeof(TW_SG_Entry_ISO));
+	sglist[0].length = TW_SECTOR_SIZE;
+	sglist[0].address = tw_dev->generic_buffer_phys[request_id];
+
+	/* Mark internal command */
+	tw_dev->srb[request_id] = NULL;
+
+	do {
+		/* Send command to the board */
+		if (twl_scsiop_execute_scsi(tw_dev, request_id, cdb, 1, sglist)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x3, "Error posting request sense");
+			goto out;
+		}
+
+		/* Now poll for completion */
+		if (twl_poll_response(tw_dev, request_id, 30)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x4, "No valid response while draining AEN queue");
+			tw_dev->posted_request_count--;
+			goto out;
+		}
+
+		tw_dev->posted_request_count--;
+		header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
+		aen = le16_to_cpu(header->status_block.error);
+		queue = 0;
+		count++;
+
+		switch (aen) {
+		case TW_AEN_QUEUE_EMPTY:
+			if (first_reset != 1)
+				goto out;
+			else
+				finished = 1;
+			break;
+		case TW_AEN_SOFT_RESET:
+			if (first_reset == 0)
+				first_reset = 1;
+			else
+				queue = 1;
+			break;
+		case TW_AEN_SYNC_TIME_WITH_HOST:
+			break;
+		default:
+			queue = 1;
+		}
+
+		/* Now queue an event info */
+		if (queue)
+			twl_aen_queue_event(tw_dev, header);
+	} while ((finished == 0) && (count < TW_MAX_AEN_DRAIN));
+
+	if (count == TW_MAX_AEN_DRAIN)
+		goto out;
+
+	retval = 0;
+out:
+	tw_dev->state[request_id] = TW_S_INITIAL;
+	return retval;
+} /* End twl_aen_drain_queue() */
+
+/* This function will allocate memory and check if it is correctly aligned */
+static int twl_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
+{
+	int i;
+	dma_addr_t dma_handle;
+	unsigned long *cpu_addr;
+	int retval = 1;
+
+	cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle);
+	if (!cpu_addr) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed");
+		goto out;
+	}
+
+	memset(cpu_addr, 0, size*TW_Q_LENGTH);
+
+	for (i = 0; i < TW_Q_LENGTH; i++) {
+		switch(which) {
+		case 0:
+			tw_dev->command_packet_phys[i] = dma_handle+(i*size);
+			tw_dev->command_packet_virt[i] = (TW_Command_Full *)((unsigned char *)cpu_addr + (i*size));
+			break;
+		case 1:
+			tw_dev->generic_buffer_phys[i] = dma_handle+(i*size);
+			tw_dev->generic_buffer_virt[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
+			break;
+		case 2:
+			tw_dev->sense_buffer_phys[i] = dma_handle+(i*size);
+			tw_dev->sense_buffer_virt[i] = (TW_Command_Apache_Header *)((unsigned char *)cpu_addr + (i*size));
+			break;
+		}
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twl_allocate_memory() */
+
+/* This function will load the request id and various sgls for ioctls */
+static void twl_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length)
+{
+	TW_Command *oldcommand;
+	TW_Command_Apache *newcommand;
+	TW_SG_Entry_ISO *sgl;
+	unsigned int pae = 0;
+
+	if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
+		pae = 1;
+
+	if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
+		newcommand = &full_command_packet->command.newcommand;
+		newcommand->request_id__lunl =
+			cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id));
+		if (length) {
+			newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
+			newcommand->sg_list[0].length = TW_CPU_TO_SGL(length);
+		}
+		newcommand->sgl_entries__lunh =
+			cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), length ? 1 : 0));
+	} else {
+		oldcommand = &full_command_packet->command.oldcommand;
+		oldcommand->request_id = request_id;
+
+		if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
+			/* Load the sg list */
+			sgl = (TW_SG_Entry_ISO *)((u32 *)oldcommand+oldcommand->size - (sizeof(TW_SG_Entry_ISO)/4) + pae + (sizeof(dma_addr_t) > 4 ? 1 : 0));
+			sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
+			sgl->length = TW_CPU_TO_SGL(length);
+			oldcommand->size += pae;
+			oldcommand->size += sizeof(dma_addr_t) > 4 ? 1 : 0;
+		}
+	}
+} /* End twl_load_sgl() */
+
+/* This function handles ioctl for the character device
+   This interface is used by smartmontools open source software */
+static int twl_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long timeout;
+	unsigned long *cpu_addr, data_buffer_length_adjusted = 0, flags = 0;
+	dma_addr_t dma_handle;
+	int request_id = 0;
+	TW_Ioctl_Driver_Command driver_command;
+	TW_Ioctl_Buf_Apache *tw_ioctl;
+	TW_Command_Full *full_command_packet;
+	TW_Device_Extension *tw_dev = twl_device_extension_list[iminor(inode)];
+	int retval = -EFAULT;
+	void __user *argp = (void __user *)arg;
+
+	/* Only let one of these through at a time */
+	if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
+		retval = -EINTR;
+		goto out;
+	}
+
+	/* First copy down the driver command */
+	if (copy_from_user(&driver_command, argp, sizeof(TW_Ioctl_Driver_Command)))
+		goto out2;
+
+	/* Check data buffer size */
+	if (driver_command.buffer_length > TW_MAX_SECTORS * 2048) {
+		retval = -EINVAL;
+		goto out2;
+	}
+
+	/* Hardware can only do multiple of 512 byte transfers */
+	data_buffer_length_adjusted = (driver_command.buffer_length + 511) & ~511;
+
+	/* Now allocate ioctl buf memory */
+	cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, &dma_handle, GFP_KERNEL);
+	if (!cpu_addr) {
+		retval = -ENOMEM;
+		goto out2;
+	}
+
+	tw_ioctl = (TW_Ioctl_Buf_Apache *)cpu_addr;
+
+	/* Now copy down the entire ioctl */
+	if (copy_from_user(tw_ioctl, argp, driver_command.buffer_length + sizeof(TW_Ioctl_Buf_Apache) - 1))
+		goto out3;
+
+	/* See which ioctl we are doing */
+	switch (cmd) {
+	case TW_IOCTL_FIRMWARE_PASS_THROUGH:
+		spin_lock_irqsave(tw_dev->host->host_lock, flags);
+		twl_get_request_id(tw_dev, &request_id);
+
+		/* Flag internal command */
+		tw_dev->srb[request_id] = NULL;
+
+		/* Flag chrdev ioctl */
+		tw_dev->chrdev_request_id = request_id;
+
+		full_command_packet = (TW_Command_Full *)&tw_ioctl->firmware_command;
+
+		/* Load request id and sglist for both command types */
+		twl_load_sgl(tw_dev, full_command_packet, request_id, dma_handle, data_buffer_length_adjusted);
+
+		memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full));
+
+		/* Now post the command packet to the controller */
+		twl_post_command_packet(tw_dev, request_id);
+		spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+
+		timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
+
+		/* Now wait for command to complete */
+		timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
+
+		/* We timed out, and didn't get an interrupt */
+		if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
+			/* Now we need to reset the board */
+			printk(KERN_WARNING "3w-sas: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n",
+			       tw_dev->host->host_no, TW_DRIVER, 0x6,
+			       cmd);
+			retval = -EIO;
+			twl_reset_device_extension(tw_dev, 1);
+			goto out3;
+		}
+
+		/* Now copy in the command packet response */
+		memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virt[request_id], sizeof(TW_Command_Full));
+		
+		/* Now complete the io */
+		spin_lock_irqsave(tw_dev->host->host_lock, flags);
+		tw_dev->posted_request_count--;
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		twl_free_request_id(tw_dev, request_id);
+		spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+		break;
+	default:
+		retval = -ENOTTY;
+		goto out3;
+	}
+
+	/* Now copy the entire response to userspace */
+	if (copy_to_user(argp, tw_ioctl, sizeof(TW_Ioctl_Buf_Apache) + driver_command.buffer_length - 1) == 0)
+		retval = 0;
+out3:
+	/* Now free ioctl buf memory */
+	dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
+out2:
+	mutex_unlock(&tw_dev->ioctl_lock);
+out:
+	return retval;
+} /* End twl_chrdev_ioctl() */
+
+/* This function handles open for the character device */
+static int twl_chrdev_open(struct inode *inode, struct file *file)
+{
+	unsigned int minor_number;
+	int retval = -ENODEV;
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		retval = -EACCES;
+		goto out;
+	}
+
+	cycle_kernel_lock();
+	minor_number = iminor(inode);
+	if (minor_number >= twl_device_extension_count)
+		goto out;
+	retval = 0;
+out:
+	return retval;
+} /* End twl_chrdev_open() */
+
+/* File operations struct for character device */
+static const struct file_operations twl_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= twl_chrdev_ioctl,
+	.open		= twl_chrdev_open,
+	.release	= NULL
+};
+
+/* This function passes sense data from firmware to scsi layer */
+static int twl_fill_sense(TW_Device_Extension *tw_dev, int i, int request_id, int copy_sense, int print_host)
+{
+	TW_Command_Apache_Header *header;
+	TW_Command_Full *full_command_packet;
+	unsigned short error;
+	char *error_str;
+	int retval = 1;
+
+	header = tw_dev->sense_buffer_virt[i];
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+
+	/* Get embedded firmware error string */
+	error_str = &(header->err_specific_desc[strlen(header->err_specific_desc) + 1]);
+
+	/* Don't print error for Logical unit not supported during rollcall */
+	error = le16_to_cpu(header->status_block.error);
+	if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE) && (error != TW_ERROR_INVALID_FIELD_IN_CDB)) {
+		if (print_host)
+			printk(KERN_WARNING "3w-sas: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n",
+			       tw_dev->host->host_no,
+			       TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
+			       header->status_block.error,
+			       error_str, 
+			       header->err_specific_desc);
+		else
+			printk(KERN_WARNING "3w-sas: ERROR: (0x%02X:0x%04X): %s:%s.\n",
+			       TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
+			       header->status_block.error,
+			       error_str,
+			       header->err_specific_desc);
+	}
+
+	if (copy_sense) {
+		memcpy(tw_dev->srb[request_id]->sense_buffer, header->sense_data, TW_SENSE_DATA_LENGTH);
+		tw_dev->srb[request_id]->result = (full_command_packet->command.newcommand.status << 1);
+		goto out;
+	}
+out:
+	return retval;
+} /* End twl_fill_sense() */
+
+/* This function will free up device extension resources */
+static void twl_free_device_extension(TW_Device_Extension *tw_dev)
+{
+	if (tw_dev->command_packet_virt[0])
+		pci_free_consistent(tw_dev->tw_pci_dev,
+				    sizeof(TW_Command_Full)*TW_Q_LENGTH,
+				    tw_dev->command_packet_virt[0],
+				    tw_dev->command_packet_phys[0]);
+
+	if (tw_dev->generic_buffer_virt[0])
+		pci_free_consistent(tw_dev->tw_pci_dev,
+				    TW_SECTOR_SIZE*TW_Q_LENGTH,
+				    tw_dev->generic_buffer_virt[0],
+				    tw_dev->generic_buffer_phys[0]);
+
+	if (tw_dev->sense_buffer_virt[0])
+		pci_free_consistent(tw_dev->tw_pci_dev,
+				    sizeof(TW_Command_Apache_Header)*
+				    TW_Q_LENGTH,
+				    tw_dev->sense_buffer_virt[0],
+				    tw_dev->sense_buffer_phys[0]);
+
+	kfree(tw_dev->event_queue[0]);
+} /* End twl_free_device_extension() */
+
+/* This function will get parameter table entries from the firmware */
+static void *twl_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes)
+{
+	TW_Command_Full *full_command_packet;
+	TW_Command *command_packet;
+	TW_Param_Apache *param;
+	void *retval = NULL;
+
+	/* Setup the command packet */
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+	command_packet = &full_command_packet->command.oldcommand;
+
+	command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
+	command_packet->size              = TW_COMMAND_SIZE;
+	command_packet->request_id        = request_id;
+	command_packet->byte6_offset.block_count = cpu_to_le16(1);
+
+	/* Now setup the param */
+	param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
+	memset(param, 0, TW_SECTOR_SIZE);
+	param->table_id = cpu_to_le16(table_id | 0x8000);
+	param->parameter_id = cpu_to_le16(parameter_id);
+	param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes);
+
+	command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
+	command_packet->byte8_offset.param.sgl[0].length = TW_CPU_TO_SGL(TW_SECTOR_SIZE);
+
+	/* Post the command packet to the board */
+	twl_post_command_packet(tw_dev, request_id);
+
+	/* Poll for completion */
+	if (twl_poll_response(tw_dev, request_id, 30))
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x7, "No valid response during get param")
+	else
+		retval = (void *)&(param->data[0]);
+
+	tw_dev->posted_request_count--;
+	tw_dev->state[request_id] = TW_S_INITIAL;
+
+	return retval;
+} /* End twl_get_param() */
+
+/* This function will send an initconnection command to controller */
+static int twl_initconnection(TW_Device_Extension *tw_dev, int message_credits,
+ 			      u32 set_features, unsigned short current_fw_srl, 
+			      unsigned short current_fw_arch_id, 
+			      unsigned short current_fw_branch, 
+			      unsigned short current_fw_build, 
+			      unsigned short *fw_on_ctlr_srl, 
+			      unsigned short *fw_on_ctlr_arch_id, 
+			      unsigned short *fw_on_ctlr_branch, 
+			      unsigned short *fw_on_ctlr_build, 
+			      u32 *init_connect_result)
+{
+	TW_Command_Full *full_command_packet;
+	TW_Initconnect *tw_initconnect;
+	int request_id = 0, retval = 1;
+
+	/* Initialize InitConnection command packet */
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+	full_command_packet->header.header_desc.size_header = 128;
+	
+	tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand;
+	tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION);
+	tw_initconnect->request_id = request_id;
+	tw_initconnect->message_credits = cpu_to_le16(message_credits);
+	tw_initconnect->features = set_features;
+
+	/* Turn on 64-bit sgl support if we need to */
+	tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0;
+
+	tw_initconnect->features = cpu_to_le32(tw_initconnect->features);
+
+	if (set_features & TW_EXTENDED_INIT_CONNECT) {
+		tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
+		tw_initconnect->fw_srl = cpu_to_le16(current_fw_srl);
+		tw_initconnect->fw_arch_id = cpu_to_le16(current_fw_arch_id);
+		tw_initconnect->fw_branch = cpu_to_le16(current_fw_branch);
+		tw_initconnect->fw_build = cpu_to_le16(current_fw_build);
+	} else 
+		tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE;
+
+	/* Send command packet to the board */
+	twl_post_command_packet(tw_dev, request_id);
+
+	/* Poll for completion */
+	if (twl_poll_response(tw_dev, request_id, 30)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x8, "No valid response during init connection");
+	} else {
+		if (set_features & TW_EXTENDED_INIT_CONNECT) {
+			*fw_on_ctlr_srl = le16_to_cpu(tw_initconnect->fw_srl);
+			*fw_on_ctlr_arch_id = le16_to_cpu(tw_initconnect->fw_arch_id);
+			*fw_on_ctlr_branch = le16_to_cpu(tw_initconnect->fw_branch);
+			*fw_on_ctlr_build = le16_to_cpu(tw_initconnect->fw_build);
+			*init_connect_result = le32_to_cpu(tw_initconnect->result);
+		}
+		retval = 0;
+	}
+
+	tw_dev->posted_request_count--;
+	tw_dev->state[request_id] = TW_S_INITIAL;
+
+	return retval;
+} /* End twl_initconnection() */
+
+/* This function will initialize the fields of a device extension */
+static int twl_initialize_device_extension(TW_Device_Extension *tw_dev)
+{
+	int i, retval = 1;
+
+	/* Initialize command packet buffers */
+	if (twl_allocate_memory(tw_dev, sizeof(TW_Command_Full), 0)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x9, "Command packet memory allocation failed");
+		goto out;
+	}
+
+	/* Initialize generic buffer */
+	if (twl_allocate_memory(tw_dev, TW_SECTOR_SIZE, 1)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0xa, "Generic memory allocation failed");
+		goto out;
+	}
+
+	/* Allocate sense buffers */
+	if (twl_allocate_memory(tw_dev, sizeof(TW_Command_Apache_Header), 2)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0xb, "Sense buffer allocation failed");
+		goto out;
+	}
+
+	/* Allocate event info space */
+	tw_dev->event_queue[0] = kcalloc(TW_Q_LENGTH, sizeof(TW_Event), GFP_KERNEL);
+	if (!tw_dev->event_queue[0]) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0xc, "Event info memory allocation failed");
+		goto out;
+	}
+
+	for (i = 0; i < TW_Q_LENGTH; i++) {
+		tw_dev->event_queue[i] = (TW_Event *)((unsigned char *)tw_dev->event_queue[0] + (i * sizeof(TW_Event)));
+		tw_dev->free_queue[i] = i;
+		tw_dev->state[i] = TW_S_INITIAL;
+	}
+
+	tw_dev->free_head = TW_Q_START;
+	tw_dev->free_tail = TW_Q_START;
+	tw_dev->error_sequence_id = 1;
+	tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+
+	mutex_init(&tw_dev->ioctl_lock);
+	init_waitqueue_head(&tw_dev->ioctl_wqueue);
+
+	retval = 0;
+out:
+	return retval;
+} /* End twl_initialize_device_extension() */
+
+/* This function will perform a pci-dma unmap */
+static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
+{
+	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+
+	if (cmd->SCp.phase == TW_PHASE_SGLIST)
+		scsi_dma_unmap(cmd);
+} /* End twl_unmap_scsi_data() */
+
+/* This function will handle attention interrupts */
+static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev)
+{
+	int retval = 1;
+	u32 request_id, doorbell;
+
+	/* Read doorbell status */
+	doorbell = readl(TWL_HOBDB_REG_ADDR(tw_dev));
+
+	/* Check for controller errors */
+	if (doorbell & TWL_DOORBELL_CONTROLLER_ERROR) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0xd, "Microcontroller Error: clearing");
+		goto out;
+	}
+
+	/* Check if we need to perform an AEN drain */
+	if (doorbell & TWL_DOORBELL_ATTENTION_INTERRUPT) {
+		if (!(test_and_set_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags))) {
+			twl_get_request_id(tw_dev, &request_id);
+			if (twl_aen_read_queue(tw_dev, request_id)) {
+				tw_dev->state[request_id] = TW_S_COMPLETED;
+				twl_free_request_id(tw_dev, request_id);
+				clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
+			}
+		}
+	}
+
+	retval = 0;
+out:
+	/* Clear doorbell interrupt */
+	TWL_CLEAR_DB_INTERRUPT(tw_dev);
+
+	/* Make sure the clear was flushed by reading it back */
+	readl(TWL_HOBDBC_REG_ADDR(tw_dev));
+
+	return retval;
+} /* End twl_handle_attention_interrupt() */
+
+/* Interrupt service routine */
+static irqreturn_t twl_interrupt(int irq, void *dev_instance)
+{
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
+	int i, handled = 0, error = 0;
+	dma_addr_t mfa = 0;
+	u32 reg, regl, regh, response, request_id = 0;
+	struct scsi_cmnd *cmd;
+	TW_Command_Full *full_command_packet;
+
+	spin_lock(tw_dev->host->host_lock);
+
+	/* Read host interrupt status */
+	reg = readl(TWL_HISTAT_REG_ADDR(tw_dev));
+
+	/* Check if this is our interrupt, otherwise bail */
+	if (!(reg & TWL_HISTATUS_VALID_INTERRUPT))
+		goto twl_interrupt_bail;
+
+	handled = 1;
+
+	/* If we are resetting, bail */
+	if (test_bit(TW_IN_RESET, &tw_dev->flags))
+		goto twl_interrupt_bail;
+
+	/* Attention interrupt */
+	if (reg & TWL_HISTATUS_ATTENTION_INTERRUPT) {
+		if (twl_handle_attention_interrupt(tw_dev)) {
+			TWL_MASK_INTERRUPTS(tw_dev);
+			goto twl_interrupt_bail;
+		}
+	}
+
+	/* Response interrupt */
+	while (reg & TWL_HISTATUS_RESPONSE_INTERRUPT) {
+		if (sizeof(dma_addr_t) > 4) {
+			regh = readl(TWL_HOBQPH_REG_ADDR(tw_dev));
+			regl = readl(TWL_HOBQPL_REG_ADDR(tw_dev));
+			mfa = ((u64)regh << 32) | regl;
+		} else
+			mfa = readl(TWL_HOBQPL_REG_ADDR(tw_dev));
+
+		error = 0;
+		response = (u32)mfa;
+
+		/* Check for command packet error */
+		if (!TW_NOTMFA_OUT(response)) {
+			for (i=0;i<TW_Q_LENGTH;i++) {
+				if (tw_dev->sense_buffer_phys[i] == mfa) {
+					request_id = le16_to_cpu(tw_dev->sense_buffer_virt[i]->header_desc.request_id);
+					if (tw_dev->srb[request_id] != NULL)
+						error = twl_fill_sense(tw_dev, i, request_id, 1, 1);
+					else {
+						/* Skip ioctl error prints */
+						if (request_id != tw_dev->chrdev_request_id)
+							error = twl_fill_sense(tw_dev, i, request_id, 0, 1);
+						else
+							memcpy(tw_dev->command_packet_virt[request_id], tw_dev->sense_buffer_virt[i], sizeof(TW_Command_Apache_Header));
+					}
+
+					/* Now re-post the sense buffer */
+					writel((u32)((u64)tw_dev->sense_buffer_phys[i] >> 32), TWL_HOBQPH_REG_ADDR(tw_dev));
+					writel((u32)tw_dev->sense_buffer_phys[i], TWL_HOBQPL_REG_ADDR(tw_dev));
+					break;
+				}
+			}
+		} else
+			request_id = TW_RESID_OUT(response);
+
+		full_command_packet = tw_dev->command_packet_virt[request_id];
+
+		/* Check for correct state */
+		if (tw_dev->state[request_id] != TW_S_POSTED) {
+			if (tw_dev->srb[request_id] != NULL) {
+				TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Received a request id that wasn't posted");
+				TWL_MASK_INTERRUPTS(tw_dev);
+				goto twl_interrupt_bail;
+			}
+		}
+
+		/* Check for internal command completion */
+		if (tw_dev->srb[request_id] == NULL) {
+			if (request_id != tw_dev->chrdev_request_id) {
+				if (twl_aen_complete(tw_dev, request_id))
+					TW_PRINTK(tw_dev->host, TW_DRIVER, 0xf, "Error completing AEN during attention interrupt");
+			} else {
+				tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+				wake_up(&tw_dev->ioctl_wqueue);
+			}
+		} else {
+			cmd = tw_dev->srb[request_id];
+
+			if (!error)
+				cmd->result = (DID_OK << 16);
+			
+			/* Report residual bytes for single sgl */
+			if ((scsi_sg_count(cmd) <= 1) && (full_command_packet->command.newcommand.status == 0)) {
+				if (full_command_packet->command.newcommand.sg_list[0].length < scsi_bufflen(tw_dev->srb[request_id]))
+					scsi_set_resid(cmd, scsi_bufflen(cmd) - full_command_packet->command.newcommand.sg_list[0].length);
+			}
+
+			/* Now complete the io */
+			tw_dev->state[request_id] = TW_S_COMPLETED;
+			twl_free_request_id(tw_dev, request_id);
+			tw_dev->posted_request_count--;
+			tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+			twl_unmap_scsi_data(tw_dev, request_id);
+		}
+
+		/* Check for another response interrupt */
+		reg = readl(TWL_HISTAT_REG_ADDR(tw_dev));
+	}
+
+twl_interrupt_bail:
+	spin_unlock(tw_dev->host->host_lock);
+	return IRQ_RETVAL(handled);
+} /* End twl_interrupt() */
+
+/* This function will poll for a register change */
+static int twl_poll_register(TW_Device_Extension *tw_dev, void *reg, u32 value, u32 result, int seconds)
+{
+	unsigned long before;
+	int retval = 1;
+	u32 reg_value;
+
+	reg_value = readl(reg);
+	before = jiffies;
+
+        while ((reg_value & value) != result) {
+		reg_value = readl(reg);
+		if (time_after(jiffies, before + HZ * seconds))
+			goto out;
+		msleep(50);
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twl_poll_register() */
+
+/* This function will reset a controller */
+static int twl_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset)
+{
+	int retval = 1;
+	int i = 0;
+	u32 status = 0;
+	unsigned short fw_on_ctlr_srl = 0, fw_on_ctlr_arch_id = 0;
+	unsigned short fw_on_ctlr_branch = 0, fw_on_ctlr_build = 0;
+	u32 init_connect_result = 0;
+	int tries = 0;
+	int do_soft_reset = soft_reset;
+
+	while (tries < TW_MAX_RESET_TRIES) {
+		/* Do a soft reset if one is needed */
+		if (do_soft_reset) {
+			TWL_SOFT_RESET(tw_dev);
+
+			/* Make sure controller is in a good state */
+			if (twl_poll_register(tw_dev, TWL_SCRPD3_REG_ADDR(tw_dev), TWL_CONTROLLER_READY, 0x0, 30)) {
+				TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Controller never went non-ready during reset sequence");
+				tries++;
+				continue;
+			}
+			if (twl_poll_register(tw_dev, TWL_SCRPD3_REG_ADDR(tw_dev), TWL_CONTROLLER_READY, TWL_CONTROLLER_READY, 60)) {
+				TW_PRINTK(tw_dev->host, TW_DRIVER, 0x11, "Controller not ready during reset sequence");
+				tries++;
+				continue;
+			}
+		}
+
+		/* Initconnect */
+		if (twl_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS,
+				       TW_EXTENDED_INIT_CONNECT, TW_CURRENT_DRIVER_SRL,
+				       TW_9750_ARCH_ID, TW_CURRENT_DRIVER_BRANCH,
+				       TW_CURRENT_DRIVER_BUILD, &fw_on_ctlr_srl,
+				       &fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
+				       &fw_on_ctlr_build, &init_connect_result)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x12, "Initconnection failed while checking SRL");
+			do_soft_reset = 1;
+			tries++;
+			continue;
+		}
+
+		/* Load sense buffers */
+		while (i < TW_Q_LENGTH) {
+			writel((u32)((u64)tw_dev->sense_buffer_phys[i] >> 32), TWL_HOBQPH_REG_ADDR(tw_dev));
+			writel((u32)tw_dev->sense_buffer_phys[i], TWL_HOBQPL_REG_ADDR(tw_dev));
+
+			/* Check status for over-run after each write */
+			status = readl(TWL_STATUS_REG_ADDR(tw_dev));
+			if (!(status & TWL_STATUS_OVERRUN_SUBMIT))
+			    i++;
+		}
+
+		/* Now check status */
+		status = readl(TWL_STATUS_REG_ADDR(tw_dev));
+		if (status) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x13, "Bad controller status after loading sense buffers");
+			do_soft_reset = 1;
+			tries++;
+			continue;
+		}
+
+		/* Drain the AEN queue */
+		if (twl_aen_drain_queue(tw_dev, soft_reset)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x14, "AEN drain failed during reset sequence");
+			do_soft_reset = 1;
+			tries++;
+			continue;
+		}
+
+		/* Load rest of compatibility struct */
+		strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION));
+		tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL;
+		tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
+		tw_dev->tw_compat_info.driver_build_high = TW_CURRENT_DRIVER_BUILD;
+		tw_dev->tw_compat_info.driver_srl_low = TW_BASE_FW_SRL;
+		tw_dev->tw_compat_info.driver_branch_low = TW_BASE_FW_BRANCH;
+		tw_dev->tw_compat_info.driver_build_low = TW_BASE_FW_BUILD;
+		tw_dev->tw_compat_info.fw_on_ctlr_srl = fw_on_ctlr_srl;
+		tw_dev->tw_compat_info.fw_on_ctlr_branch = fw_on_ctlr_branch;
+		tw_dev->tw_compat_info.fw_on_ctlr_build = fw_on_ctlr_build;
+
+		/* If we got here, controller is in a good state */
+		retval = 0;
+		goto out;
+	}
+out:
+	return retval;
+} /* End twl_reset_sequence() */
+
+/* This function will reset a device extension */
+static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset)
+{
+	int i = 0, retval = 1;
+	unsigned long flags = 0;
+
+	/* Block SCSI requests while we are resetting */
+	if (ioctl_reset)
+		scsi_block_requests(tw_dev->host);
+
+	set_bit(TW_IN_RESET, &tw_dev->flags);
+	TWL_MASK_INTERRUPTS(tw_dev);
+	TWL_CLEAR_DB_INTERRUPT(tw_dev);
+
+	spin_lock_irqsave(tw_dev->host->host_lock, flags);
+
+	/* Abort all requests that are in progress */
+	for (i = 0; i < TW_Q_LENGTH; i++) {
+		if ((tw_dev->state[i] != TW_S_FINISHED) &&
+		    (tw_dev->state[i] != TW_S_INITIAL) &&
+		    (tw_dev->state[i] != TW_S_COMPLETED)) {
+			if (tw_dev->srb[i]) {
+				tw_dev->srb[i]->result = (DID_RESET << 16);
+				tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
+				twl_unmap_scsi_data(tw_dev, i);
+			}
+		}
+	}
+
+	/* Reset queues and counts */
+	for (i = 0; i < TW_Q_LENGTH; i++) {
+		tw_dev->free_queue[i] = i;
+		tw_dev->state[i] = TW_S_INITIAL;
+	}
+	tw_dev->free_head = TW_Q_START;
+	tw_dev->free_tail = TW_Q_START;
+	tw_dev->posted_request_count = 0;
+
+	spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+
+	if (twl_reset_sequence(tw_dev, 1))
+		goto out;
+
+	TWL_UNMASK_INTERRUPTS(tw_dev);
+
+	clear_bit(TW_IN_RESET, &tw_dev->flags);
+	tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+
+	retval = 0;
+out:
+	if (ioctl_reset)
+		scsi_unblock_requests(tw_dev->host);
+	return retval;
+} /* End twl_reset_device_extension() */
+
+/* This funciton returns unit geometry in cylinders/heads/sectors */
+static int twl_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[])
+{
+	int heads, sectors;
+	TW_Device_Extension *tw_dev;
+
+	tw_dev = (TW_Device_Extension *)sdev->host->hostdata;
+
+	if (capacity >= 0x200000) {
+		heads = 255;
+		sectors = 63;
+	} else {
+		heads = 64;
+		sectors = 32;
+	}
+
+	geom[0] = heads;
+	geom[1] = sectors;
+	geom[2] = sector_div(capacity, heads * sectors); /* cylinders */
+
+	return 0;
+} /* End twl_scsi_biosparam() */
+
+/* This is the new scsi eh reset function */
+static int twl_scsi_eh_reset(struct scsi_cmnd *SCpnt)
+{
+	TW_Device_Extension *tw_dev = NULL;
+	int retval = FAILED;
+
+	tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+
+	tw_dev->num_resets++;
+
+	sdev_printk(KERN_WARNING, SCpnt->device,
+		"WARNING: (0x%02X:0x%04X): Command (0x%x) timed out, resetting card.\n",
+		TW_DRIVER, 0x2c, SCpnt->cmnd[0]);
+
+	/* Make sure we are not issuing an ioctl or resetting from ioctl */
+	mutex_lock(&tw_dev->ioctl_lock);
+
+	/* Now reset the card and some of the device extension data */
+	if (twl_reset_device_extension(tw_dev, 0)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "Controller reset failed during scsi host reset");
+		goto out;
+	}
+
+	retval = SUCCESS;
+out:
+	mutex_unlock(&tw_dev->ioctl_lock);
+	return retval;
+} /* End twl_scsi_eh_reset() */
+
+/* This is the main scsi queue function to handle scsi opcodes */
+static int twl_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+	int request_id, retval;
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+
+	/* If we are resetting due to timed out ioctl, report as busy */
+	if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
+		retval = SCSI_MLQUEUE_HOST_BUSY;
+		goto out;
+	}
+
+	/* Save done function into scsi_cmnd struct */
+	SCpnt->scsi_done = done;
+		
+	/* Get a free request id */
+	twl_get_request_id(tw_dev, &request_id);
+
+	/* Save the scsi command for use by the ISR */
+	tw_dev->srb[request_id] = SCpnt;
+
+	/* Initialize phase to zero */
+	SCpnt->SCp.phase = TW_PHASE_INITIAL;
+
+	retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
+	if (retval) {
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		twl_free_request_id(tw_dev, request_id);
+		SCpnt->result = (DID_ERROR << 16);
+		done(SCpnt);
+		retval = 0;
+	}
+out:
+	return retval;
+} /* End twl_scsi_queue() */
+
+/* This function tells the controller to shut down */
+static void __twl_shutdown(TW_Device_Extension *tw_dev)
+{
+	/* Disable interrupts */
+	TWL_MASK_INTERRUPTS(tw_dev);
+
+	/* Free up the IRQ */
+	free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+
+	printk(KERN_WARNING "3w-sas: Shutting down host %d.\n", tw_dev->host->host_no);
+
+	/* Tell the card we are shutting down */
+	if (twl_initconnection(tw_dev, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x16, "Connection shutdown failed");
+	} else {
+		printk(KERN_WARNING "3w-sas: Shutdown complete.\n");
+	}
+
+	/* Clear doorbell interrupt just before exit */
+	TWL_CLEAR_DB_INTERRUPT(tw_dev);
+} /* End __twl_shutdown() */
+
+/* Wrapper for __twl_shutdown */
+static void twl_shutdown(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	TW_Device_Extension *tw_dev;
+
+	if (!host)
+		return;
+
+	tw_dev = (TW_Device_Extension *)host->hostdata;
+
+	if (tw_dev->online) 
+		__twl_shutdown(tw_dev);
+} /* End twl_shutdown() */
+
+/* This function configures unit settings when a unit is coming on-line */
+static int twl_slave_configure(struct scsi_device *sdev)
+{
+	/* Force 60 second timeout */
+	blk_queue_rq_timeout(sdev->request_queue, 60 * HZ);
+
+	return 0;
+} /* End twl_slave_configure() */
+
+/* scsi_host_template initializer */
+static struct scsi_host_template driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "3w-sas",
+	.queuecommand		= twl_scsi_queue,
+	.eh_host_reset_handler	= twl_scsi_eh_reset,
+	.bios_param		= twl_scsi_biosparam,
+	.change_queue_depth	= twl_change_queue_depth,
+	.can_queue		= TW_Q_LENGTH-2,
+	.slave_configure	= twl_slave_configure,
+	.this_id		= -1,
+	.sg_tablesize		= TW_LIBERATOR_MAX_SGL_LENGTH,
+	.max_sectors		= TW_MAX_SECTORS,
+	.cmd_per_lun		= TW_MAX_CMDS_PER_LUN,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.shost_attrs		= twl_host_attrs,
+	.emulated		= 1
+};
+
+/* This function will probe and initialize a card */
+static int __devinit twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
+{
+	struct Scsi_Host *host = NULL;
+	TW_Device_Extension *tw_dev;
+	int retval = -ENODEV;
+	int *ptr_phycount, phycount=0;
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		TW_PRINTK(host, TW_DRIVER, 0x17, "Failed to enable pci device");
+		goto out_disable_device;
+	}
+
+	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
+
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
+	    || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
+		    || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
+			TW_PRINTK(host, TW_DRIVER, 0x18, "Failed to set dma mask");
+			retval = -ENODEV;
+			goto out_disable_device;
+		}
+
+	host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension));
+	if (!host) {
+		TW_PRINTK(host, TW_DRIVER, 0x19, "Failed to allocate memory for device extension");
+		retval = -ENOMEM;
+		goto out_disable_device;
+	}
+	tw_dev = shost_priv(host);
+
+	/* Save values to device extension */
+	tw_dev->host = host;
+	tw_dev->tw_pci_dev = pdev;
+
+	if (twl_initialize_device_extension(tw_dev)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Failed to initialize device extension");
+		goto out_free_device_extension;
+	}
+
+	/* Request IO regions */
+	retval = pci_request_regions(pdev, "3w-sas");
+	if (retval) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Failed to get mem region");
+		goto out_free_device_extension;
+	}
+
+	/* Save base address, use region 1 */
+	tw_dev->base_addr = pci_iomap(pdev, 1, 0);
+	if (!tw_dev->base_addr) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to ioremap");
+		goto out_release_mem_region;
+	}
+
+	/* Disable interrupts on the card */
+	TWL_MASK_INTERRUPTS(tw_dev);
+
+	/* Initialize the card */
+	if (twl_reset_sequence(tw_dev, 0)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Controller reset failed during probe");
+		goto out_iounmap;
+	}
+
+	/* Set host specific parameters */
+	host->max_id = TW_MAX_UNITS;
+	host->max_cmd_len = TW_MAX_CDB_LEN;
+	host->max_lun = TW_MAX_LUNS;
+	host->max_channel = 0;
+
+	/* Register the card with the kernel SCSI layer */
+	retval = scsi_add_host(host, &pdev->dev);
+	if (retval) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1e, "scsi add host failed");
+		goto out_iounmap;
+	}
+
+	pci_set_drvdata(pdev, host);
+
+	printk(KERN_WARNING "3w-sas: scsi%d: Found an LSI 3ware %s Controller at 0x%llx, IRQ: %d.\n",
+	       host->host_no,
+	       (char *)twl_get_param(tw_dev, 1, TW_VERSION_TABLE,
+				     TW_PARAM_MODEL, TW_PARAM_MODEL_LENGTH),
+	       (u64)pci_resource_start(pdev, 1), pdev->irq);
+
+	ptr_phycount = twl_get_param(tw_dev, 2, TW_PARAM_PHY_SUMMARY_TABLE,
+				     TW_PARAM_PHYCOUNT, TW_PARAM_PHYCOUNT_LENGTH);
+	if (ptr_phycount)
+		phycount = le32_to_cpu(*(int *)ptr_phycount);
+
+	printk(KERN_WARNING "3w-sas: scsi%d: Firmware %s, BIOS %s, Phys: %d.\n",
+	       host->host_no,
+	       (char *)twl_get_param(tw_dev, 1, TW_VERSION_TABLE,
+				     TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH),
+	       (char *)twl_get_param(tw_dev, 2, TW_VERSION_TABLE,
+				     TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH),
+	       phycount);
+
+	/* Try to enable MSI */
+	if (use_msi && !pci_enable_msi(pdev))
+		set_bit(TW_USING_MSI, &tw_dev->flags);
+
+	/* Now setup the interrupt handler */
+	retval = request_irq(pdev->irq, twl_interrupt, IRQF_SHARED, "3w-sas", tw_dev);
+	if (retval) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1f, "Error requesting IRQ");
+		goto out_remove_host;
+	}
+
+	twl_device_extension_list[twl_device_extension_count] = tw_dev;
+	twl_device_extension_count++;
+
+	/* Re-enable interrupts on the card */
+	TWL_UNMASK_INTERRUPTS(tw_dev);
+	
+	/* Finally, scan the host */
+	scsi_scan_host(host);
+
+	/* Add sysfs binary files */
+	if (sysfs_create_bin_file(&host->shost_dev.kobj, &twl_sysfs_aen_read_attr))
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x20, "Failed to create sysfs binary file: 3ware_aen_read");
+	if (sysfs_create_bin_file(&host->shost_dev.kobj, &twl_sysfs_compat_info_attr))
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x21, "Failed to create sysfs binary file: 3ware_compat_info");
+
+	if (twl_major == -1) {
+		if ((twl_major = register_chrdev (0, "twl", &twl_fops)) < 0)
+			TW_PRINTK(host, TW_DRIVER, 0x22, "Failed to register character device");
+	}
+	tw_dev->online = 1;
+	return 0;
+
+out_remove_host:
+	if (test_bit(TW_USING_MSI, &tw_dev->flags))
+		pci_disable_msi(pdev);
+	scsi_remove_host(host);
+out_iounmap:
+	iounmap(tw_dev->base_addr);
+out_release_mem_region:
+	pci_release_regions(pdev);
+out_free_device_extension:
+	twl_free_device_extension(tw_dev);
+	scsi_host_put(host);
+out_disable_device:
+	pci_disable_device(pdev);
+
+	return retval;
+} /* End twl_probe() */
+
+/* This function is called to remove a device */
+static void twl_remove(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	TW_Device_Extension *tw_dev;
+
+	if (!host)
+		return;
+
+	tw_dev = (TW_Device_Extension *)host->hostdata;
+
+	if (!tw_dev->online)
+		return;
+
+	/* Remove sysfs binary files */
+	sysfs_remove_bin_file(&host->shost_dev.kobj, &twl_sysfs_aen_read_attr);
+	sysfs_remove_bin_file(&host->shost_dev.kobj, &twl_sysfs_compat_info_attr);
+
+	scsi_remove_host(tw_dev->host);
+
+	/* Unregister character device */
+	if (twl_major >= 0) {
+		unregister_chrdev(twl_major, "twl");
+		twl_major = -1;
+	}
+
+	/* Shutdown the card */
+	__twl_shutdown(tw_dev);
+
+	/* Disable MSI if enabled */
+	if (test_bit(TW_USING_MSI, &tw_dev->flags))
+		pci_disable_msi(pdev);
+
+	/* Free IO remapping */
+	iounmap(tw_dev->base_addr);
+
+	/* Free up the mem region */
+	pci_release_regions(pdev);
+
+	/* Free up device extension resources */
+	twl_free_device_extension(tw_dev);
+
+	scsi_host_put(tw_dev->host);
+	pci_disable_device(pdev);
+	twl_device_extension_count--;
+} /* End twl_remove() */
+
+#ifdef CONFIG_PM
+/* This function is called on PCI suspend */
+static int twl_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+
+	printk(KERN_WARNING "3w-sas: Suspending host %d.\n", tw_dev->host->host_no);
+	/* Disable interrupts */
+	TWL_MASK_INTERRUPTS(tw_dev);
+
+	free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+
+	/* Tell the card we are shutting down */
+	if (twl_initconnection(tw_dev, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x23, "Connection shutdown failed during suspend");
+	} else {
+		printk(KERN_WARNING "3w-sas: Suspend complete.\n");
+	}
+
+	/* Clear doorbell interrupt */
+	TWL_CLEAR_DB_INTERRUPT(tw_dev);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+} /* End twl_suspend() */
+
+/* This function is called on PCI resume */
+static int twl_resume(struct pci_dev *pdev)
+{
+	int retval = 0;
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+
+	printk(KERN_WARNING "3w-sas: Resuming host %d.\n", tw_dev->host->host_no);
+	pci_set_power_state(pdev, PCI_D0);
+	pci_enable_wake(pdev, PCI_D0, 0);
+	pci_restore_state(pdev);
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x24, "Enable device failed during resume");
+		return retval;
+	}
+
+	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
+
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
+	    || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
+		    || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
+			TW_PRINTK(host, TW_DRIVER, 0x25, "Failed to set dma mask during resume");
+			retval = -ENODEV;
+			goto out_disable_device;
+		}
+
+	/* Initialize the card */
+	if (twl_reset_sequence(tw_dev, 0)) {
+		retval = -ENODEV;
+		goto out_disable_device;
+	}
+
+	/* Now setup the interrupt handler */
+	retval = request_irq(pdev->irq, twl_interrupt, IRQF_SHARED, "3w-sas", tw_dev);
+	if (retval) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x26, "Error requesting IRQ during resume");
+		retval = -ENODEV;
+		goto out_disable_device;
+	}
+
+	/* Now enable MSI if enabled */
+	if (test_bit(TW_USING_MSI, &tw_dev->flags))
+		pci_enable_msi(pdev);
+
+	/* Re-enable interrupts on the card */
+	TWL_UNMASK_INTERRUPTS(tw_dev);
+
+	printk(KERN_WARNING "3w-sas: Resume complete.\n");
+	return 0;
+
+out_disable_device:
+	scsi_remove_host(host);
+	pci_disable_device(pdev);
+
+	return retval;
+} /* End twl_resume() */
+#endif
+
+/* PCI Devices supported by this driver */
+static struct pci_device_id twl_pci_tbl[] __devinitdata = {
+	{ PCI_VDEVICE(3WARE, PCI_DEVICE_ID_3WARE_9750) },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, twl_pci_tbl);
+
+/* pci_driver initializer */
+static struct pci_driver twl_driver = {
+	.name		= "3w-sas",
+	.id_table	= twl_pci_tbl,
+	.probe		= twl_probe,
+	.remove		= twl_remove,
+#ifdef CONFIG_PM
+	.suspend	= twl_suspend,
+	.resume		= twl_resume,
+#endif
+	.shutdown	= twl_shutdown
+};
+
+/* This function is called on driver initialization */
+static int __init twl_init(void)
+{
+	printk(KERN_INFO "LSI 3ware SAS/SATA-RAID Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION);
+
+	return pci_register_driver(&twl_driver);
+} /* End twl_init() */
+
+/* This function is called on driver exit */
+static void __exit twl_exit(void)
+{
+	pci_unregister_driver(&twl_driver);
+} /* End twl_exit() */
+
+module_init(twl_init);
+module_exit(twl_exit);
+

+ 396 - 0
drivers/scsi/3w-sas.h

@@ -0,0 +1,396 @@
+/*
+   3w-sas.h -- LSI 3ware SAS/SATA-RAID Controller device driver for Linux.
+
+   Written By: Adam Radford <linuxraid@lsi.com>
+
+   Copyright (C) 2009 LSI Corporation.
+
+   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; version 2 of the License.
+
+   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.
+
+   NO WARRANTY
+   THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+   LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+   solely responsible for determining the appropriateness of using and
+   distributing the Program and assumes all risks associated with its
+   exercise of rights under this Agreement, including but not limited to
+   the risks and costs of program errors, damage to or loss of data,
+   programs or equipment, and unavailability or interruption of operations.
+
+   DISCLAIMER OF LIABILITY
+   NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+   HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+   Bugs/Comments/Suggestions should be mailed to:
+   linuxraid@lsi.com
+
+   For more information, goto:
+   http://www.lsi.com
+*/
+
+#ifndef _3W_SAS_H
+#define _3W_SAS_H
+
+/* AEN severity table */
+static char *twl_aen_severity_table[] =
+{
+	"None", "ERROR", "WARNING", "INFO", "DEBUG", NULL
+};
+
+/* Liberator register offsets */
+#define TWL_STATUS                         0x0  /* Status */
+#define TWL_HIBDB                          0x20 /* Inbound doorbell */
+#define TWL_HISTAT                         0x30 /* Host interrupt status */
+#define TWL_HIMASK                         0x34 /* Host interrupt mask */
+#define TWL_HOBDB			   0x9C /* Outbound doorbell */
+#define TWL_HOBDBC                         0xA0 /* Outbound doorbell clear */
+#define TWL_SCRPD3                         0xBC /* Scratchpad */
+#define TWL_HIBQPL                         0xC0 /* Host inbound Q low */
+#define TWL_HIBQPH                         0xC4 /* Host inbound Q high */
+#define TWL_HOBQPL                         0xC8 /* Host outbound Q low */
+#define TWL_HOBQPH                         0xCC /* Host outbound Q high */
+#define TWL_HISTATUS_VALID_INTERRUPT	   0xC
+#define TWL_HISTATUS_ATTENTION_INTERRUPT   0x4
+#define TWL_HISTATUS_RESPONSE_INTERRUPT	   0x8
+#define TWL_STATUS_OVERRUN_SUBMIT	   0x2000
+#define TWL_ISSUE_SOFT_RESET		   0x100
+#define TWL_CONTROLLER_READY		   0x2000
+#define TWL_DOORBELL_CONTROLLER_ERROR	   0x200000
+#define TWL_DOORBELL_ATTENTION_INTERRUPT   0x40000
+#define TWL_PULL_MODE			   0x1
+
+/* Command packet opcodes used by the driver */
+#define TW_OP_INIT_CONNECTION 0x1
+#define TW_OP_GET_PARAM	      0x12
+#define TW_OP_SET_PARAM	      0x13
+#define TW_OP_EXECUTE_SCSI    0x10
+
+/* Asynchronous Event Notification (AEN) codes used by the driver */
+#define TW_AEN_QUEUE_EMPTY       0x0000
+#define TW_AEN_SOFT_RESET        0x0001
+#define TW_AEN_SYNC_TIME_WITH_HOST 0x031
+#define TW_AEN_SEVERITY_ERROR    0x1
+#define TW_AEN_SEVERITY_DEBUG    0x4
+#define TW_AEN_NOT_RETRIEVED 0x1
+
+/* Command state defines */
+#define TW_S_INITIAL   0x1  /* Initial state */
+#define TW_S_STARTED   0x2  /* Id in use */
+#define TW_S_POSTED    0x4  /* Posted to the controller */
+#define TW_S_COMPLETED 0x8  /* Completed by isr */
+#define TW_S_FINISHED  0x10 /* I/O completely done */
+
+/* Compatibility defines */
+#define TW_9750_ARCH_ID 10
+#define TW_CURRENT_DRIVER_SRL 40
+#define TW_CURRENT_DRIVER_BUILD 0
+#define TW_CURRENT_DRIVER_BRANCH 0
+
+/* Phase defines */
+#define TW_PHASE_INITIAL 0
+#define TW_PHASE_SGLIST  2
+
+/* Misc defines */
+#define TW_SECTOR_SIZE                        512
+#define TW_MAX_UNITS			      32
+#define TW_INIT_MESSAGE_CREDITS		      0x100
+#define TW_INIT_COMMAND_PACKET_SIZE	      0x3
+#define TW_INIT_COMMAND_PACKET_SIZE_EXTENDED  0x6
+#define TW_EXTENDED_INIT_CONNECT	      0x2
+#define TW_BASE_FW_SRL			      24
+#define TW_BASE_FW_BRANCH		      0
+#define TW_BASE_FW_BUILD		      1
+#define TW_Q_LENGTH			      256
+#define TW_Q_START			      0
+#define TW_MAX_SLOT			      32
+#define TW_MAX_RESET_TRIES		      2
+#define TW_MAX_CMDS_PER_LUN		      254
+#define TW_MAX_AEN_DRAIN		      255
+#define TW_IN_RESET                           2
+#define TW_USING_MSI			      3
+#define TW_IN_ATTENTION_LOOP		      4
+#define TW_MAX_SECTORS                        256
+#define TW_MAX_CDB_LEN                        16
+#define TW_IOCTL_CHRDEV_TIMEOUT               60 /* 60 seconds */
+#define TW_IOCTL_CHRDEV_FREE                  -1
+#define TW_COMMAND_OFFSET                     128 /* 128 bytes */
+#define TW_VERSION_TABLE                      0x0402
+#define TW_TIMEKEEP_TABLE		      0x040A
+#define TW_INFORMATION_TABLE		      0x0403
+#define TW_PARAM_FWVER			      3
+#define TW_PARAM_FWVER_LENGTH		      16
+#define TW_PARAM_BIOSVER		      4
+#define TW_PARAM_BIOSVER_LENGTH		      16
+#define TW_PARAM_MODEL			      8
+#define TW_PARAM_MODEL_LENGTH		      16
+#define TW_PARAM_PHY_SUMMARY_TABLE	      1
+#define TW_PARAM_PHYCOUNT		      2
+#define TW_PARAM_PHYCOUNT_LENGTH	      1
+#define TW_IOCTL_FIRMWARE_PASS_THROUGH        0x108  // Used by smartmontools
+#define TW_ALLOCATION_LENGTH		      128
+#define TW_SENSE_DATA_LENGTH		      18
+#define TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED   0x10a
+#define TW_ERROR_INVALID_FIELD_IN_CDB	      0x10d
+#define TW_ERROR_UNIT_OFFLINE                 0x128
+#define TW_MESSAGE_SOURCE_CONTROLLER_ERROR    3
+#define TW_MESSAGE_SOURCE_CONTROLLER_EVENT    4
+#define TW_DRIVER 			      6
+#ifndef PCI_DEVICE_ID_3WARE_9750
+#define PCI_DEVICE_ID_3WARE_9750 0x1010
+#endif
+
+/* Bitmask macros to eliminate bitfields */
+
+/* opcode: 5, reserved: 3 */
+#define TW_OPRES_IN(x,y) ((x << 5) | (y & 0x1f))
+#define TW_OP_OUT(x) (x & 0x1f)
+
+/* opcode: 5, sgloffset: 3 */
+#define TW_OPSGL_IN(x,y) ((x << 5) | (y & 0x1f))
+#define TW_SGL_OUT(x) ((x >> 5) & 0x7)
+
+/* severity: 3, reserved: 5 */
+#define TW_SEV_OUT(x) (x & 0x7)
+
+/* not_mfa: 1, reserved: 7, status: 8, request_id: 16 */
+#define TW_RESID_OUT(x) ((x >> 16) & 0xffff)
+#define TW_NOTMFA_OUT(x) (x & 0x1)
+
+/* request_id: 12, lun: 4 */
+#define TW_REQ_LUN_IN(lun, request_id) (((lun << 12) & 0xf000) | (request_id & 0xfff))
+#define TW_LUN_OUT(lun) ((lun >> 12) & 0xf)
+
+/* Register access macros */
+#define TWL_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_STATUS)
+#define TWL_HOBQPL_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HOBQPL)
+#define TWL_HOBQPH_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HOBQPH)
+#define TWL_HOBDB_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HOBDB)
+#define TWL_HOBDBC_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HOBDBC)
+#define TWL_HIMASK_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HIMASK)
+#define TWL_HISTAT_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HISTAT)
+#define TWL_HIBQPH_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HIBQPH)
+#define TWL_HIBQPL_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HIBQPL)
+#define TWL_HIBDB_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HIBDB)
+#define TWL_SCRPD3_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_SCRPD3)
+#define TWL_MASK_INTERRUPTS(x) (writel(~0, TWL_HIMASK_REG_ADDR(tw_dev)))
+#define TWL_UNMASK_INTERRUPTS(x) (writel(~TWL_HISTATUS_VALID_INTERRUPT, TWL_HIMASK_REG_ADDR(tw_dev)))
+#define TWL_CLEAR_DB_INTERRUPT(x) (writel(~0, TWL_HOBDBC_REG_ADDR(tw_dev)))
+#define TWL_SOFT_RESET(x) (writel(TWL_ISSUE_SOFT_RESET, TWL_HIBDB_REG_ADDR(tw_dev)))
+
+/* Macros */
+#define TW_PRINTK(h,a,b,c) { \
+if (h) \
+printk(KERN_WARNING "3w-sas: scsi%d: ERROR: (0x%02X:0x%04X): %s.\n",h->host_no,a,b,c); \
+else \
+printk(KERN_WARNING "3w-sas: ERROR: (0x%02X:0x%04X): %s.\n",a,b,c); \
+}
+#define TW_MAX_LUNS 16
+#define TW_COMMAND_SIZE (sizeof(dma_addr_t) > 4 ? 6 : 4)
+#define TW_LIBERATOR_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 46 : 92)
+#define TW_LIBERATOR_MAX_SGL_LENGTH_OLD (sizeof(dma_addr_t) > 4 ? 47 : 94)
+#define TW_PADDING_LENGTH_LIBERATOR 136
+#define TW_PADDING_LENGTH_LIBERATOR_OLD 132
+#define TW_CPU_TO_SGL(x) (sizeof(dma_addr_t) > 4 ? cpu_to_le64(x) : cpu_to_le32(x))
+
+#pragma pack(1)
+
+/* SGL entry */
+typedef struct TAG_TW_SG_Entry_ISO {
+	dma_addr_t address;
+	dma_addr_t length;
+} TW_SG_Entry_ISO;
+
+/* Old Command Packet with ISO SGL */
+typedef struct TW_Command {
+	unsigned char opcode__sgloffset;
+	unsigned char size;
+	unsigned char request_id;
+	unsigned char unit__hostid;
+	/* Second DWORD */
+	unsigned char status;
+	unsigned char flags;
+	union {
+		unsigned short block_count;
+		unsigned short parameter_count;
+	} byte6_offset;
+	union {
+		struct {
+			u32 lba;
+			TW_SG_Entry_ISO sgl[TW_LIBERATOR_MAX_SGL_LENGTH_OLD];
+			unsigned char padding[TW_PADDING_LENGTH_LIBERATOR_OLD];
+		} io;
+		struct {
+			TW_SG_Entry_ISO sgl[TW_LIBERATOR_MAX_SGL_LENGTH_OLD];
+			u32 padding;
+			unsigned char padding2[TW_PADDING_LENGTH_LIBERATOR_OLD];
+		} param;
+	} byte8_offset;
+} TW_Command;
+
+/* New Command Packet with ISO SGL */
+typedef struct TAG_TW_Command_Apache {
+	unsigned char opcode__reserved;
+	unsigned char unit;
+	unsigned short request_id__lunl;
+	unsigned char status;
+	unsigned char sgl_offset;
+	unsigned short sgl_entries__lunh;
+	unsigned char cdb[16];
+	TW_SG_Entry_ISO sg_list[TW_LIBERATOR_MAX_SGL_LENGTH];
+	unsigned char padding[TW_PADDING_LENGTH_LIBERATOR];
+} TW_Command_Apache;
+
+/* New command packet header */
+typedef struct TAG_TW_Command_Apache_Header {
+	unsigned char sense_data[TW_SENSE_DATA_LENGTH];
+	struct {
+		char reserved[4];
+		unsigned short error;
+		unsigned char padding;
+		unsigned char severity__reserved;
+	} status_block;
+	unsigned char err_specific_desc[98];
+	struct {
+		unsigned char size_header;
+		unsigned short request_id;
+		unsigned char size_sense;
+	} header_desc;
+} TW_Command_Apache_Header;
+
+/* This struct is a union of the 2 command packets */
+typedef struct TAG_TW_Command_Full {
+	TW_Command_Apache_Header header;
+	union {
+		TW_Command oldcommand;
+		TW_Command_Apache newcommand;
+	} command;
+} TW_Command_Full;
+
+/* Initconnection structure */
+typedef struct TAG_TW_Initconnect {
+	unsigned char opcode__reserved;
+	unsigned char size;
+	unsigned char request_id;
+	unsigned char res2;
+	unsigned char status;
+	unsigned char flags;
+	unsigned short message_credits;
+	u32 features;
+	unsigned short fw_srl;
+	unsigned short fw_arch_id;
+	unsigned short fw_branch;
+	unsigned short fw_build;
+	u32 result;
+} TW_Initconnect;
+
+/* Event info structure */
+typedef struct TAG_TW_Event
+{
+	unsigned int sequence_id;
+	unsigned int time_stamp_sec;
+	unsigned short aen_code;
+	unsigned char severity;
+	unsigned char retrieved;
+	unsigned char repeat_count;
+	unsigned char parameter_len;
+	unsigned char parameter_data[98];
+} TW_Event;
+
+typedef struct TAG_TW_Ioctl_Driver_Command {
+	unsigned int control_code;
+	unsigned int status;
+	unsigned int unique_id;
+	unsigned int sequence_id;
+	unsigned int os_specific;
+	unsigned int buffer_length;
+} TW_Ioctl_Driver_Command;
+
+typedef struct TAG_TW_Ioctl_Apache {
+	TW_Ioctl_Driver_Command driver_command;
+        char padding[488];
+	TW_Command_Full firmware_command;
+	char data_buffer[1];
+} TW_Ioctl_Buf_Apache;
+
+/* GetParam descriptor */
+typedef struct {
+	unsigned short	table_id;
+	unsigned short	parameter_id;
+	unsigned short	parameter_size_bytes;
+	unsigned short  actual_parameter_size_bytes;
+	unsigned char	data[1];
+} TW_Param_Apache;
+
+/* Compatibility information structure */
+typedef struct TAG_TW_Compatibility_Info
+{
+	char driver_version[32];
+	unsigned short working_srl;
+	unsigned short working_branch;
+	unsigned short working_build;
+	unsigned short driver_srl_high;
+	unsigned short driver_branch_high;
+	unsigned short driver_build_high;
+	unsigned short driver_srl_low;
+	unsigned short driver_branch_low;
+	unsigned short driver_build_low;
+	unsigned short fw_on_ctlr_srl;
+	unsigned short fw_on_ctlr_branch;
+	unsigned short fw_on_ctlr_build;
+} TW_Compatibility_Info;
+
+#pragma pack()
+
+typedef struct TAG_TW_Device_Extension {
+	void                     __iomem *base_addr;
+	unsigned long	       	*generic_buffer_virt[TW_Q_LENGTH];
+	dma_addr_t	       	generic_buffer_phys[TW_Q_LENGTH];
+	TW_Command_Full	       	*command_packet_virt[TW_Q_LENGTH];
+	dma_addr_t		command_packet_phys[TW_Q_LENGTH];
+	TW_Command_Apache_Header *sense_buffer_virt[TW_Q_LENGTH];
+	dma_addr_t		sense_buffer_phys[TW_Q_LENGTH];
+	struct pci_dev		*tw_pci_dev;
+	struct scsi_cmnd	*srb[TW_Q_LENGTH];
+	unsigned char		free_queue[TW_Q_LENGTH];
+	unsigned char		free_head;
+	unsigned char		free_tail;
+	int     		state[TW_Q_LENGTH];
+	unsigned int		posted_request_count;
+	unsigned int		max_posted_request_count;
+	unsigned int		max_sgl_entries;
+	unsigned int		sgl_entries;
+	unsigned int		num_resets;
+	unsigned int		sector_count;
+	unsigned int		max_sector_count;
+	unsigned int		aen_count;
+	struct Scsi_Host	*host;
+	long			flags;
+	TW_Event                *event_queue[TW_Q_LENGTH];
+	unsigned char           error_index;
+	unsigned int            error_sequence_id;
+	int			chrdev_request_id;
+	wait_queue_head_t	ioctl_wqueue;
+	struct mutex		ioctl_lock;
+	TW_Compatibility_Info	tw_compat_info;
+	char			online;
+} TW_Device_Extension;
+
+#endif /* _3W_SAS_H */
+

+ 5 - 1
drivers/scsi/3w-xxxx.c

@@ -521,8 +521,12 @@ static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr,
 } /* End tw_show_stats() */
 
 /* This function will set a devices queue depth */
-static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				 int reason)
 {
+	if (reason != SCSI_QDEPTH_DEFAULT)
+		return -EOPNOTSUPP;
+
 	if (queue_depth > TW_Q_LENGTH-2)
 		queue_depth = TW_Q_LENGTH-2;
 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);

+ 5 - 2
drivers/scsi/53c700.c

@@ -175,7 +175,7 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
 STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt);
 STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt);
 STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt);
-static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth);
+static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth, int reason);
 static int NCR_700_change_queue_type(struct scsi_device *SDpnt, int depth);
 
 STATIC struct device_attribute *NCR_700_dev_attrs[];
@@ -2082,8 +2082,11 @@ NCR_700_slave_destroy(struct scsi_device *SDp)
 }
 
 static int
-NCR_700_change_queue_depth(struct scsi_device *SDp, int depth)
+NCR_700_change_queue_depth(struct scsi_device *SDp, int depth, int reason)
 {
+	if (reason != SCSI_QDEPTH_DEFAULT)
+		return -EOPNOTSUPP;
+
 	if (depth > NCR_700_MAX_TAGS)
 		depth = NCR_700_MAX_TAGS;
 

+ 28 - 1
drivers/scsi/Kconfig

@@ -399,6 +399,17 @@ config SCSI_3W_9XXX
 	  Please read the comments at the top of
 	  <file:drivers/scsi/3w-9xxx.c>.
 
+config SCSI_3W_SAS
+	tristate "3ware 97xx SAS/SATA-RAID support"
+	depends on PCI && SCSI
+	help
+	  This driver supports the LSI 3ware 9750 6Gb/s SAS/SATA-RAID cards.
+
+	  <http://www.lsi.com>
+
+	  Please read the comments at the top of
+	  <file:drivers/scsi/3w-sas.c>.
+
 config SCSI_7000FASST
 	tristate "7000FASST SCSI support"
 	depends on ISA && SCSI && ISA_DMA_API
@@ -621,6 +632,14 @@ config SCSI_FLASHPOINT
 	  substantial, so users of MultiMaster Host Adapters may not
 	  wish to include it.
 
+config VMWARE_PVSCSI
+	tristate "VMware PVSCSI driver support"
+	depends on PCI && SCSI && X86
+	help
+	  This driver supports VMware's para virtualized SCSI HBA.
+	  To compile this driver as a module, choose M here: the
+	  module will be called vmw_pvscsi.
+
 config LIBFC
 	tristate "LibFC module"
 	select SCSI_FC_ATTRS
@@ -644,7 +663,7 @@ config FCOE
 config FCOE_FNIC
 	tristate "Cisco FNIC Driver"
 	depends on PCI && X86
-	select LIBFC
+	select LIBFCOE
 	help
 	  This is support for the Cisco PCI-Express FCoE HBA.
 
@@ -1818,6 +1837,14 @@ config SCSI_PMCRAID
 	---help---
 	  This driver supports the PMC SIERRA MaxRAID adapters.
 
+config SCSI_PM8001
+	tristate "PMC-Sierra SPC 8001 SAS/SATA Based Host Adapter driver"
+	depends on PCI && SCSI
+	select SCSI_SAS_LIBSAS
+	help
+	  This driver supports PMC-Sierra PCIE SAS/SATA 8x6G SPC 8001 chip
+	  based host adapters.
+
 config SCSI_SRP
 	tristate "SCSI RDMA Protocol helper library"
 	depends on SCSI && PCI

+ 3 - 0
drivers/scsi/Makefile

@@ -70,6 +70,7 @@ obj-$(CONFIG_SCSI_AIC79XX)	+= aic7xxx/
 obj-$(CONFIG_SCSI_AACRAID)	+= aacraid/
 obj-$(CONFIG_SCSI_AIC7XXX_OLD)	+= aic7xxx_old.o
 obj-$(CONFIG_SCSI_AIC94XX)	+= aic94xx/
+obj-$(CONFIG_SCSI_PM8001)	+= pm8001/
 obj-$(CONFIG_SCSI_IPS)		+= ips.o
 obj-$(CONFIG_SCSI_FD_MCS)	+= fd_mcs.o
 obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
@@ -113,6 +114,7 @@ obj-$(CONFIG_SCSI_MESH)		+= mesh.o
 obj-$(CONFIG_SCSI_MAC53C94)	+= mac53c94.o
 obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
 obj-$(CONFIG_SCSI_3W_9XXX)	+= 3w-9xxx.o
+obj-$(CONFIG_SCSI_3W_SAS)	+= 3w-sas.o
 obj-$(CONFIG_SCSI_PPA)		+= ppa.o
 obj-$(CONFIG_SCSI_IMM)		+= imm.o
 obj-$(CONFIG_JAZZ_ESP)		+= esp_scsi.o	jazz_esp.o
@@ -133,6 +135,7 @@ obj-$(CONFIG_SCSI_CXGB3_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgb3i/
 obj-$(CONFIG_SCSI_BNX2_ISCSI)	+= libiscsi.o bnx2i/
 obj-$(CONFIG_BE2ISCSI)		+= libiscsi.o be2iscsi/
 obj-$(CONFIG_SCSI_PMCRAID)	+= pmcraid.o
+obj-$(CONFIG_VMWARE_PVSCSI)	+= vmw_pvscsi.o
 
 obj-$(CONFIG_ARM)		+= arm/
 

+ 5 - 1
drivers/scsi/aacraid/linit.c

@@ -472,8 +472,12 @@ static int aac_slave_configure(struct scsi_device *sdev)
  *	total capacity and the queue depth supported by the target device.
  */
 
-static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
+static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
+				  int reason)
 {
+	if (reason != SCSI_QDEPTH_DEFAULT)
+		return -EOPNOTSUPP;
+
 	if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
 	    (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
 		struct scsi_device * dev;

+ 4 - 1
drivers/scsi/arcmsr/arcmsr_hba.c

@@ -98,8 +98,11 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb);
 static const char *arcmsr_info(struct Scsi_Host *);
 static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
 static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
-								int queue_depth)
+					  int queue_depth, int reason)
 {
+	if (reason != SCSI_QDEPTH_DEFAULT)
+		return -EOPNOTSUPP;
+
 	if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
 		queue_depth = ARCMSR_MAX_CMD_PERLUN;
 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);

+ 9 - 15
drivers/scsi/be2iscsi/be.h

@@ -20,8 +20,10 @@
 
 #include <linux/pci.h>
 #include <linux/if_vlan.h>
-
-#define FW_VER_LEN 32
+#include <linux/blk-iopoll.h>
+#define FW_VER_LEN	32
+#define MCC_Q_LEN	128
+#define MCC_CQ_LEN	256
 
 struct be_dma_mem {
 	void *va;
@@ -74,18 +76,14 @@ static inline void queue_tail_inc(struct be_queue_info *q)
 
 struct be_eq_obj {
 	struct be_queue_info q;
-	char desc[32];
-
-	/* Adaptive interrupt coalescing (AIC) info */
-	bool enable_aic;
-	u16 min_eqd;		/* in usecs */
-	u16 max_eqd;		/* in usecs */
-	u16 cur_eqd;		/* in usecs */
+	struct beiscsi_hba *phba;
+	struct be_queue_info *cq;
+	struct blk_iopoll	iopoll;
 };
 
 struct be_mcc_obj {
-	struct be_queue_info *q;
-	struct be_queue_info *cq;
+	struct be_queue_info q;
+	struct be_queue_info cq;
 };
 
 struct be_ctrl_info {
@@ -176,8 +174,4 @@ static inline void swap_dws(void *wrb, int len)
 	} while (len);
 #endif /* __BIG_ENDIAN */
 }
-
-extern void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
-			      u16 num_popped);
-
 #endif /* BEISCSI_H */

+ 234 - 29
drivers/scsi/be2iscsi/be_cmds.c

@@ -19,6 +19,16 @@
 #include "be_mgmt.h"
 #include "be_main.h"
 
+static void be_mcc_notify(struct beiscsi_hba *phba)
+{
+	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+	u32 val = 0;
+
+	val |= mccq->id & DB_MCCQ_RING_ID_MASK;
+	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
+	iowrite32(val, phba->db_va + DB_MCCQ_OFFSET);
+}
+
 static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
 {
 	if (compl->flags != 0) {
@@ -54,13 +64,56 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
 	return 0;
 }
 
+
 static inline bool is_link_state_evt(u32 trailer)
 {
 	return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
-		ASYNC_TRAILER_EVENT_CODE_MASK) == ASYNC_EVENT_CODE_LINK_STATE);
+		  ASYNC_TRAILER_EVENT_CODE_MASK) ==
+		  ASYNC_EVENT_CODE_LINK_STATE);
+}
+
+static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba)
+{
+	struct be_queue_info *mcc_cq = &phba->ctrl.mcc_obj.cq;
+	struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
+
+	if (be_mcc_compl_is_new(compl)) {
+		queue_tail_inc(mcc_cq);
+		return compl;
+	}
+	return NULL;
+}
+
+static void be2iscsi_fail_session(struct iscsi_cls_session *cls_session)
+{
+	iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
+}
+
+static void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
+		struct be_async_event_link_state *evt)
+{
+	switch (evt->port_link_status) {
+	case ASYNC_EVENT_LINK_DOWN:
+		SE_DEBUG(DBG_LVL_1, "Link Down on Physical Port %d \n",
+						evt->physical_port);
+		phba->state |= BE_ADAPTER_LINK_DOWN;
+		break;
+	case ASYNC_EVENT_LINK_UP:
+		phba->state = BE_ADAPTER_UP;
+		SE_DEBUG(DBG_LVL_1, "Link UP on Physical Port %d \n",
+						evt->physical_port);
+		iscsi_host_for_each_session(phba->shost,
+					    be2iscsi_fail_session);
+		break;
+	default:
+		SE_DEBUG(DBG_LVL_1, "Unexpected Async Notification %d on"
+				    "Physical Port %d \n",
+				     evt->port_link_status,
+				     evt->physical_port);
+	}
 }
 
-void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
+static void beiscsi_cq_notify(struct beiscsi_hba *phba, u16 qid, bool arm,
 		       u16 num_popped)
 {
 	u32 val = 0;
@@ -68,7 +121,66 @@ void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
 	if (arm)
 		val |= 1 << DB_CQ_REARM_SHIFT;
 	val |= num_popped << DB_CQ_NUM_POPPED_SHIFT;
-	iowrite32(val, ctrl->db + DB_CQ_OFFSET);
+	iowrite32(val, phba->db_va + DB_CQ_OFFSET);
+}
+
+
+int beiscsi_process_mcc(struct beiscsi_hba *phba)
+{
+	struct be_mcc_compl *compl;
+	int num = 0, status = 0;
+	struct be_ctrl_info *ctrl = &phba->ctrl;
+
+	spin_lock_bh(&phba->ctrl.mcc_cq_lock);
+	while ((compl = be_mcc_compl_get(phba))) {
+		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
+			/* Interpret flags as an async trailer */
+			BUG_ON(!is_link_state_evt(compl->flags));
+
+			/* Interpret compl as a async link evt */
+			beiscsi_async_link_state_process(phba,
+				(struct be_async_event_link_state *) compl);
+		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
+				status = be_mcc_compl_process(ctrl, compl);
+				atomic_dec(&phba->ctrl.mcc_obj.q.used);
+		}
+		be_mcc_compl_use(compl);
+		num++;
+	}
+
+	if (num)
+		beiscsi_cq_notify(phba, phba->ctrl.mcc_obj.cq.id, true, num);
+
+	spin_unlock_bh(&phba->ctrl.mcc_cq_lock);
+	return status;
+}
+
+/* Wait till no more pending mcc requests are present */
+static int be_mcc_wait_compl(struct beiscsi_hba *phba)
+{
+#define mcc_timeout		120000 /* 5s timeout */
+	int i, status;
+	for (i = 0; i < mcc_timeout; i++) {
+		status = beiscsi_process_mcc(phba);
+		if (status)
+			return status;
+
+		if (atomic_read(&phba->ctrl.mcc_obj.q.used) == 0)
+			break;
+		udelay(100);
+	}
+	if (i == mcc_timeout) {
+		dev_err(&phba->pcidev->dev, "mccq poll timed out\n");
+		return -1;
+	}
+	return 0;
+}
+
+/* Notify MCC requests and wait for completion */
+int be_mcc_notify_wait(struct beiscsi_hba *phba)
+{
+	be_mcc_notify(phba);
+	return be_mcc_wait_compl(phba);
 }
 
 static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
@@ -142,6 +254,52 @@ int be_mbox_notify(struct be_ctrl_info *ctrl)
 	return 0;
 }
 
+/*
+ * Insert the mailbox address into the doorbell in two steps
+ * Polls on the mbox doorbell till a command completion (or a timeout) occurs
+ */
+static int be_mbox_notify_wait(struct beiscsi_hba *phba)
+{
+	int status;
+	u32 val = 0;
+	void __iomem *db = phba->ctrl.db + MPU_MAILBOX_DB_OFFSET;
+	struct be_dma_mem *mbox_mem = &phba->ctrl.mbox_mem;
+	struct be_mcc_mailbox *mbox = mbox_mem->va;
+	struct be_mcc_compl *compl = &mbox->compl;
+	struct be_ctrl_info *ctrl = &phba->ctrl;
+
+	val |= MPU_MAILBOX_DB_HI_MASK;
+	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
+	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
+	iowrite32(val, db);
+
+	/* wait for ready to be set */
+	status = be_mbox_db_ready_wait(ctrl);
+	if (status != 0)
+		return status;
+
+	val = 0;
+	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
+	val |= (u32)(mbox_mem->dma >> 4) << 2;
+	iowrite32(val, db);
+
+	status = be_mbox_db_ready_wait(ctrl);
+	if (status != 0)
+		return status;
+
+	/* A cq entry has been made now */
+	if (be_mcc_compl_is_new(compl)) {
+		status = be_mcc_compl_process(ctrl, &mbox->compl);
+		be_mcc_compl_use(compl);
+		if (status)
+			return status;
+	} else {
+		dev_err(&phba->pcidev->dev, "invalid mailbox completion\n");
+		return -1;
+	}
+	return 0;
+}
+
 void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
 				bool embedded, u8 sge_cnt)
 {
@@ -203,6 +361,20 @@ struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem)
 	return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
 }
 
+struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba)
+{
+	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+	struct be_mcc_wrb *wrb;
+
+	BUG_ON(atomic_read(&mccq->used) >= mccq->len);
+	wrb = queue_head_node(mccq);
+	queue_head_inc(mccq);
+	atomic_inc(&mccq->used);
+	memset(wrb, 0, sizeof(*wrb));
+	return wrb;
+}
+
+
 int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
 			  struct be_queue_info *eq, int eq_delay)
 {
@@ -212,6 +384,7 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
 	struct be_dma_mem *q_mem = &eq->dma_mem;
 	int status;
 
+	SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_eq_create\n");
 	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
@@ -249,6 +422,7 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
 	int status;
 	u8 *endian_check;
 
+	SE_DEBUG(DBG_LVL_8, "In be_cmd_fw_initialize\n");
 	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
@@ -282,6 +456,7 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
 	void *ctxt = &req->context;
 	int status;
 
+	SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_cq_create \n");
 	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
@@ -289,7 +464,6 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 			OPCODE_COMMON_CQ_CREATE, sizeof(*req));
-
 	if (!q_mem->va)
 		SE_DEBUG(DBG_LVL_1, "uninitialized q_mem->va\n");
 
@@ -329,6 +503,53 @@ static u32 be_encoded_q_len(int q_len)
 		len_encoded = 0;
 	return len_encoded;
 }
+
+int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
+			struct be_queue_info *mccq,
+			struct be_queue_info *cq)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_mcc_create *req;
+	struct be_dma_mem *q_mem = &mccq->dma_mem;
+	struct be_ctrl_info *ctrl;
+	void *ctxt;
+	int status;
+
+	spin_lock(&phba->ctrl.mbox_lock);
+	ctrl = &phba->ctrl;
+	wrb = wrb_from_mbox(&ctrl->mbox_mem);
+	req = embedded_payload(wrb);
+	ctxt = &req->context;
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			OPCODE_COMMON_MCC_CREATE, sizeof(*req));
+
+	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
+
+	AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt,
+		      PCI_FUNC(phba->pcidev->devfn));
+	AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1);
+	AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
+		be_encoded_q_len(mccq->len));
+	AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id);
+
+	be_dws_cpu_to_le(ctxt, sizeof(req->context));
+
+	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+	status = be_mbox_notify_wait(phba);
+	if (!status) {
+		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
+		mccq->id = le16_to_cpu(resp->id);
+		mccq->created = true;
+	}
+	spin_unlock(&phba->ctrl.mbox_lock);
+
+	return status;
+}
+
 int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
 			  int queue_type)
 {
@@ -337,6 +558,7 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
 	u8 subsys = 0, opcode = 0;
 	int status;
 
+	SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_q_destroy \n");
 	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -350,6 +572,10 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
 		subsys = CMD_SUBSYSTEM_COMMON;
 		opcode = OPCODE_COMMON_CQ_DESTROY;
 		break;
+	case QTYPE_MCCQ:
+		subsys = CMD_SUBSYSTEM_COMMON;
+		opcode = OPCODE_COMMON_MCC_DESTROY;
+		break;
 	case QTYPE_WRBQ:
 		subsys = CMD_SUBSYSTEM_ISCSI;
 		opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY;
@@ -377,30 +603,6 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
 	return status;
 }
 
-int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr)
-{
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_get_mac_addr *req = embedded_payload(wrb);
-	int status;
-
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
-			   OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
-			   sizeof(*req));
-
-	status = be_mbox_notify(ctrl);
-	if (!status) {
-		struct be_cmd_resp_get_mac_addr *resp = embedded_payload(wrb);
-
-		memcpy(mac_addr, resp->mac_address, ETH_ALEN);
-	}
-
-	spin_unlock(&ctrl->mbox_lock);
-	return status;
-}
-
 int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
 				    struct be_queue_info *cq,
 				    struct be_queue_info *dq, int length,
@@ -412,6 +614,7 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
 	void *ctxt = &req->context;
 	int status;
 
+	SE_DEBUG(DBG_LVL_8, "In be_cmd_create_default_pdu_queue\n");
 	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
@@ -468,8 +671,10 @@ int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
 
 	status = be_mbox_notify(ctrl);
-	if (!status)
+	if (!status) {
 		wrbq->id = le16_to_cpu(resp->cid);
+		wrbq->created = true;
+	}
 	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }

+ 31 - 6
drivers/scsi/be2iscsi/be_cmds.h

@@ -47,6 +47,8 @@ struct be_mcc_wrb {
 
 #define CQE_FLAGS_VALID_MASK (1 << 31)
 #define CQE_FLAGS_ASYNC_MASK (1 << 30)
+#define CQE_FLAGS_COMPLETED_MASK 	(1 << 28)
+#define CQE_FLAGS_CONSUMED_MASK 	(1 << 27)
 
 /* Completion Status */
 #define MCC_STATUS_SUCCESS 0x0
@@ -173,7 +175,7 @@ struct be_cmd_req_hdr {
 	u8 domain;		/* dword 0 */
 	u32 timeout;		/* dword 1 */
 	u32 request_length;	/* dword 2 */
-	u32 rsvd;		/* dword 3 */
+	u32 rsvd0;		/* dword 3 */
 };
 
 struct be_cmd_resp_hdr {
@@ -382,7 +384,6 @@ struct be_cmd_req_modify_eq_delay {
 
 #define ETH_ALEN	6
 
-
 struct be_cmd_req_get_mac_addr {
 	struct be_cmd_req_hdr hdr;
 	u32 nic_port_count;
@@ -417,14 +418,21 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
 
 int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
 			  int type);
+int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
+			struct be_queue_info *mccq,
+			struct be_queue_info *cq);
+
 int be_poll_mcc(struct be_ctrl_info *ctrl);
-unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl);
-int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr);
+unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
+				      struct beiscsi_hba *phba);
+int be_cmd_get_mac_addr(struct beiscsi_hba *phba, u8 *mac_addr);
 
 /*ISCSI Functuions */
 int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
 
 struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
+struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba);
+int be_mcc_notify_wait(struct beiscsi_hba *phba);
 
 int be_mbox_notify(struct be_ctrl_info *ctrl);
 
@@ -531,6 +539,23 @@ struct amap_sol_cqe {
 	u8 valid;		/* dword 3 */
 } __packed;
 
+#define SOL_ICD_INDEX_MASK	0x0003FFC0
+struct amap_sol_cqe_ring {
+	u8 hw_sts[8];		/* dword 0 */
+	u8 i_sts[8];		/* dword 0 */
+	u8 i_resp[8];		/* dword 0 */
+	u8 i_flags[7];		/* dword 0 */
+	u8 s;			/* dword 0 */
+	u8 i_exp_cmd_sn[32];	/* dword 1 */
+	u8 code[6];		/* dword 2 */
+	u8 icd_index[12];	/* dword 2 */
+	u8 rsvd[6];		/* dword 2 */
+	u8 i_cmd_wnd[8];	/* dword 2 */
+	u8 i_res_cnt[31];	/* dword 3 */
+	u8 valid;		/* dword 3 */
+} __packed;
+
+
 
 /**
  * Post WRB Queue Doorbell Register used by the host Storage
@@ -664,8 +689,8 @@ struct be_fw_cfg {
 #define	OPCODE_COMMON_TCP_UPLOAD	56
 #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1
 /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
-#define CMD_ISCSI_CONNECTION_INVALIDATE 1
-#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 2
+#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001
+#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002
 #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
 
 #define INI_WR_CMD			1	/* Initiator write command */

+ 13 - 10
drivers/scsi/be2iscsi/be_iscsi.c

@@ -67,11 +67,11 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
 		cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
 	}
 
-	 cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
-					   shost, cmds_max,
-					   sizeof(*beiscsi_sess),
-					   sizeof(*io_task),
-					   initial_cmdsn, ISCSI_MAX_TARGET);
+	cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
+					  shost, cmds_max,
+					  sizeof(*beiscsi_sess),
+					  sizeof(*io_task),
+					  initial_cmdsn, ISCSI_MAX_TARGET);
 	if (!cls_session)
 		return NULL;
 	sess = cls_session->dd_data;
@@ -297,7 +297,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
 
 	switch (param) {
 	case ISCSI_HOST_PARAM_HWADDRESS:
-		be_cmd_get_mac_addr(&phba->ctrl, phba->mac_address);
+		be_cmd_get_mac_addr(phba, phba->mac_address);
 		len = sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
 		break;
 	default:
@@ -377,16 +377,12 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
 	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
 	struct beiscsi_endpoint *beiscsi_ep;
 	struct beiscsi_offload_params params;
-	struct iscsi_session *session = conn->session;
-	struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
-	struct beiscsi_hba *phba = iscsi_host_priv(shost);
 
 	memset(&params, 0, sizeof(struct beiscsi_offload_params));
 	beiscsi_ep = beiscsi_conn->ep;
 	if (!beiscsi_ep)
 		SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n");
 
-	free_mgmt_sgl_handle(phba, beiscsi_conn->plogin_sgl_handle);
 	beiscsi_conn->login_in_progress = 0;
 	beiscsi_set_params_for_offld(beiscsi_conn, &params);
 	beiscsi_offload_connection(beiscsi_conn, &params);
@@ -498,6 +494,13 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
 		SE_DEBUG(DBG_LVL_1, "shost is NULL \n");
 		return ERR_PTR(ret);
 	}
+
+	if (phba->state) {
+		ret = -EBUSY;
+		SE_DEBUG(DBG_LVL_1, "The Adapet state is Not UP \n");
+		return ERR_PTR(ret);
+	}
+
 	ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
 	if (!ep) {
 		ret = -ENOMEM;

File diff suppressed because it is too large
+ 473 - 171
drivers/scsi/be2iscsi/be_main.c


+ 28 - 21
drivers/scsi/be2iscsi/be_main.h

@@ -21,11 +21,9 @@
 #ifndef _BEISCSI_MAIN_
 #define _BEISCSI_MAIN_
 
-
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/in.h>
-#include <linux/blk-iopoll.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -35,12 +33,8 @@
 #include <scsi/scsi_transport_iscsi.h>
 
 #include "be.h"
-
-
-
 #define DRV_NAME		"be2iscsi"
 #define BUILD_STR		"2.0.527.0"
-
 #define BE_NAME			"ServerEngines BladeEngine2" \
 				"Linux iSCSI Driver version" BUILD_STR
 #define DRV_DESC		BE_NAME " " "Driver"
@@ -49,6 +43,8 @@
 #define BE_DEVICE_ID1		0x212
 #define OC_DEVICE_ID1		0x702
 #define OC_DEVICE_ID2		0x703
+#define OC_DEVICE_ID3		0x712
+#define OC_DEVICE_ID4		0x222
 
 #define BE2_MAX_SESSIONS	64
 #define BE2_CMDS_PER_CXN	128
@@ -63,6 +59,7 @@
 #define BE2_IO_DEPTH \
 	(BE2_MAX_ICDS / 2 - (BE2_LOGOUTS + BE2_TMFS + BE2_NOPOUT_REQ))
 
+#define MAX_CPUS		31
 #define BEISCSI_SGLIST_ELEMENTS	BE2_SGE
 
 #define BEISCSI_MAX_CMNDS	1024	/* Max IO's per Ctrlr sht->can_queue */
@@ -79,7 +76,7 @@
 #define BE_SENSE_INFO_SIZE		258
 #define BE_ISCSI_PDU_HEADER_SIZE	64
 #define BE_MIN_MEM_SIZE			16384
-
+#define MAX_CMD_SZ			65536
 #define IIOC_SCSI_DATA                  0x05	/* Write Operation */
 
 #define DBG_LVL				0x00000001
@@ -100,6 +97,8 @@ do {							\
 	}						\
 } while (0);
 
+#define BE_ADAPTER_UP		0x00000000
+#define BE_ADAPTER_LINK_DOWN	0x00000001
 /**
  * hardware needs the async PDU buffers to be posted in multiples of 8
  * So have atleast 8 of them by default
@@ -160,21 +159,19 @@ do {							\
 
 enum be_mem_enum {
 	HWI_MEM_ADDN_CONTEXT,
-	HWI_MEM_CQ,
-	HWI_MEM_EQ,
 	HWI_MEM_WRB,
 	HWI_MEM_WRBH,
-	HWI_MEM_SGLH,	/* 5 */
+	HWI_MEM_SGLH,
 	HWI_MEM_SGE,
-	HWI_MEM_ASYNC_HEADER_BUF,
+	HWI_MEM_ASYNC_HEADER_BUF, 	/* 5 */
 	HWI_MEM_ASYNC_DATA_BUF,
 	HWI_MEM_ASYNC_HEADER_RING,
-	HWI_MEM_ASYNC_DATA_RING,	/* 10 */
+	HWI_MEM_ASYNC_DATA_RING,
 	HWI_MEM_ASYNC_HEADER_HANDLE,
-	HWI_MEM_ASYNC_DATA_HANDLE,
+	HWI_MEM_ASYNC_DATA_HANDLE, 	/* 10 */
 	HWI_MEM_ASYNC_PDU_CONTEXT,
 	ISCSI_MEM_GLOBAL_HEADER,
-	SE_MEM_MAX  	/* 15 */
+	SE_MEM_MAX
 };
 
 struct be_bus_address32 {
@@ -212,6 +209,9 @@ struct be_mem_descriptor {
 
 struct sgl_handle {
 	unsigned int sgl_index;
+	unsigned int type;
+	unsigned int cid;
+	struct iscsi_task *task;
 	struct iscsi_sge *pfrag;
 };
 
@@ -274,13 +274,17 @@ struct beiscsi_hba {
 	struct pci_dev *pcidev;
 	unsigned int state;
 	unsigned short asic_revision;
-	struct blk_iopoll	iopoll;
+	unsigned int num_cpus;
+	unsigned int nxt_cqid;
+	struct msix_entry msix_entries[MAX_CPUS + 1];
+	bool msix_enabled;
 	struct be_mem_descriptor *init_mem;
 
 	unsigned short io_sgl_alloc_index;
 	unsigned short io_sgl_free_index;
 	unsigned short io_sgl_hndl_avbl;
 	struct sgl_handle **io_sgl_hndl_base;
+	struct sgl_handle **sgl_hndl_array;
 
 	unsigned short eh_sgl_alloc_index;
 	unsigned short eh_sgl_free_index;
@@ -315,6 +319,7 @@ struct beiscsi_hba {
 		unsigned short cid_alloc;
 		unsigned short cid_free;
 		unsigned short avlbl_cids;
+		unsigned short iscsi_features;
 		spinlock_t cid_lock;
 	} fw_config;
 
@@ -343,6 +348,7 @@ struct beiscsi_conn {
 	unsigned short login_in_progress;
 	struct sgl_handle *plogin_sgl_handle;
 	struct beiscsi_session *beiscsi_sess;
+	struct iscsi_task *task;
 };
 
 /* This structure is used by the chip */
@@ -390,7 +396,7 @@ struct beiscsi_io_task {
 	unsigned int flags;
 	unsigned short cid;
 	unsigned short header_len;
-
+	itt_t libiscsi_itt;
 	struct be_cmd_bhs *cmd_bhs;
 	struct be_bus_address bhs_pa;
 	unsigned short bhs_len;
@@ -599,7 +605,6 @@ struct amap_cq_db {
 
 void beiscsi_process_eq(struct beiscsi_hba *phba);
 
-
 struct iscsi_wrb {
 	u32 dw[16];
 } __packed;
@@ -820,10 +825,12 @@ struct wrb_handle {
 };
 
 struct hwi_context_memory {
-	struct be_eq_obj be_eq;
-	struct be_queue_info be_cq;
-	struct be_queue_info be_mcc_cq;
-	struct be_queue_info be_mcc;
+	/* Adaptive interrupt coalescing (AIC) info */
+	u16 min_eqd;		/* in usecs */
+	u16 max_eqd;		/* in usecs */
+	u16 cur_eqd;		/* in usecs */
+	struct be_eq_obj be_eq[MAX_CPUS];
+	struct be_queue_info be_cq[MAX_CPUS];
 
 	struct be_queue_info be_def_hdrq;
 	struct be_queue_info be_def_dataq;

+ 52 - 17
drivers/scsi/be2iscsi/be_mgmt.c

@@ -35,7 +35,6 @@ unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl,
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 			   OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
-
 	status = be_mbox_notify(ctrl);
 	if (!status) {
 		struct be_fw_cfg *pfw_cfg;
@@ -58,7 +57,8 @@ unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl,
 	return status;
 }
 
-unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl)
+unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
+				      struct beiscsi_hba *phba)
 {
 	struct be_dma_mem nonemb_cmd;
 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
@@ -85,7 +85,6 @@ unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl)
 	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
 	sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
 	sge->len = cpu_to_le32(nonemb_cmd.size);
-
 	status = be_mbox_notify(ctrl);
 	if (!status) {
 		struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va;
@@ -95,21 +94,25 @@ unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl)
 			resp->params.hba_attribs.firmware_version_string);
 		SE_DEBUG(DBG_LVL_8,
 			"Developer Build, not performing version check...\n");
-
+		phba->fw_config.iscsi_features =
+				resp->params.hba_attribs.iscsi_features;
+		SE_DEBUG(DBG_LVL_8, " phba->fw_config.iscsi_features = %d\n",
+				      phba->fw_config.iscsi_features);
 	} else
 		SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n");
+	spin_unlock(&ctrl->mbox_lock);
 	if (nonemb_cmd.va)
 		pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
 				    nonemb_cmd.va, nonemb_cmd.dma);
 
-	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
+
 unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
 {
 	struct be_ctrl_info *ctrl = &phba->ctrl;
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+	struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
 	struct iscsi_cleanup_req *req = embedded_payload(wrb);
 	int status = 0;
 
@@ -124,7 +127,7 @@ unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
 	req->hdr_ring_id = 0;
 	req->data_ring_id = 0;
 
-	status = be_mbox_notify(ctrl);
+	status =  be_mcc_notify_wait(phba);
 	if (status)
 		shost_printk(KERN_WARNING, phba->shost,
 			     " mgmt_epfw_cleanup , FAILED\n");
@@ -137,7 +140,7 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
 {
 	struct be_dma_mem nonemb_cmd;
 	struct be_ctrl_info *ctrl = &phba->ctrl;
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+	struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
 	struct be_sge *sge = nonembedded_sgl(wrb);
 	struct invalidate_commands_params_in *req;
 	int status = 0;
@@ -169,7 +172,7 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
 	sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
 	sge->len = cpu_to_le32(nonemb_cmd.size);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mcc_notify_wait(phba);
 	if (status)
 		SE_DEBUG(DBG_LVL_1, "ICDS Invalidation Failed\n");
 	spin_unlock(&ctrl->mbox_lock);
@@ -186,7 +189,7 @@ unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba,
 					 unsigned short savecfg_flag)
 {
 	struct be_ctrl_info *ctrl = &phba->ctrl;
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+	struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
 	struct iscsi_invalidate_connection_params_in *req =
 						embedded_payload(wrb);
 	int status = 0;
@@ -205,7 +208,7 @@ unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba,
 	else
 		req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE;
 	req->save_cfg = savecfg_flag;
-	status = be_mbox_notify(ctrl);
+	status =  be_mcc_notify_wait(phba);
 	if (status)
 		SE_DEBUG(DBG_LVL_1, "Invalidation Failed\n");
 
@@ -217,7 +220,7 @@ unsigned char mgmt_upload_connection(struct beiscsi_hba *phba,
 				unsigned short cid, unsigned int upload_flag)
 {
 	struct be_ctrl_info *ctrl = &phba->ctrl;
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+	struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
 	struct tcp_upload_params_in *req = embedded_payload(wrb);
 	int status = 0;
 
@@ -229,7 +232,7 @@ unsigned char mgmt_upload_connection(struct beiscsi_hba *phba,
 			   OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
 	req->id = (unsigned short)cid;
 	req->upload_type = (unsigned char)upload_flag;
-	status = be_mbox_notify(ctrl);
+	status = be_mcc_notify_wait(phba);
 	if (status)
 		SE_DEBUG(DBG_LVL_1, "mgmt_upload_connection Failed\n");
 	spin_unlock(&ctrl->mbox_lock);
@@ -245,13 +248,14 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
 	struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr;
 	struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr;
 	struct be_ctrl_info *ctrl = &phba->ctrl;
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+	struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
 	struct tcp_connect_and_offload_in *req = embedded_payload(wrb);
 	unsigned short def_hdr_id;
 	unsigned short def_data_id;
 	struct phys_addr template_address = { 0, 0 };
 	struct phys_addr *ptemplate_address;
 	int status = 0;
+	unsigned int i;
 	unsigned short cid = beiscsi_ep->ep_cid;
 
 	phwi_ctrlr = phba->phwi_ctrlr;
@@ -296,14 +300,18 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
 
 	}
 	req->cid = cid;
-	req->cq_id = phwi_context->be_cq.id;
+	i = phba->nxt_cqid++;
+	if (phba->nxt_cqid == phba->num_cpus)
+		phba->nxt_cqid = 0;
+	req->cq_id = phwi_context->be_cq[i].id;
+	SE_DEBUG(DBG_LVL_8, "i=%d cq_id=%d \n", i, req->cq_id);
 	req->defq_id = def_hdr_id;
 	req->hdr_ring_id = def_hdr_id;
 	req->data_ring_id = def_data_id;
 	req->do_offload = 1;
 	req->dataout_template_pa.lo = ptemplate_address->lo;
 	req->dataout_template_pa.hi = ptemplate_address->hi;
-	status = be_mbox_notify(ctrl);
+	status = be_mcc_notify_wait(phba);
 	if (!status) {
 		struct iscsi_endpoint *ep;
 		struct tcp_connect_and_offload_out *ptcpcnct_out =
@@ -311,7 +319,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
 
 		ep = phba->ep_array[ptcpcnct_out->cid];
 		beiscsi_ep = ep->dd_data;
-		beiscsi_ep->fw_handle = 0;
+		beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
 		beiscsi_ep->cid_vld = 1;
 		SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
 	} else
@@ -319,3 +327,30 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
 	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
+
+int be_cmd_get_mac_addr(struct beiscsi_hba *phba, u8 *mac_addr)
+{
+	struct be_ctrl_info *ctrl = &phba->ctrl;
+	struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
+	struct be_cmd_req_get_mac_addr *req = embedded_payload(wrb);
+	int status;
+
+	SE_DEBUG(DBG_LVL_8, "In be_cmd_get_mac_addr\n");
+	spin_lock(&ctrl->mbox_lock);
+	memset(wrb, 0, sizeof(*wrb));
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+			   OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
+			   sizeof(*req));
+
+	status = be_mcc_notify_wait(phba);
+	if (!status) {
+		struct be_cmd_resp_get_mac_addr *resp = embedded_payload(wrb);
+
+		memcpy(mac_addr, resp->mac_address, ETH_ALEN);
+	}
+
+	spin_unlock(&ctrl->mbox_lock);
+	return status;
+}
+

+ 7 - 1
drivers/scsi/be2iscsi/be_mgmt.h

@@ -175,7 +175,9 @@ struct mgmt_hba_attributes {
 	u8 phy_port;
 	u32 firmware_post_status;
 	u32 hba_mtu[8];
-	u32 future_u32[4];
+	u8 iscsi_features;
+	u8 future_u8[3];
+	u32 future_u32[3];
 } __packed;
 
 struct mgmt_controller_attributes {
@@ -246,4 +248,8 @@ unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba,
 					 unsigned short cid,
 					 unsigned short issue_reset,
 					 unsigned short savecfg_flag);
+
+unsigned char mgmt_fw_cmd(struct be_ctrl_info *ctrl,
+			  struct beiscsi_hba *phba,
+			  char *buf, unsigned int len);
 #endif

+ 5 - 5
drivers/scsi/bfa/bfa_cb_ioim_macros.h

@@ -51,7 +51,7 @@ bfad_int_to_lun(u32 luno)
 	lun.bfa_lun     = 0;
 	lun.scsi_lun[0] = bfa_os_htons(luno);
 
-	return (lun.bfa_lun);
+	return lun.bfa_lun;
 }
 
 /**
@@ -68,7 +68,7 @@ bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio)
 {
 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
 
-	return ((u8 *) cmnd->cmnd);
+	return (u8 *) cmnd->cmnd;
 }
 
 /**
@@ -97,7 +97,7 @@ bfa_cb_ioim_get_size(struct bfad_ioim_s *dio)
 {
 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
 
-	return (scsi_bufflen(cmnd));
+	return scsi_bufflen(cmnd);
 }
 
 /**
@@ -129,7 +129,7 @@ bfa_cb_ioim_get_sgaddr(struct bfad_ioim_s *dio, int sgeid)
 	sge = (struct scatterlist *)scsi_sglist(cmnd) + sgeid;
 	addr = (u64) sg_dma_address(sge);
 
-	return (*(union bfi_addr_u *) &addr);
+	return *((union bfi_addr_u *) &addr);
 }
 
 static inline u32
@@ -197,7 +197,7 @@ bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio)
 {
 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
 
-	return (cmnd->cmd_len);
+	return cmnd->cmd_len;
 }
 
 

+ 1 - 1
drivers/scsi/bfa/bfa_cee.c

@@ -228,7 +228,7 @@ bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
 u32
 bfa_cee_meminfo(void)
 {
-	return (bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo());
+	return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
 }
 
 /**

+ 2 - 2
drivers/scsi/bfa/bfa_csdebug.c

@@ -47,12 +47,12 @@ bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
 	tqe = bfa_q_next(q);
 	while (tqe != q) {
 		if (tqe == qe)
-			return (1);
+			return 1;
 		tqe = bfa_q_next(tqe);
 		if (tqe == NULL)
 			break;
 	}
-	return (0);
+	return 0;
 }
 
 

+ 2 - 2
drivers/scsi/bfa/bfa_fcpim.c

@@ -131,7 +131,7 @@ bfa_fcpim_path_tov_get(struct bfa_s *bfa)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 
-	return (fcpim->path_tov / 1000);
+	return fcpim->path_tov / 1000;
 }
 
 bfa_status_t
@@ -169,7 +169,7 @@ bfa_fcpim_qdepth_get(struct bfa_s *bfa)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 
-	return (fcpim->q_depth);
+	return fcpim->q_depth;
 }
 
 

+ 2 - 2
drivers/scsi/bfa/bfa_fcpim_priv.h

@@ -35,7 +35,7 @@
 #define BFA_FCPIM_PATHTOV_MAX	(90 * 1000)	/* in millisecs */
 
 #define bfa_fcpim_stats(__fcpim, __stats)   \
-    (__fcpim)->stats.__stats ++
+    ((__fcpim)->stats.__stats++)
 
 struct bfa_fcpim_mod_s {
 	struct bfa_s 	*bfa;
@@ -143,7 +143,7 @@ struct bfa_itnim_s {
 	struct bfa_itnim_hal_stats_s	stats;
 };
 
-#define bfa_itnim_is_online(_itnim) (_itnim)->is_online
+#define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
 #define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
 #define BFA_IOIM_FROM_TAG(_fcpim, _iotag)	\
 	(&fcpim->ioim_arr[_iotag])

+ 28 - 31
drivers/scsi/bfa/bfa_fcport.c

@@ -388,32 +388,29 @@ bfa_pport_sm_linkup(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 		bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
 		bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
 			     BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
-		if (BFA_PORT_IS_DISABLED(pport->bfa)) {
+		if (BFA_PORT_IS_DISABLED(pport->bfa))
 			bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
-		} else {
+		else
 			bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
-		}
 		break;
 
 	case BFA_PPORT_SM_STOP:
 		bfa_sm_set_state(pport, bfa_pport_sm_stopped);
 		bfa_pport_reset_linkinfo(pport);
-		if (BFA_PORT_IS_DISABLED(pport->bfa)) {
+		if (BFA_PORT_IS_DISABLED(pport->bfa))
 			bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
-		} else {
+		else
 			bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
-		}
 		break;
 
 	case BFA_PPORT_SM_HWFAIL:
 		bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
 		bfa_pport_reset_linkinfo(pport);
 		bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
-		if (BFA_PORT_IS_DISABLED(pport->bfa)) {
+		if (BFA_PORT_IS_DISABLED(pport->bfa))
 			bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
-		} else {
+		else
 			bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
-		}
 		break;
 
 	default:
@@ -999,10 +996,10 @@ bfa_pport_enable(struct bfa_s *bfa)
 	struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
 
 	if (pport->diag_busy)
-		return (BFA_STATUS_DIAG_BUSY);
+		return BFA_STATUS_DIAG_BUSY;
 	else if (bfa_sm_cmp_state
 		 (BFA_PORT_MOD(bfa), bfa_pport_sm_disabling_qwait))
-		return (BFA_STATUS_DEVBUSY);
+		return BFA_STATUS_DEVBUSY;
 
 	bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_ENABLE);
 	return BFA_STATUS_OK;
@@ -1032,7 +1029,7 @@ bfa_pport_cfg_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
 
 	pport->cfg.speed = speed;
 
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 /**
@@ -1068,7 +1065,7 @@ bfa_pport_cfg_topology(struct bfa_s *bfa, enum bfa_pport_topology topology)
 	}
 
 	pport->cfg.topology = topology;
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 /**
@@ -1094,7 +1091,7 @@ bfa_pport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
 	pport->cfg.cfg_hardalpa = BFA_TRUE;
 	pport->cfg.hardalpa = alpa;
 
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 bfa_status_t
@@ -1106,7 +1103,7 @@ bfa_pport_clr_hardalpa(struct bfa_s *bfa)
 	bfa_trc(bfa, pport->cfg.hardalpa);
 
 	pport->cfg.cfg_hardalpa = BFA_FALSE;
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 bfa_boolean_t
@@ -1138,16 +1135,16 @@ bfa_pport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
 	 * with in range
 	 */
 	if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
-		return (BFA_STATUS_INVLD_DFSZ);
+		return BFA_STATUS_INVLD_DFSZ;
 
 	/*
 	 * power of 2, if not the max frame size of 2112
 	 */
 	if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
-		return (BFA_STATUS_INVLD_DFSZ);
+		return BFA_STATUS_INVLD_DFSZ;
 
 	pport->cfg.maxfrsize = maxfrsize;
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 u16
@@ -1415,7 +1412,7 @@ bfa_pport_get_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats,
 
 	if (port->stats_busy) {
 		bfa_trc(bfa, port->stats_busy);
-		return (BFA_STATUS_DEVBUSY);
+		return BFA_STATUS_DEVBUSY;
 	}
 
 	port->stats_busy = BFA_TRUE;
@@ -1427,7 +1424,7 @@ bfa_pport_get_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats,
 
 	bfa_timer_start(bfa, &port->timer, bfa_port_stats_timeout, port,
 			BFA_PORT_STATS_TOV);
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 bfa_status_t
@@ -1437,7 +1434,7 @@ bfa_pport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
 
 	if (port->stats_busy) {
 		bfa_trc(bfa, port->stats_busy);
-		return (BFA_STATUS_DEVBUSY);
+		return BFA_STATUS_DEVBUSY;
 	}
 
 	port->stats_busy = BFA_TRUE;
@@ -1448,7 +1445,7 @@ bfa_pport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
 
 	bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port,
 			BFA_PORT_STATS_TOV);
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 bfa_status_t
@@ -1515,7 +1512,7 @@ bfa_pport_get_qos_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats,
 	/*
 	 * QoS stats is embedded in port stats
 	 */
-	return (bfa_pport_get_stats(bfa, stats, cbfn, cbarg));
+	return bfa_pport_get_stats(bfa, stats, cbfn, cbarg);
 }
 
 bfa_status_t
@@ -1525,7 +1522,7 @@ bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
 
 	if (port->stats_busy) {
 		bfa_trc(bfa, port->stats_busy);
-		return (BFA_STATUS_DEVBUSY);
+		return BFA_STATUS_DEVBUSY;
 	}
 
 	port->stats_busy = BFA_TRUE;
@@ -1536,7 +1533,7 @@ bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
 
 	bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port,
 			BFA_PORT_STATS_TOV);
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 /**
@@ -1545,7 +1542,7 @@ bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
 bfa_status_t
 bfa_pport_trunk_disable(struct bfa_s *bfa)
 {
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 bfa_boolean_t
@@ -1562,8 +1559,8 @@ bfa_pport_is_disabled(struct bfa_s *bfa)
 {
 	struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
 
-	return (bfa_sm_to_state(hal_pport_sm_table, port->sm) ==
-		BFA_PPORT_ST_DISABLED);
+	return bfa_sm_to_state(hal_pport_sm_table, port->sm) ==
+		BFA_PPORT_ST_DISABLED;
 
 }
 
@@ -1572,7 +1569,7 @@ bfa_pport_is_ratelim(struct bfa_s *bfa)
 {
 	struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
 
-return (pport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE);
+	return pport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
 
 }
 
@@ -1620,7 +1617,7 @@ bfa_pport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
 
 	pport->cfg.trl_def_speed = speed;
 
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 /**
@@ -1632,7 +1629,7 @@ bfa_pport_get_ratelim_speed(struct bfa_s *bfa)
 	struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
 
 	bfa_trc(bfa, pport->cfg.trl_def_speed);
-	return (pport->cfg.trl_def_speed);
+	return pport->cfg.trl_def_speed;
 
 }
 

+ 5 - 6
drivers/scsi/bfa/bfa_fcs_lport.c

@@ -568,11 +568,10 @@ bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port)
 
 	__port_action[port->fabric->fab_type].offline(port);
 
-	if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) {
+	if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
 		bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
-	} else {
+	else
 		bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE);
-	}
 	bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles,
 			port->fabric->vf_drv,
 			(port->vport == NULL) ? NULL : port->vport->vport_drv);
@@ -777,7 +776,7 @@ bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn)
 	}
 
 	bfa_trc(port->fcs, pwwn);
-	return (NULL);
+	return NULL;
 }
 
 /**
@@ -796,7 +795,7 @@ bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn)
 	}
 
 	bfa_trc(port->fcs, nwwn);
-	return (NULL);
+	return NULL;
 }
 
 /**
@@ -870,7 +869,7 @@ bfa_fcs_port_lip(struct bfa_fcs_port_s *port)
 bfa_boolean_t
 bfa_fcs_port_is_online(struct bfa_fcs_port_s *port)
 {
-	return (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online));
+	return bfa_sm_cmp_state(port, bfa_fcs_port_sm_online);
 }
 
 /**

+ 4 - 4
drivers/scsi/bfa/bfa_fcxp.c

@@ -199,7 +199,7 @@ bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
 	if (fcxp)
 		list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
 
-	return (fcxp);
+	return fcxp;
 }
 
 static void
@@ -503,7 +503,7 @@ bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
 
 	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
 	if (fcxp == NULL)
-		return (NULL);
+		return NULL;
 
 	bfa_trc(bfa, fcxp->fcxp_tag);
 
@@ -568,7 +568,7 @@ bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
 		}
 	}
 
-	return (fcxp);
+	return fcxp;
 }
 
 /**
@@ -709,7 +709,7 @@ bfa_status_t
 bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
 {
 	bfa_assert(0);
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 void

+ 1 - 1
drivers/scsi/bfa/bfa_intr.c

@@ -59,7 +59,7 @@ bfa_intx(struct bfa_s *bfa)
 	qintr = intr & __HFN_INT_RME_MASK;
 	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
 
-	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue ++) {
+	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
 		if (intr & (__HFN_INT_RME_Q0 << queue))
 			bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
 	}

+ 10 - 8
drivers/scsi/bfa/bfa_intr_priv.h

@@ -26,9 +26,9 @@ void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
 void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
 
 
-#define bfa_reqq_pi(__bfa, __reqq)	(__bfa)->iocfc.req_cq_pi[__reqq]
+#define bfa_reqq_pi(__bfa, __reqq)	((__bfa)->iocfc.req_cq_pi[__reqq])
 #define bfa_reqq_ci(__bfa, __reqq)					\
-	*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva)
+	(*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva))
 
 #define bfa_reqq_full(__bfa, __reqq)				\
 	(((bfa_reqq_pi(__bfa, __reqq) + 1) &			\
@@ -50,14 +50,16 @@ void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
 } while (0)
 
 #define bfa_rspq_pi(__bfa, __rspq)					\
-	*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva)
+	(*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva))
 
-#define bfa_rspq_ci(__bfa, __rspq)	(__bfa)->iocfc.rsp_cq_ci[__rspq]
+#define bfa_rspq_ci(__bfa, __rspq)	((__bfa)->iocfc.rsp_cq_ci[__rspq])
 #define bfa_rspq_elem(__bfa, __rspq, __ci)				\
-	&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci]
+	(&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci])
 
-#define CQ_INCR(__index, __size)					\
-			(__index)++; (__index) &= ((__size) - 1)
+#define CQ_INCR(__index, __size) do {					\
+			(__index)++;					\
+			(__index) &= ((__size) - 1);      \
+} while (0)
 
 /**
  * Queue element to wait for room in request queue. FIFO order is
@@ -94,7 +96,7 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
 	wqe->cbarg = cbarg;
 }
 
-#define bfa_reqq(__bfa, __reqq)	&(__bfa)->reqq_waitq[__reqq]
+#define bfa_reqq(__bfa, __reqq)	(&(__bfa)->reqq_waitq[__reqq])
 
 /**
  * static inline void

+ 5 - 5
drivers/scsi/bfa/bfa_ioc.c

@@ -51,7 +51,7 @@ BFA_TRC_FILE(HAL, IOC);
 	 (sizeof(struct bfa_trc_mod_s) -			\
 	  BFA_TRC_MAX * sizeof(struct bfa_trc_s)))
 #define BFA_DBG_FWTRC_OFF(_fn)	(BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
-#define bfa_ioc_stats(_ioc, _stats)	(_ioc)->stats._stats ++
+#define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)
 
 #define BFA_FLASH_CHUNK_NO(off)         (off / BFI_FLASH_CHUNK_SZ_WORDS)
 #define BFA_FLASH_OFFSET_IN_CHUNK(off)  (off % BFI_FLASH_CHUNK_SZ_WORDS)
@@ -1953,8 +1953,8 @@ bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
 bfa_boolean_t
 bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
 {
-	return (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
-		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled));
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
+		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
 }
 
 /**
@@ -1963,9 +1963,9 @@ bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
 bfa_boolean_t
 bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
 {
-	return (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
 		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck)
-		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch));
+		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch);
 }
 
 #define bfa_ioc_state_disabled(__sm)		\

+ 6 - 6
drivers/scsi/bfa/bfa_ioc.h

@@ -179,16 +179,16 @@ struct bfa_ioc_s {
 	struct bfa_ioc_mbox_mod_s mbox_mod;
 };
 
-#define bfa_ioc_pcifn(__ioc)		(__ioc)->pcidev.pci_func
-#define bfa_ioc_devid(__ioc)		(__ioc)->pcidev.device_id
-#define bfa_ioc_bar0(__ioc)		(__ioc)->pcidev.pci_bar_kva
+#define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
+#define bfa_ioc_devid(__ioc)		((__ioc)->pcidev.device_id)
+#define bfa_ioc_bar0(__ioc)		((__ioc)->pcidev.pci_bar_kva)
 #define bfa_ioc_portid(__ioc)		((__ioc)->port_id)
 #define bfa_ioc_fetch_stats(__ioc, __stats) \
-		((__stats)->drv_stats) = (__ioc)->stats
+		(((__stats)->drv_stats) = (__ioc)->stats)
 #define bfa_ioc_clr_stats(__ioc)	\
 		bfa_os_memset(&(__ioc)->stats, 0, sizeof((__ioc)->stats))
-#define bfa_ioc_maxfrsize(__ioc)	(__ioc)->attr->maxfrsize
-#define bfa_ioc_rx_bbcredit(__ioc)	(__ioc)->attr->rx_bbcredit
+#define bfa_ioc_maxfrsize(__ioc)	((__ioc)->attr->maxfrsize)
+#define bfa_ioc_rx_bbcredit(__ioc)	((__ioc)->attr->rx_bbcredit)
 #define bfa_ioc_speed_sup(__ioc)	\
 	BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
 

+ 4 - 4
drivers/scsi/bfa/bfa_iocfc.c

@@ -794,7 +794,7 @@ bfa_iocfc_get_stats(struct bfa_s *bfa, struct bfa_iocfc_stats_s *stats,
 
 	if (iocfc->stats_busy) {
 		bfa_trc(bfa, iocfc->stats_busy);
-		return (BFA_STATUS_DEVBUSY);
+		return BFA_STATUS_DEVBUSY;
 	}
 
 	iocfc->stats_busy = BFA_TRUE;
@@ -804,7 +804,7 @@ bfa_iocfc_get_stats(struct bfa_s *bfa, struct bfa_iocfc_stats_s *stats,
 
 	bfa_iocfc_stats_query(bfa);
 
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 bfa_status_t
@@ -814,7 +814,7 @@ bfa_iocfc_clear_stats(struct bfa_s *bfa, bfa_cb_ioc_t cbfn, void *cbarg)
 
 	if (iocfc->stats_busy) {
 		bfa_trc(bfa, iocfc->stats_busy);
-		return (BFA_STATUS_DEVBUSY);
+		return BFA_STATUS_DEVBUSY;
 	}
 
 	iocfc->stats_busy = BFA_TRUE;
@@ -822,7 +822,7 @@ bfa_iocfc_clear_stats(struct bfa_s *bfa, bfa_cb_ioc_t cbfn, void *cbarg)
 	iocfc->stats_cbarg = cbarg;
 
 	bfa_iocfc_stats_clear(bfa);
-	return (BFA_STATUS_OK);
+	return BFA_STATUS_OK;
 }
 
 /**

+ 4 - 4
drivers/scsi/bfa/bfa_iocfc.h

@@ -107,13 +107,13 @@ struct bfa_iocfc_s {
 
 #define bfa_lpuid(__bfa)		bfa_ioc_portid(&(__bfa)->ioc)
 #define bfa_msix_init(__bfa, __nvecs)	\
-	(__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs)
+	((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
 #define bfa_msix_install(__bfa)	\
-	(__bfa)->iocfc.hwif.hw_msix_install(__bfa)
+	((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
 #define bfa_msix_uninstall(__bfa)	\
-	(__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa)
+	((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
 #define bfa_isr_mode_set(__bfa, __msix)	\
-	(__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix)
+	((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
 #define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)	\
 	(__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)
 

+ 2 - 2
drivers/scsi/bfa/bfa_ioim.c

@@ -105,13 +105,13 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
 				bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
 				list_del(&ioim->qe);
 				list_add_tail(&ioim->qe,
-					&ioim->fcpim->ioim_comp_q);
+						&ioim->fcpim->ioim_comp_q);
 				bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
 						__bfa_cb_ioim_pathtov, ioim);
 			} else {
 				list_del(&ioim->qe);
 				list_add_tail(&ioim->qe,
-					&ioim->itnim->pending_q);
+						&ioim->itnim->pending_q);
 			}
 			break;
 		}

+ 3 - 3
drivers/scsi/bfa/bfa_itnim.c

@@ -1029,7 +1029,7 @@ bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
 	bfa_stats(itnim, creates);
 	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
 
-	return (itnim);
+	return itnim;
 }
 
 void
@@ -1061,7 +1061,7 @@ bfa_itnim_offline(struct bfa_itnim_s *itnim)
 bfa_boolean_t
 bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
 {
-	return (
+	return
 		itnim->fcpim->path_tov && itnim->iotov_active &&
 		(bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
@@ -1069,7 +1069,7 @@ bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable))
-);
+	;
 }
 
 void

+ 2 - 2
drivers/scsi/bfa/bfa_log.c

@@ -231,9 +231,9 @@ bfa_log_get_level(struct bfa_log_mod_s *log_mod, int mod_id)
 		return BFA_LOG_INVALID;
 
 	if (log_mod)
-		return (log_mod->log_level[mod_id]);
+		return log_mod->log_level[mod_id];
 	else
-		return (bfa_log_info[mod_id].level);
+		return bfa_log_info[mod_id].level;
 }
 
 enum bfa_log_severity

+ 2 - 2
drivers/scsi/bfa/bfa_port_priv.h

@@ -59,8 +59,8 @@ struct bfa_pport_s {
 	u8			*stats_kva;
 	u64		stats_pa;
 	union bfa_pport_stats_u *stats;	/*  pport stats */
-	u32		mypid : 24;
-	u32		rsvd_b : 8;
+	u32		mypid:24;
+	u32		rsvd_b:8;
 	struct bfa_timer_s 	timer;	/*  timer */
 	union bfa_pport_stats_u 	*stats_ret;
 					/*  driver stats location */

+ 3 - 3
drivers/scsi/bfa/bfa_rport.c

@@ -677,7 +677,7 @@ bfa_rport_alloc(struct bfa_rport_mod_s *mod)
 	if (rport)
 		list_add_tail(&rport->qe, &mod->rp_active_q);
 
-	return (rport);
+	return rport;
 }
 
 static void
@@ -834,7 +834,7 @@ bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
 	rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
 
 	if (rp == NULL)
-		return (NULL);
+		return NULL;
 
 	rp->bfa = bfa;
 	rp->rport_drv = rport_drv;
@@ -843,7 +843,7 @@ bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
 	bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
 	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
 
-	return (rp);
+	return rp;
 }
 
 void

+ 5 - 4
drivers/scsi/bfa/bfa_tskim.c

@@ -23,13 +23,14 @@ BFA_TRC_FILE(HAL, TSKIM);
 /**
  * task management completion handling
  */
-#define bfa_tskim_qcomp(__tskim, __cbfn) do {			     \
-	bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, __cbfn, (__tskim)); \
+#define bfa_tskim_qcomp(__tskim, __cbfn) do {			\
+	bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe,	\
+			 __cbfn, (__tskim));      \
 	bfa_tskim_notify_comp(__tskim);      \
 } while (0)
 
-#define bfa_tskim_notify_comp(__tskim) do {				     \
-	if ((__tskim)->notify)					     	     \
+#define bfa_tskim_notify_comp(__tskim) do {			 \
+	if ((__tskim)->notify)					 \
 		bfa_itnim_tskdone((__tskim)->itnim);      \
 } while (0)
 

+ 1 - 1
drivers/scsi/bfa/bfa_uf.c

@@ -185,7 +185,7 @@ bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
 	struct bfa_uf_s   *uf;
 
 	bfa_q_deq(&uf_mod->uf_free_q, &uf);
-	return (uf);
+	return uf;
 }
 
 static void

+ 3 - 3
drivers/scsi/bfa/bfad.c

@@ -188,8 +188,8 @@ static struct bfad_port_s *
 bfad_get_drv_port(struct bfad_s *bfad, struct bfad_vf_s *vf_drv,
 		  struct bfad_vport_s *vp_drv)
 {
-	return ((vp_drv) ? (&(vp_drv)->drv_port)
-		: ((vf_drv) ? (&(vf_drv)->base_port) : (&(bfad)->pport)));
+	return (vp_drv) ? (&(vp_drv)->drv_port)
+		: ((vf_drv) ? (&(vf_drv)->base_port) : (&(bfad)->pport));
 }
 
 struct bfad_port_s *
@@ -716,7 +716,7 @@ bfad_drv_init(struct bfad_s *bfad)
 	if ((bfad->bfad_flags & BFAD_MSIX_ON)
 	    && bfad_install_msix_handler(bfad)) {
 		printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
-		       __FUNCTION__, bfad->inst_no);
+		       __func__, bfad->inst_no);
 	}
 
 	bfad_init_timer(bfad);

+ 4 - 4
drivers/scsi/bfa/bfad_fwimg.c

@@ -65,10 +65,10 @@ bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
 	memcpy(*bfi_image, fw->data, fw->size);
 	*bfi_image_size = fw->size/sizeof(u32);
 
-	return(*bfi_image);
+	return *bfi_image;
 
 error:
-	return(NULL);
+	return NULL;
 }
 
 u32 *
@@ -78,12 +78,12 @@ bfad_get_firmware_buf(struct pci_dev *pdev)
 		if (bfi_image_ct_size == 0)
 			bfad_read_firmware(pdev, &bfi_image_ct,
 				&bfi_image_ct_size, BFAD_FW_FILE_CT);
-		return(bfi_image_ct);
+		return bfi_image_ct;
 	} else {
 		if (bfi_image_cb_size == 0)
 			bfad_read_firmware(pdev, &bfi_image_cb,
 				&bfi_image_cb_size, BFAD_FW_FILE_CB);
-		return(bfi_image_cb);
+		return bfi_image_cb;
 	}
 }
 

+ 1 - 1
drivers/scsi/bfa/bfad_im.c

@@ -1050,7 +1050,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)
 		} else {
 			printk(KERN_WARNING
 				"%s: itnim %llx is already in online state\n",
-				__FUNCTION__,
+				__func__,
 				bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim));
 		}
 

+ 1 - 1
drivers/scsi/bfa/bfad_im_compat.h

@@ -31,7 +31,7 @@ u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
 static inline u32 *
 bfad_load_fwimg(struct pci_dev *pdev)
 {
-	return(bfad_get_firmware_buf(pdev));
+	return bfad_get_firmware_buf(pdev);
 }
 
 static inline void

+ 1 - 2
drivers/scsi/bfa/bfad_intr.c

@@ -23,13 +23,12 @@ BFA_TRC_FILE(LDRV, INTR);
 /**
  *  bfa_isr BFA driver interrupt functions
  */
-irqreturn_t bfad_intx(int irq, void *dev_id);
 static int msix_disable;
 module_param(msix_disable, int, S_IRUGO | S_IWUSR);
 /**
  * Line based interrupt handler.
  */
-irqreturn_t
+static irqreturn_t
 bfad_intx(int irq, void *dev_id)
 {
 	struct bfad_s         *bfad = dev_id;

+ 9 - 9
drivers/scsi/bfa/fabric.c

@@ -36,12 +36,12 @@ BFA_TRC_FILE(FCS, FABRIC);
 #define BFA_FCS_FABRIC_RETRY_DELAY	(2000)	/* Milliseconds */
 #define BFA_FCS_FABRIC_CLEANUP_DELAY	(10000)	/* Milliseconds */
 
-#define bfa_fcs_fabric_set_opertype(__fabric) do {          \
-    if (bfa_pport_get_topology((__fabric)->fcs->bfa)    \
-				== BFA_PPORT_TOPOLOGY_P2P)   \
-	    (__fabric)->oper_type = BFA_PPORT_TYPE_NPORT;       \
-    else                                                    \
-	    (__fabric)->oper_type = BFA_PPORT_TYPE_NLPORT;      \
+#define bfa_fcs_fabric_set_opertype(__fabric) do {             \
+	if (bfa_pport_get_topology((__fabric)->fcs->bfa)       \
+				== BFA_PPORT_TOPOLOGY_P2P)     \
+		(__fabric)->oper_type = BFA_PPORT_TYPE_NPORT;  \
+	else                                                   \
+		(__fabric)->oper_type = BFA_PPORT_TYPE_NLPORT; \
 } while (0)
 
 /*
@@ -887,7 +887,7 @@ bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
 bfa_boolean_t
 bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
 {
-	return (bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback));
+	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
 }
 
 enum bfa_pport_type
@@ -974,7 +974,7 @@ bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
 int
 bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
 {
-	return (bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online));
+	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
 }
 
 
@@ -1015,7 +1015,7 @@ bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
 u16
 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
 {
-	return (fabric->num_vports);
+	return fabric->num_vports;
 }
 
 /**

+ 95 - 95
drivers/scsi/bfa/fcbuild.c

@@ -188,14 +188,14 @@ fc_els_rsp_parse(struct fchs_s *fchs, int len)
 	switch (els_cmd->els_code) {
 	case FC_ELS_LS_RJT:
 		if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
-			return (FC_PARSE_BUSY);
+			return FC_PARSE_BUSY;
 		else
-			return (FC_PARSE_FAILURE);
+			return FC_PARSE_FAILURE;
 
 	case FC_ELS_ACC:
-		return (FC_PARSE_OK);
+		return FC_PARSE_OK;
 	}
-	return (FC_PARSE_OK);
+	return FC_PARSE_OK;
 }
 
 static void
@@ -228,7 +228,7 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 	bfa_os_memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
 	bfa_os_memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
 
-	return (sizeof(struct fc_logi_s));
+	return sizeof(struct fc_logi_s);
 }
 
 u16
@@ -267,7 +267,7 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
 	flogi->csp.npiv_supp    = 1; /* @todo. field name is not correct */
 	vvl_info[0]	= bfa_os_htonl(FLOGI_VVL_BRCD);
 
-	return (sizeof(struct fc_logi_s));
+	return sizeof(struct fc_logi_s);
 }
 
 u16
@@ -287,7 +287,7 @@ fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
 
 	flogi->csp.bbcred = bfa_os_htons(local_bb_credits);
 
-	return (sizeof(struct fc_logi_s));
+	return sizeof(struct fc_logi_s);
 }
 
 u16
@@ -306,7 +306,7 @@ fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
 	flogi->port_name = port_name;
 	flogi->node_name = node_name;
 
-	return (sizeof(struct fc_logi_s));
+	return sizeof(struct fc_logi_s);
 }
 
 u16
@@ -338,26 +338,26 @@ fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
 	case FC_ELS_LS_RJT:
 		ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1);
 		if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
-			return (FC_PARSE_BUSY);
+			return FC_PARSE_BUSY;
 		else
-			return (FC_PARSE_FAILURE);
+			return FC_PARSE_FAILURE;
 	case FC_ELS_ACC:
 		plogi = (struct fc_logi_s *) (fchs + 1);
 		if (len < sizeof(struct fc_logi_s))
-			return (FC_PARSE_FAILURE);
+			return FC_PARSE_FAILURE;
 
 		if (!wwn_is_equal(plogi->port_name, port_name))
-			return (FC_PARSE_FAILURE);
+			return FC_PARSE_FAILURE;
 
 		if (!plogi->class3.class_valid)
-			return (FC_PARSE_FAILURE);
+			return FC_PARSE_FAILURE;
 
 		if (bfa_os_ntohs(plogi->class3.rxsz) < (FC_MIN_PDUSZ))
-			return (FC_PARSE_FAILURE);
+			return FC_PARSE_FAILURE;
 
-		return (FC_PARSE_OK);
+		return FC_PARSE_OK;
 	default:
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 	}
 }
 
@@ -372,7 +372,7 @@ fc_plogi_parse(struct fchs_s *fchs)
 	if ((bfa_os_ntohs(plogi->class3.rxsz) < FC_MIN_PDUSZ)
 	    || (bfa_os_ntohs(plogi->class3.rxsz) > FC_MAX_PDUSZ)
 	    || (plogi->class3.rxsz == 0))
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	return FC_PARSE_OK;
 }
@@ -393,7 +393,7 @@ fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 	prli->parampage.servparams.task_retry_id = 0;
 	prli->parampage.servparams.confirm       = 1;
 
-	return (sizeof(struct fc_prli_s));
+	return sizeof(struct fc_prli_s);
 }
 
 u16
@@ -414,41 +414,41 @@ fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 
 	prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
 
-	return (sizeof(struct fc_prli_s));
+	return sizeof(struct fc_prli_s);
 }
 
 enum fc_parse_status
 fc_prli_rsp_parse(struct fc_prli_s *prli, int len)
 {
 	if (len < sizeof(struct fc_prli_s))
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if (prli->command != FC_ELS_ACC)
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD)
 	    && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG))
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if (prli->parampage.servparams.target != 1)
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
-	return (FC_PARSE_OK);
+	return FC_PARSE_OK;
 }
 
 enum fc_parse_status
 fc_prli_parse(struct fc_prli_s *prli)
 {
 	if (prli->parampage.type != FC_TYPE_FCP)
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if (!prli->parampage.imagepair)
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if (!prli->parampage.servparams.initiator)
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
-	return (FC_PARSE_OK);
+	return FC_PARSE_OK;
 }
 
 u16
@@ -462,7 +462,7 @@ fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
 	logo->nport_id = (s_id);
 	logo->orig_port_name = port_name;
 
-	return (sizeof(struct fc_logo_s));
+	return sizeof(struct fc_logo_s);
 }
 
 static          u16
@@ -484,7 +484,7 @@ fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
 	adisc->orig_node_name = node_name;
 	adisc->nport_id = (s_id);
 
-	return (sizeof(struct fc_adisc_s));
+	return sizeof(struct fc_adisc_s);
 }
 
 u16
@@ -511,15 +511,15 @@ fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
 {
 
 	if (len < sizeof(struct fc_adisc_s))
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if (adisc->els_cmd.els_code != FC_ELS_ACC)
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if (!wwn_is_equal(adisc->orig_port_name, port_name))
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
-	return (FC_PARSE_OK);
+	return FC_PARSE_OK;
 }
 
 enum fc_parse_status
@@ -529,14 +529,14 @@ fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap,
 	struct fc_adisc_s     *adisc = (struct fc_adisc_s *) pld;
 
 	if (adisc->els_cmd.els_code != FC_ELS_ACC)
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if ((adisc->nport_id == (host_dap))
 	    && wwn_is_equal(adisc->orig_port_name, port_name)
 	    && wwn_is_equal(adisc->orig_node_name, node_name))
-		return (FC_PARSE_OK);
+		return FC_PARSE_OK;
 
-	return (FC_PARSE_FAILURE);
+	return FC_PARSE_FAILURE;
 }
 
 enum fc_parse_status
@@ -550,13 +550,13 @@ fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
 	if ((bfa_os_ntohs(pdisc->class3.rxsz) <
 		 (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
 	    || (pdisc->class3.rxsz == 0))
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if (!wwn_is_equal(pdisc->port_name, port_name))
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	if (!wwn_is_equal(pdisc->node_name, node_name))
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	return FC_PARSE_OK;
 }
@@ -570,7 +570,7 @@ fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
 	fchs->s_id = (s_id);
 	fchs->ox_id = bfa_os_htons(ox_id);
 
-	return (sizeof(struct fchs_s));
+	return sizeof(struct fchs_s);
 }
 
 enum fc_parse_status
@@ -578,9 +578,9 @@ fc_abts_rsp_parse(struct fchs_s *fchs, int len)
 {
 	if ((fchs->cat_info == FC_CAT_BA_ACC)
 	    || (fchs->cat_info == FC_CAT_BA_RJT))
-		return (FC_PARSE_OK);
+		return FC_PARSE_OK;
 
-	return (FC_PARSE_FAILURE);
+	return FC_PARSE_FAILURE;
 }
 
 u16
@@ -597,7 +597,7 @@ fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id,
 	rrq->ox_id = bfa_os_htons(rrq_oxid);
 	rrq->rx_id = FC_RXID_ANY;
 
-	return (sizeof(struct fc_rrq_s));
+	return sizeof(struct fc_rrq_s);
 }
 
 u16
@@ -611,7 +611,7 @@ fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 	memset(acc, 0, sizeof(struct fc_els_cmd_s));
 	acc->els_code = FC_ELS_ACC;
 
-	return (sizeof(struct fc_els_cmd_s));
+	return sizeof(struct fc_els_cmd_s);
 }
 
 u16
@@ -627,7 +627,7 @@ fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
 	ls_rjt->reason_code_expl = reason_code_expl;
 	ls_rjt->vendor_unique = 0x00;
 
-	return (sizeof(struct fc_ls_rjt_s));
+	return sizeof(struct fc_ls_rjt_s);
 }
 
 u16
@@ -643,7 +643,7 @@ fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
 	ba_acc->ox_id = fchs->ox_id;
 	ba_acc->rx_id = fchs->rx_id;
 
-	return (sizeof(struct fc_ba_acc_s));
+	return sizeof(struct fc_ba_acc_s);
 }
 
 u16
@@ -654,7 +654,7 @@ fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
 	memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
 	els_cmd->els_code = FC_ELS_ACC;
 
-	return (sizeof(struct fc_els_cmd_s));
+	return sizeof(struct fc_els_cmd_s);
 }
 
 int
@@ -696,7 +696,7 @@ fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
 		tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0;
 		tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0;
 	}
-	return (bfa_os_ntohs(tprlo_acc->payload_len));
+	return bfa_os_ntohs(tprlo_acc->payload_len);
 }
 
 u16
@@ -721,7 +721,7 @@ fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
 		prlo_acc->prlo_acc_params[page].resp_process_assc = 0;
 	}
 
-	return (bfa_os_ntohs(prlo_acc->payload_len));
+	return bfa_os_ntohs(prlo_acc->payload_len);
 }
 
 u16
@@ -735,7 +735,7 @@ fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
 	rnid->els_cmd.els_code = FC_ELS_RNID;
 	rnid->node_id_data_format = data_format;
 
-	return (sizeof(struct fc_rnid_cmd_s));
+	return sizeof(struct fc_rnid_cmd_s);
 }
 
 u16
@@ -759,10 +759,10 @@ fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
 		rnid_acc->specific_id_data_length =
 			sizeof(struct fc_rnid_general_topology_data_s);
 		bfa_os_assign(rnid_acc->gen_topology_data, *gen_topo_data);
-		return (sizeof(struct fc_rnid_acc_s));
+		return sizeof(struct fc_rnid_acc_s);
 	} else {
-		return (sizeof(struct fc_rnid_acc_s) -
-			sizeof(struct fc_rnid_general_topology_data_s));
+		return sizeof(struct fc_rnid_acc_s) -
+			sizeof(struct fc_rnid_general_topology_data_s);
 	}
 
 }
@@ -776,7 +776,7 @@ fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
 	memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
 
 	rpsc->els_cmd.els_code = FC_ELS_RPSC;
-	return (sizeof(struct fc_rpsc_cmd_s));
+	return sizeof(struct fc_rpsc_cmd_s);
 }
 
 u16
@@ -797,8 +797,8 @@ fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2,
 	for (i = 0; i < npids; i++)
 		rpsc2->pid_list[i].pid = pid_list[i];
 
-	return (sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) *
-			(sizeof(u32))));
+	return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) *
+			(sizeof(u32)));
 }
 
 u16
@@ -819,7 +819,7 @@ fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
 	rpsc_acc->speed_info[0].port_op_speed =
 		bfa_os_htons(oper_speed->port_op_speed);
 
-	return (sizeof(struct fc_rpsc_acc_s));
+	return sizeof(struct fc_rpsc_acc_s);
 
 }
 
@@ -856,7 +856,7 @@ fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
 	pdisc->port_name = port_name;
 	pdisc->node_name = node_name;
 
-	return (sizeof(struct fc_logi_s));
+	return sizeof(struct fc_logi_s);
 }
 
 u16
@@ -865,21 +865,21 @@ fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
 	struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
 
 	if (len < sizeof(struct fc_logi_s))
-		return (FC_PARSE_LEN_INVAL);
+		return FC_PARSE_LEN_INVAL;
 
 	if (pdisc->els_cmd.els_code != FC_ELS_ACC)
-		return (FC_PARSE_ACC_INVAL);
+		return FC_PARSE_ACC_INVAL;
 
 	if (!wwn_is_equal(pdisc->port_name, port_name))
-		return (FC_PARSE_PWWN_NOT_EQUAL);
+		return FC_PARSE_PWWN_NOT_EQUAL;
 
 	if (!pdisc->class3.class_valid)
-		return (FC_PARSE_NWWN_NOT_EQUAL);
+		return FC_PARSE_NWWN_NOT_EQUAL;
 
 	if (bfa_os_ntohs(pdisc->class3.rxsz) < (FC_MIN_PDUSZ))
-		return (FC_PARSE_RXSZ_INVAL);
+		return FC_PARSE_RXSZ_INVAL;
 
-	return (FC_PARSE_OK);
+	return FC_PARSE_OK;
 }
 
 u16
@@ -903,7 +903,7 @@ fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
 		prlo->prlo_params[page].resp_process_assc = 0;
 	}
 
-	return (bfa_os_ntohs(prlo->payload_len));
+	return bfa_os_ntohs(prlo->payload_len);
 }
 
 u16
@@ -916,7 +916,7 @@ fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
 	len = len;
 
 	if (prlo->command != FC_ELS_ACC)
-		return (FC_PARSE_FAILURE);
+		return FC_PARSE_FAILURE;
 
 	num_pages = ((bfa_os_ntohs(prlo->payload_len)) - 4) / 16;
 
@@ -936,7 +936,7 @@ fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
 		if (prlo->prlo_acc_params[page].resp_process_assc != 0)
 			return FC_PARSE_FAILURE;
 	}
-	return (FC_PARSE_OK);
+	return FC_PARSE_OK;
 
 }
 
@@ -968,7 +968,7 @@ fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
 		}
 	}
 
-	return (bfa_os_ntohs(tprlo->payload_len));
+	return bfa_os_ntohs(tprlo->payload_len);
 }
 
 u16
@@ -981,23 +981,23 @@ fc_tprlo_rsp_parse(struct fchs_s *fchs, int len)
 	len = len;
 
 	if (tprlo->command != FC_ELS_ACC)
-		return (FC_PARSE_ACC_INVAL);
+		return FC_PARSE_ACC_INVAL;
 
 	num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16;
 
 	for (page = 0; page < num_pages; page++) {
 		if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP)
-			return (FC_PARSE_NOT_FCP);
+			return FC_PARSE_NOT_FCP;
 		if (tprlo->tprlo_acc_params[page].opa_valid != 0)
-			return (FC_PARSE_OPAFLAG_INVAL);
+			return FC_PARSE_OPAFLAG_INVAL;
 		if (tprlo->tprlo_acc_params[page].rpa_valid != 0)
-			return (FC_PARSE_RPAFLAG_INVAL);
+			return FC_PARSE_RPAFLAG_INVAL;
 		if (tprlo->tprlo_acc_params[page].orig_process_assc != 0)
-			return (FC_PARSE_OPA_INVAL);
+			return FC_PARSE_OPA_INVAL;
 		if (tprlo->tprlo_acc_params[page].resp_process_assc != 0)
-			return (FC_PARSE_RPA_INVAL);
+			return FC_PARSE_RPA_INVAL;
 	}
-	return (FC_PARSE_OK);
+	return FC_PARSE_OK;
 }
 
 enum fc_parse_status
@@ -1024,7 +1024,7 @@ fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
 	fchs->cat_info = FC_CAT_BA_RJT;
 	ba_rjt->reason_code = reason_code;
 	ba_rjt->reason_expl = reason_expl;
-	return (sizeof(struct fc_ba_rjt_s));
+	return sizeof(struct fc_ba_rjt_s);
 }
 
 static void
@@ -1073,7 +1073,7 @@ fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 
 	bfa_os_memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s));
 	gidpn->port_name = port_name;
-	return (sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1090,7 +1090,7 @@ fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 
 	bfa_os_memset(gpnid, 0, sizeof(fcgs_gpnid_req_t));
 	gpnid->dap = port_id;
-	return (sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s));
+	return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1107,7 +1107,7 @@ fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 
 	bfa_os_memset(gnnid, 0, sizeof(fcgs_gnnid_req_t));
 	gnnid->dap = port_id;
-	return (sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s));
+	return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1137,7 +1137,7 @@ fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, u8 set_br_reg,
 	if (set_br_reg)
 		scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE;
 
-	return (sizeof(struct fc_scr_s));
+	return sizeof(struct fc_scr_s);
 }
 
 u16
@@ -1157,7 +1157,7 @@ fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
 	rscn->event[0].format = FC_RSCN_FORMAT_PORTID;
 	rscn->event[0].portid = s_id;
 
-	return (sizeof(struct fc_rscn_pl_s));
+	return sizeof(struct fc_rscn_pl_s);
 }
 
 u16
@@ -1188,7 +1188,7 @@ fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 		rftid->fc4_type[index] |= bfa_os_htonl(type_value);
 	}
 
-	return (sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1210,7 +1210,7 @@ fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
 	bfa_os_memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
 			(bitmap_size < 32 ? bitmap_size : 32));
 
-	return (sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1231,7 +1231,7 @@ fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 	rffid->fc4ftr_bits  = fc4_ftrs;
 	rffid->fc4_type		= fc4_type;
 
-	return (sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1253,7 +1253,7 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 	rspnid->spn_len = (u8) strlen((char *)name);
 	strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len);
 
-	return (sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1275,7 +1275,7 @@ fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id,
 	gidft->domain_id = 0;
 	gidft->area_id = 0;
 
-	return (sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1294,7 +1294,7 @@ fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
 	rpnid->port_id = port_id;
 	rpnid->port_name = port_name;
 
-	return (sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1313,7 +1313,7 @@ fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
 	rnnid->port_id = port_id;
 	rnnid->node_name = node_name;
 
-	return (sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1332,7 +1332,7 @@ fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
 	rcsid->port_id = port_id;
 	rcsid->cos = cos;
 
-	return (sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1351,7 +1351,7 @@ fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
 	rptid->port_id = port_id;
 	rptid->port_type = port_type;
 
-	return (sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s));
+	return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
@@ -1368,7 +1368,7 @@ fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
 	bfa_os_memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s));
 	ganxt->port_id = port_id;
 
-	return (sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s));
+	return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s);
 }
 
 /*
@@ -1385,7 +1385,7 @@ fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 	fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
 
-	return (sizeof(struct ct_hdr_s));
+	return sizeof(struct ct_hdr_s);
 }
 
 /*
@@ -1425,7 +1425,7 @@ fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
 	bfa_os_memset(gmal, 0, sizeof(fcgs_gmal_req_t));
 	gmal->wwn = wwn;
 
-	return (sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t));
+	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t);
 }
 
 /*
@@ -1445,5 +1445,5 @@ fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
 	bfa_os_memset(gfn, 0, sizeof(fcgs_gfn_req_t));
 	gfn->wwn = wwn;
 
-	return (sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t));
+	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t);
 }

+ 3 - 3
drivers/scsi/bfa/fcbuild.h

@@ -32,8 +32,8 @@
  * Utility Macros/functions
  */
 
-#define fcif_sof_set(_ifhdr, _sof)	(_ifhdr)->sof = FC_ ## _sof
-#define fcif_eof_set(_ifhdr, _eof)	(_ifhdr)->eof = FC_ ## _eof
+#define fcif_sof_set(_ifhdr, _sof)	((_ifhdr)->sof = FC_ ## _sof)
+#define fcif_eof_set(_ifhdr, _eof)	((_ifhdr)->eof = FC_ ## _eof)
 
 #define wwn_is_equal(_wwn1, _wwn2)		\
 	(memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
@@ -49,7 +49,7 @@
 static inline   u32
 fc_get_ctresp_pyld_len(u32 resp_len)
 {
-	return (resp_len - sizeof(struct ct_hdr_s));
+	return resp_len - sizeof(struct ct_hdr_s);
 }
 
 /*

+ 3 - 4
drivers/scsi/bfa/fcpim.c

@@ -286,11 +286,10 @@ bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
 		bfa_fcb_itnim_offline(itnim->itnim_drv);
 		bfa_itnim_offline(itnim->bfa_itnim);
-		if (bfa_fcs_port_is_online(itnim->rport->port) == BFA_TRUE) {
+		if (bfa_fcs_port_is_online(itnim->rport->port) == BFA_TRUE)
 			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
-		} else {
+		else
 			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
-		}
 		break;
 
 	case BFA_FCS_ITNIM_SM_DELETE:
@@ -732,7 +731,7 @@ bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
 		return NULL;
 
 	bfa_assert(rport->itnim != NULL);
-	return (rport->itnim);
+	return rport->itnim;
 }
 
 bfa_status_t

+ 1 - 1
drivers/scsi/bfa/fcs.h

@@ -23,7 +23,7 @@
 #ifndef __FCS_H__
 #define __FCS_H__
 
-#define __fcs_min_cfg(__fcs)       (__fcs)->min_cfg
+#define __fcs_min_cfg(__fcs)       ((__fcs)->min_cfg)
 
 void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
 

+ 4 - 4
drivers/scsi/bfa/fdmi.c

@@ -72,9 +72,9 @@ static u16 bfa_fcs_port_fdmi_build_rpa_pyld(
 			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
 static u16 bfa_fcs_port_fdmi_build_portattr_block(
 			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
+static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
 			struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
-void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
+static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
 			struct bfa_fcs_fdmi_port_attr_s *port_attr);
 /**
  *  fcs_fdmi_sm FCS FDMI state machine
@@ -1091,7 +1091,7 @@ bfa_fcs_port_fdmi_timeout(void *arg)
 	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
 }
 
-void
+static void
 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
 			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
 {
@@ -1145,7 +1145,7 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
 
 }
 
-void
+static void
 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
 			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
 {

+ 1 - 1
drivers/scsi/bfa/include/aen/bfa_aen.h

@@ -54,7 +54,7 @@ bfa_aen_get_max_cfg_entry(void)
 static inline s32
 bfa_aen_get_meminfo(void)
 {
-	return (sizeof(struct bfa_aen_entry_s) * bfa_aen_get_max_cfg_entry());
+	return sizeof(struct bfa_aen_entry_s) * bfa_aen_get_max_cfg_entry();
 }
 
 static inline s32

+ 5 - 5
drivers/scsi/bfa/include/bfa.h

@@ -76,11 +76,11 @@ struct bfa_meminfo_s {
 	struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
 };
 #define bfa_meminfo_kva(_m)	\
-	(_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp
+	((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
 #define bfa_meminfo_dma_virt(_m)	\
-	(_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp
+	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
 #define bfa_meminfo_dma_phys(_m)	\
-	(_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp
+	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
 
 /**
  * Generic Scatter Gather Element used by driver
@@ -100,7 +100,7 @@ struct bfa_sge_s {
 /*
  * bfa stats interfaces
  */
-#define bfa_stats(_mod, _stats)	(_mod)->stats._stats ++
+#define bfa_stats(_mod, _stats)	((_mod)->stats._stats++)
 
 #define bfa_ioc_get_stats(__bfa, __ioc_stats)	\
 	bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
@@ -136,7 +136,7 @@ void bfa_isr_enable(struct bfa_s *bfa);
 void bfa_isr_disable(struct bfa_s *bfa);
 void bfa_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
 			u32 *num_vecs, u32 *max_vec_bit);
-#define bfa_msix(__bfa, __vec) (__bfa)->msix.handler[__vec](__bfa, __vec)
+#define bfa_msix(__bfa, __vec) ((__bfa)->msix.handler[__vec](__bfa, __vec))
 
 void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
 void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);

+ 4 - 4
drivers/scsi/bfa/include/bfa_svc.h

@@ -34,10 +34,10 @@ struct bfa_fcxp_s;
  */
 struct bfa_rport_info_s {
 	u16        max_frmsz;	/*  max rcv pdu size               */
-	u32        pid : 24,	/*  remote port ID                 */
-			lp_tag : 8;
-	u32        local_pid : 24,	/*  local port ID		    */
-			cisc : 8;	/*  CIRO supported		    */
+	u32        pid:24,		/*  remote port ID                 */
+			lp_tag:8;
+	u32        local_pid:24,	/*  local port ID		    */
+			cisc:8;		/*  CIRO supported		    */
 	u8         fc_class;	/*  supported FC classes. enum fc_cos */
 	u8         vf_en;		/*  virtual fabric enable          */
 	u16        vf_id;		/*  virtual fabric ID              */

+ 6 - 6
drivers/scsi/bfa/include/bfi/bfi.h

@@ -93,13 +93,13 @@ union bfi_addr_u {
  */
 struct bfi_sge_s {
 #ifdef __BIGENDIAN
-	u32        flags	: 2,
-			rsvd	: 2,
-			sg_len	: 28;
+	u32        flags:2,
+			rsvd:2,
+			sg_len:28;
 #else
-	u32        sg_len	: 28,
-			rsvd	: 2,
-			flags	: 2;
+	u32        sg_len:28,
+			rsvd:2,
+			flags:2;
 #endif
 	union bfi_addr_u sga;
 };

+ 1 - 1
drivers/scsi/bfa/include/bfi/bfi_ioc.h

@@ -142,7 +142,7 @@ enum {
 	BFI_ADAPTER_UNSUPP    = 0x400000,	/*  unknown adapter type  */
 };
 
-#define BFI_ADAPTER_GETP(__prop,__adap_prop)          		\
+#define BFI_ADAPTER_GETP(__prop, __adap_prop)          		\
     (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >>         \
      BFI_ADAPTER_ ## __prop ## _SH)
 #define BFI_ADAPTER_SETP(__prop, __val)         		\

+ 2 - 2
drivers/scsi/bfa/include/bfi/bfi_lps.h

@@ -55,8 +55,8 @@ struct bfi_lps_login_rsp_s {
 	u16	bb_credit;
 	u8		f_port;
 	u8		npiv_en;
-	u32	lp_pid : 24;
-	u32	auth_req : 8;
+	u32	lp_pid:24;
+	u32	auth_req:8;
 	mac_t		lp_mac;
 	mac_t		fcf_mac;
 	u8		ext_status;

+ 4 - 4
drivers/scsi/bfa/include/bfi/bfi_rport.h

@@ -38,10 +38,10 @@ struct bfi_rport_create_req_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		*/
 	u16        bfa_handle;	/*  host rport handle		*/
 	u16        max_frmsz;	/*  max rcv pdu size		*/
-	u32        pid       : 24,	/*  remote port ID		*/
-			lp_tag    : 8;	/*  local port tag		*/
-	u32        local_pid : 24,	/*  local port ID		*/
-			cisc      : 8;
+	u32        pid:24,		/*  remote port ID		*/
+			lp_tag:8;	/*  local port tag		*/
+	u32        local_pid:24,	/*  local port ID		*/
+			cisc:8;
 	u8         fc_class;	/*  supported FC classes	*/
 	u8         vf_en;		/*  virtual fabric enable	*/
 	u16        vf_id;		/*  virtual fabric ID		*/

+ 3 - 3
drivers/scsi/bfa/include/cs/bfa_checksum.h

@@ -31,7 +31,7 @@ bfa_checksum_u32(u32 *buf, int sz)
 	for (i = 0; i < m; i++)
 		sum ^= buf[i];
 
-	return (sum);
+	return sum;
 }
 
 static inline u16
@@ -43,7 +43,7 @@ bfa_checksum_u16(u16 *buf, int sz)
 	for (i = 0; i < m; i++)
 		sum ^= buf[i];
 
-	return (sum);
+	return sum;
 }
 
 static inline u8
@@ -55,6 +55,6 @@ bfa_checksum_u8(u8 *buf, int sz)
 	for (i = 0; i < sz; i++)
 		sum ^= buf[i];
 
-	return (sum);
+	return sum;
 }
 #endif

+ 3 - 3
drivers/scsi/bfa/include/cs/bfa_sm.h

@@ -24,8 +24,8 @@
 
 typedef void (*bfa_sm_t)(void *sm, int event);
 
-#define bfa_sm_set_state(_sm, _state)	(_sm)->sm = (bfa_sm_t)(_state)
-#define bfa_sm_send_event(_sm, _event)	(_sm)->sm((_sm), (_event))
+#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
+#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
 #define bfa_sm_get_state(_sm)		((_sm)->sm)
 #define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
 
@@ -62,7 +62,7 @@ typedef void (*bfa_fsm_t)(void *fsm, int event);
 } while (0)
 
 #define bfa_fsm_send_event(_fsm, _event)	\
-	(_fsm)->fsm((_fsm), (_event))
+	((_fsm)->fsm((_fsm), (_event)))
 #define bfa_fsm_cmp_state(_fsm, _state)		\
 	((_fsm)->fsm == (bfa_fsm_t)(_state))
 

+ 1 - 1
drivers/scsi/bfa/include/cs/bfa_trc.h

@@ -24,7 +24,7 @@
 #endif
 
 #ifndef BFA_TRC_TS
-#define BFA_TRC_TS(_trcm)	((_trcm)->ticks ++)
+#define BFA_TRC_TS(_trcm)	((_trcm)->ticks++)
 #endif
 
 struct bfa_trc_s {

+ 1 - 1
drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h

@@ -75,7 +75,7 @@ struct bfa_fcs_fabric_s {
 							    */
 };
 
-#define bfa_fcs_fabric_npiv_capable(__f)    (__f)->is_npiv
+#define bfa_fcs_fabric_npiv_capable(__f)    ((__f)->is_npiv)
 #define bfa_fcs_fabric_is_switched(__f)			\
 	((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED)
 

+ 9 - 8
drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h

@@ -125,12 +125,12 @@ union bfa_fcs_port_topo_u {
 struct bfa_fcs_port_s {
 	struct list_head         qe;	/*  used by port/vport */
 	bfa_sm_t               sm;	/*  state machine */
-	struct bfa_fcs_fabric_s *fabric;	/*  parent fabric */
-	struct bfa_port_cfg_s  port_cfg;	/*  port configuration */
+	struct bfa_fcs_fabric_s *fabric;/*  parent fabric */
+	struct bfa_port_cfg_s  port_cfg;/*  port configuration */
 	struct bfa_timer_s link_timer;	/*  timer for link offline */
-	u32        pid : 24;	/*  FC address */
-	u8         lp_tag;		/*  lport tag */
-	u16        num_rports;	/*  Num of r-ports */
+	u32 pid:24;	/*  FC address */
+	u8  lp_tag;	/*  lport tag */
+	u16 num_rports;	/*  Num of r-ports */
 	struct list_head rport_q;	/*  queue of discovered r-ports */
 	struct bfa_fcs_s *fcs;	/*  FCS instance */
 	union bfa_fcs_port_topo_u port_topo;	/*  fabric/loop/n2n details */
@@ -188,13 +188,14 @@ bfa_fcs_port_get_drvport(struct bfa_fcs_port_s *port)
 }
 
 
-#define bfa_fcs_port_get_opertype(_lport)	(_lport)->fabric->oper_type
+#define bfa_fcs_port_get_opertype(_lport)	((_lport)->fabric->oper_type)
 
 
-#define bfa_fcs_port_get_fabric_name(_lport)	(_lport)->fabric->fabric_name
+#define bfa_fcs_port_get_fabric_name(_lport)	((_lport)->fabric->fabric_name)
 
 
-#define bfa_fcs_port_get_fabric_ipaddr(_lport)	(_lport)->fabric->fabric_ip_addr
+#define bfa_fcs_port_get_fabric_ipaddr(_lport) \
+		((_lport)->fabric->fabric_ip_addr)
 
 /**
  * bfa fcs port public functions

+ 5 - 5
drivers/scsi/bfa/include/protocol/ct.h

@@ -193,11 +193,11 @@ struct fcgs_rftid_req_s {
 #define FC_GS_FCP_FC4_FEATURE_TARGET	 0x01
 
 struct fcgs_rffid_req_s{
-    u32    rsvd          :8;
-    u32    dap        	  :24;		/* port identifier	*/
-    u32    rsvd1         :16;
-    u32    fc4ftr_bits   :8;		/* fc4 feature bits	*/
-    u32    fc4_type      :8;		/* corresponding FC4 Type */
+    u32    rsvd:8;
+    u32    dap:24;		/* port identifier	*/
+    u32    rsvd1:16;
+    u32    fc4ftr_bits:8;	/* fc4 feature bits	*/
+    u32    fc4_type:8;	/* corresponding FC4 Type */
 };
 
 /**

+ 11 - 11
drivers/scsi/bfa/include/protocol/fc.h

@@ -486,14 +486,14 @@ struct fc_rsi_s {
  * see FC-PH-X table 113 & 115 for explanation also FCP table 8
  */
 struct fc_prli_params_s{
-	u32        reserved: 16;
+	u32        reserved:16;
 #ifdef __BIGENDIAN
-	u32        reserved1: 5;
-	u32        rec_support : 1;
-	u32        task_retry_id : 1;
-	u32        retry : 1;
+	u32        reserved1:5;
+	u32        rec_support:1;
+	u32        task_retry_id:1;
+	u32        retry:1;
 
-	u32        confirm : 1;
+	u32        confirm:1;
 	u32        doverlay:1;
 	u32        initiator:1;
 	u32        target:1;
@@ -502,10 +502,10 @@ struct fc_prli_params_s{
 	u32        rxrdisab:1;
 	u32        wxrdisab:1;
 #else
-	u32        retry : 1;
-	u32        task_retry_id : 1;
-	u32        rec_support : 1;
-	u32        reserved1: 5;
+	u32        retry:1;
+	u32        task_retry_id:1;
+	u32        rec_support:1;
+	u32        reserved1:5;
 
 	u32        wxrdisab:1;
 	u32        rxrdisab:1;
@@ -514,7 +514,7 @@ struct fc_prli_params_s{
 	u32        target:1;
 	u32        initiator:1;
 	u32        doverlay:1;
-	u32        confirm : 1;
+	u32        confirm:1;
 #endif
 };
 

+ 12 - 221
drivers/scsi/bfa/loop.c

@@ -58,49 +58,16 @@ static const u8   port_loop_alpa_map[] = {
 /*
  * Local Functions
  */
-bfa_status_t    bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port,
-					     u8 alpa);
-
-void            bfa_fcs_port_loop_plogi_response(void *fcsarg,
-						 struct bfa_fcxp_s *fcxp,
-						 void *cbarg,
-						 bfa_status_t req_status,
-						 u32 rsp_len,
-						 u32 resid_len,
-						 struct fchs_s *rsp_fchs);
-
-bfa_status_t    bfa_fcs_port_loop_send_adisc(struct bfa_fcs_port_s *port,
-					     u8 alpa);
-
-void            bfa_fcs_port_loop_adisc_response(void *fcsarg,
-						 struct bfa_fcxp_s *fcxp,
-						 void *cbarg,
-						 bfa_status_t req_status,
-						 u32 rsp_len,
-						 u32 resid_len,
-						 struct fchs_s *rsp_fchs);
-
-bfa_status_t    bfa_fcs_port_loop_send_plogi_acc(struct bfa_fcs_port_s *port,
-						 u8 alpa);
-
-void            bfa_fcs_port_loop_plogi_acc_response(void *fcsarg,
-						     struct bfa_fcxp_s *fcxp,
-						     void *cbarg,
-						     bfa_status_t req_status,
-						     u32 rsp_len,
-						     u32 resid_len,
-						     struct fchs_s *rsp_fchs);
-
-bfa_status_t    bfa_fcs_port_loop_send_adisc_acc(struct bfa_fcs_port_s *port,
-						 u8 alpa);
-
-void            bfa_fcs_port_loop_adisc_acc_response(void *fcsarg,
-						     struct bfa_fcxp_s *fcxp,
-						     void *cbarg,
-						     bfa_status_t req_status,
-						     u32 rsp_len,
-						     u32 resid_len,
-						     struct fchs_s *rsp_fchs);
+static bfa_status_t bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port,
+					u8 alpa);
+
+static void bfa_fcs_port_loop_plogi_response(void *fcsarg,
+					struct bfa_fcxp_s *fcxp,
+					void *cbarg,
+					bfa_status_t req_status,
+					u32 rsp_len,
+					u32 resid_len,
+					struct fchs_s *rsp_fchs);
 /**
  *   Called by port to initializar in provate LOOP topology.
  */
@@ -179,7 +146,7 @@ bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port)
 /**
  * Local Functions.
  */
-bfa_status_t
+static bfa_status_t
 bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port, u8 alpa)
 {
 	struct fchs_s          fchs;
@@ -208,7 +175,7 @@ bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port, u8 alpa)
 /**
  *   Called by fcxp to notify the Plogi response
  */
-void
+static void
 bfa_fcs_port_loop_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
 				 void *cbarg, bfa_status_t req_status,
 				 u32 rsp_len, u32 resid_len,
@@ -244,179 +211,3 @@ bfa_fcs_port_loop_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
 		bfa_assert(0);
 	}
 }
-
-bfa_status_t
-bfa_fcs_port_loop_send_plogi_acc(struct bfa_fcs_port_s *port, u8 alpa)
-{
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	int             len;
-
-	bfa_trc(port->fcs, alpa);
-
-	fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
-				  NULL);
-	bfa_assert(fcxp);
-
-	len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
-				 bfa_fcs_port_get_fcid(port), 0,
-				 port->port_cfg.pwwn, port->port_cfg.nwwn,
-				 bfa_pport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-				 FC_CLASS_3, len, &fchs,
-				 bfa_fcs_port_loop_plogi_acc_response,
-				 (void *)port, FC_MAX_PDUSZ, 0); /* No response
-								  * expected
-								  */
-
-	return BFA_STATUS_OK;
-}
-
-/*
- *  Plogi Acc Response
- * We donot do any processing here.
- */
-void
-bfa_fcs_port_loop_plogi_acc_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				     void *cbarg, bfa_status_t req_status,
-				     u32 rsp_len, u32 resid_len,
-				     struct fchs_s *rsp_fchs)
-{
-
-	struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
-
-	bfa_trc(port->fcs, port->pid);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		return;
-	}
-}
-
-bfa_status_t
-bfa_fcs_port_loop_send_adisc(struct bfa_fcs_port_s *port, u8 alpa)
-{
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	int             len;
-
-	bfa_trc(port->fcs, alpa);
-
-	fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
-				  NULL);
-	bfa_assert(fcxp);
-
-	len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-			  FC_CLASS_3, len, &fchs,
-			  bfa_fcs_port_loop_adisc_response, (void *)port,
-			  FC_MAX_PDUSZ, FC_RA_TOV);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *   Called by fcxp to notify the ADISC response
- */
-void
-bfa_fcs_port_loop_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				 void *cbarg, bfa_status_t req_status,
-				 u32 rsp_len, u32 resid_len,
-				 struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
-	struct bfa_fcs_rport_s *rport;
-	struct fc_adisc_s     *adisc_resp;
-	struct fc_els_cmd_s   *els_cmd;
-	u32        pid = rsp_fchs->s_id;
-
-	bfa_trc(port->fcs, req_status);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		/*
-		 * TBD : we may need to retry certain requests
-		 */
-		bfa_fcxp_free(fcxp);
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-	adisc_resp = (struct fc_adisc_s *) els_cmd;
-
-	if (els_cmd->els_code == FC_ELS_ACC) {
-	} else {
-		bfa_trc(port->fcs, adisc_resp->els_cmd.els_code);
-
-		/*
-		 * TBD: we may need to check for reject codes and retry
-		 */
-		rport = bfa_fcs_port_get_rport_by_pid(port, pid);
-		if (rport) {
-			list_del(&rport->qe);
-			bfa_fcs_rport_delete(rport);
-		}
-
-	}
-	return;
-}
-
-bfa_status_t
-bfa_fcs_port_loop_send_adisc_acc(struct bfa_fcs_port_s *port, u8 alpa)
-{
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	int             len;
-
-	bfa_trc(port->fcs, alpa);
-
-	fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
-				  NULL);
-	bfa_assert(fcxp);
-
-	len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
-				 bfa_fcs_port_get_fcid(port), 0,
-				 port->port_cfg.pwwn, port->port_cfg.nwwn);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-				FC_CLASS_3, len, &fchs,
-				bfa_fcs_port_loop_adisc_acc_response,
-				(void *)port, FC_MAX_PDUSZ, 0); /* no reponse
-								 * expected
-								 */
-
-	return BFA_STATUS_OK;
-}
-
-/*
- *  Adisc Acc Response
- * We donot do any processing here.
- */
-void
-bfa_fcs_port_loop_adisc_acc_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				     void *cbarg, bfa_status_t req_status,
-				     u32 rsp_len, u32 resid_len,
-				     struct fchs_s *rsp_fchs)
-{
-
-	struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
-
-	bfa_trc(port->fcs, port->pid);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		return;
-	}
-}

+ 7 - 8
drivers/scsi/bfa/lport_api.c

@@ -43,7 +43,7 @@ bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg)
 struct bfa_fcs_port_s *
 bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
 {
-	return (&fcs->fabric.bport);
+	return &fcs->fabric.bport;
 }
 
 wwn_t
@@ -88,11 +88,10 @@ bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn, int index,
 	}
 
 	bfa_trc(fcs, i);
-	if (rport) {
+	if (rport)
 		return rport->pwwn;
-	} else {
+	else
 		return (wwn_t) 0;
-	}
 }
 
 void
@@ -198,17 +197,17 @@ bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
 	vf = bfa_fcs_vf_lookup(fcs, vf_id);
 	if (vf == NULL) {
 		bfa_trc(fcs, vf_id);
-		return (NULL);
+		return NULL;
 	}
 
 	if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
-		return (&vf->bport);
+		return &vf->bport;
 
 	vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
 	if (vport)
-		return (&vport->lport);
+		return &vport->lport;
 
-	return (NULL);
+	return NULL;
 }
 
 /*

+ 2 - 3
drivers/scsi/bfa/ns.c

@@ -932,11 +932,10 @@ bfa_fcs_port_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 	}
 	ns->fcxp = fcxp;
 
-	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
 		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
-	} else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port)) {
+	else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port))
 		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_TARGET;
-	}
 
 	len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
 			     bfa_fcs_port_get_fcid(port), 0, FC_TYPE_FCP,

+ 1 - 1
drivers/scsi/bfa/plog.c

@@ -180,5 +180,5 @@ bfa_plog_disable(struct bfa_plog_s *plog)
 bfa_boolean_t
 bfa_plog_get_setting(struct bfa_plog_s *plog)
 {
-	return((bfa_boolean_t)plog->plog_enabled);
+	return (bfa_boolean_t)plog->plog_enabled;
 }

+ 13 - 15
drivers/scsi/bfa/rport_ftrs.c

@@ -79,7 +79,7 @@ bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
 	bfa_trc(rport->fcs, event);
 
 	switch (event) {
-	case RPFSM_EVENT_RPORT_ONLINE :
+	case RPFSM_EVENT_RPORT_ONLINE:
 		if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
 			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
 			rpf->rpsc_retries = 0;
@@ -87,7 +87,7 @@ bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
 			break;
 		};
 
-	case RPFSM_EVENT_RPORT_OFFLINE :
+	case RPFSM_EVENT_RPORT_OFFLINE:
 		break;
 
 	default:
@@ -107,7 +107,7 @@ bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
 		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
 		break;
 
-	case RPFSM_EVENT_RPORT_OFFLINE :
+	case RPFSM_EVENT_RPORT_OFFLINE:
 		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
 		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
 		rpf->rpsc_retries = 0;
@@ -130,11 +130,10 @@ bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
 	case RPFSM_EVENT_RPSC_COMP:
 		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
 		/* Update speed info in f/w via BFA */
-		if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN) {
+		if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN)
 			bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
-		} else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN) {
+		else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN)
 			bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
-		}
 		break;
 
 	case RPFSM_EVENT_RPSC_FAIL:
@@ -154,7 +153,7 @@ bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
 		}
 		break;
 
-	case RPFSM_EVENT_RPORT_OFFLINE :
+	case RPFSM_EVENT_RPORT_OFFLINE:
 		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
 		bfa_fcxp_discard(rpf->fcxp);
 		rpf->rpsc_retries = 0;
@@ -174,13 +173,13 @@ bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
 	bfa_trc(rport->fcs, event);
 
 	switch (event) {
-	case RPFSM_EVENT_TIMEOUT :
+	case RPFSM_EVENT_TIMEOUT:
 		/* re-send the RPSC */
 		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
 		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
 		break;
 
-	case RPFSM_EVENT_RPORT_OFFLINE :
+	case RPFSM_EVENT_RPORT_OFFLINE:
 		bfa_timer_stop(&rpf->timer);
 		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
 		rpf->rpsc_retries = 0;
@@ -201,7 +200,7 @@ bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
 	bfa_trc(rport->fcs, event);
 
 	switch (event) {
-	case RPFSM_EVENT_RPORT_OFFLINE :
+	case RPFSM_EVENT_RPORT_OFFLINE:
 		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
 		rpf->rpsc_retries = 0;
 		break;
@@ -221,12 +220,12 @@ bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
 	bfa_trc(rport->fcs, event);
 
 	switch (event) {
-	case RPFSM_EVENT_RPORT_ONLINE :
+	case RPFSM_EVENT_RPORT_ONLINE:
 		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
 		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
 		break;
 
-	case RPFSM_EVENT_RPORT_OFFLINE :
+	case RPFSM_EVENT_RPORT_OFFLINE:
 		break;
 
 	default:
@@ -366,10 +365,9 @@ bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
 		bfa_trc(rport->fcs, ls_rjt->reason_code);
 		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
 		rport->stats.rpsc_rejects++;
-		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
+		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
 			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
-		} else {
+		else
 			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
-		}
 	}
 }

+ 1 - 1
drivers/scsi/bfa/vfapi.c

@@ -189,7 +189,7 @@ bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
 {
 	bfa_trc(fcs, vf_id);
 	if (vf_id == FC_VF_ID_NULL)
-		return (&fcs->fabric);
+		return &fcs->fabric;
 
 	/**
 	 * @todo vf support

+ 10 - 10
drivers/scsi/bfa/vport.c

@@ -31,13 +31,13 @@
 
 BFA_TRC_FILE(FCS, VPORT);
 
-#define __vport_fcs(__vp)       (__vp)->lport.fcs
-#define __vport_pwwn(__vp)      (__vp)->lport.port_cfg.pwwn
-#define __vport_nwwn(__vp)      (__vp)->lport.port_cfg.nwwn
-#define __vport_bfa(__vp)       (__vp)->lport.fcs->bfa
-#define __vport_fcid(__vp)      (__vp)->lport.pid
-#define __vport_fabric(__vp)    (__vp)->lport.fabric
-#define __vport_vfid(__vp)      (__vp)->lport.fabric->vf_id
+#define __vport_fcs(__vp)       ((__vp)->lport.fcs)
+#define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
+#define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
+#define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
+#define __vport_fcid(__vp)      ((__vp)->lport.pid)
+#define __vport_fabric(__vp)    ((__vp)->lport.fabric)
+#define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
 
 #define BFA_FCS_VPORT_MAX_RETRIES  5
 /*
@@ -641,9 +641,9 @@ bfa_fcs_vport_get_max(struct bfa_fcs_s *fcs)
 	bfa_get_attr(fcs->bfa, &ioc_attr);
 
 	if (ioc_attr.pci_attr.device_id == BFA_PCI_DEVICE_ID_CT)
-		return (BFA_FCS_MAX_VPORTS_SUPP_CT);
+		return BFA_FCS_MAX_VPORTS_SUPP_CT;
 	else
-		return (BFA_FCS_MAX_VPORTS_SUPP_CB);
+		return BFA_FCS_MAX_VPORTS_SUPP_CB;
 }
 
 
@@ -675,7 +675,7 @@ bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
 		     struct bfad_vport_s *vport_drv)
 {
 	if (vport_cfg->pwwn == 0)
-		return (BFA_STATUS_INVALID_WWN);
+		return BFA_STATUS_INVALID_WWN;
 
 	if (bfa_fcs_port_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
 		return BFA_STATUS_VPORT_WWN_BP;

+ 0 - 1
drivers/scsi/bnx2i/bnx2i.h

@@ -232,7 +232,6 @@ struct bnx2i_conn {
 	struct iscsi_cls_conn *cls_conn;
 	struct bnx2i_hba *hba;
 	struct completion cmd_cleanup_cmpl;
-	int is_bound;
 
 	u32 iscsi_conn_cid;
 #define BNX2I_CID_RESERVED	0x5AFF

+ 2 - 8
drivers/scsi/bnx2i/bnx2i_iscsi.c

@@ -1161,9 +1161,6 @@ static int bnx2i_task_xmit(struct iscsi_task *task)
 	struct bnx2i_cmd *cmd = task->dd_data;
 	struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
 
-	if (!bnx2i_conn->is_bound)
-		return -ENOTCONN;
-
 	/*
 	 * If there is no scsi_cmnd this must be a mgmt task
 	 */
@@ -1371,7 +1368,6 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
 	bnx2i_conn->ep = bnx2i_ep;
 	bnx2i_conn->iscsi_conn_cid = bnx2i_ep->ep_iscsi_cid;
 	bnx2i_conn->fw_cid = bnx2i_ep->ep_cid;
-	bnx2i_conn->is_bound = 1;
 
 	ret_code = bnx2i_bind_conn_to_iscsi_cid(hba, bnx2i_conn,
 						bnx2i_ep->ep_iscsi_cid);
@@ -1896,9 +1892,7 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)
 		conn = bnx2i_conn->cls_conn->dd_data;
 		session = conn->session;
 
-		spin_lock_bh(&session->lock);
-		bnx2i_conn->is_bound = 0;
-		spin_unlock_bh(&session->lock);
+		iscsi_suspend_queue(conn);
 	}
 
 	hba = bnx2i_ep->hba;
@@ -2034,7 +2028,7 @@ struct iscsi_transport bnx2i_iscsi_transport = {
 				  ISCSI_USERNAME | ISCSI_PASSWORD |
 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
-				  ISCSI_LU_RESET_TMO |
+				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
 				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
 				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_NETDEV_NAME,

+ 1 - 0
drivers/scsi/constants.c

@@ -141,6 +141,7 @@ static const struct value_name_pair serv_out12_arr[] = {
 static const struct value_name_pair serv_in16_arr[] = {
 	{0x10, "Read capacity(16)"},
 	{0x11, "Read long(16)"},
+	{0x12, "Get LBA status"},
 };
 #define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr)
 

+ 1 - 1
drivers/scsi/cxgb3i/cxgb3i_iscsi.c

@@ -937,7 +937,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
 				ISCSI_USERNAME | ISCSI_PASSWORD |
 				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
 				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
-				ISCSI_LU_RESET_TMO |
+				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
 				ISCSI_PING_TMO | ISCSI_RECV_TMO |
 				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |

+ 16 - 12
drivers/scsi/device_handler/scsi_dh.c

@@ -226,7 +226,7 @@ store_dh_state(struct device *dev, struct device_attribute *attr,
 			 * Activate a device handler
 			 */
 			if (scsi_dh->activate)
-				err = scsi_dh->activate(sdev);
+				err = scsi_dh->activate(sdev, NULL, NULL);
 			else
 				err = 0;
 		}
@@ -304,18 +304,15 @@ static int scsi_dh_notifier(struct notifier_block *nb,
 	sdev = to_scsi_device(dev);
 
 	if (action == BUS_NOTIFY_ADD_DEVICE) {
+		err = device_create_file(dev, &scsi_dh_state_attr);
+		/* don't care about err */
 		devinfo = device_handler_match(NULL, sdev);
-		if (!devinfo)
-			goto out;
-
-		err = scsi_dh_handler_attach(sdev, devinfo);
-		if (!err)
-			err = device_create_file(dev, &scsi_dh_state_attr);
+		if (devinfo)
+			err = scsi_dh_handler_attach(sdev, devinfo);
 	} else if (action == BUS_NOTIFY_DEL_DEVICE) {
 		device_remove_file(dev, &scsi_dh_state_attr);
 		scsi_dh_handler_detach(sdev, NULL);
 	}
-out:
 	return err;
 }
 
@@ -423,10 +420,17 @@ EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
 /*
  * scsi_dh_activate - activate the path associated with the scsi_device
  *      corresponding to the given request queue.
- * @q - Request queue that is associated with the scsi_device to be
- *      activated.
+ *     Returns immediately without waiting for activation to be completed.
+ * @q    - Request queue that is associated with the scsi_device to be
+ *         activated.
+ * @fn   - Function to be called upon completion of the activation.
+ *         Function fn is called with data (below) and the error code.
+ *         Function fn may be called from the same calling context. So,
+ *         do not hold the lock in the caller which may be needed in fn.
+ * @data - data passed to the function fn upon completion.
+ *
  */
-int scsi_dh_activate(struct request_queue *q)
+int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
 {
 	int err = 0;
 	unsigned long flags;
@@ -445,7 +449,7 @@ int scsi_dh_activate(struct request_queue *q)
 		return err;
 
 	if (scsi_dh->activate)
-		err = scsi_dh->activate(sdev);
+		err = scsi_dh->activate(sdev, fn, data);
 	put_device(&sdev->sdev_gendev);
 	return err;
 }

Some files were not shown because too many files changed in this diff