📄 lpfc_attr.c
字号:
*/LPFC_ATTR_R(lun_queue_depth, 30, 1, 128, "Max number of FCP commands we can queue to a specific LUN");/*# Some disk devices have a "select ID" or "select Target" capability.# From a protocol standpoint "select ID" usually means select the# Fibre channel "ALPA". In the FC-AL Profile there is an "informative# annex" which contains a table that maps a "select ID" (a number# between 0 and 7F) to an ALPA. By default, for compatibility with# older drivers, the lpfc driver scans this table from low ALPA to high# ALPA.## Turning on the scan-down variable (on = 1, off = 0) will# cause the lpfc driver to use an inverted table, effectively# scanning ALPAs from high to low. Value range is [0,1]. Default value is 1.## (Note: This "select ID" functionality is a LOOP ONLY characteristic# and will not work across a fabric. Also this parameter will take# effect only in the case when ALPA map is not available.)*/LPFC_ATTR_R(scan_down, 1, 0, 1, "Start scanning for devices from highest ALPA to lowest");/*# 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.# NOTE: this MUST be less then the SCSI Layer command timeout - 1.*/LPFC_ATTR_RW(nodev_tmo, 30, 0, 255, "Seconds driver will hold I/O waiting for a device to come back");/*# lpfc_topology: link topology for init link# 0x0 = attempt loop mode then point-to-point# 0x02 = attempt point-to-point mode only# 0x04 = attempt loop mode only# 0x06 = attempt point-to-point mode then loop# Set point-to-point mode if you want to run as an N_Port.# Set loop mode if you want to run as an NL_Port. Value range is [0,0x6].# Default value is 0.*/LPFC_ATTR_R(topology, 0, 0, 6, "Select Fibre Channel topology");/*# lpfc_link_speed: Link speed selection for initializing the Fibre Channel# connection.# 0 = auto select (default)# 1 = 1 Gigabaud# 2 = 2 Gigabaud# 4 = 4 Gigabaud# Value range is [0,4]. Default value is 0.*/LPFC_ATTR_R(link_speed, 0, 0, 4, "Select link speed");/*# lpfc_fcp_class: Determines FC class to use for the FCP protocol.# Value range is [2,3]. Default value is 3.*/LPFC_ATTR_R(fcp_class, 3, 2, 3, "Select Fibre Channel class of service for FCP sequences");/*# lpfc_use_adisc: Use ADISC for FCP rediscovery instead of PLOGI. Value range# is [0,1]. Default value is 0.*/LPFC_ATTR_RW(use_adisc, 0, 0, 1, "Use ADISC on rediscovery to authenticate FCP devices");/*# lpfc_ack0: Use ACK0, instead of ACK1 for class 2 acknowledgement. Value# range is [0,1]. Default value is 0.*/LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");/*# lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing# cr_delay (msec) or cr_count outstanding commands. cr_delay can take# value [0,63]. cr_count can take value [0,255]. Default value of cr_delay# is 0. Default value of cr_count is 1. The cr_count feature is disabled if# cr_delay is set to 0.*/LPFC_ATTR(cr_delay, 0, 0, 63, "A count of milliseconds after which an" "interrupt response is generated");LPFC_ATTR(cr_count, 1, 1, 255, "A count of I/O completions after which an" "interrupt response is generated");/*# lpfc_fdmi_on: controls FDMI support.# 0 = no FDMI support# 1 = support FDMI without attribute of hostname# 2 = support FDMI with attribute of hostname# Value range [0,2]. Default value is 0.*/LPFC_ATTR_RW(fdmi_on, 0, 0, 2, "Enable FDMI support");/*# Specifies the maximum number of ELS cmds we can have outstanding (for# discovery). Value range is [1,64]. Default value = 32.*/LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands" "during discovery");/*# lpfc_max_luns: maximum number of LUNs per target driver will support# Value range is [1,32768]. Default value is 256.# NOTE: The SCSI layer will scan each target for this many luns*/LPFC_ATTR_R(max_luns, 256, 1, 32768, "Maximum number of LUNs per target driver will support");struct class_device_attribute *lpfc_host_attrs[] = { &class_device_attr_info, &class_device_attr_serialnum, &class_device_attr_modeldesc, &class_device_attr_modelname, &class_device_attr_programtype, &class_device_attr_portnum, &class_device_attr_fwrev, &class_device_attr_hdw, &class_device_attr_option_rom_version, &class_device_attr_state, &class_device_attr_num_discovered_ports, &class_device_attr_lpfc_drvr_version, &class_device_attr_lpfc_log_verbose, &class_device_attr_lpfc_lun_queue_depth, &class_device_attr_lpfc_nodev_tmo, &class_device_attr_lpfc_fcp_class, &class_device_attr_lpfc_use_adisc, &class_device_attr_lpfc_ack0, &class_device_attr_lpfc_topology, &class_device_attr_lpfc_scan_down, &class_device_attr_lpfc_link_speed, &class_device_attr_lpfc_fdmi_on, &class_device_attr_lpfc_max_luns, &class_device_attr_nport_evt_cnt, &class_device_attr_management_version, &class_device_attr_board_online, NULL,};static ssize_tsysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count){ size_t buf_off; struct Scsi_Host *host = class_to_shost(container_of(kobj, struct class_device, kobj)); struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; if ((off + count) > FF_REG_AREA_SIZE) return -ERANGE; if (count == 0) return 0; if (off % 4 || count % 4 || (unsigned long)buf % 4) return -EINVAL; spin_lock_irq(phba->host->host_lock); if (!(phba->fc_flag & FC_OFFLINE_MODE)) { spin_unlock_irq(phba->host->host_lock); return -EPERM; } for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) writel(*((uint32_t *)(buf + buf_off)), phba->ctrl_regs_memmap_p + off + buf_off); spin_unlock_irq(phba->host->host_lock); return count;}static ssize_tsysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count){ size_t buf_off; uint32_t * tmp_ptr; struct Scsi_Host *host = class_to_shost(container_of(kobj, struct class_device, kobj)); struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; if (off > FF_REG_AREA_SIZE) return -ERANGE; if ((off + count) > FF_REG_AREA_SIZE) count = FF_REG_AREA_SIZE - off; if (count == 0) return 0; if (off % 4 || count % 4 || (unsigned long)buf % 4) return -EINVAL; spin_lock_irq(phba->host->host_lock); for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) { tmp_ptr = (uint32_t *)(buf + buf_off); *tmp_ptr = readl(phba->ctrl_regs_memmap_p + off + buf_off); } spin_unlock_irq(phba->host->host_lock); return count;}static struct bin_attribute sysfs_ctlreg_attr = { .attr = { .name = "ctlreg", .mode = S_IRUSR | S_IWUSR, .owner = THIS_MODULE, }, .size = 256, .read = sysfs_ctlreg_read, .write = sysfs_ctlreg_write,};static voidsysfs_mbox_idle (struct lpfc_hba * phba){ phba->sysfs_mbox.state = SMBOX_IDLE; phba->sysfs_mbox.offset = 0; if (phba->sysfs_mbox.mbox) { mempool_free(phba->sysfs_mbox.mbox, phba->mbox_mem_pool); phba->sysfs_mbox.mbox = NULL; }}static ssize_tsysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count){ struct Scsi_Host * host = class_to_shost(container_of(kobj, struct class_device, kobj)); struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfcMboxq * mbox = NULL; if ((count + off) > MAILBOX_CMD_SIZE) return -ERANGE; if (off % 4 || count % 4 || (unsigned long)buf % 4) return -EINVAL; if (count == 0) return 0; if (off == 0) { mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) return -ENOMEM; } spin_lock_irq(host->host_lock); if (off == 0) { if (phba->sysfs_mbox.mbox) mempool_free(mbox, phba->mbox_mem_pool); else phba->sysfs_mbox.mbox = mbox; phba->sysfs_mbox.state = SMBOX_WRITING; } else { if (phba->sysfs_mbox.state != SMBOX_WRITING || phba->sysfs_mbox.offset != off || phba->sysfs_mbox.mbox == NULL ) { sysfs_mbox_idle(phba); spin_unlock_irq(host->host_lock); return -EINVAL; } } memcpy((uint8_t *) & phba->sysfs_mbox.mbox->mb + off, buf, count); phba->sysfs_mbox.offset = off + count; spin_unlock_irq(host->host_lock); return count;}static ssize_tsysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count){ struct Scsi_Host *host = class_to_shost(container_of(kobj, struct class_device, kobj)); struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; int rc; if (off > sizeof(MAILBOX_t)) return -ERANGE; if ((count + off) > sizeof(MAILBOX_t)) count = sizeof(MAILBOX_t) - off; if (off % 4 || count % 4 || (unsigned long)buf % 4) return -EINVAL; if (off && count == 0) return 0; spin_lock_irq(phba->host->host_lock); 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: case MBX_CONFIG_RING: case MBX_RESET_RING: case MBX_UNREG_LOGIN: case MBX_CLEAR_LA: 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 (!(phba->fc_flag & FC_OFFLINE_MODE)) { printk(KERN_WARNING "mbox_read:Command 0x%x " "is illegal in on-line state\n", phba->sysfs_mbox.mbox->mb.mbxCommand); sysfs_mbox_idle(phba); spin_unlock_irq(phba->host->host_lock); return -EPERM; } case MBX_LOAD_SM: case MBX_READ_NV: case MBX_READ_CONFIG: case MBX_READ_RCONFIG: case MBX_READ_STATUS: case MBX_READ_XRI: case MBX_READ_REV: case MBX_READ_LNK_STAT: case MBX_DUMP_MEMORY: case MBX_DOWN_LOAD: case MBX_UPDATE_CFG: case MBX_LOAD_AREA: case MBX_LOAD_EXP_ROM: break; case MBX_READ_SPARM64: case MBX_READ_LA: case MBX_READ_LA64: case MBX_REG_LOGIN: case MBX_REG_LOGIN64: case MBX_CONFIG_PORT: case MBX_RUN_BIU_DIAG: printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n", phba->sysfs_mbox.mbox->mb.mbxCommand); sysfs_mbox_idle(phba); spin_unlock_irq(phba->host->host_lock); return -EPERM; default: printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n", phba->sysfs_mbox.mbox->mb.mbxCommand); sysfs_mbox_idle(phba); spin_unlock_irq(phba->host->host_lock); return -EPERM; } if ((phba->fc_flag & FC_OFFLINE_MODE) || (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){ spin_unlock_irq(phba->host->host_lock); rc = lpfc_sli_issue_mbox (phba, phba->sysfs_mbox.mbox, MBX_POLL); spin_lock_irq(phba->host->host_lock); } else { spin_unlock_irq(phba->host->host_lock); rc = lpfc_sli_issue_mbox_wait (phba, phba->sysfs_mbox.mbox, phba->fc_ratov * 2); spin_lock_irq(phba->host->host_lock); } if (rc != MBX_SUCCESS) { sysfs_mbox_idle(phba); spin_unlock_irq(host->host_lock); return -ENODEV; } phba->sysfs_mbox.state = SMBOX_READING; } else if (phba->sysfs_mbox.offset != off || phba->sysfs_mbox.state != SMBOX_READING) { printk(KERN_WARNING "mbox_read: Bad State\n"); sysfs_mbox_idle(phba); spin_unlock_irq(host->host_lock); return -EINVAL; } memcpy(buf, (uint8_t *) & phba->sysfs_mbox.mbox->mb + off, count); phba->sysfs_mbox.offset = off + count; if (phba->sysfs_mbox.offset == sizeof(MAILBOX_t)) sysfs_mbox_idle(phba); spin_unlock_irq(phba->host->host_lock); return count;}static struct bin_attribute sysfs_mbox_attr = { .attr = { .name = "mbox", .mode = S_IRUSR | S_IWUSR, .owner = THIS_MODULE, }, .size = sizeof(MAILBOX_t), .read = sysfs_mbox_read, .write = sysfs_mbox_write,};intlpfc_alloc_sysfs_attr(struct lpfc_hba *phba){ struct Scsi_Host *host = phba->host; int error; error = sysfs_create_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr); if (error) goto out; error = sysfs_create_bin_file(&host->shost_classdev.kobj, &sysfs_mbox_attr); if (error) goto out_remove_ctlreg_attr; return 0;out_remove_ctlreg_attr: sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -