aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_attr.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c628
1 files changed, 573 insertions, 55 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 00656fc92b93..8d5b6ceec9c9 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -529,6 +529,27 @@ lpfc_sli4_protocol_show(struct device *dev, struct device_attribute *attr,
529} 529}
530 530
531/** 531/**
532 * lpfc_oas_supported_show - Return whether or not Optimized Access Storage
533 * (OAS) is supported.
534 * @dev: class unused variable.
535 * @attr: device attribute, not used.
536 * @buf: on return contains the module description text.
537 *
538 * Returns: size of formatted string.
539 **/
540static ssize_t
541lpfc_oas_supported_show(struct device *dev, struct device_attribute *attr,
542 char *buf)
543{
544 struct Scsi_Host *shost = class_to_shost(dev);
545 struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
546 struct lpfc_hba *phba = vport->phba;
547
548 return snprintf(buf, PAGE_SIZE, "%d\n",
549 phba->sli4_hba.pc_sli4_params.oas_supported);
550}
551
552/**
532 * lpfc_link_state_store - Transition the link_state on an HBA port 553 * lpfc_link_state_store - Transition the link_state on an HBA port
533 * @dev: class device that is converted into a Scsi_host. 554 * @dev: class device that is converted into a Scsi_host.
534 * @attr: device attribute, not used. 555 * @attr: device attribute, not used.
@@ -2041,9 +2062,53 @@ static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL);
2041static DEVICE_ATTR(lpfc_sriov_hw_max_virtfn, S_IRUGO, 2062static DEVICE_ATTR(lpfc_sriov_hw_max_virtfn, S_IRUGO,
2042 lpfc_sriov_hw_max_virtfn_show, NULL); 2063 lpfc_sriov_hw_max_virtfn_show, NULL);
2043static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL); 2064static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL);
2065static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show,
2066 NULL);
2044 2067
2045static char *lpfc_soft_wwn_key = "C99G71SL8032A"; 2068static char *lpfc_soft_wwn_key = "C99G71SL8032A";
2069#define WWN_SZ 8
2070/**
2071 * lpfc_wwn_set - Convert string to the 8 byte WWN value.
2072 * @buf: WWN string.
2073 * @cnt: Length of string.
2074 * @wwn: Array to receive converted wwn value.
2075 *
2076 * Returns:
2077 * -EINVAL if the buffer does not contain a valid wwn
2078 * 0 success
2079 **/
2080static size_t
2081lpfc_wwn_set(const char *buf, size_t cnt, char wwn[])
2082{
2083 unsigned int i, j;
2084
2085 /* Count may include a LF at end of string */
2086 if (buf[cnt-1] == '\n')
2087 cnt--;
2046 2088
2089 if ((cnt < 16) || (cnt > 18) || ((cnt == 17) && (*buf++ != 'x')) ||
2090 ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))
2091 return -EINVAL;
2092
2093 memset(wwn, 0, WWN_SZ);
2094
2095 /* Validate and store the new name */
2096 for (i = 0, j = 0; i < 16; i++) {
2097 if ((*buf >= 'a') && (*buf <= 'f'))
2098 j = ((j << 4) | ((*buf++ - 'a') + 10));
2099 else if ((*buf >= 'A') && (*buf <= 'F'))
2100 j = ((j << 4) | ((*buf++ - 'A') + 10));
2101 else if ((*buf >= '0') && (*buf <= '9'))
2102 j = ((j << 4) | (*buf++ - '0'));
2103 else
2104 return -EINVAL;
2105 if (i % 2) {
2106 wwn[i/2] = j & 0xff;
2107 j = 0;
2108 }
2109 }
2110 return 0;
2111}
2047/** 2112/**
2048 * lpfc_soft_wwn_enable_store - Allows setting of the wwn if the key is valid 2113 * lpfc_soft_wwn_enable_store - Allows setting of the wwn if the key is valid
2049 * @dev: class device that is converted into a Scsi_host. 2114 * @dev: class device that is converted into a Scsi_host.
@@ -2132,9 +2197,9 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
2132 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 2197 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2133 struct lpfc_hba *phba = vport->phba; 2198 struct lpfc_hba *phba = vport->phba;
2134 struct completion online_compl; 2199 struct completion online_compl;
2135 int stat1=0, stat2=0; 2200 int stat1 = 0, stat2 = 0;
2136 unsigned int i, j, cnt=count; 2201 unsigned int cnt = count;
2137 u8 wwpn[8]; 2202 u8 wwpn[WWN_SZ];
2138 int rc; 2203 int rc;
2139 2204
2140 if (!phba->cfg_enable_hba_reset) 2205 if (!phba->cfg_enable_hba_reset)
@@ -2149,29 +2214,19 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
2149 if (buf[cnt-1] == '\n') 2214 if (buf[cnt-1] == '\n')
2150 cnt--; 2215 cnt--;
2151 2216
2152 if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) || 2217 if (!phba->soft_wwn_enable)
2153 ((cnt == 17) && (*buf++ != 'x')) ||
2154 ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))
2155 return -EINVAL; 2218 return -EINVAL;
2156 2219
2220 /* lock setting wwpn, wwnn down */
2157 phba->soft_wwn_enable = 0; 2221 phba->soft_wwn_enable = 0;
2158 2222
2159 memset(wwpn, 0, sizeof(wwpn)); 2223 rc = lpfc_wwn_set(buf, cnt, wwpn);
2160 2224 if (!rc) {
2161 /* Validate and store the new name */ 2225 /* not able to set wwpn, unlock it */
2162 for (i=0, j=0; i < 16; i++) { 2226 phba->soft_wwn_enable = 1;
2163 int value; 2227 return rc;
2164
2165 value = hex_to_bin(*buf++);
2166 if (value >= 0)
2167 j = (j << 4) | value;
2168 else
2169 return -EINVAL;
2170 if (i % 2) {
2171 wwpn[i/2] = j & 0xff;
2172 j = 0;
2173 }
2174 } 2228 }
2229
2175 phba->cfg_soft_wwpn = wwn_to_u64(wwpn); 2230 phba->cfg_soft_wwpn = wwn_to_u64(wwpn);
2176 fc_host_port_name(shost) = phba->cfg_soft_wwpn; 2231 fc_host_port_name(shost) = phba->cfg_soft_wwpn;
2177 if (phba->cfg_soft_wwnn) 2232 if (phba->cfg_soft_wwnn)
@@ -2198,7 +2253,7 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
2198 "reinit adapter - %d\n", stat2); 2253 "reinit adapter - %d\n", stat2);
2199 return (stat1 || stat2) ? -EIO : count; 2254 return (stat1 || stat2) ? -EIO : count;
2200} 2255}
2201static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ 2256static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,
2202 lpfc_soft_wwpn_show, lpfc_soft_wwpn_store); 2257 lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
2203 2258
2204/** 2259/**
@@ -2235,39 +2290,25 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
2235{ 2290{
2236 struct Scsi_Host *shost = class_to_shost(dev); 2291 struct Scsi_Host *shost = class_to_shost(dev);
2237 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 2292 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2238 unsigned int i, j, cnt=count; 2293 unsigned int cnt = count;
2239 u8 wwnn[8]; 2294 u8 wwnn[WWN_SZ];
2295 int rc;
2240 2296
2241 /* count may include a LF at end of string */ 2297 /* count may include a LF at end of string */
2242 if (buf[cnt-1] == '\n') 2298 if (buf[cnt-1] == '\n')
2243 cnt--; 2299 cnt--;
2244 2300
2245 if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) || 2301 if (!phba->soft_wwn_enable)
2246 ((cnt == 17) && (*buf++ != 'x')) ||
2247 ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))
2248 return -EINVAL; 2302 return -EINVAL;
2249 2303
2250 /* 2304 rc = lpfc_wwn_set(buf, cnt, wwnn);
2251 * Allow wwnn to be set many times, as long as the enable is set. 2305 if (!rc) {
2252 * However, once the wwpn is set, everything locks. 2306 /* Allow wwnn to be set many times, as long as the enable
2253 */ 2307 * is set. However, once the wwpn is set, everything locks.
2254 2308 */
2255 memset(wwnn, 0, sizeof(wwnn)); 2309 return rc;
2256
2257 /* Validate and store the new name */
2258 for (i=0, j=0; i < 16; i++) {
2259 int value;
2260
2261 value = hex_to_bin(*buf++);
2262 if (value >= 0)
2263 j = (j << 4) | value;
2264 else
2265 return -EINVAL;
2266 if (i % 2) {
2267 wwnn[i/2] = j & 0xff;
2268 j = 0;
2269 }
2270 } 2310 }
2311
2271 phba->cfg_soft_wwnn = wwn_to_u64(wwnn); 2312 phba->cfg_soft_wwnn = wwn_to_u64(wwnn);
2272 2313
2273 dev_printk(KERN_NOTICE, &phba->pcidev->dev, 2314 dev_printk(KERN_NOTICE, &phba->pcidev->dev,
@@ -2276,9 +2317,438 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
2276 2317
2277 return count; 2318 return count;
2278} 2319}
2279static DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\ 2320static DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,
2280 lpfc_soft_wwnn_show, lpfc_soft_wwnn_store); 2321 lpfc_soft_wwnn_show, lpfc_soft_wwnn_store);
2281 2322
2323/**
2324 * lpfc_oas_tgt_show - Return wwpn of target whose luns maybe enabled for
2325 * Optimized Access Storage (OAS) operations.
2326 * @dev: class device that is converted into a Scsi_host.
2327 * @attr: device attribute, not used.
2328 * @buf: buffer for passing information.
2329 *
2330 * Returns:
2331 * value of count
2332 **/
2333static ssize_t
2334lpfc_oas_tgt_show(struct device *dev, struct device_attribute *attr,
2335 char *buf)
2336{
2337 struct Scsi_Host *shost = class_to_shost(dev);
2338 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2339
2340 return snprintf(buf, PAGE_SIZE, "0x%llx\n",
2341 wwn_to_u64(phba->cfg_oas_tgt_wwpn));
2342}
2343
2344/**
2345 * lpfc_oas_tgt_store - Store wwpn of target whose luns maybe enabled for
2346 * Optimized Access Storage (OAS) operations.
2347 * @dev: class device that is converted into a Scsi_host.
2348 * @attr: device attribute, not used.
2349 * @buf: buffer for passing information.
2350 * @count: Size of the data buffer.
2351 *
2352 * Returns:
2353 * -EINVAL count is invalid, invalid wwpn byte invalid
2354 * -EPERM oas is not supported by hba
2355 * value of count on success
2356 **/
2357static ssize_t
2358lpfc_oas_tgt_store(struct device *dev, struct device_attribute *attr,
2359 const char *buf, size_t count)
2360{
2361 struct Scsi_Host *shost = class_to_shost(dev);
2362 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2363 unsigned int cnt = count;
2364 uint8_t wwpn[WWN_SZ];
2365 int rc;
2366
2367 if (!phba->cfg_EnableXLane)
2368 return -EPERM;
2369
2370 /* count may include a LF at end of string */
2371 if (buf[cnt-1] == '\n')
2372 cnt--;
2373
2374 rc = lpfc_wwn_set(buf, cnt, wwpn);
2375 if (rc)
2376 return rc;
2377
2378 memcpy(phba->cfg_oas_tgt_wwpn, wwpn, (8 * sizeof(uint8_t)));
2379 memcpy(phba->sli4_hba.oas_next_tgt_wwpn, wwpn, (8 * sizeof(uint8_t)));
2380 if (wwn_to_u64(wwpn) == 0)
2381 phba->cfg_oas_flags |= OAS_FIND_ANY_TARGET;
2382 else
2383 phba->cfg_oas_flags &= ~OAS_FIND_ANY_TARGET;
2384 phba->cfg_oas_flags &= ~OAS_LUN_VALID;
2385 phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN;
2386 return count;
2387}
2388static DEVICE_ATTR(lpfc_xlane_tgt, S_IRUGO | S_IWUSR,
2389 lpfc_oas_tgt_show, lpfc_oas_tgt_store);
2390
2391/**
2392 * lpfc_oas_vpt_show - Return wwpn of vport whose targets maybe enabled
2393 * for Optimized Access Storage (OAS) operations.
2394 * @dev: class device that is converted into a Scsi_host.
2395 * @attr: device attribute, not used.
2396 * @buf: buffer for passing information.
2397 *
2398 * Returns:
2399 * value of count on success
2400 **/
2401static ssize_t
2402lpfc_oas_vpt_show(struct device *dev, struct device_attribute *attr,
2403 char *buf)
2404{
2405 struct Scsi_Host *shost = class_to_shost(dev);
2406 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2407
2408 return snprintf(buf, PAGE_SIZE, "0x%llx\n",
2409 wwn_to_u64(phba->cfg_oas_vpt_wwpn));
2410}
2411
2412/**
2413 * lpfc_oas_vpt_store - Store wwpn of vport whose targets maybe enabled
2414 * for Optimized Access Storage (OAS) operations.
2415 * @dev: class device that is converted into a Scsi_host.
2416 * @attr: device attribute, not used.
2417 * @buf: buffer for passing information.
2418 * @count: Size of the data buffer.
2419 *
2420 * Returns:
2421 * -EINVAL count is invalid, invalid wwpn byte invalid
2422 * -EPERM oas is not supported by hba
2423 * value of count on success
2424 **/
2425static ssize_t
2426lpfc_oas_vpt_store(struct device *dev, struct device_attribute *attr,
2427 const char *buf, size_t count)
2428{
2429 struct Scsi_Host *shost = class_to_shost(dev);
2430 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2431 unsigned int cnt = count;
2432 uint8_t wwpn[WWN_SZ];
2433 int rc;
2434
2435 if (!phba->cfg_EnableXLane)
2436 return -EPERM;
2437
2438 /* count may include a LF at end of string */
2439 if (buf[cnt-1] == '\n')
2440 cnt--;
2441
2442 rc = lpfc_wwn_set(buf, cnt, wwpn);
2443 if (rc)
2444 return rc;
2445
2446 memcpy(phba->cfg_oas_vpt_wwpn, wwpn, (8 * sizeof(uint8_t)));
2447 memcpy(phba->sli4_hba.oas_next_vpt_wwpn, wwpn, (8 * sizeof(uint8_t)));
2448 if (wwn_to_u64(wwpn) == 0)
2449 phba->cfg_oas_flags |= OAS_FIND_ANY_VPORT;
2450 else
2451 phba->cfg_oas_flags &= ~OAS_FIND_ANY_VPORT;
2452 phba->cfg_oas_flags &= ~OAS_LUN_VALID;
2453 phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN;
2454 return count;
2455}
2456static DEVICE_ATTR(lpfc_xlane_vpt, S_IRUGO | S_IWUSR,
2457 lpfc_oas_vpt_show, lpfc_oas_vpt_store);
2458
2459/**
2460 * lpfc_oas_lun_state_show - Return the current state (enabled or disabled)
2461 * of whether luns will be enabled or disabled
2462 * for Optimized Access Storage (OAS) operations.
2463 * @dev: class device that is converted into a Scsi_host.
2464 * @attr: device attribute, not used.
2465 * @buf: buffer for passing information.
2466 *
2467 * Returns:
2468 * size of formatted string.
2469 **/
2470static ssize_t
2471lpfc_oas_lun_state_show(struct device *dev, struct device_attribute *attr,
2472 char *buf)
2473{
2474 struct Scsi_Host *shost = class_to_shost(dev);
2475 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2476
2477 return snprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_state);
2478}
2479
2480/**
2481 * lpfc_oas_lun_state_store - Store the state (enabled or disabled)
2482 * of whether luns will be enabled or disabled
2483 * for Optimized Access Storage (OAS) operations.
2484 * @dev: class device that is converted into a Scsi_host.
2485 * @attr: device attribute, not used.
2486 * @buf: buffer for passing information.
2487 * @count: Size of the data buffer.
2488 *
2489 * Returns:
2490 * -EINVAL count is invalid, invalid wwpn byte invalid
2491 * -EPERM oas is not supported by hba
2492 * value of count on success
2493 **/
2494static ssize_t
2495lpfc_oas_lun_state_store(struct device *dev, struct device_attribute *attr,
2496 const char *buf, size_t count)
2497{
2498 struct Scsi_Host *shost = class_to_shost(dev);
2499 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2500 int val = 0;
2501
2502 if (!phba->cfg_EnableXLane)
2503 return -EPERM;
2504
2505 if (!isdigit(buf[0]))
2506 return -EINVAL;
2507
2508 if (sscanf(buf, "%i", &val) != 1)
2509 return -EINVAL;
2510
2511 if ((val != 0) && (val != 1))
2512 return -EINVAL;
2513
2514 phba->cfg_oas_lun_state = val;
2515
2516 return strlen(buf);
2517}
2518static DEVICE_ATTR(lpfc_xlane_lun_state, S_IRUGO | S_IWUSR,
2519 lpfc_oas_lun_state_show, lpfc_oas_lun_state_store);
2520
2521/**
2522 * lpfc_oas_lun_status_show - Return the status of the Optimized Access
2523 * Storage (OAS) lun returned by the
2524 * lpfc_oas_lun_show function.
2525 * @dev: class device that is converted into a Scsi_host.
2526 * @attr: device attribute, not used.
2527 * @buf: buffer for passing information.
2528 *
2529 * Returns:
2530 * size of formatted string.
2531 **/
2532static ssize_t
2533lpfc_oas_lun_status_show(struct device *dev, struct device_attribute *attr,
2534 char *buf)
2535{
2536 struct Scsi_Host *shost = class_to_shost(dev);
2537 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2538
2539 if (!(phba->cfg_oas_flags & OAS_LUN_VALID))
2540 return -EFAULT;
2541
2542 return snprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_status);
2543}
2544static DEVICE_ATTR(lpfc_xlane_lun_status, S_IRUGO,
2545 lpfc_oas_lun_status_show, NULL);
2546
2547
2548/**
2549 * lpfc_oas_lun_state_set - enable or disable a lun for Optimized Access Storage
2550 * (OAS) operations.
2551 * @phba: lpfc_hba pointer.
2552 * @ndlp: pointer to fcp target node.
2553 * @lun: the fc lun for setting oas state.
2554 * @oas_state: the oas state to be set to the lun.
2555 *
2556 * Returns:
2557 * SUCCESS : 0
2558 * -EPERM OAS is not enabled or not supported by this port.
2559 *
2560 */
2561static size_t
2562lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
2563 uint8_t tgt_wwpn[], uint64_t lun, uint32_t oas_state)
2564{
2565
2566 int rc = 0;
2567
2568 if (!phba->cfg_EnableXLane)
2569 return -EPERM;
2570
2571 if (oas_state) {
2572 if (!lpfc_enable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn,
2573 (struct lpfc_name *)tgt_wwpn, lun))
2574 rc = -ENOMEM;
2575 } else {
2576 lpfc_disable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn,
2577 (struct lpfc_name *)tgt_wwpn, lun);
2578 }
2579 return rc;
2580
2581}
2582
2583/**
2584 * lpfc_oas_lun_get_next - get the next lun that has been enabled for Optimized
2585 * Access Storage (OAS) operations.
2586 * @phba: lpfc_hba pointer.
2587 * @vpt_wwpn: wwpn of the vport associated with the returned lun
2588 * @tgt_wwpn: wwpn of the target associated with the returned lun
2589 * @lun_status: status of the lun returned lun
2590 *
2591 * Returns the first or next lun enabled for OAS operations for the vport/target
2592 * specified. If a lun is found, its vport wwpn, target wwpn and status is
2593 * returned. If the lun is not found, NOT_OAS_ENABLED_LUN is returned.
2594 *
2595 * Return:
2596 * lun that is OAS enabled for the vport/target
2597 * NOT_OAS_ENABLED_LUN when no oas enabled lun found.
2598 */
2599static uint64_t
2600lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
2601 uint8_t tgt_wwpn[], uint32_t *lun_status)
2602{
2603 uint64_t found_lun;
2604
2605 if (unlikely(!phba) || !vpt_wwpn || !tgt_wwpn)
2606 return NOT_OAS_ENABLED_LUN;
2607 if (lpfc_find_next_oas_lun(phba, (struct lpfc_name *)
2608 phba->sli4_hba.oas_next_vpt_wwpn,
2609 (struct lpfc_name *)
2610 phba->sli4_hba.oas_next_tgt_wwpn,
2611 &phba->sli4_hba.oas_next_lun,
2612 (struct lpfc_name *)vpt_wwpn,
2613 (struct lpfc_name *)tgt_wwpn,
2614 &found_lun, lun_status))
2615 return found_lun;
2616 else
2617 return NOT_OAS_ENABLED_LUN;
2618}
2619
2620/**
2621 * lpfc_oas_lun_state_change - enable/disable a lun for OAS operations
2622 * @phba: lpfc_hba pointer.
2623 * @vpt_wwpn: vport wwpn by reference.
2624 * @tgt_wwpn: target wwpn by reference.
2625 * @lun: the fc lun for setting oas state.
2626 * @oas_state: the oas state to be set to the oas_lun.
2627 *
2628 * This routine enables (OAS_LUN_ENABLE) or disables (OAS_LUN_DISABLE)
2629 * a lun for OAS operations.
2630 *
2631 * Return:
2632 * SUCCESS: 0
2633 * -ENOMEM: failed to enable an lun for OAS operations
2634 * -EPERM: OAS is not enabled
2635 */
2636static ssize_t
2637lpfc_oas_lun_state_change(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
2638 uint8_t tgt_wwpn[], uint64_t lun,
2639 uint32_t oas_state)
2640{
2641
2642 int rc;
2643
2644 rc = lpfc_oas_lun_state_set(phba, vpt_wwpn, tgt_wwpn, lun,
2645 oas_state);
2646 return rc;
2647}
2648
2649/**
2650 * lpfc_oas_lun_show - Return oas enabled luns from a chosen target
2651 * @dev: class device that is converted into a Scsi_host.
2652 * @attr: device attribute, not used.
2653 * @buf: buffer for passing information.
2654 *
2655 * This routine returns a lun enabled for OAS each time the function
2656 * is called.
2657 *
2658 * Returns:
2659 * SUCCESS: size of formatted string.
2660 * -EFAULT: target or vport wwpn was not set properly.
2661 * -EPERM: oas is not enabled.
2662 **/
2663static ssize_t
2664lpfc_oas_lun_show(struct device *dev, struct device_attribute *attr,
2665 char *buf)
2666{
2667 struct Scsi_Host *shost = class_to_shost(dev);
2668 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2669
2670 uint64_t oas_lun;
2671 int len = 0;
2672
2673 if (!phba->cfg_EnableXLane)
2674 return -EPERM;
2675
2676 if (wwn_to_u64(phba->cfg_oas_vpt_wwpn) == 0)
2677 if (!(phba->cfg_oas_flags & OAS_FIND_ANY_VPORT))
2678 return -EFAULT;
2679
2680 if (wwn_to_u64(phba->cfg_oas_tgt_wwpn) == 0)
2681 if (!(phba->cfg_oas_flags & OAS_FIND_ANY_TARGET))
2682 return -EFAULT;
2683
2684 oas_lun = lpfc_oas_lun_get_next(phba, phba->cfg_oas_vpt_wwpn,
2685 phba->cfg_oas_tgt_wwpn,
2686 &phba->cfg_oas_lun_status);
2687 if (oas_lun != NOT_OAS_ENABLED_LUN)
2688 phba->cfg_oas_flags |= OAS_LUN_VALID;
2689
2690 len += snprintf(buf + len, PAGE_SIZE-len, "0x%llx", oas_lun);
2691
2692 return len;
2693}
2694
2695/**
2696 * lpfc_oas_lun_store - Sets the OAS state for lun
2697 * @dev: class device that is converted into a Scsi_host.
2698 * @attr: device attribute, not used.
2699 * @buf: buffer for passing information.
2700 *
2701 * This function sets the OAS state for lun. Before this function is called,
2702 * the vport wwpn, target wwpn, and oas state need to be set.
2703 *
2704 * Returns:
2705 * SUCCESS: size of formatted string.
2706 * -EFAULT: target or vport wwpn was not set properly.
2707 * -EPERM: oas is not enabled.
2708 * size of formatted string.
2709 **/
2710static ssize_t
2711lpfc_oas_lun_store(struct device *dev, struct device_attribute *attr,
2712 const char *buf, size_t count)
2713{
2714 struct Scsi_Host *shost = class_to_shost(dev);
2715 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2716 uint64_t scsi_lun;
2717 ssize_t rc;
2718
2719 if (!phba->cfg_EnableXLane)
2720 return -EPERM;
2721
2722 if (wwn_to_u64(phba->cfg_oas_vpt_wwpn) == 0)
2723 return -EFAULT;
2724
2725 if (wwn_to_u64(phba->cfg_oas_tgt_wwpn) == 0)
2726 return -EFAULT;
2727
2728 if (!isdigit(buf[0]))
2729 return -EINVAL;
2730
2731 if (sscanf(buf, "0x%llx", &scsi_lun) != 1)
2732 return -EINVAL;
2733
2734 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2735 "3372 Try to set vport 0x%llx target 0x%llx lun:%lld "
2736 "with oas set to %d\n",
2737 wwn_to_u64(phba->cfg_oas_vpt_wwpn),
2738 wwn_to_u64(phba->cfg_oas_tgt_wwpn), scsi_lun,
2739 phba->cfg_oas_lun_state);
2740
2741 rc = lpfc_oas_lun_state_change(phba, phba->cfg_oas_vpt_wwpn,
2742 phba->cfg_oas_tgt_wwpn, scsi_lun,
2743 phba->cfg_oas_lun_state);
2744
2745 if (rc)
2746 return rc;
2747
2748 return count;
2749}
2750static DEVICE_ATTR(lpfc_xlane_lun, S_IRUGO | S_IWUSR,
2751 lpfc_oas_lun_show, lpfc_oas_lun_store);
2282 2752
2283static int lpfc_poll = 0; 2753static int lpfc_poll = 0;
2284module_param(lpfc_poll, int, S_IRUGO); 2754module_param(lpfc_poll, int, S_IRUGO);
@@ -3818,7 +4288,7 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
3818 struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 4288 struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
3819 struct lpfc_hba *phba = vport->phba; 4289 struct lpfc_hba *phba = vport->phba;
3820 struct lpfc_vector_map_info *cpup; 4290 struct lpfc_vector_map_info *cpup;
3821 int idx, len = 0; 4291 int len = 0;
3822 4292
3823 if ((phba->sli_rev != LPFC_SLI_REV4) || 4293 if ((phba->sli_rev != LPFC_SLI_REV4) ||
3824 (phba->intr_type != MSIX)) 4294 (phba->intr_type != MSIX))
@@ -3846,23 +4316,39 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
3846 break; 4316 break;
3847 } 4317 }
3848 4318
3849 cpup = phba->sli4_hba.cpu_map; 4319 while (phba->sli4_hba.curr_disp_cpu < phba->sli4_hba.num_present_cpu) {
3850 for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) { 4320 cpup = &phba->sli4_hba.cpu_map[phba->sli4_hba.curr_disp_cpu];
4321
4322 /* margin should fit in this and the truncated message */
3851 if (cpup->irq == LPFC_VECTOR_MAP_EMPTY) 4323 if (cpup->irq == LPFC_VECTOR_MAP_EMPTY)
3852 len += snprintf(buf + len, PAGE_SIZE-len, 4324 len += snprintf(buf + len, PAGE_SIZE-len,
3853 "CPU %02d io_chan %02d " 4325 "CPU %02d io_chan %02d "
3854 "physid %d coreid %d\n", 4326 "physid %d coreid %d\n",
3855 idx, cpup->channel_id, cpup->phys_id, 4327 phba->sli4_hba.curr_disp_cpu,
4328 cpup->channel_id, cpup->phys_id,
3856 cpup->core_id); 4329 cpup->core_id);
3857 else 4330 else
3858 len += snprintf(buf + len, PAGE_SIZE-len, 4331 len += snprintf(buf + len, PAGE_SIZE-len,
3859 "CPU %02d io_chan %02d " 4332 "CPU %02d io_chan %02d "
3860 "physid %d coreid %d IRQ %d\n", 4333 "physid %d coreid %d IRQ %d\n",
3861 idx, cpup->channel_id, cpup->phys_id, 4334 phba->sli4_hba.curr_disp_cpu,
4335 cpup->channel_id, cpup->phys_id,
3862 cpup->core_id, cpup->irq); 4336 cpup->core_id, cpup->irq);
3863 4337
3864 cpup++; 4338 phba->sli4_hba.curr_disp_cpu++;
4339
4340 /* display max number of CPUs keeping some margin */
4341 if (phba->sli4_hba.curr_disp_cpu <
4342 phba->sli4_hba.num_present_cpu &&
4343 (len >= (PAGE_SIZE - 64))) {
4344 len += snprintf(buf + len, PAGE_SIZE-len, "more...\n");
4345 break;
4346 }
3865 } 4347 }
4348
4349 if (phba->sli4_hba.curr_disp_cpu == phba->sli4_hba.num_present_cpu)
4350 phba->sli4_hba.curr_disp_cpu = 0;
4351
3866 return len; 4352 return len;
3867} 4353}
3868 4354
@@ -4157,6 +4643,21 @@ LPFC_ATTR_R(enable_hba_reset, 1, 0, 1, "Enable HBA resets from the driver.");
4157LPFC_ATTR_R(enable_hba_heartbeat, 0, 0, 1, "Enable HBA Heartbeat."); 4643LPFC_ATTR_R(enable_hba_heartbeat, 0, 0, 1, "Enable HBA Heartbeat.");
4158 4644
4159/* 4645/*
4646# lpfc_EnableXLane: Enable Express Lane Feature
4647# 0x0 Express Lane Feature disabled
4648# 0x1 Express Lane Feature enabled
4649# Value range is [0,1]. Default value is 0.
4650*/
4651LPFC_ATTR_R(EnableXLane, 0, 0, 1, "Enable Express Lane Feature.");
4652
4653/*
4654# lpfc_XLanePriority: Define CS_CTL priority for Express Lane Feature
4655# 0x0 - 0x7f = CS_CTL field in FC header (high 7 bits)
4656# Value range is [0x0,0x7f]. Default value is 0
4657*/
4658LPFC_ATTR_R(XLanePriority, 0, 0x0, 0x7f, "CS_CTL for Express Lane Feature.");
4659
4660/*
4160# lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF) 4661# lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF)
4161# 0 = BlockGuard disabled (default) 4662# 0 = BlockGuard disabled (default)
4162# 1 = BlockGuard enabled 4663# 1 = BlockGuard enabled
@@ -4317,6 +4818,13 @@ struct device_attribute *lpfc_hba_attrs[] = {
4317 &dev_attr_lpfc_soft_wwn_enable, 4818 &dev_attr_lpfc_soft_wwn_enable,
4318 &dev_attr_lpfc_enable_hba_reset, 4819 &dev_attr_lpfc_enable_hba_reset,
4319 &dev_attr_lpfc_enable_hba_heartbeat, 4820 &dev_attr_lpfc_enable_hba_heartbeat,
4821 &dev_attr_lpfc_EnableXLane,
4822 &dev_attr_lpfc_XLanePriority,
4823 &dev_attr_lpfc_xlane_lun,
4824 &dev_attr_lpfc_xlane_tgt,
4825 &dev_attr_lpfc_xlane_vpt,
4826 &dev_attr_lpfc_xlane_lun_state,
4827 &dev_attr_lpfc_xlane_lun_status,
4320 &dev_attr_lpfc_sg_seg_cnt, 4828 &dev_attr_lpfc_sg_seg_cnt,
4321 &dev_attr_lpfc_max_scsicmpl_time, 4829 &dev_attr_lpfc_max_scsicmpl_time,
4322 &dev_attr_lpfc_stat_data_ctrl, 4830 &dev_attr_lpfc_stat_data_ctrl,
@@ -4335,6 +4843,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
4335 &dev_attr_lpfc_dss, 4843 &dev_attr_lpfc_dss,
4336 &dev_attr_lpfc_sriov_hw_max_virtfn, 4844 &dev_attr_lpfc_sriov_hw_max_virtfn,
4337 &dev_attr_protocol, 4845 &dev_attr_protocol,
4846 &dev_attr_lpfc_xlane_supported,
4338 NULL, 4847 NULL,
4339}; 4848};
4340 4849
@@ -5296,11 +5805,20 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
5296 lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel); 5805 lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel);
5297 lpfc_enable_hba_reset_init(phba, lpfc_enable_hba_reset); 5806 lpfc_enable_hba_reset_init(phba, lpfc_enable_hba_reset);
5298 lpfc_enable_hba_heartbeat_init(phba, lpfc_enable_hba_heartbeat); 5807 lpfc_enable_hba_heartbeat_init(phba, lpfc_enable_hba_heartbeat);
5808 lpfc_EnableXLane_init(phba, lpfc_EnableXLane);
5809 if (phba->sli_rev != LPFC_SLI_REV4)
5810 phba->cfg_EnableXLane = 0;
5811 lpfc_XLanePriority_init(phba, lpfc_XLanePriority);
5812 memset(phba->cfg_oas_tgt_wwpn, 0, (8 * sizeof(uint8_t)));
5813 memset(phba->cfg_oas_vpt_wwpn, 0, (8 * sizeof(uint8_t)));
5814 phba->cfg_oas_lun_state = 0;
5815 phba->cfg_oas_lun_status = 0;
5816 phba->cfg_oas_flags = 0;
5299 lpfc_enable_bg_init(phba, lpfc_enable_bg); 5817 lpfc_enable_bg_init(phba, lpfc_enable_bg);
5300 if (phba->sli_rev == LPFC_SLI_REV4) 5818 if (phba->sli_rev == LPFC_SLI_REV4)
5301 phba->cfg_poll = 0; 5819 phba->cfg_poll = 0;
5302 else 5820 else
5303 phba->cfg_poll = lpfc_poll; 5821 phba->cfg_poll = lpfc_poll;
5304 phba->cfg_soft_wwnn = 0L; 5822 phba->cfg_soft_wwnn = 0L;
5305 phba->cfg_soft_wwpn = 0L; 5823 phba->cfg_soft_wwpn = 0L;
5306 lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); 5824 lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt);