diff options
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 53 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 217 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 33 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 304 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 157 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 623 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 372 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 112 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 429 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_logmsg.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 32 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mem.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 160 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 54 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 534 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_version.h | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 93 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.h | 2 |
21 files changed, 2318 insertions, 880 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index ba3ecab9baf..f26b9538aff 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -29,7 +29,8 @@ struct lpfc_sli2_slim; #define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact the NameServer before giving up. */ #define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */ -#define LPFC_SG_SEG_CNT 64 /* sg element count per scsi cmnd */ +#define LPFC_DEFAULT_SG_SEG_CNT 64 /* sg element count per scsi cmnd */ +#define LPFC_MAX_SG_SEG_CNT 256 /* sg element count per scsi cmnd */ #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ #define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */ @@ -68,6 +69,7 @@ struct lpfc_dmabuf { struct list_head list; void *virt; /* virtual address ptr */ dma_addr_t phys; /* mapped address */ + uint32_t buffer_tag; /* used for tagged queue ring */ }; struct lpfc_dma_pool { @@ -272,10 +274,16 @@ struct lpfc_vport { #define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */ #define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */ #define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */ -#define FC_RFF_NOT_SUPPORTED 0x40000 /* RFF_ID was rejected by switch */ #define FC_VPORT_NEEDS_REG_VPI 0x80000 /* Needs to have its vpi registered */ #define FC_RSCN_DEFERRED 0x100000 /* A deferred RSCN being processed */ + uint32_t ct_flags; +#define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */ +#define FC_CT_RNN_ID 0x2 /* RNN_ID accepted by switch */ +#define FC_CT_RSNN_NN 0x4 /* RSNN_NN accepted by switch */ +#define FC_CT_RSPN_ID 0x8 /* RSPN_ID accepted by switch */ +#define FC_CT_RFT_ID 0x10 /* RFT_ID accepted by switch */ + struct list_head fc_nodes; /* Keep counters for the number of entries in each list. */ @@ -344,6 +352,7 @@ struct lpfc_vport { uint32_t cfg_discovery_threads; uint32_t cfg_log_verbose; uint32_t cfg_max_luns; + uint32_t cfg_enable_da_id; uint32_t dev_loss_tmo_changed; @@ -360,6 +369,7 @@ struct lpfc_vport { struct hbq_s { uint16_t entry_count; /* Current number of HBQ slots */ + uint16_t buffer_count; /* Current number of buffers posted */ uint32_t next_hbqPutIdx; /* Index to next HBQ slot to use */ uint32_t hbqPutIdx; /* HBQ slot to use */ uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */ @@ -377,6 +387,11 @@ struct hbq_s { #define LPFC_ELS_HBQ 0 #define LPFC_EXTRA_HBQ 1 +enum hba_temp_state { + HBA_NORMAL_TEMP, + HBA_OVER_TEMP +}; + struct lpfc_hba { struct lpfc_sli sli; uint32_t sli_rev; /* SLI2 or SLI3 */ @@ -457,7 +472,8 @@ struct lpfc_hba { uint64_t cfg_soft_wwnn; uint64_t cfg_soft_wwpn; uint32_t cfg_hba_queue_depth; - + uint32_t cfg_enable_hba_reset; + uint32_t cfg_enable_hba_heartbeat; lpfc_vpd_t vpd; /* vital product data */ @@ -544,8 +560,7 @@ struct lpfc_hba { struct list_head port_list; struct lpfc_vport *pport; /* physical lpfc_vport pointer */ uint16_t max_vpi; /* Maximum virtual nports */ -#define LPFC_MAX_VPI 100 /* Max number of VPI supported */ -#define LPFC_MAX_VPORTS (LPFC_MAX_VPI+1)/* Max number of VPorts supported */ +#define LPFC_MAX_VPI 0xFFFF /* Max number of VPI supported */ unsigned long *vpi_bmask; /* vpi allocation table */ /* Data structure used by fabric iocb scheduler */ @@ -563,16 +578,30 @@ struct lpfc_hba { struct dentry *hba_debugfs_root; atomic_t debugfs_vport_count; struct dentry *debug_hbqinfo; - struct dentry *debug_dumpslim; + struct dentry *debug_dumpHostSlim; + struct dentry *debug_dumpHBASlim; struct dentry *debug_slow_ring_trc; struct lpfc_debugfs_trc *slow_ring_trc; atomic_t slow_ring_trc_cnt; #endif + /* Used for deferred freeing of ELS data buffers */ + struct list_head elsbuf; + int elsbuf_cnt; + int elsbuf_prev_cnt; + + uint8_t temp_sensor_support; /* Fields used for heart beat. */ unsigned long last_completion_time; struct timer_list hb_tmofunc; uint8_t hb_outstanding; + /* + * Following bit will be set for all buffer tags which are not + * associated with any HBQ. + */ +#define QUE_BUFTAG_BIT (1<<31) + uint32_t buffer_tag_count; + enum hba_temp_state over_temp_state; }; static inline struct Scsi_Host * @@ -598,5 +627,15 @@ lpfc_is_link_up(struct lpfc_hba *phba) phba->link_state == LPFC_HBA_READY; } -#define FC_REG_DUMP_EVENT 0x10 /* Register for Dump events */ +#define FC_REG_DUMP_EVENT 0x10 /* Register for Dump events */ +#define FC_REG_TEMPERATURE_EVENT 0x20 /* Register for temperature + event */ +struct temp_event { + uint32_t event_type; + uint32_t event_code; + uint32_t data; +}; +#define LPFC_CRIT_TEMP 0x1 +#define LPFC_THRESHOLD_TEMP 0x2 +#define LPFC_NORMAL_TEMP 0x3 diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 80a11218b9b..4bae4a2ed2f 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2008 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -45,6 +45,10 @@ #define LPFC_MIN_DEVLOSS_TMO 1 #define LPFC_MAX_DEVLOSS_TMO 255 +#define LPFC_MAX_LINK_SPEED 8 +#define LPFC_LINK_SPEED_BITMAP 0x00000117 +#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8" + static void lpfc_jedec_to_ascii(int incr, char hdw[]) { @@ -86,6 +90,15 @@ lpfc_serialnum_show(struct class_device *cdev, char *buf) } static ssize_t +lpfc_temp_sensor_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support); +} + +static ssize_t lpfc_modeldesc_show(struct class_device *cdev, char *buf) { struct Scsi_Host *shost = class_to_shost(cdev); @@ -178,12 +191,9 @@ lpfc_state_show(struct class_device *cdev, char *buf) case LPFC_LINK_UP: case LPFC_CLEAR_LA: case LPFC_HBA_READY: - len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - \n"); + len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - "); switch (vport->port_state) { - len += snprintf(buf + len, PAGE_SIZE-len, - "initializing\n"); - break; case LPFC_LOCAL_CFG_LINK: len += snprintf(buf + len, PAGE_SIZE-len, "Configuring Link\n"); @@ -252,8 +262,7 @@ lpfc_issue_lip(struct Scsi_Host *shost) int mbxstatus = MBXERR_ERROR; if ((vport->fc_flag & FC_OFFLINE_MODE) || - (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) || - (vport->port_state != LPFC_VPORT_READY)) + (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)) return -EPERM; pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); @@ -305,12 +314,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) psli = &phba->sli; + /* Wait a little for things to settle down, but not + * long enough for dev loss timeout to expire. + */ for (i = 0; i < psli->num_rings; i++) { pring = &psli->ring[i]; - /* The linkdown event takes 30 seconds to timeout. */ while (pring->txcmplq_cnt) { msleep(10); - if (cnt++ > 3000) { + if (cnt++ > 500) { /* 5 secs */ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, "0466 Outstanding IO when " @@ -336,6 +347,9 @@ lpfc_selective_reset(struct lpfc_hba *phba) struct completion online_compl; int status = 0; + if (!phba->cfg_enable_hba_reset) + return -EIO; + status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); if (status != 0) @@ -409,6 +423,8 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count) struct completion online_compl; int status=0; + if (!phba->cfg_enable_hba_reset) + return -EACCES; init_completion(&online_compl); if(strncmp(buf, "online", sizeof("online") - 1) == 0) { @@ -908,6 +924,8 @@ static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL); static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); +static CLASS_DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, + NULL); static char *lpfc_soft_wwn_key = "C99G71SL8032A"; @@ -971,6 +989,14 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) unsigned int i, j, cnt=count; u8 wwpn[8]; + if (!phba->cfg_enable_hba_reset) + return -EACCES; + spin_lock_irq(&phba->hbalock); + if (phba->over_temp_state == HBA_OVER_TEMP) { + spin_unlock_irq(&phba->hbalock); + return -EACCES; + } + spin_unlock_irq(&phba->hbalock); /* count may include a LF at end of string */ if (buf[cnt-1] == '\n') cnt--; @@ -1102,7 +1128,13 @@ MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:" " 2 - select SLI-2 even on SLI-3 capable HBAs," " 3 - select SLI-3"); -LPFC_ATTR_R(enable_npiv, 0, 0, 1, "Enable NPIV functionality"); +int lpfc_enable_npiv = 0; +module_param(lpfc_enable_npiv, int, 0); +MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality"); +lpfc_param_show(enable_npiv); +lpfc_param_init(enable_npiv, 0, 0, 1); +static CLASS_DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, + lpfc_enable_npiv_show, NULL); /* # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear @@ -1248,6 +1280,13 @@ LPFC_VPORT_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffff, "Verbose logging bit-mask"); /* +# lpfc_enable_da_id: This turns on the DA_ID CT command that deregisters +# objects that have been registered with the nameserver after login. +*/ +LPFC_VPORT_ATTR_R(enable_da_id, 0, 0, 1, + "Deregister nameserver objects before LOGO"); + +/* # lun_queue_depth: This parameter is used to limit the number of outstanding # commands per FCP LUN. Value range is [1,128]. Default value is 30. */ @@ -1369,7 +1408,33 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1, # Set loop mode if you want to run as an NL_Port. Value range is [0,0x6]. # Default value is 0. */ -LPFC_ATTR_RW(topology, 0, 0, 6, "Select Fibre Channel topology"); +static int +lpfc_topology_set(struct lpfc_hba *phba, int val) +{ + int err; + uint32_t prev_val; + if (val >= 0 && val <= 6) { + prev_val = phba->cfg_topology; + phba->cfg_topology = val; + err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); + if (err) + phba->cfg_topology = prev_val; + return err; + } + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "%d:0467 lpfc_topology attribute cannot be set to %d, " + "allowed range is [0, 6]\n", + phba->brd_no, val); + return -EINVAL; +} +static int lpfc_topology = 0; +module_param(lpfc_topology, int, 0); +MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology"); +lpfc_param_show(topology) +lpfc_param_init(topology, 0, 0, 6) +lpfc_param_store(topology) +static CLASS_DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR, + lpfc_topology_show, lpfc_topology_store); /* # lpfc_link_speed: Link speed selection for initializing the Fibre Channel @@ -1381,7 +1446,59 @@ LPFC_ATTR_RW(topology, 0, 0, 6, "Select Fibre Channel topology"); # 8 = 8 Gigabaud # Value range is [0,8]. Default value is 0. */ -LPFC_ATTR_R(link_speed, 0, 0, 8, "Select link speed"); +static int +lpfc_link_speed_set(struct lpfc_hba *phba, int val) +{ + int err; + uint32_t prev_val; + + if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) || + ((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) || + ((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) || + ((val == LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) || + ((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb))) + return -EINVAL; + + if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED) + && (LPFC_LINK_SPEED_BITMAP & (1 << val))) { + prev_val = phba->cfg_link_speed; + phba->cfg_link_speed = val; + err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); + if (err) + phba->cfg_link_speed = prev_val; + return err; + } + + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "%d:0469 lpfc_link_speed attribute cannot be set to %d, " + "allowed range is [0, 8]\n", + phba->brd_no, val); + return -EINVAL; +} + +static int lpfc_link_speed = 0; +module_param(lpfc_link_speed, int, 0); +MODULE_PARM_DESC(lpfc_link_speed, "Select link speed"); +lpfc_param_show(link_speed) +static int +lpfc_link_speed_init(struct lpfc_hba *phba, int val) +{ + if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED) + && (LPFC_LINK_SPEED_BITMAP & (1 << val))) { + phba->cfg_link_speed = val; + return 0; + } + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0454 lpfc_link_speed attribute cannot " + "be set to %d, allowed values are " + "["LPFC_LINK_SPEED_STRING"]\n", val); + phba->cfg_link_speed = 0; + return -EINVAL; +} + +lpfc_param_store(link_speed) +static CLASS_DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR, + lpfc_link_speed_show, lpfc_link_speed_store); /* # lpfc_fcp_class: Determines FC class to use for the FCP protocol. @@ -1479,7 +1596,30 @@ LPFC_ATTR_RW(poll_tmo, 10, 1, 255, */ LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible"); +/* +# lpfc_enable_hba_reset: Allow or prevent HBA resets to the hardware. +# 0 = HBA resets disabled +# 1 = HBA resets enabled (default) +# Value range is [0,1]. Default value is 1. +*/ +LPFC_ATTR_R(enable_hba_reset, 1, 0, 1, "Enable HBA resets from the driver."); + +/* +# lpfc_enable_hba_heartbeat: Enable HBA heartbeat timer.. +# 0 = HBA Heartbeat disabled +# 1 = HBA Heartbeat enabled (default) +# Value range is [0,1]. Default value is 1. +*/ +LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat."); +/* + * lpfc_sg_seg_cnt: Initial Maximum DMA Segment Count + * This value can be set to values between 64 and 256. The default value is + * 64, but may be increased to allow for larger Max I/O sizes. The scsi layer + * will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE). + */ +LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT, + LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count"); struct class_device_attribute *lpfc_hba_attrs[] = { &class_device_attr_info, @@ -1494,6 +1634,7 @@ struct class_device_attribute *lpfc_hba_attrs[] = { &class_device_attr_state, &class_device_attr_num_discovered_ports, &class_device_attr_lpfc_drvr_version, + &class_device_attr_lpfc_temp_sensor, &class_device_attr_lpfc_log_verbose, &class_device_attr_lpfc_lun_queue_depth, &class_device_attr_lpfc_hba_queue_depth, @@ -1530,6 +1671,9 @@ struct class_device_attribute *lpfc_hba_attrs[] = { &class_device_attr_lpfc_soft_wwnn, &class_device_attr_lpfc_soft_wwpn, &class_device_attr_lpfc_soft_wwn_enable, + &class_device_attr_lpfc_enable_hba_reset, + &class_device_attr_lpfc_enable_hba_heartbeat, + &class_device_attr_lpfc_sg_seg_cnt, NULL, }; @@ -1552,6 +1696,7 @@ struct class_device_attribute *lpfc_vport_attrs[] = { &class_device_attr_lpfc_max_luns, &class_device_attr_nport_evt_cnt, &class_device_attr_npiv_info, + &class_device_attr_lpfc_enable_da_id, NULL, }; @@ -1727,13 +1872,18 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, spin_lock_irq(&phba->hbalock); + if (phba->over_temp_state == HBA_OVER_TEMP) { + sysfs_mbox_idle(phba); + spin_unlock_irq(&phba->hbalock); + return -EACCES; + } + if (off == 0 && phba->sysfs_mbox.state == SMBOX_WRITING && phba->sysfs_mbox.offset >= 2 * sizeof(uint32_t)) { switch (phba->sysfs_mbox.mbox->mb.mbxCommand) { /* Offline only */ - case MBX_WRITE_NV: case MBX_INIT_LINK: case MBX_DOWN_LINK: case MBX_CONFIG_LINK: @@ -1744,9 +1894,7 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, case MBX_DUMP_CONTEXT: case MBX_RUN_DIAGS: case MBX_RESTART: - case MBX_FLASH_WR_ULA: case MBX_SET_MASK: - case MBX_SET_SLIM: case MBX_SET_DEBUG: if (!(vport->fc_flag & FC_OFFLINE_MODE)) { printk(KERN_WARNING "mbox_read:Command 0x%x " @@ -1756,6 +1904,8 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, spin_unlock_irq(&phba->hbalock); return -EPERM; } + case MBX_WRITE_NV: + case MBX_WRITE_VPARMS: case MBX_LOAD_SM: case MBX_READ_NV: case MBX_READ_CONFIG: @@ -1772,6 +1922,8 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, case MBX_LOAD_EXP_ROM: case MBX_BEACON: case MBX_DEL_LD_ENTRY: + case MBX_SET_VARIABLE: + case MBX_WRITE_WWN: break; case MBX_READ_SPARM64: case MBX_READ_LA: @@ -1793,6 +1945,17 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, return -EPERM; } + /* If HBA encountered an error attention, allow only DUMP + * mailbox command until the HBA is restarted. + */ + if ((phba->pport->stopped) && + (phba->sysfs_mbox.mbox->mb.mbxCommand + != MBX_DUMP_MEMORY)) { + sysfs_mbox_idle(phba); + spin_unlock_irq(&phba->hbalock); + return -EPERM; + } + phba->sysfs_mbox.mbox->vport = vport; if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { @@ -1993,7 +2156,8 @@ lpfc_get_host_speed(struct Scsi_Host *shost) fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; break; } - } + } else + fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; spin_unlock_irq(shost->host_lock); } @@ -2013,7 +2177,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost) node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn); else /* fabric is local port if there is no F/FL_Port */ - node_name = wwn_to_u64(vport->fc_nodename.u.wwn); + node_name = 0; spin_unlock_irq(shost->host_lock); @@ -2337,8 +2501,6 @@ struct fc_function_template lpfc_transport_functions = { .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk, .terminate_rport_io = lpfc_terminate_rport_io, - .vport_create = lpfc_vport_create, - .vport_delete = lpfc_vport_delete, .dd_fcvport_size = sizeof(struct lpfc_vport *), }; @@ -2414,21 +2576,23 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_poll_tmo_init(phba, lpfc_poll_tmo); lpfc_enable_npiv_init(phba, lpfc_enable_npiv); lpfc_use_msi_init(phba, lpfc_use_msi); + lpfc_enable_hba_reset_init(phba, lpfc_enable_hba_reset); + lpfc_enable_hba_heartbeat_init(phba, lpfc_enable_hba_heartbeat); phba->cfg_poll = lpfc_poll; phba->cfg_soft_wwnn = 0L; phba->cfg_soft_wwpn = 0L; - /* - * The total number of segments is the configuration value plus 2 - * since the IOCB need a command and response bde. - */ - phba->cfg_sg_seg_cnt = LPFC_SG_SEG_CNT + 2; + lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); + /* Also reinitialize the host templates with new values. */ + lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt; + lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt; /* * Since the sg_tablesize is module parameter, the sg_dma_buf_size - * used to create the sg_dma_buf_pool must be dynamically calculated + * used to create the sg_dma_buf_pool must be dynamically calculated. + * 2 segments are added since the IOCB needs a command and response bde. */ phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) + - (phba->cfg_sg_seg_cnt * sizeof(struct ulp_bde64)); + ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct ulp_bde64)); lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); return; } @@ -2448,5 +2612,6 @@ lpfc_get_vport_cfgparam(struct lpfc_vport *vport) lpfc_discovery_threads_init(vport, lpfc_discovery_threads); lpfc_max_luns_init(vport, lpfc_max_luns); lpfc_scan_down_init(vport, lpfc_scan_down); + lpfc_enable_da_id_init(vport, lpfc_enable_da_id); return; } diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index a599e151071..50fcb7c930b 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -23,6 +23,8 @@ typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param); struct fc_rport; void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); +void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); + void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp); @@ -43,9 +45,9 @@ void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove); int lpfc_linkdown(struct lpfc_hba *); +void lpfc_port_link_failure(struct lpfc_vport *); void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *); -void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); @@ -66,15 +68,15 @@ int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *, void lpfc_nlp_init(struct lpfc_vport *, struct lpfc_nodelist *, uint32_t); struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *); int lpfc_nlp_put(struct lpfc_nodelist *); +int lpfc_nlp_not_used(struct lpfc_nodelist *ndlp); struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t); void lpfc_disc_list_loopmap(struct lpfc_vport *); void lpfc_disc_start(struct lpfc_vport *); -void lpfc_disc_flush_list(struct lpfc_vport *); void lpfc_cleanup_discovery_resources(struct lpfc_vport *); +void lpfc_cleanup(struct lpfc_vport *); void lpfc_disc_timeout(unsigned long); struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); -struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); void lpfc_worker_wake_up(struct lpfc_hba *); int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t); @@ -82,17 +84,17 @@ int lpfc_do_work(void *); int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t); -void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *, - struct lpfc_nodelist *); void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *); int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *, struct serv_parm *, uint32_t); int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *); +void lpfc_more_plogi(struct lpfc_vport *); +void lpfc_more_adisc(struct lpfc_vport *); +void lpfc_end_rscn(struct lpfc_vport *); int lpfc_els_chk_latt(struct lpfc_vport *); int lpfc_els_abort_flogi(struct lpfc_hba *); int lpfc_initial_flogi(struct lpfc_vport *); int lpfc_initial_fdisc(struct lpfc_vport *); -int lpfc_issue_els_fdisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_plogi(struct lpfc_vport *, uint32_t, uint8_t); int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); @@ -112,7 +114,6 @@ int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *, void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *); void lpfc_els_retry_delay(unsigned long); void lpfc_els_retry_delay_handler(struct lpfc_nodelist *); -void lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *); void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_iocbq *); int lpfc_els_handle_rscn(struct lpfc_vport *); @@ -124,7 +125,6 @@ int lpfc_els_disc_adisc(struct lpfc_vport *); int lpfc_els_disc_plogi(struct lpfc_vport *); void lpfc_els_timeout(unsigned long); void lpfc_els_timeout_handler(struct lpfc_vport *); -void lpfc_hb_timeout(unsigned long); void lpfc_hb_timeout_handler(struct lpfc_hba *); void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, @@ -142,7 +142,6 @@ void lpfc_hba_init(struct lpfc_hba *, uint32_t *); int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int); void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); int lpfc_online(struct lpfc_hba *); -void lpfc_block_mgmt_io(struct lpfc_hba *); void lpfc_unblock_mgmt_io(struct lpfc_hba *); void lpfc_offline_prep(struct lpfc_hba *); void lpfc_offline(struct lpfc_hba *); @@ -165,7 +164,6 @@ int lpfc_mbox_tmo_val(struct lpfc_hba *, int); void lpfc_config_hbq(struct lpfc_hba *, uint32_t, struct lpfc_hbq_init *, uint32_t , LPFC_MBOXQ_t *); -struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t); struct hbq_dmabuf *lpfc_els_hbq_alloc(struct lpfc_hba *); void lpfc_els_hbq_free(struct lpfc_hba *, struct hbq_dmabuf *); @@ -178,7 +176,6 @@ void lpfc_poll_start_timer(struct lpfc_hba * phba); void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba); struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *); void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); -void __lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); void lpfc_reset_barrier(struct lpfc_hba * phba); @@ -204,11 +201,14 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, struct lpfc_sli_ring *, dma_addr_t); + +uint32_t lpfc_sli_get_buffer_tag(struct lpfc_hba *); +struct lpfc_dmabuf * lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *, + struct lpfc_sli_ring *, uint32_t ); + int lpfc_sli_hbq_count(void); -int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t); int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t); void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *); -struct hbq_dmabuf *lpfc_sli_hbqbuf_find(struct lpfc_hba *, uint32_t); int lpfc_sli_hbq_size(void); int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_iocbq *); @@ -219,9 +219,6 @@ int lpfc_sli_abort_iocb(struct lpfc_vport *, struct lpfc_sli_ring *, uint16_t, void lpfc_mbox_timeout(unsigned long); void lpfc_mbox_timeout_handler(struct lpfc_hba *); -struct lpfc_nodelist *__lpfc_find_node(struct lpfc_vport *, node_filter, - void *); -struct lpfc_nodelist *lpfc_find_node(struct lpfc_vport *, node_filter, void *); struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_vport *, uint32_t); struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *, struct lpfc_name *); @@ -260,6 +257,7 @@ extern struct scsi_host_template lpfc_vport_template; extern struct fc_function_template lpfc_transport_functions; extern struct fc_function_template lpfc_vport_transport_functions; extern int lpfc_sli_mode; +extern int lpfc_enable_npiv; int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t); void lpfc_terminate_rport_io(struct fc_rport *); @@ -281,11 +279,8 @@ extern void lpfc_debugfs_slow_ring_trc(struct lpfc_hba *, char *, uint32_t, extern struct lpfc_hbq_init *lpfc_hbq_defs[]; /* Interface exported by fabric iocb scheduler */ -int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *); -void lpfc_fabric_abort_vport(struct lpfc_vport *); void lpfc_fabric_abort_nport(struct lpfc_nodelist *); void lpfc_fabric_abort_hba(struct lpfc_hba *); -void lpfc_fabric_abort_flogi(struct lpfc_hba *); void lpfc_fabric_block_timeout(unsigned long); void lpfc_unblock_fabric_iocbs(struct lpfc_hba *); void lpfc_adjust_queue_depth(struct lpfc_hba *); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index c701e4d611a..92441ce610e 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -19,7 +19,7 @@ *******************************************************************/ /* - * Fibre Channel SCSI LAN Device Driver CT support + * Fibre Channel SCSI LAN Device Driver CT support: FC Generic Services FC-GS */ #include <linux/blkdev.h> @@ -57,45 +57,27 @@ static char *lpfc_release_version = LPFC_DRIVER_VERSION; -/* - * lpfc_ct_unsol_event - */ static void -lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, - struct lpfc_dmabuf *mp, uint32_t size) +lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, + struct lpfc_dmabuf *mp, uint32_t size) { if (!mp) { - printk(KERN_ERR "%s (%d): Unsolited CT, no buffer, " - "piocbq = %p, status = x%x, mp = %p, size = %d\n", - __FUNCTION__, __LINE__, - piocbq, piocbq->iocb.ulpStatus, mp, size); + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, + "0146 Ignoring unsolicted CT No HBQ " + "status = x%x\n", + piocbq->iocb.ulpStatus); } - - printk(KERN_ERR "%s (%d): Ignoring unsolicted CT piocbq = %p, " - "buffer = %p, size = %d, status = x%x\n", - __FUNCTION__, __LINE__, - piocbq, mp, size, - piocbq->iocb.ulpStatus); - + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, + "0145 Ignoring unsolicted CT HBQ Size:%d " + "status = x%x\n", + size, piocbq->iocb.ulpStatus); } static void -lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, - struct lpfc_dmabuf *mp, uint32_t size) +lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, + struct lpfc_dmabuf *mp, uint32_t size) { - if (!mp) { - printk(KERN_ERR "%s (%d): Unsolited CT, no " - "HBQ buffer, piocbq = %p, status = x%x\n", - __FUNCTION__, __LINE__, - piocbq, piocbq->iocb.ulpStatus); - } else { - lpfc_ct_unsol_buffer(phba, piocbq, mp, size); - printk(KERN_ERR "%s (%d): Ignoring unsolicted CT " - "piocbq = %p, buffer = %p, size = %d, " - "status = x%x\n", - __FUNCTION__, __LINE__, - piocbq, mp, size, piocbq->iocb.ulpStatus); - } + lpfc_ct_ignore_hbq_buffer(phba, piocbq, mp, size); } void @@ -109,11 +91,8 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *iocbq; dma_addr_t paddr; uint32_t size; - struct lpfc_dmabuf *bdeBuf1 = piocbq->context2; - struct lpfc_dmabuf *bdeBuf2 = piocbq->context3; - - piocbq->context2 = NULL; - piocbq->context3 = NULL; + struct list_head head; + struct lpfc_dmabuf *bdeBuf; if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) { lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ); @@ -122,7 +101,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* Not enough posted buffers; Try posting more buffers */ phba->fc_stat.NoRcvBuf++; if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) - lpfc_post_buffer(phba, pring, 0, 1); + lpfc_post_buffer(phba, pring, 2, 1); return; } @@ -133,38 +112,34 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, return; if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { - list_for_each_entry(iocbq, &piocbq->list, list) { + INIT_LIST_HEAD(&head); + list_add_tail(&head, &piocbq->list); + list_for_each_entry(iocbq, &head, list) { icmd = &iocbq->iocb; - if (icmd->ulpBdeCount == 0) { - printk(KERN_ERR "%s (%d): Unsolited CT, no " - "BDE, iocbq = %p, status = x%x\n", - __FUNCTION__, __LINE__, - iocbq, iocbq->iocb.ulpStatus); + if (icmd->ulpBdeCount == 0) continue; - } - + bdeBuf = iocbq->context2; + iocbq->context2 = NULL; size = icmd->un.cont64[0].tus.f.bdeSize; - lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf1, size); - lpfc_in_buf_free(phba, bdeBuf1); + lpfc_ct_unsol_buffer(phba, piocbq, bdeB |