| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1 | /* | 
|  | 2 | *  linux/drivers/message/fusion/mptfc.c | 
| Prakash, Sathya | f36789e | 2007-08-14 16:22:54 +0530 | [diff] [blame] | 3 | *      For use with LSI PCI chip/adapter(s) | 
|  | 4 | *      running LSI Fusion MPT (Message Passing Technology) firmware. | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 5 | * | 
| Prakash, Sathya | cddc0ab | 2008-05-21 00:56:41 +0530 | [diff] [blame] | 6 | *  Copyright (c) 1999-2008 LSI Corporation | 
| Eric Moore | 16d2010 | 2007-06-13 16:31:07 -0600 | [diff] [blame] | 7 | *  (mailto:DL-MPTFusionLinux@lsi.com) | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 8 | * | 
|  | 9 | */ | 
|  | 10 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 
|  | 11 | /* | 
|  | 12 | This program is free software; you can redistribute it and/or modify | 
|  | 13 | it under the terms of the GNU General Public License as published by | 
|  | 14 | the Free Software Foundation; version 2 of the License. | 
|  | 15 |  | 
|  | 16 | This program is distributed in the hope that it will be useful, | 
|  | 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 19 | GNU General Public License for more details. | 
|  | 20 |  | 
|  | 21 | NO WARRANTY | 
|  | 22 | THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | 
|  | 23 | CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | 
|  | 24 | LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | 
|  | 25 | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | 
|  | 26 | solely responsible for determining the appropriateness of using and | 
|  | 27 | distributing the Program and assumes all risks associated with its | 
|  | 28 | exercise of rights under this Agreement, including but not limited to | 
|  | 29 | the risks and costs of program errors, damage to or loss of data, | 
|  | 30 | programs or equipment, and unavailability or interruption of operations. | 
|  | 31 |  | 
|  | 32 | DISCLAIMER OF LIABILITY | 
|  | 33 | NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | 
|  | 34 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
|  | 35 | DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | 
|  | 36 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | 
|  | 37 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | 
|  | 38 | USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | 
|  | 39 | HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | 
|  | 40 |  | 
|  | 41 | You should have received a copy of the GNU General Public License | 
|  | 42 | along with this program; if not, write to the Free Software | 
|  | 43 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|  | 44 | */ | 
|  | 45 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 46 | #include <linux/module.h> | 
|  | 47 | #include <linux/kernel.h> | 
|  | 48 | #include <linux/init.h> | 
|  | 49 | #include <linux/errno.h> | 
|  | 50 | #include <linux/kdev_t.h> | 
|  | 51 | #include <linux/blkdev.h> | 
|  | 52 | #include <linux/delay.h>	/* for mdelay */ | 
|  | 53 | #include <linux/interrupt.h>	/* needed for in_interrupt() proto */ | 
|  | 54 | #include <linux/reboot.h>	/* notifier code */ | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 55 | #include <linux/workqueue.h> | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 56 | #include <linux/sort.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 57 | #include <linux/slab.h> | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 58 |  | 
|  | 59 | #include <scsi/scsi.h> | 
|  | 60 | #include <scsi/scsi_cmnd.h> | 
|  | 61 | #include <scsi/scsi_device.h> | 
|  | 62 | #include <scsi/scsi_host.h> | 
|  | 63 | #include <scsi/scsi_tcq.h> | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 64 | #include <scsi/scsi_transport_fc.h> | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 65 |  | 
|  | 66 | #include "mptbase.h" | 
|  | 67 | #include "mptscsih.h" | 
|  | 68 |  | 
|  | 69 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 
|  | 70 | #define my_NAME		"Fusion MPT FC Host driver" | 
|  | 71 | #define my_VERSION	MPT_LINUX_VERSION_COMMON | 
|  | 72 | #define MYNAM		"mptfc" | 
|  | 73 |  | 
|  | 74 | MODULE_AUTHOR(MODULEAUTHOR); | 
|  | 75 | MODULE_DESCRIPTION(my_NAME); | 
|  | 76 | MODULE_LICENSE("GPL"); | 
| Eric Moore | 9f4203b | 2007-01-04 20:47:47 -0700 | [diff] [blame] | 77 | MODULE_VERSION(my_VERSION); | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 78 |  | 
|  | 79 | /* Command line args */ | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 80 | #define MPTFC_DEV_LOSS_TMO (60) | 
|  | 81 | static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;	/* reasonable default */ | 
|  | 82 | module_param(mptfc_dev_loss_tmo, int, 0); | 
|  | 83 | MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the " | 
|  | 84 | " transport to wait for an rport to " | 
|  | 85 | " return following a device loss event." | 
|  | 86 | "  Default=60."); | 
|  | 87 |  | 
| Eric Moore | 793955f | 2007-01-29 09:42:20 -0700 | [diff] [blame] | 88 | /* scsi-mid layer global parmeter is max_report_luns, which is 511 */ | 
|  | 89 | #define MPTFC_MAX_LUN (16895) | 
|  | 90 | static int max_lun = MPTFC_MAX_LUN; | 
|  | 91 | module_param(max_lun, int, 0); | 
|  | 92 | MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); | 
|  | 93 |  | 
| Prakash, Sathya | f606f57 | 2007-08-14 16:12:53 +0530 | [diff] [blame] | 94 | static u8	mptfcDoneCtx = MPT_MAX_PROTOCOL_DRIVERS; | 
|  | 95 | static u8	mptfcTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; | 
|  | 96 | static u8	mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 97 |  | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 98 | static int mptfc_target_alloc(struct scsi_target *starget); | 
|  | 99 | static int mptfc_slave_alloc(struct scsi_device *sdev); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 100 | static int mptfc_qcmd(struct scsi_cmnd *SCpnt, | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 101 | void (*done)(struct scsi_cmnd *)); | 
|  | 102 | static void mptfc_target_destroy(struct scsi_target *starget); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 103 | static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); | 
|  | 104 | static void __devexit mptfc_remove(struct pci_dev *pdev); | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 105 | static int mptfc_abort(struct scsi_cmnd *SCpnt); | 
|  | 106 | static int mptfc_dev_reset(struct scsi_cmnd *SCpnt); | 
|  | 107 | static int mptfc_bus_reset(struct scsi_cmnd *SCpnt); | 
|  | 108 | static int mptfc_host_reset(struct scsi_cmnd *SCpnt); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 109 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 110 | static struct scsi_host_template mptfc_driver_template = { | 
| Moore, Eric Dean | f78496d | 2005-11-16 18:54:14 -0700 | [diff] [blame] | 111 | .module				= THIS_MODULE, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 112 | .proc_name			= "mptfc", | 
|  | 113 | .proc_info			= mptscsih_proc_info, | 
|  | 114 | .name				= "MPT FC Host", | 
|  | 115 | .info				= mptscsih_info, | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 116 | .queuecommand			= mptfc_qcmd, | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 117 | .target_alloc			= mptfc_target_alloc, | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 118 | .slave_alloc			= mptfc_slave_alloc, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 119 | .slave_configure		= mptscsih_slave_configure, | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 120 | .target_destroy			= mptfc_target_destroy, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 121 | .slave_destroy			= mptscsih_slave_destroy, | 
| Moore, Eric Dean | 6e3815b | 2005-06-24 12:18:57 -0600 | [diff] [blame] | 122 | .change_queue_depth 		= mptscsih_change_queue_depth, | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 123 | .eh_abort_handler		= mptfc_abort, | 
|  | 124 | .eh_device_reset_handler	= mptfc_dev_reset, | 
|  | 125 | .eh_bus_reset_handler		= mptfc_bus_reset, | 
|  | 126 | .eh_host_reset_handler		= mptfc_host_reset, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 127 | .bios_param			= mptscsih_bios_param, | 
|  | 128 | .can_queue			= MPT_FC_CAN_QUEUE, | 
|  | 129 | .this_id			= -1, | 
|  | 130 | .sg_tablesize			= MPT_SCSI_SG_DEPTH, | 
|  | 131 | .max_sectors			= 8192, | 
|  | 132 | .cmd_per_lun			= 7, | 
|  | 133 | .use_clustering			= ENABLE_CLUSTERING, | 
| Prakash, Sathya | edb9068 | 2007-07-17 14:39:14 +0530 | [diff] [blame] | 134 | .shost_attrs			= mptscsih_host_attrs, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 135 | }; | 
|  | 136 |  | 
|  | 137 | /**************************************************************************** | 
|  | 138 | * Supported hardware | 
|  | 139 | */ | 
|  | 140 |  | 
|  | 141 | static struct pci_device_id mptfc_pci_table[] = { | 
| Eric Moore | 87cf898 | 2006-06-27 16:09:26 -0600 | [diff] [blame] | 142 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 143 | PCI_ANY_ID, PCI_ANY_ID }, | 
| Eric Moore | 87cf898 | 2006-06-27 16:09:26 -0600 | [diff] [blame] | 144 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 145 | PCI_ANY_ID, PCI_ANY_ID }, | 
| Eric Moore | 87cf898 | 2006-06-27 16:09:26 -0600 | [diff] [blame] | 146 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 147 | PCI_ANY_ID, PCI_ANY_ID }, | 
| Eric Moore | 87cf898 | 2006-06-27 16:09:26 -0600 | [diff] [blame] | 148 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 149 | PCI_ANY_ID, PCI_ANY_ID }, | 
| Eric Moore | 87cf898 | 2006-06-27 16:09:26 -0600 | [diff] [blame] | 150 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 151 | PCI_ANY_ID, PCI_ANY_ID }, | 
| Eric Moore | 87cf898 | 2006-06-27 16:09:26 -0600 | [diff] [blame] | 152 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X, | 
| Moore, Eric Dean | 3fadc59 | 2005-05-11 17:46:52 -0600 | [diff] [blame] | 153 | PCI_ANY_ID, PCI_ANY_ID }, | 
| Eric Moore | 87cf898 | 2006-06-27 16:09:26 -0600 | [diff] [blame] | 154 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X, | 
| Moore, Eric Dean | 3fadc59 | 2005-05-11 17:46:52 -0600 | [diff] [blame] | 155 | PCI_ANY_ID, PCI_ANY_ID }, | 
| Eric Moore | 87cf898 | 2006-06-27 16:09:26 -0600 | [diff] [blame] | 156 | { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E, | 
| Moore, Eric | 6d5b0c3 | 2006-01-13 16:25:26 -0700 | [diff] [blame] | 157 | PCI_ANY_ID, PCI_ANY_ID }, | 
| Prakash, Sathya | ef1d8df | 2007-07-17 14:18:41 +0530 | [diff] [blame] | 158 | { PCI_VENDOR_ID_BROCADE, MPI_MANUFACTPAGE_DEVICEID_FC949E, | 
|  | 159 | PCI_ANY_ID, PCI_ANY_ID }, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 160 | {0}	/* Terminating entry */ | 
|  | 161 | }; | 
|  | 162 | MODULE_DEVICE_TABLE(pci, mptfc_pci_table); | 
|  | 163 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 164 | static struct scsi_transport_template *mptfc_transport_template = NULL; | 
|  | 165 |  | 
| Adrian Bunk | 03fbcbc | 2006-01-25 02:00:52 +0100 | [diff] [blame] | 166 | static struct fc_function_template mptfc_transport_functions = { | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 167 | .dd_fcrport_size = 8, | 
|  | 168 | .show_host_node_name = 1, | 
|  | 169 | .show_host_port_name = 1, | 
|  | 170 | .show_host_supported_classes = 1, | 
|  | 171 | .show_host_port_id = 1, | 
|  | 172 | .show_rport_supported_classes = 1, | 
|  | 173 | .show_starget_node_name = 1, | 
|  | 174 | .show_starget_port_name = 1, | 
|  | 175 | .show_starget_port_id = 1, | 
|  | 176 | .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo, | 
|  | 177 | .show_rport_dev_loss_tmo = 1, | 
| Michael Reed | 5d947f2 | 2006-07-31 12:19:30 -0500 | [diff] [blame] | 178 | .show_host_supported_speeds = 1, | 
|  | 179 | .show_host_maxframe_size = 1, | 
|  | 180 | .show_host_speed = 1, | 
|  | 181 | .show_host_fabric_name = 1, | 
|  | 182 | .show_host_port_type = 1, | 
|  | 183 | .show_host_port_state = 1, | 
|  | 184 | .show_host_symbolic_name = 1, | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 185 | }; | 
|  | 186 |  | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 187 | static int | 
|  | 188 | mptfc_block_error_handler(struct scsi_cmnd *SCpnt, | 
|  | 189 | int (*func)(struct scsi_cmnd *SCpnt), | 
|  | 190 | const char *caller) | 
|  | 191 | { | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 192 | MPT_SCSI_HOST		*hd; | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 193 | struct scsi_device	*sdev = SCpnt->device; | 
|  | 194 | struct Scsi_Host	*shost = sdev->host; | 
|  | 195 | struct fc_rport		*rport = starget_to_rport(scsi_target(sdev)); | 
|  | 196 | unsigned long		flags; | 
|  | 197 | int			ready; | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 198 | MPT_ADAPTER 		*ioc; | 
| Michael Reed | 03cb382 | 2010-02-10 14:32:00 -0600 | [diff] [blame] | 199 | int			loops = 40;	/* seconds */ | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 200 |  | 
| Eric Moore | e7eae9f | 2007-09-29 10:15:59 -0600 | [diff] [blame] | 201 | hd = shost_priv(SCpnt->device->host); | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 202 | ioc = hd->ioc; | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 203 | spin_lock_irqsave(shost->host_lock, flags); | 
| Michael Reed | 03cb382 | 2010-02-10 14:32:00 -0600 | [diff] [blame] | 204 | while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY | 
|  | 205 | || (loops > 0 && ioc->active == 0)) { | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 206 | spin_unlock_irqrestore(shost->host_lock, flags); | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 207 | dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 208 | "mptfc_block_error_handler.%d: %d:%d, port status is " | 
| Michael Reed | 03cb382 | 2010-02-10 14:32:00 -0600 | [diff] [blame] | 209 | "%x, active flag %d, deferring %s recovery.\n", | 
| Eric Moore | e7eae9f | 2007-09-29 10:15:59 -0600 | [diff] [blame] | 210 | ioc->name, ioc->sh->host_no, | 
| Michael Reed | 03cb382 | 2010-02-10 14:32:00 -0600 | [diff] [blame] | 211 | SCpnt->device->id, SCpnt->device->lun, | 
|  | 212 | ready, ioc->active, caller)); | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 213 | msleep(1000); | 
|  | 214 | spin_lock_irqsave(shost->host_lock, flags); | 
| Michael Reed | 03cb382 | 2010-02-10 14:32:00 -0600 | [diff] [blame] | 215 | loops --; | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 216 | } | 
|  | 217 | spin_unlock_irqrestore(shost->host_lock, flags); | 
|  | 218 |  | 
| Michael Reed | 03cb382 | 2010-02-10 14:32:00 -0600 | [diff] [blame] | 219 | if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata | 
|  | 220 | || ioc->active == 0) { | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 221 | dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 222 | "%s.%d: %d:%d, failing recovery, " | 
| Michael Reed | 03cb382 | 2010-02-10 14:32:00 -0600 | [diff] [blame] | 223 | "port state %x, active %d, vdevice %p.\n", caller, | 
| Eric Moore | e7eae9f | 2007-09-29 10:15:59 -0600 | [diff] [blame] | 224 | ioc->name, ioc->sh->host_no, | 
| Eric Moore | 29dd360 | 2007-09-14 18:46:51 -0600 | [diff] [blame] | 225 | SCpnt->device->id, SCpnt->device->lun, ready, | 
| Michael Reed | 03cb382 | 2010-02-10 14:32:00 -0600 | [diff] [blame] | 226 | ioc->active, SCpnt->device->hostdata)); | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 227 | return FAILED; | 
|  | 228 | } | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 229 | dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 230 | "%s.%d: %d:%d, executing recovery.\n", caller, | 
| Eric Moore | e7eae9f | 2007-09-29 10:15:59 -0600 | [diff] [blame] | 231 | ioc->name, ioc->sh->host_no, | 
| Eric Moore | 29dd360 | 2007-09-14 18:46:51 -0600 | [diff] [blame] | 232 | SCpnt->device->id, SCpnt->device->lun)); | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 233 | return (*func)(SCpnt); | 
|  | 234 | } | 
|  | 235 |  | 
|  | 236 | static int | 
|  | 237 | mptfc_abort(struct scsi_cmnd *SCpnt) | 
|  | 238 | { | 
|  | 239 | return | 
| Harvey Harrison | cadbd4a | 2008-07-03 23:47:27 -0700 | [diff] [blame] | 240 | mptfc_block_error_handler(SCpnt, mptscsih_abort, __func__); | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 241 | } | 
|  | 242 |  | 
|  | 243 | static int | 
|  | 244 | mptfc_dev_reset(struct scsi_cmnd *SCpnt) | 
|  | 245 | { | 
|  | 246 | return | 
| Harvey Harrison | cadbd4a | 2008-07-03 23:47:27 -0700 | [diff] [blame] | 247 | mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __func__); | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 248 | } | 
|  | 249 |  | 
|  | 250 | static int | 
|  | 251 | mptfc_bus_reset(struct scsi_cmnd *SCpnt) | 
|  | 252 | { | 
|  | 253 | return | 
| Harvey Harrison | cadbd4a | 2008-07-03 23:47:27 -0700 | [diff] [blame] | 254 | mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __func__); | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 255 | } | 
|  | 256 |  | 
|  | 257 | static int | 
|  | 258 | mptfc_host_reset(struct scsi_cmnd *SCpnt) | 
|  | 259 | { | 
|  | 260 | return | 
| Harvey Harrison | cadbd4a | 2008-07-03 23:47:27 -0700 | [diff] [blame] | 261 | mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __func__); | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 262 | } | 
|  | 263 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 264 | static void | 
|  | 265 | mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) | 
|  | 266 | { | 
|  | 267 | if (timeout > 0) | 
|  | 268 | rport->dev_loss_tmo = timeout; | 
|  | 269 | else | 
|  | 270 | rport->dev_loss_tmo = mptfc_dev_loss_tmo; | 
|  | 271 | } | 
|  | 272 |  | 
|  | 273 | static int | 
|  | 274 | mptfc_FcDevPage0_cmp_func(const void *a, const void *b) | 
|  | 275 | { | 
|  | 276 | FCDevicePage0_t **aa = (FCDevicePage0_t **)a; | 
|  | 277 | FCDevicePage0_t **bb = (FCDevicePage0_t **)b; | 
|  | 278 |  | 
|  | 279 | if ((*aa)->CurrentBus == (*bb)->CurrentBus) { | 
|  | 280 | if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID) | 
|  | 281 | return 0; | 
|  | 282 | if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID) | 
|  | 283 | return -1; | 
|  | 284 | return 1; | 
|  | 285 | } | 
|  | 286 | if ((*aa)->CurrentBus < (*bb)->CurrentBus) | 
|  | 287 | return -1; | 
|  | 288 | return 1; | 
|  | 289 | } | 
|  | 290 |  | 
|  | 291 | static int | 
|  | 292 | mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port, | 
|  | 293 | void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg)) | 
|  | 294 | { | 
|  | 295 | ConfigPageHeader_t	 hdr; | 
|  | 296 | CONFIGPARMS		 cfg; | 
|  | 297 | FCDevicePage0_t		*ppage0_alloc, *fc; | 
|  | 298 | dma_addr_t		 page0_dma; | 
|  | 299 | int			 data_sz; | 
|  | 300 | int			 ii; | 
|  | 301 |  | 
|  | 302 | FCDevicePage0_t		*p0_array=NULL, *p_p0; | 
|  | 303 | FCDevicePage0_t		**pp0_array=NULL, **p_pp0; | 
|  | 304 |  | 
|  | 305 | int			 rc = -ENOMEM; | 
|  | 306 | U32			 port_id = 0xffffff; | 
|  | 307 | int			 num_targ = 0; | 
|  | 308 | int			 max_bus = ioc->facts.MaxBuses; | 
| Eric Moore | 793955f | 2007-01-29 09:42:20 -0700 | [diff] [blame] | 309 | int			 max_targ; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 310 |  | 
| Eric Moore | 793955f | 2007-01-29 09:42:20 -0700 | [diff] [blame] | 311 | max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 312 |  | 
|  | 313 | data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ; | 
|  | 314 | p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL); | 
|  | 315 | if (!p0_array) | 
|  | 316 | goto out; | 
|  | 317 |  | 
|  | 318 | data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ; | 
|  | 319 | p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL); | 
|  | 320 | if (!pp0_array) | 
|  | 321 | goto out; | 
|  | 322 |  | 
|  | 323 | do { | 
|  | 324 | /* Get FC Device Page 0 header */ | 
|  | 325 | hdr.PageVersion = 0; | 
|  | 326 | hdr.PageLength = 0; | 
|  | 327 | hdr.PageNumber = 0; | 
|  | 328 | hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE; | 
|  | 329 | cfg.cfghdr.hdr = &hdr; | 
|  | 330 | cfg.physAddr = -1; | 
|  | 331 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | 
|  | 332 | cfg.dir = 0; | 
|  | 333 | cfg.pageAddr = port_id; | 
|  | 334 | cfg.timeout = 0; | 
|  | 335 |  | 
|  | 336 | if ((rc = mpt_config(ioc, &cfg)) != 0) | 
|  | 337 | break; | 
|  | 338 |  | 
|  | 339 | if (hdr.PageLength <= 0) | 
|  | 340 | break; | 
|  | 341 |  | 
|  | 342 | data_sz = hdr.PageLength * 4; | 
|  | 343 | ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz, | 
|  | 344 | &page0_dma); | 
|  | 345 | rc = -ENOMEM; | 
|  | 346 | if (!ppage0_alloc) | 
|  | 347 | break; | 
|  | 348 |  | 
|  | 349 | cfg.physAddr = page0_dma; | 
|  | 350 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | 
|  | 351 |  | 
|  | 352 | if ((rc = mpt_config(ioc, &cfg)) == 0) { | 
|  | 353 | ppage0_alloc->PortIdentifier = | 
|  | 354 | le32_to_cpu(ppage0_alloc->PortIdentifier); | 
|  | 355 |  | 
|  | 356 | ppage0_alloc->WWNN.Low = | 
|  | 357 | le32_to_cpu(ppage0_alloc->WWNN.Low); | 
|  | 358 |  | 
|  | 359 | ppage0_alloc->WWNN.High = | 
|  | 360 | le32_to_cpu(ppage0_alloc->WWNN.High); | 
|  | 361 |  | 
|  | 362 | ppage0_alloc->WWPN.Low = | 
|  | 363 | le32_to_cpu(ppage0_alloc->WWPN.Low); | 
|  | 364 |  | 
|  | 365 | ppage0_alloc->WWPN.High = | 
|  | 366 | le32_to_cpu(ppage0_alloc->WWPN.High); | 
|  | 367 |  | 
|  | 368 | ppage0_alloc->BBCredit = | 
|  | 369 | le16_to_cpu(ppage0_alloc->BBCredit); | 
|  | 370 |  | 
|  | 371 | ppage0_alloc->MaxRxFrameSize = | 
|  | 372 | le16_to_cpu(ppage0_alloc->MaxRxFrameSize); | 
|  | 373 |  | 
|  | 374 | port_id = ppage0_alloc->PortIdentifier; | 
|  | 375 | num_targ++; | 
|  | 376 | *p_p0 = *ppage0_alloc;	/* save data */ | 
|  | 377 | *p_pp0++ = p_p0++;	/* save addr */ | 
|  | 378 | } | 
|  | 379 | pci_free_consistent(ioc->pcidev, data_sz, | 
|  | 380 | (u8 *) ppage0_alloc, page0_dma); | 
|  | 381 | if (rc != 0) | 
|  | 382 | break; | 
|  | 383 |  | 
|  | 384 | } while (port_id <= 0xff0000); | 
|  | 385 |  | 
|  | 386 | if (num_targ) { | 
|  | 387 | /* sort array */ | 
|  | 388 | if (num_targ > 1) | 
|  | 389 | sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *), | 
|  | 390 | mptfc_FcDevPage0_cmp_func, NULL); | 
|  | 391 | /* call caller's func for each targ */ | 
|  | 392 | for (ii = 0; ii < num_targ;  ii++) { | 
|  | 393 | fc = *(pp0_array+ii); | 
|  | 394 | func(ioc, ioc_port, fc); | 
|  | 395 | } | 
|  | 396 | } | 
|  | 397 |  | 
|  | 398 | out: | 
| Jesper Juhl | 8f76078 | 2006-06-27 02:55:06 -0700 | [diff] [blame] | 399 | kfree(pp0_array); | 
|  | 400 | kfree(p0_array); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 401 | return rc; | 
|  | 402 | } | 
|  | 403 |  | 
|  | 404 | static int | 
|  | 405 | mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid) | 
|  | 406 | { | 
|  | 407 | /* not currently usable */ | 
|  | 408 | if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID | | 
|  | 409 | MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID)) | 
|  | 410 | return -1; | 
|  | 411 |  | 
|  | 412 | if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID)) | 
|  | 413 | return -1; | 
|  | 414 |  | 
|  | 415 | if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET)) | 
|  | 416 | return -1; | 
|  | 417 |  | 
|  | 418 | /* | 
|  | 419 | * board data structure already normalized to platform endianness | 
|  | 420 | * shifted to avoid unaligned access on 64 bit architecture | 
|  | 421 | */ | 
|  | 422 | rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low; | 
|  | 423 | rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low; | 
|  | 424 | rid->port_id =   pg0->PortIdentifier; | 
|  | 425 | rid->roles = FC_RPORT_ROLE_UNKNOWN; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 426 |  | 
|  | 427 | return 0; | 
|  | 428 | } | 
|  | 429 |  | 
|  | 430 | static void | 
|  | 431 | mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | 
|  | 432 | { | 
|  | 433 | struct fc_rport_identifiers rport_ids; | 
|  | 434 | struct fc_rport		*rport; | 
|  | 435 | struct mptfc_rport_info	*ri; | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 436 | int			new_ri = 1; | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 437 | u64			pn, nn; | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 438 | VirtTarget		*vtarget; | 
| mdr@sgi.com | 6dd727d | 2006-05-01 13:07:04 -0500 | [diff] [blame] | 439 | u32			roles = FC_RPORT_ROLE_UNKNOWN; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 440 |  | 
|  | 441 | if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0) | 
|  | 442 | return; | 
|  | 443 |  | 
| mdr@sgi.com | 6dd727d | 2006-05-01 13:07:04 -0500 | [diff] [blame] | 444 | roles |= FC_RPORT_ROLE_FCP_TARGET; | 
|  | 445 | if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR) | 
|  | 446 | roles |= FC_RPORT_ROLE_FCP_INITIATOR; | 
|  | 447 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 448 | /* scan list looking for a match */ | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 449 | list_for_each_entry(ri, &ioc->fc_rports, list) { | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 450 | pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; | 
|  | 451 | if (pn == rport_ids.port_name) {	/* match */ | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 452 | list_move_tail(&ri->list, &ioc->fc_rports); | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 453 | new_ri = 0; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 454 | break; | 
|  | 455 | } | 
|  | 456 | } | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 457 | if (new_ri) {	/* allocate one */ | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 458 | ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL); | 
|  | 459 | if (!ri) | 
|  | 460 | return; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 461 | list_add_tail(&ri->list, &ioc->fc_rports); | 
|  | 462 | } | 
|  | 463 |  | 
|  | 464 | ri->pg0 = *pg0;	/* add/update pg0 data */ | 
|  | 465 | ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING; | 
|  | 466 |  | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 467 | /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */ | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 468 | if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) { | 
|  | 469 | ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED; | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 470 | rport = fc_remote_port_add(ioc->sh, channel, &rport_ids); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 471 | if (rport) { | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 472 | ri->rport = rport; | 
|  | 473 | if (new_ri) /* may have been reset by user */ | 
|  | 474 | rport->dev_loss_tmo = mptfc_dev_loss_tmo; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 475 | /* | 
|  | 476 | * if already mapped, remap here.  If not mapped, | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 477 | * target_alloc will allocate vtarget and map, | 
| Eric Moore | a69de50 | 2007-09-14 18:48:19 -0600 | [diff] [blame] | 478 | * slave_alloc will fill in vdevice from vtarget. | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 479 | */ | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 480 | if (ri->starget) { | 
|  | 481 | vtarget = ri->starget->hostdata; | 
|  | 482 | if (vtarget) { | 
| Eric Moore | 793955f | 2007-01-29 09:42:20 -0700 | [diff] [blame] | 483 | vtarget->id = pg0->CurrentTargetID; | 
|  | 484 | vtarget->channel = pg0->CurrentBus; | 
| Kashyap, Desai | 08f5c5c | 2010-03-18 19:22:45 +0530 | [diff] [blame] | 485 | vtarget->deleted = 0; | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 486 | } | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 487 | } | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 488 | *((struct mptfc_rport_info **)rport->dd_data) = ri; | 
| mdr@sgi.com | 6dd727d | 2006-05-01 13:07:04 -0500 | [diff] [blame] | 489 | /* scan will be scheduled once rport becomes a target */ | 
|  | 490 | fc_remote_port_rolechg(rport,roles); | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 491 |  | 
|  | 492 | pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; | 
|  | 493 | nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low; | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 494 | dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 495 | "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 496 | "rport tid %d, tmo %d\n", | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 497 | ioc->name, | 
| Moore, Eric | 914c2d8 | 2006-03-14 09:19:36 -0700 | [diff] [blame] | 498 | ioc->sh->host_no, | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 499 | pg0->PortIdentifier, | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 500 | (unsigned long long)nn, | 
|  | 501 | (unsigned long long)pn, | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 502 | pg0->CurrentTargetID, | 
|  | 503 | ri->rport->scsi_target_id, | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 504 | ri->rport->dev_loss_tmo)); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 505 | } else { | 
|  | 506 | list_del(&ri->list); | 
|  | 507 | kfree(ri); | 
|  | 508 | ri = NULL; | 
|  | 509 | } | 
|  | 510 | } | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 511 | } | 
|  | 512 |  | 
|  | 513 | /* | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 514 | *	OS entry point to allow for host driver to free allocated memory | 
|  | 515 | *	Called if no device present or device being unloaded | 
|  | 516 | */ | 
|  | 517 | static void | 
|  | 518 | mptfc_target_destroy(struct scsi_target *starget) | 
|  | 519 | { | 
|  | 520 | struct fc_rport		*rport; | 
|  | 521 | struct mptfc_rport_info *ri; | 
|  | 522 |  | 
|  | 523 | rport = starget_to_rport(starget); | 
|  | 524 | if (rport) { | 
|  | 525 | ri = *((struct mptfc_rport_info **)rport->dd_data); | 
|  | 526 | if (ri)	/* better be! */ | 
|  | 527 | ri->starget = NULL; | 
|  | 528 | } | 
|  | 529 | if (starget->hostdata) | 
|  | 530 | kfree(starget->hostdata); | 
|  | 531 | starget->hostdata = NULL; | 
|  | 532 | } | 
|  | 533 |  | 
|  | 534 | /* | 
|  | 535 | *	OS entry point to allow host driver to alloc memory | 
|  | 536 | *	for each scsi target. Called once per device the bus scan. | 
|  | 537 | *	Return non-zero if allocation fails. | 
|  | 538 | */ | 
|  | 539 | static int | 
|  | 540 | mptfc_target_alloc(struct scsi_target *starget) | 
|  | 541 | { | 
|  | 542 | VirtTarget		*vtarget; | 
|  | 543 | struct fc_rport		*rport; | 
|  | 544 | struct mptfc_rport_info *ri; | 
|  | 545 | int			rc; | 
|  | 546 |  | 
|  | 547 | vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); | 
|  | 548 | if (!vtarget) | 
|  | 549 | return -ENOMEM; | 
|  | 550 | starget->hostdata = vtarget; | 
|  | 551 |  | 
|  | 552 | rc = -ENODEV; | 
|  | 553 | rport = starget_to_rport(starget); | 
|  | 554 | if (rport) { | 
|  | 555 | ri = *((struct mptfc_rport_info **)rport->dd_data); | 
|  | 556 | if (ri) {	/* better be! */ | 
| Eric Moore | 793955f | 2007-01-29 09:42:20 -0700 | [diff] [blame] | 557 | vtarget->id = ri->pg0.CurrentTargetID; | 
|  | 558 | vtarget->channel = ri->pg0.CurrentBus; | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 559 | ri->starget = starget; | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 560 | rc = 0; | 
|  | 561 | } | 
|  | 562 | } | 
|  | 563 | if (rc != 0) { | 
|  | 564 | kfree(vtarget); | 
|  | 565 | starget->hostdata = NULL; | 
|  | 566 | } | 
|  | 567 |  | 
|  | 568 | return rc; | 
|  | 569 | } | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 570 | /* | 
|  | 571 | *	mptfc_dump_lun_info | 
|  | 572 | *	@ioc | 
|  | 573 | *	@rport | 
|  | 574 | *	@sdev | 
|  | 575 | * | 
|  | 576 | */ | 
|  | 577 | static void | 
|  | 578 | mptfc_dump_lun_info(MPT_ADAPTER *ioc, struct fc_rport *rport, struct scsi_device *sdev, | 
|  | 579 | VirtTarget *vtarget) | 
|  | 580 | { | 
|  | 581 | u64 nn, pn; | 
|  | 582 | struct mptfc_rport_info *ri; | 
|  | 583 |  | 
|  | 584 | ri = *((struct mptfc_rport_info **)rport->dd_data); | 
|  | 585 | pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; | 
|  | 586 | nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low; | 
|  | 587 | dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT | 
|  | 588 | "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " | 
|  | 589 | "CurrentTargetID %d, %x %llx %llx\n", | 
|  | 590 | ioc->name, | 
|  | 591 | sdev->host->host_no, | 
|  | 592 | vtarget->num_luns, | 
|  | 593 | sdev->id, ri->pg0.CurrentTargetID, | 
|  | 594 | ri->pg0.PortIdentifier, | 
|  | 595 | (unsigned long long)pn, | 
|  | 596 | (unsigned long long)nn)); | 
|  | 597 | } | 
|  | 598 |  | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 599 |  | 
|  | 600 | /* | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 601 | *	OS entry point to allow host driver to alloc memory | 
|  | 602 | *	for each scsi device. Called once per device the bus scan. | 
|  | 603 | *	Return non-zero if allocation fails. | 
|  | 604 | *	Init memory once per LUN. | 
|  | 605 | */ | 
| Adrian Bunk | 03fbcbc | 2006-01-25 02:00:52 +0100 | [diff] [blame] | 606 | static int | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 607 | mptfc_slave_alloc(struct scsi_device *sdev) | 
|  | 608 | { | 
|  | 609 | MPT_SCSI_HOST		*hd; | 
|  | 610 | VirtTarget		*vtarget; | 
| Eric Moore | a69de50 | 2007-09-14 18:48:19 -0600 | [diff] [blame] | 611 | VirtDevice		*vdevice; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 612 | struct scsi_target	*starget; | 
|  | 613 | struct fc_rport		*rport; | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 614 | MPT_ADAPTER 		*ioc; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 615 |  | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 616 | starget = scsi_target(sdev); | 
|  | 617 | rport = starget_to_rport(starget); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 618 |  | 
|  | 619 | if (!rport || fc_remote_port_chkready(rport)) | 
|  | 620 | return -ENXIO; | 
|  | 621 |  | 
| Eric Moore | e7eae9f | 2007-09-29 10:15:59 -0600 | [diff] [blame] | 622 | hd = shost_priv(sdev->host); | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 623 | ioc = hd->ioc; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 624 |  | 
| Eric Moore | a69de50 | 2007-09-14 18:48:19 -0600 | [diff] [blame] | 625 | vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL); | 
|  | 626 | if (!vdevice) { | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 627 | printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 628 | ioc->name, sizeof(VirtDevice)); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 629 | return -ENOMEM; | 
|  | 630 | } | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 631 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 632 |  | 
| Eric Moore | a69de50 | 2007-09-14 18:48:19 -0600 | [diff] [blame] | 633 | sdev->hostdata = vdevice; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 634 | vtarget = starget->hostdata; | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 635 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 636 | if (vtarget->num_luns == 0) { | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 637 | vtarget->ioc_id = ioc->id; | 
| Eric Moore | ba856d3 | 2006-07-11 17:34:01 -0600 | [diff] [blame] | 638 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 639 | } | 
|  | 640 |  | 
| Eric Moore | a69de50 | 2007-09-14 18:48:19 -0600 | [diff] [blame] | 641 | vdevice->vtarget = vtarget; | 
|  | 642 | vdevice->lun = sdev->lun; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 643 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 644 | vtarget->num_luns++; | 
|  | 645 |  | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 646 |  | 
| Eric Moore | e80b002 | 2007-09-14 18:49:03 -0600 | [diff] [blame] | 647 | mptfc_dump_lun_info(ioc, rport, sdev, vtarget); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 648 |  | 
|  | 649 | return 0; | 
|  | 650 | } | 
|  | 651 |  | 
|  | 652 | static int | 
|  | 653 | mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | 
|  | 654 | { | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 655 | struct mptfc_rport_info	*ri; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 656 | struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device)); | 
|  | 657 | int		err; | 
| Eric Moore | a69de50 | 2007-09-14 18:48:19 -0600 | [diff] [blame] | 658 | VirtDevice	*vdevice = SCpnt->device->hostdata; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 659 |  | 
| Eric Moore | a69de50 | 2007-09-14 18:48:19 -0600 | [diff] [blame] | 660 | if (!vdevice || !vdevice->vtarget) { | 
| Eric Moore | 793955f | 2007-01-29 09:42:20 -0700 | [diff] [blame] | 661 | SCpnt->result = DID_NO_CONNECT << 16; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 662 | done(SCpnt); | 
|  | 663 | return 0; | 
|  | 664 | } | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 665 |  | 
| Eric Moore | 793955f | 2007-01-29 09:42:20 -0700 | [diff] [blame] | 666 | err = fc_remote_port_chkready(rport); | 
|  | 667 | if (unlikely(err)) { | 
|  | 668 | SCpnt->result = err; | 
| Michael Reed | 35508e4 | 2006-10-06 15:39:25 -0500 | [diff] [blame] | 669 | done(SCpnt); | 
|  | 670 | return 0; | 
|  | 671 | } | 
|  | 672 |  | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 673 | /* dd_data is null until finished adding target */ | 
|  | 674 | ri = *((struct mptfc_rport_info **)rport->dd_data); | 
|  | 675 | if (unlikely(!ri)) { | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 676 | SCpnt->result = DID_IMM_RETRY << 16; | 
|  | 677 | done(SCpnt); | 
|  | 678 | return 0; | 
|  | 679 | } | 
|  | 680 |  | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 681 | return mptscsih_qcmd(SCpnt,done); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 682 | } | 
|  | 683 |  | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 684 | /* | 
| Prakash, Sathya | eb5329f | 2007-08-14 16:19:32 +0530 | [diff] [blame] | 685 | *	mptfc_display_port_link_speed - displaying link speed | 
|  | 686 | *	@ioc: Pointer to MPT_ADAPTER structure | 
|  | 687 | *	@portnum: IOC Port number | 
|  | 688 | *	@pp0dest: port page0 data payload | 
|  | 689 | * | 
|  | 690 | */ | 
|  | 691 | static void | 
|  | 692 | mptfc_display_port_link_speed(MPT_ADAPTER *ioc, int portnum, FCPortPage0_t *pp0dest) | 
|  | 693 | { | 
|  | 694 | u8	old_speed, new_speed, state; | 
|  | 695 | char	*old, *new; | 
|  | 696 |  | 
|  | 697 | if (portnum >= 2) | 
|  | 698 | return; | 
|  | 699 |  | 
|  | 700 | old_speed = ioc->fc_link_speed[portnum]; | 
|  | 701 | new_speed = pp0dest->CurrentSpeed; | 
|  | 702 | state = pp0dest->PortState; | 
|  | 703 |  | 
|  | 704 | if (state != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE && | 
|  | 705 | new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) { | 
|  | 706 |  | 
|  | 707 | old = old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" : | 
|  | 708 | old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" : | 
|  | 709 | old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : | 
|  | 710 | "Unknown"; | 
|  | 711 | new = new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" : | 
|  | 712 | new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" : | 
|  | 713 | new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : | 
|  | 714 | "Unknown"; | 
|  | 715 | if (old_speed == 0) | 
|  | 716 | printk(MYIOC_s_NOTE_FMT | 
|  | 717 | "FC Link Established, Speed = %s\n", | 
|  | 718 | ioc->name, new); | 
|  | 719 | else if (old_speed != new_speed) | 
|  | 720 | printk(MYIOC_s_WARN_FMT | 
|  | 721 | "FC Link Speed Change, Old Speed = %s, New Speed = %s\n", | 
|  | 722 | ioc->name, old, new); | 
|  | 723 |  | 
|  | 724 | ioc->fc_link_speed[portnum] = new_speed; | 
|  | 725 | } | 
|  | 726 | } | 
|  | 727 |  | 
|  | 728 | /* | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 729 | *	mptfc_GetFcPortPage0 - Fetch FCPort config Page0. | 
|  | 730 | *	@ioc: Pointer to MPT_ADAPTER structure | 
|  | 731 | *	@portnum: IOC Port number | 
|  | 732 | * | 
|  | 733 | *	Return: 0 for success | 
|  | 734 | *	-ENOMEM if no memory available | 
|  | 735 | *		-EPERM if not allowed due to ISR context | 
|  | 736 | *		-EAGAIN if no msg frames currently available | 
|  | 737 | *		-EFAULT for non-successful reply or no reply (timeout) | 
|  | 738 | *		-EINVAL portnum arg out of range (hardwired to two elements) | 
|  | 739 | */ | 
|  | 740 | static int | 
|  | 741 | mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) | 
|  | 742 | { | 
|  | 743 | ConfigPageHeader_t	 hdr; | 
|  | 744 | CONFIGPARMS		 cfg; | 
|  | 745 | FCPortPage0_t		*ppage0_alloc; | 
|  | 746 | FCPortPage0_t		*pp0dest; | 
|  | 747 | dma_addr_t		 page0_dma; | 
|  | 748 | int			 data_sz; | 
|  | 749 | int			 copy_sz; | 
|  | 750 | int			 rc; | 
|  | 751 | int			 count = 400; | 
|  | 752 |  | 
|  | 753 | if (portnum > 1) | 
|  | 754 | return -EINVAL; | 
|  | 755 |  | 
|  | 756 | /* Get FCPort Page 0 header */ | 
|  | 757 | hdr.PageVersion = 0; | 
|  | 758 | hdr.PageLength = 0; | 
|  | 759 | hdr.PageNumber = 0; | 
|  | 760 | hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; | 
|  | 761 | cfg.cfghdr.hdr = &hdr; | 
|  | 762 | cfg.physAddr = -1; | 
|  | 763 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | 
|  | 764 | cfg.dir = 0; | 
|  | 765 | cfg.pageAddr = portnum; | 
|  | 766 | cfg.timeout = 0; | 
|  | 767 |  | 
|  | 768 | if ((rc = mpt_config(ioc, &cfg)) != 0) | 
|  | 769 | return rc; | 
|  | 770 |  | 
|  | 771 | if (hdr.PageLength == 0) | 
|  | 772 | return 0; | 
|  | 773 |  | 
|  | 774 | data_sz = hdr.PageLength * 4; | 
|  | 775 | rc = -ENOMEM; | 
|  | 776 | ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); | 
|  | 777 | if (ppage0_alloc) { | 
|  | 778 |  | 
|  | 779 | try_again: | 
|  | 780 | memset((u8 *)ppage0_alloc, 0, data_sz); | 
|  | 781 | cfg.physAddr = page0_dma; | 
|  | 782 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | 
|  | 783 |  | 
|  | 784 | if ((rc = mpt_config(ioc, &cfg)) == 0) { | 
|  | 785 | /* save the data */ | 
|  | 786 | pp0dest = &ioc->fc_port_page0[portnum]; | 
|  | 787 | copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz); | 
|  | 788 | memcpy(pp0dest, ppage0_alloc, copy_sz); | 
|  | 789 |  | 
|  | 790 | /* | 
|  | 791 | *	Normalize endianness of structure data, | 
|  | 792 | *	by byte-swapping all > 1 byte fields! | 
|  | 793 | */ | 
|  | 794 | pp0dest->Flags = le32_to_cpu(pp0dest->Flags); | 
|  | 795 | pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); | 
|  | 796 | pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); | 
|  | 797 | pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); | 
|  | 798 | pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); | 
|  | 799 | pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); | 
|  | 800 | pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); | 
|  | 801 | pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); | 
|  | 802 | pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); | 
|  | 803 | pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); | 
|  | 804 | pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); | 
|  | 805 | pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); | 
|  | 806 | pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); | 
|  | 807 | pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); | 
|  | 808 | pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); | 
|  | 809 | pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); | 
|  | 810 |  | 
|  | 811 | /* | 
|  | 812 | * if still doing discovery, | 
|  | 813 | * hang loose a while until finished | 
|  | 814 | */ | 
| Michael Reed | 77d88ee | 2006-07-31 12:19:40 -0500 | [diff] [blame] | 815 | if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) || | 
|  | 816 | (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE && | 
|  | 817 | (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK) | 
|  | 818 | == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) { | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 819 | if (count-- > 0) { | 
| Michael Reed | d6be06c | 2006-05-24 15:07:57 -0500 | [diff] [blame] | 820 | msleep(100); | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 821 | goto try_again; | 
|  | 822 | } | 
|  | 823 | printk(MYIOC_s_INFO_FMT "Firmware discovery not" | 
|  | 824 | " complete.\n", | 
|  | 825 | ioc->name); | 
|  | 826 | } | 
| Prakash, Sathya | eb5329f | 2007-08-14 16:19:32 +0530 | [diff] [blame] | 827 | mptfc_display_port_link_speed(ioc, portnum, pp0dest); | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 828 | } | 
|  | 829 |  | 
|  | 830 | pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); | 
|  | 831 | } | 
|  | 832 |  | 
|  | 833 | return rc; | 
|  | 834 | } | 
|  | 835 |  | 
| Michael Reed | ca2f938 | 2006-05-24 15:07:24 -0500 | [diff] [blame] | 836 | static int | 
|  | 837 | mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum) | 
|  | 838 | { | 
|  | 839 | ConfigPageHeader_t	 hdr; | 
|  | 840 | CONFIGPARMS		 cfg; | 
|  | 841 | int			 rc; | 
|  | 842 |  | 
|  | 843 | if (portnum > 1) | 
|  | 844 | return -EINVAL; | 
|  | 845 |  | 
|  | 846 | if (!(ioc->fc_data.fc_port_page1[portnum].data)) | 
|  | 847 | return -EINVAL; | 
|  | 848 |  | 
|  | 849 | /* get fcport page 1 header */ | 
|  | 850 | hdr.PageVersion = 0; | 
|  | 851 | hdr.PageLength = 0; | 
|  | 852 | hdr.PageNumber = 1; | 
|  | 853 | hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; | 
|  | 854 | cfg.cfghdr.hdr = &hdr; | 
|  | 855 | cfg.physAddr = -1; | 
|  | 856 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | 
|  | 857 | cfg.dir = 0; | 
|  | 858 | cfg.pageAddr = portnum; | 
|  | 859 | cfg.timeout = 0; | 
|  | 860 |  | 
|  | 861 | if ((rc = mpt_config(ioc, &cfg)) != 0) | 
|  | 862 | return rc; | 
|  | 863 |  | 
|  | 864 | if (hdr.PageLength == 0) | 
|  | 865 | return -ENODEV; | 
|  | 866 |  | 
|  | 867 | if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz) | 
|  | 868 | return -EINVAL; | 
|  | 869 |  | 
|  | 870 | cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma; | 
|  | 871 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | 
|  | 872 | cfg.dir = 1; | 
|  | 873 |  | 
|  | 874 | rc = mpt_config(ioc, &cfg); | 
|  | 875 |  | 
|  | 876 | return rc; | 
|  | 877 | } | 
|  | 878 |  | 
|  | 879 | static int | 
|  | 880 | mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum) | 
|  | 881 | { | 
|  | 882 | ConfigPageHeader_t	 hdr; | 
|  | 883 | CONFIGPARMS		 cfg; | 
|  | 884 | FCPortPage1_t		*page1_alloc; | 
|  | 885 | dma_addr_t		 page1_dma; | 
|  | 886 | int			 data_sz; | 
|  | 887 | int			 rc; | 
|  | 888 |  | 
|  | 889 | if (portnum > 1) | 
|  | 890 | return -EINVAL; | 
|  | 891 |  | 
|  | 892 | /* get fcport page 1 header */ | 
|  | 893 | hdr.PageVersion = 0; | 
|  | 894 | hdr.PageLength = 0; | 
|  | 895 | hdr.PageNumber = 1; | 
|  | 896 | hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; | 
|  | 897 | cfg.cfghdr.hdr = &hdr; | 
|  | 898 | cfg.physAddr = -1; | 
|  | 899 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | 
|  | 900 | cfg.dir = 0; | 
|  | 901 | cfg.pageAddr = portnum; | 
|  | 902 | cfg.timeout = 0; | 
|  | 903 |  | 
|  | 904 | if ((rc = mpt_config(ioc, &cfg)) != 0) | 
|  | 905 | return rc; | 
|  | 906 |  | 
|  | 907 | if (hdr.PageLength == 0) | 
|  | 908 | return -ENODEV; | 
|  | 909 |  | 
|  | 910 | start_over: | 
|  | 911 |  | 
|  | 912 | if (ioc->fc_data.fc_port_page1[portnum].data == NULL) { | 
|  | 913 | data_sz = hdr.PageLength * 4; | 
|  | 914 | if (data_sz < sizeof(FCPortPage1_t)) | 
|  | 915 | data_sz = sizeof(FCPortPage1_t); | 
|  | 916 |  | 
|  | 917 | page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev, | 
|  | 918 | data_sz, | 
|  | 919 | &page1_dma); | 
|  | 920 | if (!page1_alloc) | 
|  | 921 | return -ENOMEM; | 
|  | 922 | } | 
|  | 923 | else { | 
|  | 924 | page1_alloc = ioc->fc_data.fc_port_page1[portnum].data; | 
|  | 925 | page1_dma = ioc->fc_data.fc_port_page1[portnum].dma; | 
|  | 926 | data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz; | 
|  | 927 | if (hdr.PageLength * 4 > data_sz) { | 
|  | 928 | ioc->fc_data.fc_port_page1[portnum].data = NULL; | 
|  | 929 | pci_free_consistent(ioc->pcidev, data_sz, (u8 *) | 
|  | 930 | page1_alloc, page1_dma); | 
|  | 931 | goto start_over; | 
|  | 932 | } | 
|  | 933 | } | 
|  | 934 |  | 
|  | 935 | memset(page1_alloc,0,data_sz); | 
|  | 936 |  | 
|  | 937 | cfg.physAddr = page1_dma; | 
|  | 938 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | 
|  | 939 |  | 
|  | 940 | if ((rc = mpt_config(ioc, &cfg)) == 0) { | 
|  | 941 | ioc->fc_data.fc_port_page1[portnum].data = page1_alloc; | 
|  | 942 | ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz; | 
|  | 943 | ioc->fc_data.fc_port_page1[portnum].dma = page1_dma; | 
|  | 944 | } | 
|  | 945 | else { | 
|  | 946 | ioc->fc_data.fc_port_page1[portnum].data = NULL; | 
|  | 947 | pci_free_consistent(ioc->pcidev, data_sz, (u8 *) | 
|  | 948 | page1_alloc, page1_dma); | 
|  | 949 | } | 
|  | 950 |  | 
|  | 951 | return rc; | 
|  | 952 | } | 
|  | 953 |  | 
|  | 954 | static void | 
|  | 955 | mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc) | 
|  | 956 | { | 
|  | 957 | int		ii; | 
|  | 958 | FCPortPage1_t	*pp1; | 
|  | 959 |  | 
|  | 960 | #define MPTFC_FW_DEVICE_TIMEOUT	(1) | 
|  | 961 | #define MPTFC_FW_IO_PEND_TIMEOUT (1) | 
|  | 962 | #define ON_FLAGS  (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY) | 
|  | 963 | #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS) | 
|  | 964 |  | 
|  | 965 | for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) { | 
|  | 966 | if (mptfc_GetFcPortPage1(ioc, ii) != 0) | 
|  | 967 | continue; | 
|  | 968 | pp1 = ioc->fc_data.fc_port_page1[ii].data; | 
|  | 969 | if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT) | 
|  | 970 | && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT) | 
|  | 971 | && ((pp1->Flags & ON_FLAGS) == ON_FLAGS) | 
|  | 972 | && ((pp1->Flags & OFF_FLAGS) == 0)) | 
|  | 973 | continue; | 
|  | 974 | pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT; | 
|  | 975 | pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT; | 
|  | 976 | pp1->Flags &= ~OFF_FLAGS; | 
|  | 977 | pp1->Flags |= ON_FLAGS; | 
|  | 978 | mptfc_WriteFcPortPage1(ioc, ii); | 
|  | 979 | } | 
|  | 980 | } | 
|  | 981 |  | 
|  | 982 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 983 | static void | 
|  | 984 | mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) | 
|  | 985 | { | 
| Michael Reed | 5d947f2 | 2006-07-31 12:19:30 -0500 | [diff] [blame] | 986 | unsigned	class = 0; | 
|  | 987 | unsigned	cos = 0; | 
|  | 988 | unsigned	speed; | 
|  | 989 | unsigned	port_type; | 
|  | 990 | unsigned	port_state; | 
|  | 991 | FCPortPage0_t	*pp0; | 
|  | 992 | struct Scsi_Host *sh; | 
|  | 993 | char		*sn; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 994 |  | 
|  | 995 | /* don't know what to do as only one scsi (fc) host was allocated */ | 
|  | 996 | if (portnum != 0) | 
|  | 997 | return; | 
|  | 998 |  | 
| Michael Reed | 5d947f2 | 2006-07-31 12:19:30 -0500 | [diff] [blame] | 999 | pp0 = &ioc->fc_port_page0[portnum]; | 
|  | 1000 | sh = ioc->sh; | 
|  | 1001 |  | 
|  | 1002 | sn = fc_host_symbolic_name(sh); | 
|  | 1003 | snprintf(sn, FC_SYMBOLIC_NAME_SIZE, "%s %s%08xh", | 
|  | 1004 | ioc->prod_name, | 
|  | 1005 | MPT_FW_REV_MAGIC_ID_STRING, | 
|  | 1006 | ioc->facts.FWVersion.Word); | 
|  | 1007 |  | 
|  | 1008 | fc_host_tgtid_bind_type(sh) = FC_TGTID_BIND_BY_WWPN; | 
|  | 1009 |  | 
|  | 1010 | fc_host_maxframe_size(sh) = pp0->MaxFrameSize; | 
|  | 1011 |  | 
|  | 1012 | fc_host_node_name(sh) = | 
|  | 1013 | (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low; | 
|  | 1014 |  | 
|  | 1015 | fc_host_port_name(sh) = | 
|  | 1016 | (u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low; | 
|  | 1017 |  | 
|  | 1018 | fc_host_port_id(sh) = pp0->PortIdentifier; | 
|  | 1019 |  | 
|  | 1020 | class = pp0->SupportedServiceClass; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1021 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1) | 
|  | 1022 | cos |= FC_COS_CLASS1; | 
|  | 1023 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2) | 
|  | 1024 | cos |= FC_COS_CLASS2; | 
|  | 1025 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3) | 
|  | 1026 | cos |= FC_COS_CLASS3; | 
| Michael Reed | 5d947f2 | 2006-07-31 12:19:30 -0500 | [diff] [blame] | 1027 | fc_host_supported_classes(sh) = cos; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1028 |  | 
| Michael Reed | 5d947f2 | 2006-07-31 12:19:30 -0500 | [diff] [blame] | 1029 | if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT) | 
|  | 1030 | speed = FC_PORTSPEED_1GBIT; | 
|  | 1031 | else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT) | 
|  | 1032 | speed = FC_PORTSPEED_2GBIT; | 
|  | 1033 | else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT) | 
|  | 1034 | speed = FC_PORTSPEED_4GBIT; | 
|  | 1035 | else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT) | 
|  | 1036 | speed = FC_PORTSPEED_10GBIT; | 
|  | 1037 | else | 
|  | 1038 | speed = FC_PORTSPEED_UNKNOWN; | 
|  | 1039 | fc_host_speed(sh) = speed; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1040 |  | 
| Michael Reed | 5d947f2 | 2006-07-31 12:19:30 -0500 | [diff] [blame] | 1041 | speed = 0; | 
|  | 1042 | if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED) | 
|  | 1043 | speed |= FC_PORTSPEED_1GBIT; | 
|  | 1044 | if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED) | 
|  | 1045 | speed |= FC_PORTSPEED_2GBIT; | 
|  | 1046 | if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED) | 
|  | 1047 | speed |= FC_PORTSPEED_4GBIT; | 
|  | 1048 | if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED) | 
|  | 1049 | speed |= FC_PORTSPEED_10GBIT; | 
|  | 1050 | fc_host_supported_speeds(sh) = speed; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1051 |  | 
| Michael Reed | 5d947f2 | 2006-07-31 12:19:30 -0500 | [diff] [blame] | 1052 | port_state = FC_PORTSTATE_UNKNOWN; | 
|  | 1053 | if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE) | 
|  | 1054 | port_state = FC_PORTSTATE_ONLINE; | 
|  | 1055 | else if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_OFFLINE) | 
|  | 1056 | port_state = FC_PORTSTATE_LINKDOWN; | 
|  | 1057 | fc_host_port_state(sh) = port_state; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1058 |  | 
| Michael Reed | 5d947f2 | 2006-07-31 12:19:30 -0500 | [diff] [blame] | 1059 | port_type = FC_PORTTYPE_UNKNOWN; | 
|  | 1060 | if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT) | 
|  | 1061 | port_type = FC_PORTTYPE_PTP; | 
|  | 1062 | else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP) | 
|  | 1063 | port_type = FC_PORTTYPE_LPORT; | 
|  | 1064 | else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP) | 
|  | 1065 | port_type = FC_PORTTYPE_NLPORT; | 
|  | 1066 | else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT) | 
|  | 1067 | port_type = FC_PORTTYPE_NPORT; | 
|  | 1068 | fc_host_port_type(sh) = port_type; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1069 |  | 
| Michael Reed | 5d947f2 | 2006-07-31 12:19:30 -0500 | [diff] [blame] | 1070 | fc_host_fabric_name(sh) = | 
|  | 1071 | (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID) ? | 
|  | 1072 | (u64) pp0->FabricWWNN.High << 32 | (u64) pp0->FabricWWPN.Low : | 
|  | 1073 | (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low; | 
|  | 1074 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1075 | } | 
|  | 1076 |  | 
|  | 1077 | static void | 
| Prakash, Sathya | eb5329f | 2007-08-14 16:19:32 +0530 | [diff] [blame] | 1078 | mptfc_link_status_change(struct work_struct *work) | 
|  | 1079 | { | 
|  | 1080 | MPT_ADAPTER             *ioc = | 
|  | 1081 | container_of(work, MPT_ADAPTER, fc_rescan_work); | 
|  | 1082 | int ii; | 
|  | 1083 |  | 
|  | 1084 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) | 
|  | 1085 | (void) mptfc_GetFcPortPage0(ioc, ii); | 
|  | 1086 |  | 
|  | 1087 | } | 
|  | 1088 |  | 
|  | 1089 | static void | 
| David Howells | c402895 | 2006-11-22 14:57:56 +0000 | [diff] [blame] | 1090 | mptfc_setup_reset(struct work_struct *work) | 
| Michael Reed | 419835e | 2006-05-24 15:07:40 -0500 | [diff] [blame] | 1091 | { | 
| David Howells | c402895 | 2006-11-22 14:57:56 +0000 | [diff] [blame] | 1092 | MPT_ADAPTER		*ioc = | 
|  | 1093 | container_of(work, MPT_ADAPTER, fc_setup_reset_work); | 
| Michael Reed | 419835e | 2006-05-24 15:07:40 -0500 | [diff] [blame] | 1094 | u64			pn; | 
|  | 1095 | struct mptfc_rport_info *ri; | 
| Kashyap, Desai | 08f5c5c | 2010-03-18 19:22:45 +0530 | [diff] [blame] | 1096 | struct scsi_target      *starget; | 
|  | 1097 | VirtTarget              *vtarget; | 
| Michael Reed | 419835e | 2006-05-24 15:07:40 -0500 | [diff] [blame] | 1098 |  | 
|  | 1099 | /* reset about to happen, delete (block) all rports */ | 
|  | 1100 | list_for_each_entry(ri, &ioc->fc_rports, list) { | 
|  | 1101 | if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { | 
|  | 1102 | ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED; | 
|  | 1103 | fc_remote_port_delete(ri->rport);	/* won't sleep */ | 
|  | 1104 | ri->rport = NULL; | 
| Kashyap, Desai | 08f5c5c | 2010-03-18 19:22:45 +0530 | [diff] [blame] | 1105 | starget = ri->starget; | 
|  | 1106 | if (starget) { | 
|  | 1107 | vtarget = starget->hostdata; | 
|  | 1108 | if (vtarget) | 
|  | 1109 | vtarget->deleted = 1; | 
|  | 1110 | } | 
| Michael Reed | 419835e | 2006-05-24 15:07:40 -0500 | [diff] [blame] | 1111 |  | 
|  | 1112 | pn = (u64)ri->pg0.WWPN.High << 32 | | 
|  | 1113 | (u64)ri->pg0.WWPN.Low; | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 1114 | dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT | 
| Michael Reed | 419835e | 2006-05-24 15:07:40 -0500 | [diff] [blame] | 1115 | "mptfc_setup_reset.%d: %llx deleted\n", | 
|  | 1116 | ioc->name, | 
|  | 1117 | ioc->sh->host_no, | 
|  | 1118 | (unsigned long long)pn)); | 
|  | 1119 | } | 
|  | 1120 | } | 
|  | 1121 | } | 
|  | 1122 |  | 
|  | 1123 | static void | 
| David Howells | c402895 | 2006-11-22 14:57:56 +0000 | [diff] [blame] | 1124 | mptfc_rescan_devices(struct work_struct *work) | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1125 | { | 
| David Howells | c402895 | 2006-11-22 14:57:56 +0000 | [diff] [blame] | 1126 | MPT_ADAPTER		*ioc = | 
|  | 1127 | container_of(work, MPT_ADAPTER, fc_rescan_work); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1128 | int			ii; | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 1129 | u64			pn; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1130 | struct mptfc_rport_info *ri; | 
| Kashyap, Desai | 08f5c5c | 2010-03-18 19:22:45 +0530 | [diff] [blame] | 1131 | struct scsi_target      *starget; | 
|  | 1132 | VirtTarget              *vtarget; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1133 |  | 
| Michael Reed | 3a0c56d | 2006-07-31 12:19:50 -0500 | [diff] [blame] | 1134 | /* start by tagging all ports as missing */ | 
|  | 1135 | list_for_each_entry(ri, &ioc->fc_rports, list) { | 
|  | 1136 | if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { | 
|  | 1137 | ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1138 | } | 
| Michael Reed | 3a0c56d | 2006-07-31 12:19:50 -0500 | [diff] [blame] | 1139 | } | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1140 |  | 
| Michael Reed | 3a0c56d | 2006-07-31 12:19:50 -0500 | [diff] [blame] | 1141 | /* | 
|  | 1142 | * now rescan devices known to adapter, | 
|  | 1143 | * will reregister existing rports | 
|  | 1144 | */ | 
|  | 1145 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { | 
|  | 1146 | (void) mptfc_GetFcPortPage0(ioc, ii); | 
|  | 1147 | mptfc_init_host_attr(ioc, ii);	/* refresh */ | 
|  | 1148 | mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev); | 
|  | 1149 | } | 
|  | 1150 |  | 
|  | 1151 | /* delete devices still missing */ | 
|  | 1152 | list_for_each_entry(ri, &ioc->fc_rports, list) { | 
|  | 1153 | /* if newly missing, delete it */ | 
|  | 1154 | if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) { | 
|  | 1155 |  | 
|  | 1156 | ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| | 
|  | 1157 | MPT_RPORT_INFO_FLAGS_MISSING); | 
|  | 1158 | fc_remote_port_delete(ri->rport);	/* won't sleep */ | 
|  | 1159 | ri->rport = NULL; | 
| Kashyap, Desai | 08f5c5c | 2010-03-18 19:22:45 +0530 | [diff] [blame] | 1160 | starget = ri->starget; | 
|  | 1161 | if (starget) { | 
|  | 1162 | vtarget = starget->hostdata; | 
|  | 1163 | if (vtarget) | 
|  | 1164 | vtarget->deleted = 1; | 
|  | 1165 | } | 
| Michael Reed | 3a0c56d | 2006-07-31 12:19:50 -0500 | [diff] [blame] | 1166 |  | 
|  | 1167 | pn = (u64)ri->pg0.WWPN.High << 32 | | 
|  | 1168 | (u64)ri->pg0.WWPN.Low; | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 1169 | dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT | 
| Michael Reed | 3a0c56d | 2006-07-31 12:19:50 -0500 | [diff] [blame] | 1170 | "mptfc_rescan.%d: %llx deleted\n", | 
|  | 1171 | ioc->name, | 
|  | 1172 | ioc->sh->host_no, | 
|  | 1173 | (unsigned long long)pn)); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1174 | } | 
| Michael Reed | 3a0c56d | 2006-07-31 12:19:50 -0500 | [diff] [blame] | 1175 | } | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1176 | } | 
|  | 1177 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1178 | static int | 
|  | 1179 | mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 
|  | 1180 | { | 
|  | 1181 | struct Scsi_Host	*sh; | 
|  | 1182 | MPT_SCSI_HOST		*hd; | 
|  | 1183 | MPT_ADAPTER 		*ioc; | 
|  | 1184 | unsigned long		 flags; | 
| Christoph Hellwig | 1ca00bb | 2006-01-13 18:27:50 +0100 | [diff] [blame] | 1185 | int			 ii; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1186 | int			 numSGE = 0; | 
|  | 1187 | int			 scale; | 
|  | 1188 | int			 ioc_cap; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1189 | int			error=0; | 
|  | 1190 | int			r; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1191 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1192 | if ((r = mpt_attach(pdev,id)) != 0) | 
|  | 1193 | return r; | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1194 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1195 | ioc = pci_get_drvdata(pdev); | 
| Moore, Eric Dean | d335cc3 | 2005-04-30 17:09:38 -0500 | [diff] [blame] | 1196 | ioc->DoneCtx = mptfcDoneCtx; | 
|  | 1197 | ioc->TaskCtx = mptfcTaskCtx; | 
|  | 1198 | ioc->InternalCtx = mptfcInternalCtx; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1199 |  | 
|  | 1200 | /*  Added sanity check on readiness of the MPT adapter. | 
|  | 1201 | */ | 
|  | 1202 | if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { | 
|  | 1203 | printk(MYIOC_s_WARN_FMT | 
|  | 1204 | "Skipping because it's not operational!\n", | 
|  | 1205 | ioc->name); | 
| Moore, Eric Dean | 7acec1e | 2005-11-16 18:54:17 -0700 | [diff] [blame] | 1206 | error = -ENODEV; | 
|  | 1207 | goto out_mptfc_probe; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1208 | } | 
|  | 1209 |  | 
|  | 1210 | if (!ioc->active) { | 
|  | 1211 | printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", | 
|  | 1212 | ioc->name); | 
| Moore, Eric Dean | 7acec1e | 2005-11-16 18:54:17 -0700 | [diff] [blame] | 1213 | error = -ENODEV; | 
|  | 1214 | goto out_mptfc_probe; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1215 | } | 
|  | 1216 |  | 
|  | 1217 | /*  Sanity check - ensure at least 1 port is INITIATOR capable | 
|  | 1218 | */ | 
|  | 1219 | ioc_cap = 0; | 
|  | 1220 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { | 
|  | 1221 | if (ioc->pfacts[ii].ProtocolFlags & | 
|  | 1222 | MPI_PORTFACTS_PROTOCOL_INITIATOR) | 
|  | 1223 | ioc_cap ++; | 
|  | 1224 | } | 
|  | 1225 |  | 
|  | 1226 | if (!ioc_cap) { | 
|  | 1227 | printk(MYIOC_s_WARN_FMT | 
|  | 1228 | "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", | 
|  | 1229 | ioc->name, ioc); | 
| Eric Moore | 793955f | 2007-01-29 09:42:20 -0700 | [diff] [blame] | 1230 | return 0; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1231 | } | 
|  | 1232 |  | 
|  | 1233 | sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); | 
|  | 1234 |  | 
|  | 1235 | if (!sh) { | 
|  | 1236 | printk(MYIOC_s_WARN_FMT | 
|  | 1237 | "Unable to register controller with SCSI subsystem\n", | 
|  | 1238 | ioc->name); | 
| Moore, Eric Dean | 7acec1e | 2005-11-16 18:54:17 -0700 | [diff] [blame] | 1239 | error = -1; | 
|  | 1240 | goto out_mptfc_probe; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1241 | } | 
|  | 1242 |  | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1243 | spin_lock_init(&ioc->fc_rescan_work_lock); | 
| David Howells | c402895 | 2006-11-22 14:57:56 +0000 | [diff] [blame] | 1244 | INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices); | 
|  | 1245 | INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset); | 
| Prakash, Sathya | eb5329f | 2007-08-14 16:19:32 +0530 | [diff] [blame] | 1246 | INIT_WORK(&ioc->fc_lsc_work, mptfc_link_status_change); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1247 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1248 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 
|  | 1249 |  | 
|  | 1250 | /* Attach the SCSI Host to the IOC structure | 
|  | 1251 | */ | 
|  | 1252 | ioc->sh = sh; | 
|  | 1253 |  | 
|  | 1254 | sh->io_port = 0; | 
|  | 1255 | sh->n_io_port = 0; | 
|  | 1256 | sh->irq = 0; | 
|  | 1257 |  | 
|  | 1258 | /* set 16 byte cdb's */ | 
|  | 1259 | sh->max_cmd_len = 16; | 
|  | 1260 |  | 
| Eric Moore | 793955f | 2007-01-29 09:42:20 -0700 | [diff] [blame] | 1261 | sh->max_id = ioc->pfacts->MaxDevices; | 
|  | 1262 | sh->max_lun = max_lun; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1263 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1264 | /* Required entry. | 
|  | 1265 | */ | 
|  | 1266 | sh->unique_id = ioc->id; | 
|  | 1267 |  | 
|  | 1268 | /* Verify that we won't exceed the maximum | 
|  | 1269 | * number of chain buffers | 
|  | 1270 | * We can optimize:  ZZ = req_sz/sizeof(SGE) | 
|  | 1271 | * For 32bit SGE's: | 
|  | 1272 | *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ | 
|  | 1273 | *               + (req_sz - 64)/sizeof(SGE) | 
|  | 1274 | * A slightly different algorithm is required for | 
|  | 1275 | * 64bit SGEs. | 
|  | 1276 | */ | 
| Kashyap, Desai | 14d0f0b | 2009-05-29 16:37:04 +0530 | [diff] [blame] | 1277 | scale = ioc->req_sz/ioc->SGE_size; | 
|  | 1278 | if (ioc->sg_addr_size == sizeof(u64)) { | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1279 | numSGE = (scale - 1) * | 
|  | 1280 | (ioc->facts.MaxChainDepth-1) + scale + | 
| Kashyap, Desai | 14d0f0b | 2009-05-29 16:37:04 +0530 | [diff] [blame] | 1281 | (ioc->req_sz - 60) / ioc->SGE_size; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1282 | } else { | 
|  | 1283 | numSGE = 1 + (scale - 1) * | 
|  | 1284 | (ioc->facts.MaxChainDepth-1) + scale + | 
| Kashyap, Desai | 14d0f0b | 2009-05-29 16:37:04 +0530 | [diff] [blame] | 1285 | (ioc->req_sz - 64) / ioc->SGE_size; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1286 | } | 
|  | 1287 |  | 
|  | 1288 | if (numSGE < sh->sg_tablesize) { | 
|  | 1289 | /* Reset this value */ | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 1290 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1291 | "Resetting sg_tablesize to %d from %d\n", | 
|  | 1292 | ioc->name, numSGE, sh->sg_tablesize)); | 
|  | 1293 | sh->sg_tablesize = numSGE; | 
|  | 1294 | } | 
|  | 1295 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1296 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 
|  | 1297 |  | 
| Eric Moore | e7eae9f | 2007-09-29 10:15:59 -0600 | [diff] [blame] | 1298 | hd = shost_priv(sh); | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1299 | hd->ioc = ioc; | 
|  | 1300 |  | 
|  | 1301 | /* SCSI needs scsi_cmnd lookup table! | 
|  | 1302 | * (with size equal to req_depth*PtrSz!) | 
|  | 1303 | */ | 
| Eric Moore | e820638 | 2007-09-29 10:16:53 -0600 | [diff] [blame] | 1304 | ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); | 
|  | 1305 | if (!ioc->ScsiLookup) { | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1306 | error = -ENOMEM; | 
| Moore, Eric Dean | 7acec1e | 2005-11-16 18:54:17 -0700 | [diff] [blame] | 1307 | goto out_mptfc_probe; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1308 | } | 
| Eric Moore | e820638 | 2007-09-29 10:16:53 -0600 | [diff] [blame] | 1309 | spin_lock_init(&ioc->scsi_lookup_lock); | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1310 |  | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 1311 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n", | 
| Eric Moore | e820638 | 2007-09-29 10:16:53 -0600 | [diff] [blame] | 1312 | ioc->name, ioc->ScsiLookup)); | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1313 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1314 | hd->last_queue_full = 0; | 
|  | 1315 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1316 | sh->transportt = mptfc_transport_template; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1317 | error = scsi_add_host (sh, &ioc->pcidev->dev); | 
|  | 1318 | if(error) { | 
| Eric Moore | 29dd360 | 2007-09-14 18:46:51 -0600 | [diff] [blame] | 1319 | dprintk(ioc, printk(MYIOC_s_ERR_FMT | 
|  | 1320 | "scsi_add_host failed\n", ioc->name)); | 
| Moore, Eric Dean | 7acec1e | 2005-11-16 18:54:17 -0700 | [diff] [blame] | 1321 | goto out_mptfc_probe; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1322 | } | 
|  | 1323 |  | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 1324 | /* initialize workqueue */ | 
|  | 1325 |  | 
| Kay Sievers | aab0de2 | 2008-05-02 06:02:41 +0200 | [diff] [blame] | 1326 | snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name), | 
|  | 1327 | "mptfc_wq_%d", sh->host_no); | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 1328 | ioc->fc_rescan_work_q = | 
|  | 1329 | create_singlethread_workqueue(ioc->fc_rescan_work_q_name); | 
|  | 1330 | if (!ioc->fc_rescan_work_q) | 
|  | 1331 | goto out_mptfc_probe; | 
|  | 1332 |  | 
|  | 1333 | /* | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1334 | *  Pre-fetch FC port WWN and stuff... | 
|  | 1335 | *  (FCPortPage0_t stuff) | 
|  | 1336 | */ | 
|  | 1337 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { | 
|  | 1338 | (void) mptfc_GetFcPortPage0(ioc, ii); | 
|  | 1339 | } | 
| Michael Reed | ca2f938 | 2006-05-24 15:07:24 -0500 | [diff] [blame] | 1340 | mptfc_SetFcPortPage1_defaults(ioc); | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1341 |  | 
|  | 1342 | /* | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 1343 | * scan for rports - | 
|  | 1344 | *	by doing it via the workqueue, some locking is eliminated | 
|  | 1345 | */ | 
|  | 1346 |  | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 1347 | queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work); | 
|  | 1348 | flush_workqueue(ioc->fc_rescan_work_q); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1349 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1350 | return 0; | 
|  | 1351 |  | 
| Moore, Eric Dean | 7acec1e | 2005-11-16 18:54:17 -0700 | [diff] [blame] | 1352 | out_mptfc_probe: | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1353 |  | 
|  | 1354 | mptscsih_remove(pdev); | 
|  | 1355 | return error; | 
|  | 1356 | } | 
|  | 1357 |  | 
|  | 1358 | static struct pci_driver mptfc_driver = { | 
|  | 1359 | .name		= "mptfc", | 
|  | 1360 | .id_table	= mptfc_pci_table, | 
|  | 1361 | .probe		= mptfc_probe, | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1362 | .remove		= __devexit_p(mptfc_remove), | 
| Greg Kroah-Hartman | d18c3db | 2005-06-23 17:35:56 -0700 | [diff] [blame] | 1363 | .shutdown	= mptscsih_shutdown, | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1364 | #ifdef CONFIG_PM | 
|  | 1365 | .suspend	= mptscsih_suspend, | 
|  | 1366 | .resume		= mptscsih_resume, | 
|  | 1367 | #endif | 
|  | 1368 | }; | 
|  | 1369 |  | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1370 | static int | 
|  | 1371 | mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | 
|  | 1372 | { | 
|  | 1373 | MPT_SCSI_HOST *hd; | 
|  | 1374 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; | 
|  | 1375 | unsigned long flags; | 
|  | 1376 | int rc=1; | 
|  | 1377 |  | 
| Kashyap, Desai | ffb7fef | 2010-03-18 19:20:38 +0530 | [diff] [blame] | 1378 | if (ioc->bus_type != FC) | 
|  | 1379 | return 0; | 
|  | 1380 |  | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 1381 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1382 | ioc->name, event)); | 
|  | 1383 |  | 
|  | 1384 | if (ioc->sh == NULL || | 
| Eric Moore | e7eae9f | 2007-09-29 10:15:59 -0600 | [diff] [blame] | 1385 | ((hd = shost_priv(ioc->sh)) == NULL)) | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1386 | return 1; | 
|  | 1387 |  | 
|  | 1388 | switch (event) { | 
|  | 1389 | case MPI_EVENT_RESCAN: | 
|  | 1390 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | 
|  | 1391 | if (ioc->fc_rescan_work_q) { | 
| Michael Reed | 3a0c56d | 2006-07-31 12:19:50 -0500 | [diff] [blame] | 1392 | queue_work(ioc->fc_rescan_work_q, | 
|  | 1393 | &ioc->fc_rescan_work); | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1394 | } | 
|  | 1395 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | 
|  | 1396 | break; | 
| Prakash, Sathya | eb5329f | 2007-08-14 16:19:32 +0530 | [diff] [blame] | 1397 | case MPI_EVENT_LINK_STATUS_CHANGE: | 
|  | 1398 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | 
|  | 1399 | if (ioc->fc_rescan_work_q) { | 
|  | 1400 | queue_work(ioc->fc_rescan_work_q, | 
|  | 1401 | &ioc->fc_lsc_work); | 
|  | 1402 | } | 
|  | 1403 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | 
|  | 1404 | break; | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1405 | default: | 
|  | 1406 | rc = mptscsih_event_process(ioc,pEvReply); | 
|  | 1407 | break; | 
|  | 1408 | } | 
|  | 1409 | return rc; | 
|  | 1410 | } | 
|  | 1411 |  | 
|  | 1412 | static int | 
|  | 1413 | mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 
|  | 1414 | { | 
|  | 1415 | int		rc; | 
|  | 1416 | unsigned long	flags; | 
|  | 1417 |  | 
|  | 1418 | rc = mptscsih_ioc_reset(ioc,reset_phase); | 
| Kashyap, Desai | ffb7fef | 2010-03-18 19:20:38 +0530 | [diff] [blame] | 1419 | if ((ioc->bus_type != FC) || (!rc)) | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1420 | return rc; | 
|  | 1421 |  | 
|  | 1422 |  | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 1423 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 
|  | 1424 | ": IOC %s_reset routed to FC host driver!\n",ioc->name, | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1425 | reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | 
|  | 1426 | reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); | 
|  | 1427 |  | 
|  | 1428 | if (reset_phase == MPT_IOC_SETUP_RESET) { | 
| Michael Reed | 419835e | 2006-05-24 15:07:40 -0500 | [diff] [blame] | 1429 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | 
|  | 1430 | if (ioc->fc_rescan_work_q) { | 
|  | 1431 | queue_work(ioc->fc_rescan_work_q, | 
|  | 1432 | &ioc->fc_setup_reset_work); | 
|  | 1433 | } | 
|  | 1434 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1435 | } | 
|  | 1436 |  | 
|  | 1437 | else if (reset_phase == MPT_IOC_PRE_RESET) { | 
|  | 1438 | } | 
|  | 1439 |  | 
|  | 1440 | else {	/* MPT_IOC_POST_RESET */ | 
| Michael Reed | ca2f938 | 2006-05-24 15:07:24 -0500 | [diff] [blame] | 1441 | mptfc_SetFcPortPage1_defaults(ioc); | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1442 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | 
|  | 1443 | if (ioc->fc_rescan_work_q) { | 
| Michael Reed | 3a0c56d | 2006-07-31 12:19:50 -0500 | [diff] [blame] | 1444 | queue_work(ioc->fc_rescan_work_q, | 
|  | 1445 | &ioc->fc_rescan_work); | 
| Michael Reed | 80d3ac7 | 2006-05-24 15:07:09 -0500 | [diff] [blame] | 1446 | } | 
|  | 1447 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | 
|  | 1448 | } | 
|  | 1449 | return 1; | 
|  | 1450 | } | 
|  | 1451 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1452 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 
|  | 1453 | /** | 
| Randy Dunlap | d9489fb | 2006-12-06 20:38:43 -0800 | [diff] [blame] | 1454 | *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer. | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1455 | * | 
|  | 1456 | *	Returns 0 for success, non-zero for failure. | 
|  | 1457 | */ | 
|  | 1458 | static int __init | 
|  | 1459 | mptfc_init(void) | 
|  | 1460 | { | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1461 | int error; | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1462 |  | 
|  | 1463 | show_mptmod_ver(my_NAME, my_VERSION); | 
|  | 1464 |  | 
| Michael Reed | ca2f938 | 2006-05-24 15:07:24 -0500 | [diff] [blame] | 1465 | /* sanity check module parameters */ | 
|  | 1466 | if (mptfc_dev_loss_tmo <= 0) | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1467 | mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; | 
|  | 1468 |  | 
|  | 1469 | mptfc_transport_template = | 
|  | 1470 | fc_attach_transport(&mptfc_transport_functions); | 
|  | 1471 |  | 
|  | 1472 | if (!mptfc_transport_template) | 
|  | 1473 | return -ENODEV; | 
|  | 1474 |  | 
| Kashyap, Desai | 213aaca | 2010-07-26 18:57:36 +0530 | [diff] [blame] | 1475 | mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER, | 
|  | 1476 | "mptscsih_scandv_complete"); | 
|  | 1477 | mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER, | 
|  | 1478 | "mptscsih_scandv_complete"); | 
|  | 1479 | mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER, | 
|  | 1480 | "mptscsih_scandv_complete"); | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1481 |  | 
| Prakash, Sathya | d6ecdd6 | 2007-07-24 15:47:41 +0530 | [diff] [blame] | 1482 | mpt_event_register(mptfcDoneCtx, mptfc_event_process); | 
|  | 1483 | mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset); | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1484 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1485 | error = pci_register_driver(&mptfc_driver); | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 1486 | if (error) | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1487 | fc_release_transport(mptfc_transport_template); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1488 |  | 
|  | 1489 | return error; | 
|  | 1490 | } | 
|  | 1491 |  | 
|  | 1492 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 
|  | 1493 | /** | 
| Randy Dunlap | d9489fb | 2006-12-06 20:38:43 -0800 | [diff] [blame] | 1494 | *	mptfc_remove - Remove fc infrastructure for devices | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1495 | *	@pdev: Pointer to pci_dev structure | 
|  | 1496 | * | 
|  | 1497 | */ | 
| Michael Reed | 3bc7bf1 | 2006-01-25 18:05:18 -0700 | [diff] [blame] | 1498 | static void __devexit | 
|  | 1499 | mptfc_remove(struct pci_dev *pdev) | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1500 | { | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 1501 | MPT_ADAPTER		*ioc = pci_get_drvdata(pdev); | 
|  | 1502 | struct mptfc_rport_info	*p, *n; | 
|  | 1503 | struct workqueue_struct *work_q; | 
|  | 1504 | unsigned long		flags; | 
| Michael Reed | ca2f938 | 2006-05-24 15:07:24 -0500 | [diff] [blame] | 1505 | int			ii; | 
| Moore, Eric | 65207fe | 2006-04-21 16:14:35 -0600 | [diff] [blame] | 1506 |  | 
|  | 1507 | /* destroy workqueue */ | 
|  | 1508 | if ((work_q=ioc->fc_rescan_work_q)) { | 
|  | 1509 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | 
|  | 1510 | ioc->fc_rescan_work_q = NULL; | 
|  | 1511 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | 
|  | 1512 | destroy_workqueue(work_q); | 
|  | 1513 | } | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1514 |  | 
|  | 1515 | fc_remove_host(ioc->sh); | 
|  | 1516 |  | 
|  | 1517 | list_for_each_entry_safe(p, n, &ioc->fc_rports, list) { | 
|  | 1518 | list_del(&p->list); | 
|  | 1519 | kfree(p); | 
|  | 1520 | } | 
|  | 1521 |  | 
| Michael Reed | ca2f938 | 2006-05-24 15:07:24 -0500 | [diff] [blame] | 1522 | for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) { | 
|  | 1523 | if (ioc->fc_data.fc_port_page1[ii].data) { | 
|  | 1524 | pci_free_consistent(ioc->pcidev, | 
|  | 1525 | ioc->fc_data.fc_port_page1[ii].pg_sz, | 
|  | 1526 | (u8 *) ioc->fc_data.fc_port_page1[ii].data, | 
|  | 1527 | ioc->fc_data.fc_port_page1[ii].dma); | 
|  | 1528 | ioc->fc_data.fc_port_page1[ii].data = NULL; | 
|  | 1529 | } | 
|  | 1530 | } | 
|  | 1531 |  | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1532 | mptscsih_remove(pdev); | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1533 | } | 
|  | 1534 |  | 
|  | 1535 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 
|  | 1536 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 
|  | 1537 | /** | 
|  | 1538 | *	mptfc_exit - Unregisters MPT adapter(s) | 
|  | 1539 | * | 
|  | 1540 | */ | 
|  | 1541 | static void __exit | 
|  | 1542 | mptfc_exit(void) | 
|  | 1543 | { | 
|  | 1544 | pci_unregister_driver(&mptfc_driver); | 
| Michael Reed | 05e8ec1 | 2006-01-13 14:31:54 -0600 | [diff] [blame] | 1545 | fc_release_transport(mptfc_transport_template); | 
|  | 1546 |  | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1547 | mpt_reset_deregister(mptfcDoneCtx); | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1548 | mpt_event_deregister(mptfcDoneCtx); | 
| Moore, Eric Dean | 2496af3 | 2005-04-22 18:02:41 -0400 | [diff] [blame] | 1549 |  | 
|  | 1550 | mpt_deregister(mptfcInternalCtx); | 
|  | 1551 | mpt_deregister(mptfcTaskCtx); | 
|  | 1552 | mpt_deregister(mptfcDoneCtx); | 
|  | 1553 | } | 
|  | 1554 |  | 
|  | 1555 | module_init(mptfc_init); | 
|  | 1556 | module_exit(mptfc_exit); |