Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

Linux/drivers/message/fusion/mptfc.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us