lpfc_attr.c

来自「linux 内核源代码」· C语言 代码 · 共 2,217 行 · 第 1/5 页

C
2,217
字号
static CLASS_DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);static CLASS_DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);static CLASS_DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);static CLASS_DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);static CLASS_DEVICE_ATTR(option_rom_version, S_IRUGO,					lpfc_option_rom_version_show, NULL);static CLASS_DEVICE_ATTR(num_discovered_ports, S_IRUGO,					lpfc_num_discovered_ports_show, NULL);static CLASS_DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show,			 NULL);static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,			 lpfc_board_mode_show, lpfc_board_mode_store);static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);static CLASS_DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);static CLASS_DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);static CLASS_DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);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 char *lpfc_soft_wwn_key = "C99G71SL8032A";static ssize_tlpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,				size_t count){	struct Scsi_Host  *shost = class_to_shost(cdev);	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;	struct lpfc_hba   *phba = vport->phba;	unsigned int cnt = count;	/*	 * We're doing a simple sanity check for soft_wwpn setting.	 * We require that the user write a specific key to enable	 * the soft_wwpn attribute to be settable. Once the attribute	 * is written, the enable key resets. If further updates are	 * desired, the key must be written again to re-enable the	 * attribute.	 *	 * The "key" is not secret - it is a hardcoded string shown	 * here. The intent is to protect against the random user or	 * application that is just writing attributes.	 */	/* count may include a LF at end of string */	if (buf[cnt-1] == '\n')		cnt--;	if ((cnt != strlen(lpfc_soft_wwn_key)) ||	    (strncmp(buf, lpfc_soft_wwn_key, strlen(lpfc_soft_wwn_key)) != 0))		return -EINVAL;	phba->soft_wwn_enable = 1;	return count;}static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,				lpfc_soft_wwn_enable_store);static ssize_tlpfc_soft_wwpn_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, "0x%llx\n",			(unsigned long long)phba->cfg_soft_wwpn);}static ssize_tlpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count){	struct Scsi_Host  *shost = class_to_shost(cdev);	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;	struct lpfc_hba   *phba = vport->phba;	struct completion online_compl;	int stat1=0, stat2=0;	unsigned int i, j, cnt=count;	u8 wwpn[8];	/* count may include a LF at end of string */	if (buf[cnt-1] == '\n')		cnt--;	if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) ||	    ((cnt == 17) && (*buf++ != 'x')) ||	    ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))		return -EINVAL;	phba->soft_wwn_enable = 0;	memset(wwpn, 0, sizeof(wwpn));	/* Validate and store the new name */	for (i=0, j=0; i < 16; i++) {		if ((*buf >= 'a') && (*buf <= 'f'))			j = ((j << 4) | ((*buf++ -'a') + 10));		else if ((*buf >= 'A') && (*buf <= 'F'))			j = ((j << 4) | ((*buf++ -'A') + 10));		else if ((*buf >= '0') && (*buf <= '9'))			j = ((j << 4) | (*buf++ -'0'));		else			return -EINVAL;		if (i % 2) {			wwpn[i/2] = j & 0xff;			j = 0;		}	}	phba->cfg_soft_wwpn = wwn_to_u64(wwpn);	fc_host_port_name(shost) = phba->cfg_soft_wwpn;	if (phba->cfg_soft_wwnn)		fc_host_node_name(shost) = phba->cfg_soft_wwnn;	dev_printk(KERN_NOTICE, &phba->pcidev->dev,		   "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);	stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);	if (stat1)		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,				"0463 lpfc_soft_wwpn attribute set failed to "				"reinit adapter - %d\n", stat1);	init_completion(&online_compl);	lpfc_workq_post_event(phba, &stat2, &online_compl, LPFC_EVT_ONLINE);	wait_for_completion(&online_compl);	if (stat2)		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,				"0464 lpfc_soft_wwpn attribute set failed to "				"reinit adapter - %d\n", stat2);	return (stat1 || stat2) ? -EIO : count;}static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\			 lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);static ssize_tlpfc_soft_wwnn_show(struct class_device *cdev, char *buf){	struct Scsi_Host *shost = class_to_shost(cdev);	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;	return snprintf(buf, PAGE_SIZE, "0x%llx\n",			(unsigned long long)phba->cfg_soft_wwnn);}static ssize_tlpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count){	struct Scsi_Host *shost = class_to_shost(cdev);	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;	unsigned int i, j, cnt=count;	u8 wwnn[8];	/* count may include a LF at end of string */	if (buf[cnt-1] == '\n')		cnt--;	if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) ||	    ((cnt == 17) && (*buf++ != 'x')) ||	    ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))		return -EINVAL;	/*	 * Allow wwnn to be set many times, as long as the enable is set.	 * However, once the wwpn is set, everything locks.	 */	memset(wwnn, 0, sizeof(wwnn));	/* Validate and store the new name */	for (i=0, j=0; i < 16; i++) {		if ((*buf >= 'a') && (*buf <= 'f'))			j = ((j << 4) | ((*buf++ -'a') + 10));		else if ((*buf >= 'A') && (*buf <= 'F'))			j = ((j << 4) | ((*buf++ -'A') + 10));		else if ((*buf >= '0') && (*buf <= '9'))			j = ((j << 4) | (*buf++ -'0'));		else			return -EINVAL;		if (i % 2) {			wwnn[i/2] = j & 0xff;			j = 0;		}	}	phba->cfg_soft_wwnn = wwn_to_u64(wwnn);	dev_printk(KERN_NOTICE, &phba->pcidev->dev,		   "lpfc%d: soft_wwnn set. Value will take effect upon "		   "setting of the soft_wwpn\n", phba->brd_no);	return count;}static CLASS_DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\			 lpfc_soft_wwnn_show, lpfc_soft_wwnn_store);static int lpfc_poll = 0;module_param(lpfc_poll, int, 0);MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"		 " 0 - none,"		 " 1 - poll with interrupts enabled"		 " 3 - poll and disable FCP ring interrupts");static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,			 lpfc_poll_show, lpfc_poll_store);int  lpfc_sli_mode = 0;module_param(lpfc_sli_mode, int, 0);MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"		 " 0 - auto (SLI-3 if supported),"		 " 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");/*# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear# until the timer expires. Value range is [0,255]. Default value is 30.*/static int lpfc_nodev_tmo = LPFC_DEF_DEVLOSS_TMO;static int lpfc_devloss_tmo = LPFC_DEF_DEVLOSS_TMO;module_param(lpfc_nodev_tmo, int, 0);MODULE_PARM_DESC(lpfc_nodev_tmo,		 "Seconds driver will hold I/O waiting "		 "for a device to come back");static ssize_tlpfc_nodev_tmo_show(struct class_device *cdev, char *buf){	struct Scsi_Host  *shost = class_to_shost(cdev);	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;	int val = 0;	val = vport->cfg_devloss_tmo;	return snprintf(buf, PAGE_SIZE, "%d\n",	vport->cfg_devloss_tmo);}static intlpfc_nodev_tmo_init(struct lpfc_vport *vport, int val){	if (vport->cfg_devloss_tmo != LPFC_DEF_DEVLOSS_TMO) {		vport->cfg_nodev_tmo = vport->cfg_devloss_tmo;		if (val != LPFC_DEF_DEVLOSS_TMO)			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,					 "0402 Ignoring nodev_tmo module "					 "parameter because devloss_tmo is "					 "set.\n");		return 0;	}	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {		vport->cfg_nodev_tmo = val;		vport->cfg_devloss_tmo = val;		return 0;	}	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,			 "0400 lpfc_nodev_tmo attribute cannot be set to"			 " %d, allowed range is [%d, %d]\n",			 val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO);	vport->cfg_nodev_tmo = LPFC_DEF_DEVLOSS_TMO;	return -EINVAL;}static voidlpfc_update_rport_devloss_tmo(struct lpfc_vport *vport){	struct Scsi_Host  *shost;	struct lpfc_nodelist  *ndlp;	shost = lpfc_shost_from_vport(vport);	spin_lock_irq(shost->host_lock);	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)		if (ndlp->rport)			ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;	spin_unlock_irq(shost->host_lock);}static intlpfc_nodev_tmo_set(struct lpfc_vport *vport, int val){	if (vport->dev_loss_tmo_changed ||	    (lpfc_devloss_tmo != LPFC_DEF_DEVLOSS_TMO)) {		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,				 "0401 Ignoring change to nodev_tmo "				 "because devloss_tmo is set.\n");		return 0;	}	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {		vport->cfg_nodev_tmo = val;		vport->cfg_devloss_tmo = val;		lpfc_update_rport_devloss_tmo(vport);		return 0;	}	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,			 "0403 lpfc_nodev_tmo attribute cannot be set to"			 "%d, allowed range is [%d, %d]\n",			 val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO);	return -EINVAL;}lpfc_vport_param_store(nodev_tmo)static CLASS_DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR,			 lpfc_nodev_tmo_show, lpfc_nodev_tmo_store);/*# lpfc_devloss_tmo: If set, it will hold all I/O errors on devices that# disappear until the timer expires. Value range is [0,255]. Default# value is 30.*/module_param(lpfc_devloss_tmo, int, 0);MODULE_PARM_DESC(lpfc_devloss_tmo,		 "Seconds driver will hold I/O waiting "		 "for a device to come back");lpfc_vport_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO,		      LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO)lpfc_vport_param_show(devloss_tmo)static intlpfc_devloss_tmo_set(struct lpfc_vport *vport, int val){	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {		vport->cfg_nodev_tmo = val;		vport->cfg_devloss_tmo = val;		vport->dev_loss_tmo_changed = 1;		lpfc_update_rport_devloss_tmo(vport);		return 0;	}	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,			 "0404 lpfc_devloss_tmo attribute cannot be set to"			 " %d, allowed range is [%d, %d]\n",			 val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO);	return -EINVAL;}lpfc_vport_param_store(devloss_tmo)static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR,	lpfc_devloss_tmo_show, lpfc_devloss_tmo_store);/*# lpfc_log_verbose: Only turn this flag on if you are willing to risk being# deluged with LOTS of information.# You can set a bit mask to record specific types of verbose messages:## LOG_ELS                       0x1        ELS events# LOG_DISCOVERY                 0x2        Link discovery events# LOG_MBOX                      0x4        Mailbox events# LOG_INIT                      0x8        Initialization events# LOG_LINK_EVENT                0x10       Link events# LOG_FCP                       0x40       FCP traffic history# LOG_NODE                      0x80       Node table events# LOG_MISC                      0x400      Miscellaneous events# LOG_SLI                       0x800      SLI events# LOG_FCP_ERROR                 0x1000     Only log FCP errors# LOG_LIBDFC                    0x2000     LIBDFC events# LOG_ALL_MSG                   0xffff     LOG all messages*/LPFC_VPORT_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffff,		       "Verbose logging bit-mask");/*# 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.*/LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 128,		  "Max number of FCP commands we can queue to a specific LUN");/*# hba_queue_depth:  This parameter is used to limit the number of outstanding# commands per lpfc HBA. Value range is [32,8192]. If this parameter# value is greater than the maximum number of exchanges supported by the HBA,# then maximum number of exchanges supported by the HBA is used to determine# the hba_queue_depth.*/LPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192,	    "Max number of FCP commands we can queue to a lpfc HBA");/*# peer_port_login:  This parameter allows/prevents logins# between peer ports hosted on the same physical port.# When this parameter is set 0 peer ports of same physical port# are not allowed to login to each other.# When this parameter is set 1 peer ports of same physical port# are allowed to login to each other.# Default value of this parameter is 0.*/LPFC_VPORT_ATTR_R(peer_port_login, 0, 0, 1,		  "Allow peer ports on the same physical port to login to each "		  "other.");/*# restrict_login:  This parameter allows/prevents logins# between Virtual Ports and remote initiators.# When this parameter is not set (0) Virtual Ports will accept PLOGIs from# other initiators and will attempt to PLOGI all remote ports.# When this parameter is set (1) Virtual Ports will reject PLOGIs from# remote ports and will not attempt to PLOGI to other initiators.# This parameter does not restrict to the physical port.# This parameter does not restrict logins to Fabric resident remote ports.# Default value of this parameter is 1.*/static int lpfc_restrict_login = 1;module_param(lpfc_restrict_login, int, 0);MODULE_PARM_DESC(lpfc_restrict_login,		 "Restrict virtual ports login to remote initiators.");lpfc_vport_param_show(restrict_login);static intlpfc_restrict_login_init(struct lpfc_vport *vport, int val){	if (val < 0 || val > 1) {		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,				 "0449 lpfc_restrict_login attribute cannot "				 "be set to %d, allowed range is [0, 1]\n",				 val);		vport->cfg_restrict_login = 1;		return -EINVAL;	}	if (vport->port_type == LPFC_PHYSICAL_PORT) {		vport->cfg_restrict_login = 0;		return 0;	}	vport->cfg_restrict_login = val;	return 0;}static intlpfc_restrict_login_set(struct lpfc_vport *vport, int val){	if (val < 0 || val > 1) {		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,				 "0450 lpfc_restrict_login attribute cannot "				 "be set to %d, allowed range is [0, 1]\n",				 val);		vport->cfg_restrict_login = 1;		return -EINVAL;	}	if (vport->port_type == LPFC_PHYSICAL_PORT && val != 0) {		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,				 "0468 lpfc_restrict_login must be 0 for "				 "Physical ports.\n");		vport->cfg_restrict_login = 0;		return 0;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?