📄 qla_cfg.c
字号:
return success;}/* * qla2x00_update_mp_device * Update the multipath control information from the port * database for that adapter. * * Inputs: * host Host adapter structure * port Device to add to the path tree. * dev_id Device id * * Synchronization: * The Adapter Lock should have already been acquired * before calling this routine. * * Return * TRUE if updated successfully; FALSE if error. * */BOOLqla2x00_update_mp_device(mp_host_t *host, fc_port_t *port, uint16_t dev_id){ BOOL success = TRUE; mp_device_t *dp; mp_path_t *path; ENTER("qla2x00_update_mp_device"); DEBUG3(printk("update_mp_device: host =%p, port =%p, id = %d\n", host, port, dev_id);) if (!qla2x00_is_ww_name_zero(port->port_name)) { /* * Search for a device with a matching node name, * or create one. */ dp = qla2x00_find_or_allocate_mp_dev(host, dev_id, port); /* * We either have found or created a path list. Find this * host's path in the path list or allocate a new one * and add it to the list. */ if (dp == NULL) { DEBUG4(printk("Device NOT found or created at.\n");) return FALSE; } /* * Find the path in the current path list, or allocate * a new one and put it in the list if it doesn't exist. * Note that we do NOT set bSuccess to FALSE in the case * of failure here. We must tolerate the situation where * the customer has more paths to a device than he can * get into a PATH_LIST. */ path = qla2x00_find_or_allocate_path(host, dp, dev_id, port); if (path == NULL) { DEBUG4(printk("Path NOT found or created.\n");) return FALSE; } /* Set the PATH flag to match the device flag * of whether this device needs a relogin. If any * device needs relogin, set the relogin countdown. */ if (port->flags & FC_CONFIG) path->config = TRUE; if (atomic_read(&port->state) != FC_ONLINE) { path->relogin = TRUE; if (host->relogin_countdown == 0) host->relogin_countdown = 30; } else { path->relogin = FALSE; } } else { /* EMPTY */ DEBUG4(printk("qla2x00_update_mp_host: " "Failed portname empty.\n");) } LEAVE("qla2x00_update_mp_device"); return success;}/* * qla2x00_update_mp_tree * Get port information from each adapter, and build or rebuild * the multipath control tree from this data. This is called * from init and during port database notification. * * Input: * None * * Return: * Local function return code. * */static uint32_tqla2x00_update_mp_tree(void){ mp_host_t *host; uint32_t rval = QLA2X00_SUCCESS; ENTER("qla2x00_update_mp_tree:"); /* Loop through each adapter and see what needs updating. */ for (host = mp_hosts_base; (host) ; host = host->next) { DEBUG4(printk("qla2x00_update_mp_tree: hba(%d) flags (%x)\n", host->instance, host->flags);) /* Clear the countdown; it may be reset in the update. */ host->relogin_countdown = 0; /* Override the NEEDS_UPDATE flag if disabled. */ if (host->flags & MP_HOST_FLAG_DISABLE || host->fcport == NULL) host->flags &= ~MP_HOST_FLAG_NEEDS_UPDATE; if (host->flags & MP_HOST_FLAG_NEEDS_UPDATE) { /* * Perform the actual updates. If this succeeds, clear * the flag that an update is needed, and failback all * devices that are visible on this path to use this * path. If the update fails, leave set the flag that * an update is needed, and it will be picked back up * during the next timer routine. */ if (qla2x00_update_mp_host(host)) { host->flags &= ~MP_HOST_FLAG_NEEDS_UPDATE; qla2x00_failback_luns(host); } else rval = QLA2X00_FUNCTION_FAILED; } } if (rval != QLA2X00_SUCCESS) { /* EMPTY */ DEBUG4(printk("qla2x00_update_mp_tree: Exit FAILED.\n");) } else { /* EMPTY */ DEBUG4(printk("qla2x00_update_mp_tree: Exit OK.\n");) } return rval;}/* * qla2x00_find_matching_lun * Find the lun in the path that matches the * specified lun number. * * Input: * lun = lun number * newpath = path to search for lun * * Returns: * NULL or pointer to lun * * Context: * Kernel context. * (dg) */static fc_lun_t *qla2x00_find_matching_lun(uint8_t lun, mp_path_t *newpath){ fc_lun_t *lp = NULL; /* lun ptr */ fc_lun_t *nlp; /* Next lun ptr */ fc_port_t *port; /* port ptr */ if ((port = newpath->port) != NULL) { for (nlp = port->fclun; (nlp); nlp = nlp->next) { if (lun == nlp->lun) { lp = nlp; break; } } } return lp;}/* * qla2x00_find_path_by_name * Find the path specified portname from the pathlist * * Input: * host = host adapter pointer. * pathlist = multi-path path list * portname portname to search for * * Returns: * pointer to the path or NULL * * Context: * Kernel context. */mp_path_t *qla2x00_find_path_by_name(mp_host_t *host, mp_path_list_t *plp, uint8_t *portname){ mp_path_t *path = NULL; /* match if not NULL */ mp_path_t *tmp_path; int cnt; if ((tmp_path = plp->last) != NULL) { for (cnt = 0; cnt < plp->path_cnt; cnt++) { if (tmp_path->host == host && qla2x00_is_portname_equal( tmp_path->portname, portname)) { path = tmp_path; break; } tmp_path = tmp_path->next; } } return path ;}/* * qla2x00_find_mp_dev_by_name * Find the mp_dev for the specified target name. * * Input: * host = host adapter pointer. * name = Target name * * Returns: * * Context: * Kernel context. */static mp_device_t *qla2x00_find_mp_dev_by_name(mp_host_t *host, uint8_t *name ){ int id; mp_device_t *dp; ENTER("qla2x00_find_mp_dev_by_name"); for (id= 0; id < MAX_MP_DEVICES; id++) { if ((dp = host->mp_devs[id] ) == NULL) continue; if (qla2x00_is_nodename_equal(dp->nodename, name)) { DEBUG3(printk("Found matching device @ index %d:\n", id);) return dp; } } LEAVE("qla2x00_find_mp_dev_by_name"); return NULL;}/* * qla2x00_find_path_by_id * Find the path for the specified path id. * * Input: * dp multi-path device * id path id * * Returns: * pointer to the path or NULL * * Context: * Kernel context. */static mp_path_t *qla2x00_find_path_by_id(mp_device_t *dp, uint8_t id){ mp_path_t *path = NULL; mp_path_t *tmp_path; mp_path_list_t *path_list; int cnt; path_list = dp->path_list; tmp_path = path_list->last; for (cnt = 0; (tmp_path) && cnt < path_list->path_cnt; cnt++) { if (tmp_path->id == id) { path = tmp_path; break; } tmp_path = tmp_path->next; } return path ;}/* * qla2x00_find_mp_dev_by_id * Find the mp_dev for the specified target id. * * Input: * host = host adapter pointer. * tgt = Target id * * Returns: * * Context: * Kernel context. */static mp_device_t *qla2x00_find_mp_dev_by_id(mp_host_t *host, uint8_t id ){ if (id < MAX_MP_DEVICES) return host->mp_devs[id]; else return NULL;}/* * qla2x00_get_visible_path * Find the the visible path for the specified device. * * Input: * dp = device pointer * * Returns: * NULL or path * * Context: * Kernel context. */static mp_path_t *qla2x00_get_visible_path(mp_device_t *dp){ uint16_t id; mp_path_list_t *path_list; mp_path_t *path; path_list = dp->path_list; /* if we don't have a visible path skip it */ if ((id = path_list->visible) == PATH_INDEX_INVALID) { return NULL; } if ((path = qla2x00_find_path_by_id(dp,id))== NULL) return NULL; return path ;}/* * qla2x00_map_os_targets * Allocate the luns and setup the OS target. * * Input: * host = host adapter pointer. * * Returns: * None * * Context: * Kernel context. */static voidqla2x00_map_os_targets(mp_host_t *host){ scsi_qla_host_t *ha = host->ha; mp_path_t *path; mp_device_t *dp; os_tgt_t *tgt; int t; ENTER("qla2x00_map_os_targets "); for (t = 0; t < MAX_TARGETS; t++ ) { dp = host->mp_devs[t]; if (dp != NULL) { DEBUG3(printk("map_os_targets: (%d) found " "a dp = %p, host=%p, ha=%p\n", t, dp, host,ha);) if ((path = qla2x00_get_visible_path(dp)) == NULL) { printk(KERN_INFO "qla_cfg(%d): No visible path " "for target %d, dp = %p\n", host->instance, t, dp); continue; } /* if not the visible path skip it */ if (path->host == host) { if (TGT_Q(ha, t) == NULL) { tgt = qla2x00_tgt_alloc( ha, t, &dp->nodename[0]); tgt->vis_port = path->port; } DEBUG3(printk("qla_cfg%ld: host=%d, " "device= %p has VISIBLE " "path=%p, path id=%d\n", ha->host_no, host->instance, dp, path, path->id);) } else { /* EMPTY */ DEBUG3(printk("qla_cfg%ld: host=%d, " "device= %p has HIDDEN " "path=%p, path id=%d\n", ha->host_no, host->instance, dp, path,path->id);) } qla2x00_map_os_luns(host, dp, t); } else { if ((tgt= TGT_Q(ha,t)) != NULL) { qla2x00_tgt_free(ha,t); } } } LEAVE("qla2x00_map_os_targets ");}/* * qla2x00_map_os_luns * Allocate the luns for the OS target. * * Input: * dp = pointer to device * t = OS target number. * * Returns: * None * * Context: * Kernel context. */static voidqla2x00_map_os_luns(mp_host_t *host, mp_device_t *dp, uint16_t t){ uint16_t lun; for (lun = 0; lun < MAX_LUNS; lun++ ) { qla2x00_map_a_oslun(host, dp, t, lun); }}static voidqla2x00_map_a_oslun(mp_host_t *host, mp_device_t *dp, uint16_t t, uint16_t lun){ fc_port_t *fcport; fc_lun_t *fclun; os_lun_t *lq; uint16_t id; mp_path_t *path, *vis_path; mp_host_t *vis_host; if ((id = dp->path_list->current_path[lun]) != PATH_INDEX_INVALID) { path = qla2x00_find_path_by_id(dp,id); if (path) { fcport = path->port; if (fcport) { /* dg 04/26/02 */ fcport->cur_path = id; fclun = qla2x00_find_matching_lun(lun,path); /* Always map all luns if they are enabled */ if (fclun && (path->lun_data.data[lun] & LUN_DATA_ENABLED) ) { /* * Mapped lun on the visible path */ if ((vis_path = qla2x00_get_visible_path(dp)) == NULL ) { printk(KERN_INFO "qla2x00(%d): No visible " "path for target %d, " "dp = %p\n", host->instance, t, dp); return; } vis_host = vis_path->host; /* ra 11/30/01 */ /* * Always alloc LUN 0 so kernel * will scan past LUN 0. */ if (lun != 0 && (EXT_IS_LUN_BIT_SET( &(fcport->lun_mask), lun))) { /* mask this LUN */ return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -