aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-09-07 11:52:10 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-10-13 09:28:57 -0400
commitea2151b4e142fa2de0319d9dd80413a997bf435a (patch)
tree1daa395a0b8584431c1b739af2761a840d013985 /drivers/scsi/lpfc
parent977b5a0af6d22a1a0170057c19cde37eeac68acd (diff)
[SCSI] lpfc 8.2.8 v2 : Add statistical reporting control and additional fc vendor events
Added support for new sysfs attributes: lpfc_stat_data_ctrl and lpfc_max_scsicmpl_time. The attributes control statistical reporting of io load. Added support for new fc vendor events for error reporting. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc.h27
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c343
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h20
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c114
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c143
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c22
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_nl.h163
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c279
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c12
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c80
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.h4
18 files changed, 1207 insertions, 15 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 3a500d683065..60a9e6e9384b 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -40,6 +40,8 @@ struct lpfc_sli2_slim;
40#define LPFC_MIN_TGT_QDEPTH 100 40#define LPFC_MIN_TGT_QDEPTH 100
41#define LPFC_MAX_TGT_QDEPTH 0xFFFF 41#define LPFC_MAX_TGT_QDEPTH 0xFFFF
42 42
43#define LPFC_MAX_BUCKET_COUNT 20 /* Maximum no. of buckets for stat data
44 collection. */
43/* 45/*
44 * Following time intervals are used of adjusting SCSI device 46 * Following time intervals are used of adjusting SCSI device
45 * queue depths when there are driver resource error or Firmware 47 * queue depths when there are driver resource error or Firmware
@@ -381,6 +383,8 @@ struct lpfc_vport {
381 struct lpfc_debugfs_trc *disc_trc; 383 struct lpfc_debugfs_trc *disc_trc;
382 atomic_t disc_trc_cnt; 384 atomic_t disc_trc_cnt;
383#endif 385#endif
386 uint8_t stat_data_enabled;
387 uint8_t stat_data_blocked;
384}; 388};
385 389
386struct hbq_s { 390struct hbq_s {
@@ -641,6 +645,17 @@ struct lpfc_hba {
641 uint32_t buffer_tag_count; 645 uint32_t buffer_tag_count;
642 int wait_4_mlo_maint_flg; 646 int wait_4_mlo_maint_flg;
643 wait_queue_head_t wait_4_mlo_m_q; 647 wait_queue_head_t wait_4_mlo_m_q;
648 /* data structure used for latency data collection */
649#define LPFC_NO_BUCKET 0
650#define LPFC_LINEAR_BUCKET 1
651#define LPFC_POWER2_BUCKET 2
652 uint8_t bucket_type;
653 uint32_t bucket_base;
654 uint32_t bucket_step;
655
656/* Maximum number of events that can be outstanding at any time*/
657#define LPFC_MAX_EVT_COUNT 512
658 atomic_t fast_event_count;
644}; 659};
645 660
646static inline struct Scsi_Host * 661static inline struct Scsi_Host *
@@ -699,15 +714,3 @@ lpfc_sli_read_hs(struct lpfc_hba *phba)
699 return; 714 return;
700} 715}
701 716
702#define FC_REG_DUMP_EVENT 0x10 /* Register for Dump events */
703#define FC_REG_TEMPERATURE_EVENT 0x20 /* Register for temperature
704 event */
705
706struct temp_event {
707 uint32_t event_type;
708 uint32_t event_code;
709 uint32_t data;
710};
711#define LPFC_CRIT_TEMP 0x1
712#define LPFC_THRESHOLD_TEMP 0x2
713#define LPFC_NORMAL_TEMP 0x3
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 343b0b36ed22..aa3d6277581d 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -32,6 +32,7 @@
32 32
33#include "lpfc_hw.h" 33#include "lpfc_hw.h"
34#include "lpfc_sli.h" 34#include "lpfc_sli.h"
35#include "lpfc_nl.h"
35#include "lpfc_disc.h" 36#include "lpfc_disc.h"
36#include "lpfc_scsi.h" 37#include "lpfc_scsi.h"
37#include "lpfc.h" 38#include "lpfc.h"
@@ -2183,6 +2184,335 @@ lpfc_param_store(topology)
2183static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR, 2184static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
2184 lpfc_topology_show, lpfc_topology_store); 2185 lpfc_topology_show, lpfc_topology_store);
2185 2186
2187
2188/**
2189 * lpfc_stat_data_ctrl_store: write call back for lpfc_stat_data_ctrl
2190 * sysfs file.
2191 * @dev: Pointer to class device.
2192 * @buf: Data buffer.
2193 * @count: Size of the data buffer.
2194 *
2195 * This function get called when an user write to the lpfc_stat_data_ctrl
2196 * sysfs file. This function parse the command written to the sysfs file
2197 * and take appropriate action. These commands are used for controlling
2198 * driver statistical data collection.
2199 * Following are the command this function handles.
2200 *
2201 * setbucket <bucket_type> <base> <step>
2202 * = Set the latency buckets.
2203 * destroybucket = destroy all the buckets.
2204 * start = start data collection
2205 * stop = stop data collection
2206 * reset = reset the collected data
2207 **/
2208static ssize_t
2209lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr,
2210 const char *buf, size_t count)
2211{
2212 struct Scsi_Host *shost = class_to_shost(dev);
2213 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2214 struct lpfc_hba *phba = vport->phba;
2215#define LPFC_MAX_DATA_CTRL_LEN 1024
2216 static char bucket_data[LPFC_MAX_DATA_CTRL_LEN];
2217 unsigned long i;
2218 char *str_ptr, *token;
2219 struct lpfc_vport **vports;
2220 struct Scsi_Host *v_shost;
2221 char *bucket_type_str, *base_str, *step_str;
2222 unsigned long base, step, bucket_type;
2223
2224 if (!strncmp(buf, "setbucket", strlen("setbucket"))) {
2225 if (strlen(buf) > LPFC_MAX_DATA_CTRL_LEN)
2226 return -EINVAL;
2227
2228 strcpy(bucket_data, buf);
2229 str_ptr = &bucket_data[0];
2230 /* Ignore this token - this is command token */
2231 token = strsep(&str_ptr, "\t ");
2232 if (!token)
2233 return -EINVAL;
2234
2235 bucket_type_str = strsep(&str_ptr, "\t ");
2236 if (!bucket_type_str)
2237 return -EINVAL;
2238
2239 if (!strncmp(bucket_type_str, "linear", strlen("linear")))
2240 bucket_type = LPFC_LINEAR_BUCKET;
2241 else if (!strncmp(bucket_type_str, "power2", strlen("power2")))
2242 bucket_type = LPFC_POWER2_BUCKET;
2243 else
2244 return -EINVAL;
2245
2246 base_str = strsep(&str_ptr, "\t ");
2247 if (!base_str)
2248 return -EINVAL;
2249 base = simple_strtoul(base_str, NULL, 0);
2250
2251 step_str = strsep(&str_ptr, "\t ");
2252 if (!step_str)
2253 return -EINVAL;
2254 step = simple_strtoul(step_str, NULL, 0);
2255 if (!step)
2256 return -EINVAL;
2257
2258 /* Block the data collection for every vport */
2259 vports = lpfc_create_vport_work_array(phba);
2260 if (vports == NULL)
2261 return -ENOMEM;
2262
2263 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
2264 v_shost = lpfc_shost_from_vport(vports[i]);
2265 spin_lock_irq(v_shost->host_lock);
2266 /* Block and reset data collection */
2267 vports[i]->stat_data_blocked = 1;
2268 if (vports[i]->stat_data_enabled)
2269 lpfc_vport_reset_stat_data(vports[i]);
2270 spin_unlock_irq(v_shost->host_lock);
2271 }
2272
2273 /* Set the bucket attributes */
2274 phba->bucket_type = bucket_type;
2275 phba->bucket_base = base;
2276 phba->bucket_step = step;
2277
2278 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
2279 v_shost = lpfc_shost_from_vport(vports[i]);
2280
2281 /* Unblock data collection */
2282 spin_lock_irq(v_shost->host_lock);
2283 vports[i]->stat_data_blocked = 0;
2284 spin_unlock_irq(v_shost->host_lock);
2285 }
2286 lpfc_destroy_vport_work_array(phba, vports);
2287 return strlen(buf);
2288 }
2289
2290 if (!strncmp(buf, "destroybucket", strlen("destroybucket"))) {
2291 vports = lpfc_create_vport_work_array(phba);
2292 if (vports == NULL)
2293 return -ENOMEM;
2294
2295 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
2296 v_shost = lpfc_shost_from_vport(vports[i]);
2297 spin_lock_irq(shost->host_lock);
2298 vports[i]->stat_data_blocked = 1;
2299 lpfc_free_bucket(vport);
2300 vport->stat_data_enabled = 0;
2301 vports[i]->stat_data_blocked = 0;
2302 spin_unlock_irq(shost->host_lock);
2303 }
2304 lpfc_destroy_vport_work_array(phba, vports);
2305 phba->bucket_type = LPFC_NO_BUCKET;
2306 phba->bucket_base = 0;
2307 phba->bucket_step = 0;
2308 return strlen(buf);
2309 }
2310
2311 if (!strncmp(buf, "start", strlen("start"))) {
2312 /* If no buckets configured return error */
2313 if (phba->bucket_type == LPFC_NO_BUCKET)
2314 return -EINVAL;
2315 spin_lock_irq(shost->host_lock);
2316 if (vport->stat_data_enabled) {
2317 spin_unlock_irq(shost->host_lock);
2318 return strlen(buf);
2319 }
2320 lpfc_alloc_bucket(vport);
2321 vport->stat_data_enabled = 1;
2322 spin_unlock_irq(shost->host_lock);
2323 return strlen(buf);
2324 }
2325
2326 if (!strncmp(buf, "stop", strlen("stop"))) {
2327 spin_lock_irq(shost->host_lock);
2328 if (vport->stat_data_enabled == 0) {
2329 spin_unlock_irq(shost->host_lock);
2330 return strlen(buf);
2331 }
2332 lpfc_free_bucket(vport);
2333 vport->stat_data_enabled = 0;
2334 spin_unlock_irq(shost->host_lock);
2335 return strlen(buf);
2336 }
2337
2338 if (!strncmp(buf, "reset", strlen("reset"))) {
2339 if ((phba->bucket_type == LPFC_NO_BUCKET)
2340 || !vport->stat_data_enabled)
2341 return strlen(buf);
2342 spin_lock_irq(shost->host_lock);
2343 vport->stat_data_blocked = 1;
2344 lpfc_vport_reset_stat_data(vport);
2345 vport->stat_data_blocked = 0;
2346 spin_unlock_irq(shost->host_lock);
2347 return strlen(buf);
2348 }
2349 return -EINVAL;
2350}
2351
2352
2353/**
2354 * lpfc_stat_data_ctrl_show: Read callback function for
2355 * lpfc_stat_data_ctrl sysfs file.
2356 * @dev: Pointer to class device object.
2357 * @buf: Data buffer.
2358 *
2359 * This function is the read call back function for
2360 * lpfc_stat_data_ctrl sysfs file. This function report the
2361 * current statistical data collection state.
2362 **/
2363static ssize_t
2364lpfc_stat_data_ctrl_show(struct device *dev, struct device_attribute *attr,
2365 char *buf)
2366{
2367 struct Scsi_Host *shost = class_to_shost(dev);
2368 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2369 struct lpfc_hba *phba = vport->phba;
2370 int index = 0;
2371 int i;
2372 char *bucket_type;
2373 unsigned long bucket_value;
2374
2375 switch (phba->bucket_type) {
2376 case LPFC_LINEAR_BUCKET:
2377 bucket_type = "linear";
2378 break;
2379 case LPFC_POWER2_BUCKET:
2380 bucket_type = "power2";
2381 break;
2382 default:
2383 bucket_type = "No Bucket";
2384 break;
2385 }
2386
2387 sprintf(&buf[index], "Statistical Data enabled :%d, "
2388 "blocked :%d, Bucket type :%s, Bucket base :%d,"
2389 " Bucket step :%d\nLatency Ranges :",
2390 vport->stat_data_enabled, vport->stat_data_blocked,
2391 bucket_type, phba->bucket_base, phba->bucket_step);
2392 index = strlen(buf);
2393 if (phba->bucket_type != LPFC_NO_BUCKET) {
2394 for (i = 0; i < LPFC_MAX_BUCKET_COUNT; i++) {
2395 if (phba->bucket_type == LPFC_LINEAR_BUCKET)
2396 bucket_value = phba->bucket_base +
2397 phba->bucket_step * i;
2398 else
2399 bucket_value = phba->bucket_base +
2400 (1 << i) * phba->bucket_step;
2401
2402 if (index + 10 > PAGE_SIZE)
2403 break;
2404 sprintf(&buf[index], "%08ld ", bucket_value);
2405 index = strlen(buf);
2406 }
2407 }
2408 sprintf(&buf[index], "\n");
2409 return strlen(buf);
2410}
2411
2412/*
2413 * Sysfs attribute to control the statistical data collection.
2414 */
2415static DEVICE_ATTR(lpfc_stat_data_ctrl, S_IRUGO | S_IWUSR,
2416 lpfc_stat_data_ctrl_show, lpfc_stat_data_ctrl_store);
2417
2418/*
2419 * lpfc_drvr_stat_data: sysfs attr to get driver statistical data.
2420 */
2421
2422/*
2423 * Each Bucket takes 11 characters and 1 new line + 17 bytes WWN
2424 * for each target.
2425 */
2426#define STAT_DATA_SIZE_PER_TARGET(NUM_BUCKETS) ((NUM_BUCKETS) * 11 + 18)
2427#define MAX_STAT_DATA_SIZE_PER_TARGET \
2428 STAT_DATA_SIZE_PER_TARGET(LPFC_MAX_BUCKET_COUNT)
2429
2430
2431/**
2432 * sysfs_drvr_stat_data_read: Read callback function for lpfc_drvr_stat_data
2433 * sysfs attribute.
2434 * @kobj: Pointer to the kernel object
2435 * @bin_attr: Attribute object
2436 * @buff: Buffer pointer
2437 * @off: File offset
2438 * @count: Buffer size
2439 *
2440 * This function is the read call back function for lpfc_drvr_stat_data
2441 * sysfs file. This function export the statistical data to user
2442 * applications.
2443 **/
2444static ssize_t
2445sysfs_drvr_stat_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
2446 char *buf, loff_t off, size_t count)
2447{
2448 struct device *dev = container_of(kobj, struct device,
2449 kobj);
2450 struct Scsi_Host *shost = class_to_shost(dev);
2451 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2452 struct lpfc_hba *phba = vport->phba;
2453 int i = 0, index = 0;
2454 unsigned long nport_index;
2455 struct lpfc_nodelist *ndlp = NULL;
2456 nport_index = (unsigned long)off /
2457 MAX_STAT_DATA_SIZE_PER_TARGET;
2458
2459 if (!vport->stat_data_enabled || vport->stat_data_blocked
2460 || (phba->bucket_type == LPFC_NO_BUCKET))
2461 return 0;
2462
2463 spin_lock_irq(shost->host_lock);
2464 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
2465 if (!NLP_CHK_NODE_ACT(ndlp) || !ndlp->lat_data)
2466 continue;
2467
2468 if (nport_index > 0) {
2469 nport_index--;
2470 continue;
2471 }
2472
2473 if ((index + MAX_STAT_DATA_SIZE_PER_TARGET)
2474 > count)
2475 break;
2476
2477 if (!ndlp->lat_data)
2478 continue;
2479
2480 /* Print the WWN */
2481 sprintf(&buf[index], "%02x%02x%02x%02x%02x%02x%02x%02x:",
2482 ndlp->nlp_portname.u.wwn[0],
2483 ndlp->nlp_portname.u.wwn[1],
2484 ndlp->nlp_portname.u.wwn[2],
2485 ndlp->nlp_portname.u.wwn[3],
2486 ndlp->nlp_portname.u.wwn[4],
2487 ndlp->nlp_portname.u.wwn[5],
2488 ndlp->nlp_portname.u.wwn[6],
2489 ndlp->nlp_portname.u.wwn[7]);
2490
2491 index = strlen(buf);
2492
2493 for (i = 0; i < LPFC_MAX_BUCKET_COUNT; i++) {
2494 sprintf(&buf[index], "%010u,",
2495 ndlp->lat_data[i].cmd_count);
2496 index = strlen(buf);
2497 }
2498 sprintf(&buf[index], "\n");
2499 index = strlen(buf);
2500 }
2501 spin_unlock_irq(shost->host_lock);
2502 return index;
2503}
2504
2505static struct bin_attribute sysfs_drvr_stat_data_attr = {
2506 .attr = {
2507 .name = "lpfc_drvr_stat_data",
2508 .mode = S_IRUSR,
2509 .owner = THIS_MODULE,
2510 },
2511 .size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET,
2512 .read = sysfs_drvr_stat_data_read,
2513 .write = NULL,
2514};
2515
2186/* 2516/*
2187# lpfc_link_speed: Link speed selection for initializing the Fibre Channel 2517# lpfc_link_speed: Link speed selection for initializing the Fibre Channel
2188# connection. 2518# connection.
@@ -2502,6 +2832,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
2502 &dev_attr_lpfc_enable_hba_heartbeat, 2832 &dev_attr_lpfc_enable_hba_heartbeat,
2503 &dev_attr_lpfc_sg_seg_cnt, 2833 &dev_attr_lpfc_sg_seg_cnt,
2504 &dev_attr_lpfc_max_scsicmpl_time, 2834 &dev_attr_lpfc_max_scsicmpl_time,
2835 &dev_attr_lpfc_stat_data_ctrl,
2505 NULL, 2836 NULL,
2506}; 2837};
2507 2838
@@ -2524,6 +2855,8 @@ struct device_attribute *lpfc_vport_attrs[] = {
2524 &dev_attr_nport_evt_cnt, 2855 &dev_attr_nport_evt_cnt,
2525 &dev_attr_npiv_info, 2856 &dev_attr_npiv_info,
2526 &dev_attr_lpfc_enable_da_id, 2857 &dev_attr_lpfc_enable_da_id,
2858 &dev_attr_lpfc_max_scsicmpl_time,
2859 &dev_attr_lpfc_stat_data_ctrl,
2527 NULL, 2860 NULL,
2528}; 2861};
2529 2862
@@ -2958,7 +3291,14 @@ lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
2958 if (error) 3291 if (error)
2959 goto out_remove_ctlreg_attr; 3292 goto out_remove_ctlreg_attr;
2960 3293
3294 error = sysfs_create_bin_file(&shost->shost_dev.kobj,
3295 &sysfs_drvr_stat_data_attr);
3296 if (error)
3297 goto out_remove_mbox_attr;
3298
2961 return 0; 3299 return 0;
3300out_remove_mbox_attr:
3301 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
2962out_remove_ctlreg_attr: 3302out_remove_ctlreg_attr:
2963 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); 3303 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
2964out: 3304out:
@@ -2973,7 +3313,8 @@ void
2973lpfc_free_sysfs_attr(struct lpfc_vport *vport) 3313lpfc_free_sysfs_attr(struct lpfc_vport *vport)
2974{ 3314{
2975 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 3315 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2976 3316 sysfs_remove_bin_file(&shost->shost_dev.kobj,
3317 &sysfs_drvr_stat_data_attr);
2977 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr); 3318 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
2978 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); 3319 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
2979} 3320}
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 7d173f4a37f5..044ef4057d28 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -294,6 +294,12 @@ void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
294void lpfc_ramp_up_queue_handler(struct lpfc_hba *); 294void lpfc_ramp_up_queue_handler(struct lpfc_hba *);
295void lpfc_scsi_dev_block(struct lpfc_hba *); 295void lpfc_scsi_dev_block(struct lpfc_hba *);
296 296
297void
298lpfc_send_els_failure_event(struct lpfc_hba *, struct lpfc_iocbq *,
299 struct lpfc_iocbq *);
300struct lpfc_fast_path_event *lpfc_alloc_fast_evt(struct lpfc_hba *);
301void lpfc_free_fast_evt(struct lpfc_hba *, struct lpfc_fast_path_event *);
302
297#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code) 303#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
298#define HBA_EVENT_RSCN 5 304#define HBA_EVENT_RSCN 5
299#define HBA_EVENT_LINK_UP 2 305#define HBA_EVENT_LINK_UP 2
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 71cfee884b8a..26dae8bae2d1 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -34,6 +34,7 @@
34 34
35#include "lpfc_hw.h" 35#include "lpfc_hw.h"
36#include "lpfc_sli.h" 36#include "lpfc_sli.h"
37#include "lpfc_nl.h"
37#include "lpfc_disc.h" 38#include "lpfc_disc.h"
38#include "lpfc_scsi.h" 39#include "lpfc_scsi.h"
39#include "lpfc.h" 40#include "lpfc.h"
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index f85b99a7c43d..771920bdde44 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -35,6 +35,7 @@
35 35
36#include "lpfc_hw.h" 36#include "lpfc_hw.h"
37#include "lpfc_sli.h" 37#include "lpfc_sli.h"
38#include "lpfc_nl.h"
38#include "lpfc_disc.h" 39#include "lpfc_disc.h"
39#include "lpfc_scsi.h" 40#include "lpfc_scsi.h"
40#include "lpfc.h" 41#include "lpfc.h"
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index ccf8f41f345e..f29e548a90d1 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -37,6 +37,7 @@ enum lpfc_work_type {
37 LPFC_EVT_KILL, 37 LPFC_EVT_KILL,
38 LPFC_EVT_ELS_RETRY, 38 LPFC_EVT_ELS_RETRY,
39 LPFC_EVT_DEV_LOSS, 39 LPFC_EVT_DEV_LOSS,
40 LPFC_EVT_FASTPATH_MGMT_EVT,
40}; 41};
41 42
42/* structure used to queue event to the discovery tasklet */ 43/* structure used to queue event to the discovery tasklet */
@@ -47,6 +48,24 @@ struct lpfc_work_evt {
47 enum lpfc_work_type evt; 48 enum lpfc_work_type evt;
48}; 49};
49 50
51struct lpfc_scsi_check_condition_event;
52struct lpfc_scsi_varqueuedepth_event;
53struct lpfc_scsi_event_header;
54struct lpfc_fabric_event_header;
55struct lpfc_fcprdchkerr_event;
56
57/* structure used for sending events from fast path */
58struct lpfc_fast_path_event {
59 struct lpfc_work_evt work_evt;
60 struct lpfc_vport *vport;
61 union {
62 struct lpfc_scsi_check_condition_event check_cond_evt;
63 struct lpfc_scsi_varqueuedepth_event queue_depth_evt;
64 struct lpfc_scsi_event_header scsi_evt;
65 struct lpfc_fabric_event_header fabric_evt;
66 struct lpfc_fcprdchkerr_event read_check_error;
67 } un;
68};
50 69
51struct lpfc_nodelist { 70struct lpfc_nodelist {
52 struct list_head nlp_listp; 71 struct list_head nlp_listp;
@@ -91,6 +110,7 @@ struct lpfc_nodelist {
91 atomic_t cmd_pending; 110 atomic_t cmd_pending;
92 uint32_t cmd_qdepth; 111 uint32_t cmd_qdepth;
93 unsigned long last_change_time; 112 unsigned long last_change_time;
113 struct lpfc_scsicmd_bkt *lat_data; /* Latency data */
94}; 114};
95 115
96/* Defines for nlp_flag (uint32) */ 116/* Defines for nlp_flag (uint32) */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index d0730e79c1a7..630bd28fb997 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -30,6 +30,7 @@
30 30
31#include "lpfc_hw.h" 31#include "lpfc_hw.h"
32#include "lpfc_sli.h" 32#include "lpfc_sli.h"
33#include "lpfc_nl.h"
33#include "lpfc_disc.h" 34#include "lpfc_disc.h"
34#include "lpfc_scsi.h" 35#include "lpfc_scsi.h"
35#include "lpfc.h" 36#include "lpfc.h"
@@ -5085,6 +5086,116 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
5085} 5086}
5086 5087
5087/** 5088/**
5089 * lpfc_send_els_failure_event: Posts an ELS command failure event.
5090 * @phba: Pointer to hba context object.
5091 * @cmdiocbp: Pointer to command iocb which reported error.
5092 * @rspiocbp: Pointer to response iocb which reported error.
5093 *
5094 * This function sends an event when there is an ELS command
5095 * failure.
5096 **/
5097void
5098lpfc_send_els_failure_event(struct lpfc_hba *phba,
5099 struct lpfc_iocbq *cmdiocbp,
5100 struct lpfc_iocbq *rspiocbp)
5101{
5102 struct lpfc_vport *vport = cmdiocbp->vport;
5103 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
5104 struct lpfc_lsrjt_event lsrjt_event;
5105 struct lpfc_fabric_event_header fabric_event;
5106 struct ls_rjt stat;
5107 struct lpfc_nodelist *ndlp;
5108 uint32_t *pcmd;
5109
5110 ndlp = cmdiocbp->context1;
5111 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
5112 return;
5113
5114 if (rspiocbp->iocb.ulpStatus == IOSTAT_LS_RJT) {
5115 lsrjt_event.header.event_type = FC_REG_ELS_EVENT;
5116 lsrjt_event.header.subcategory = LPFC_EVENT_LSRJT_RCV;
5117 memcpy(lsrjt_event.header.wwpn, &ndlp->nlp_portname,
5118 sizeof(struct lpfc_name));
5119 memcpy(lsrjt_event.header.wwnn, &ndlp->nlp_nodename,
5120 sizeof(struct lpfc_name));
5121 pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
5122 cmdiocbp->context2)->virt);
5123 lsrjt_event.command = *pcmd;
5124 stat.un.lsRjtError = be32_to_cpu(rspiocbp->iocb.un.ulpWord[4]);
5125 lsrjt_event.reason_code = stat.un.b.lsRjtRsnCode;
5126 lsrjt_event.explanation = stat.un.b.lsRjtRsnCodeExp;
5127 fc_host_post_vendor_event(shost,
5128 fc_get_event_number(),
5129 sizeof(lsrjt_event),
5130 (char *)&lsrjt_event,
5131 SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
5132 return;
5133 }
5134 if ((rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY) ||
5135 (rspiocbp->iocb.ulpStatus == IOSTAT_FABRIC_BSY)) {
5136 fabric_event.event_type = FC_REG_FABRIC_EVENT;
5137 if (rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY)
5138 fabric_event.subcategory = LPFC_EVENT_PORT_BUSY;
5139 else
5140 fabric_event.subcategory = LPFC_EVENT_FABRIC_BUSY;
5141 memcpy(fabric_event.wwpn, &ndlp->nlp_portname,
5142 sizeof(struct lpfc_name));
5143 memcpy(fabric_event.wwnn, &ndlp->nlp_nodename,
5144 sizeof(struct lpfc_name));
5145 fc_host_post_vendor_event(shost,
5146 fc_get_event_number(),
5147 sizeof(fabric_event),
5148 (char *)&fabric_event,
5149 SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
5150 return;
5151 }
5152
5153}
5154
5155/**
5156 * lpfc_send_els_event: Posts unsolicited els event.
5157 * @vport: Pointer to vport object.
5158 * @ndlp: Pointer FC node object.
5159 * @cmd: ELS command code.
5160 *
5161 * This function posts an event when there is an incoming
5162 * unsolicited ELS command.
5163 **/
5164static void
5165lpfc_send_els_event(struct lpfc_vport *vport,
5166 struct lpfc_nodelist *ndlp,
5167 uint32_t cmd)
5168{
5169 struct lpfc_els_event_header els_data;
5170 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
5171
5172 els_data.event_type = FC_REG_ELS_EVENT;
5173 switch (cmd) {
5174 case ELS_CMD_PLOGI:
5175 els_data.subcategory = LPFC_EVENT_PLOGI_RCV;
5176 break;
5177 case ELS_CMD_PRLO:
5178 els_data.subcategory = LPFC_EVENT_PRLO_RCV;
5179 break;
5180 case ELS_CMD_ADISC:
5181 els_data.subcategory = LPFC_EVENT_ADISC_RCV;
5182 break;
5183 default:
5184 return;
5185 }
5186 memcpy(els_data.wwpn, &ndlp->nlp_portname, sizeof(struct lpfc_name));
5187 memcpy(els_data.wwnn, &ndlp->nlp_nodename, sizeof(struct lpfc_name));
5188 fc_host_post_vendor_event(shost,
5189 fc_get_event_number(),
5190 sizeof(els_data),
5191 (char *)&els_data,
5192 SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
5193
5194 return;
5195}
5196
5197
5198/**
5088 * lpfc_els_unsol_buffer: Process an unsolicited event data buffer. 5199 * lpfc_els_unsol_buffer: Process an unsolicited event data buffer.
5089 * @phba: pointer to lpfc hba data structure. 5200 * @phba: pointer to lpfc hba data structure.
5090 * @pring: pointer to a SLI ring. 5201 * @pring: pointer to a SLI ring.
@@ -5185,6 +5296,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
5185 phba->fc_stat.elsRcvPLOGI++; 5296 phba->fc_stat.elsRcvPLOGI++;
5186 ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp); 5297 ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
5187 5298
5299 lpfc_send_els_event(vport, ndlp, cmd);
5188 if (vport->port_state < LPFC_DISC_AUTH) { 5300 if (vport->port_state < LPFC_DISC_AUTH) {
5189 if (!(phba->pport->fc_flag & FC_PT2PT) || 5301 if (!(phba->pport->fc_flag & FC_PT2PT) ||
5190 (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { 5302 (phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
@@ -5234,6 +5346,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
5234 did, vport->port_state, ndlp->nlp_flag); 5346 did, vport->port_state, ndlp->nlp_flag);
5235 5347
5236 phba->fc_stat.elsRcvPRLO++; 5348 phba->fc_stat.elsRcvPRLO++;
5349 lpfc_send_els_event(vport, ndlp, cmd);
5237 if (vport->port_state < LPFC_DISC_AUTH) { 5350 if (vport->port_state < LPFC_DISC_AUTH) {
5238 rjt_err = LSRJT_UNABLE_TPC; 5351 rjt_err = LSRJT_UNABLE_TPC;
5239 break; 5352 break;
@@ -5251,6 +5364,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
5251 "RCV ADISC: did:x%x/ste:x%x flg:x%x", 5364 "RCV ADISC: did:x%x/ste:x%x flg:x%x",
5252 did, vport->port_state, ndlp->nlp_flag); 5365 did, vport->port_state, ndlp->nlp_flag);
5253 5366
5367 lpfc_send_els_event(vport, ndlp, cmd);
5254 phba->fc_stat.elsRcvADISC++; 5368 phba->fc_stat.elsRcvADISC++;
5255 if (vport->port_state < LPFC_DISC_AUTH) { 5369 if (vport->port_state < LPFC_DISC_AUTH) {
5256 rjt_err = LSRJT_UNABLE_TPC; 5370 rjt_err = LSRJT_UNABLE_TPC;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 887a5283605f..a1a70d9ffc2a 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -30,6 +30,7 @@
30#include <scsi/scsi_transport_fc.h> 30#include <scsi/scsi_transport_fc.h>
31 31
32#include "lpfc_hw.h" 32#include "lpfc_hw.h"
33#include "lpfc_nl.h"
33#include "lpfc_disc.h" 34#include "lpfc_disc.h"
34#include "lpfc_sli.h" 35#include "lpfc_sli.h"
35#include "lpfc_scsi.h" 36#include "lpfc_scsi.h"
@@ -274,6 +275,124 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
274 lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); 275 lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
275} 276}
276 277
278/**
279 * lpfc_alloc_fast_evt: Allocates data structure for posting event.
280 * @phba: Pointer to hba context object.
281 *
282 * This function is called from the functions which need to post
283 * events from interrupt context. This function allocates data
284 * structure required for posting event. It also keeps track of
285 * number of events pending and prevent event storm when there are
286 * too many events.
287 **/
288struct lpfc_fast_path_event *
289lpfc_alloc_fast_evt(struct lpfc_hba *phba) {
290 struct lpfc_fast_path_event *ret;
291
292 /* If there are lot of fast event do not exhaust memory due to this */
293 if (atomic_read(&phba->fast_event_count) > LPFC_MAX_EVT_COUNT)
294 return NULL;
295
296 ret = kzalloc(sizeof(struct lpfc_fast_path_event),
297 GFP_ATOMIC);
298 if (ret)
299 atomic_inc(&phba->fast_event_count);
300 INIT_LIST_HEAD(&ret->work_evt.evt_listp);
301 ret->work_evt.evt = LPFC_EVT_FASTPATH_MGMT_EVT;
302 return ret;
303}
304
305/**
306 * lpfc_free_fast_evt: Frees event data structure.
307 * @phba: Pointer to hba context object.
308 * @evt: Event object which need to be freed.
309 *
310 * This function frees the data structure required for posting
311 * events.
312 **/
313void
314lpfc_free_fast_evt(struct lpfc_hba *phba,
315 struct lpfc_fast_path_event *evt) {
316
317 atomic_dec(&phba->fast_event_count);
318 kfree(evt);
319}
320
321/**
322 * lpfc_send_fastpath_evt: Posts events generated from fast path.
323 * @phba: Pointer to hba context object.
324 * @evtp: Event data structure.
325 *
326 * This function is called from worker thread, when the interrupt
327 * context need to post an event. This function posts the event
328 * to fc transport netlink interface.
329 **/
330static void
331lpfc_send_fastpath_evt(struct lpfc_hba *phba,
332 struct lpfc_work_evt *evtp)
333{
334 unsigned long evt_category, evt_sub_category;
335 struct lpfc_fast_path_event *fast_evt_data;
336 char *evt_data;
337 uint32_t evt_data_size;
338 struct Scsi_Host *shost;
339
340 fast_evt_data = container_of(evtp, struct lpfc_fast_path_event,
341 work_evt);
342
343 evt_category = (unsigned long) fast_evt_data->un.fabric_evt.event_type;
344 evt_sub_category = (unsigned long) fast_evt_data->un.
345 fabric_evt.subcategory;
346 shost = lpfc_shost_from_vport(fast_evt_data->vport);
347 if (evt_category == FC_REG_FABRIC_EVENT) {
348 if (evt_sub_category == LPFC_EVENT_FCPRDCHKERR) {
349 evt_data = (char *) &fast_evt_data->un.read_check_error;
350 evt_data_size = sizeof(fast_evt_data->un.
351 read_check_error);
352 } else if ((evt_sub_category == LPFC_EVENT_FABRIC_BUSY) ||
353 (evt_sub_category == IOSTAT_NPORT_BSY)) {
354 evt_data = (char *) &fast_evt_data->un.fabric_evt;
355 evt_data_size = sizeof(fast_evt_data->un.fabric_evt);
356 } else {
357 lpfc_free_fast_evt(phba, fast_evt_data);
358 return;
359 }
360 } else if (evt_category == FC_REG_SCSI_EVENT) {
361 switch (evt_sub_category) {
362 case LPFC_EVENT_QFULL:
363 case LPFC_EVENT_DEVBSY:
364 evt_data = (char *) &fast_evt_data->un.scsi_evt;
365 evt_data_size = sizeof(fast_evt_data->un.scsi_evt);
366 break;
367 case LPFC_EVENT_CHECK_COND:
368 evt_data = (char *) &fast_evt_data->un.check_cond_evt;
369 evt_data_size = sizeof(fast_evt_data->un.
370 check_cond_evt);
371 break;
372 case LPFC_EVENT_VARQUEDEPTH:
373 evt_data = (char *) &fast_evt_data->un.queue_depth_evt;
374 evt_data_size = sizeof(fast_evt_data->un.
375 queue_depth_evt);
376 break;
377 default:
378 lpfc_free_fast_evt(phba, fast_evt_data);
379 return;
380 }
381 } else {
382 lpfc_free_fast_evt(phba, fast_evt_data);
383 return;
384 }
385
386 fc_host_post_vendor_event(shost,
387 fc_get_event_number(),
388 evt_data_size,
389 evt_data,
390 SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
391
392 lpfc_free_fast_evt(phba, fast_evt_data);
393 return;
394}
395
277static void 396static void
278lpfc_work_list_done(struct lpfc_hba *phba) 397lpfc_work_list_done(struct lpfc_hba *phba)
279{ 398{
@@ -345,6 +464,10 @@ lpfc_work_list_done(struct lpfc_hba *phba)
345 lpfc_unblock_mgmt_io(phba); 464 lpfc_unblock_mgmt_io(phba);
346 complete((struct completion *)(evtp->evt_arg2)); 465 complete((struct completion *)(evtp->evt_arg2));
347 break; 466 break;
467 case LPFC_EVT_FASTPATH_MGMT_EVT:
468 lpfc_send_fastpath_evt(phba, evtp);
469 free_evt = 0;
470 break;
348 } 471 }
349 if (free_evt) 472 if (free_evt)
350 kfree(evtp); 473 kfree(evtp);
@@ -1601,6 +1724,22 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1601 */ 1724 */
1602 lpfc_register_remote_port(vport, ndlp); 1725 lpfc_register_remote_port(vport, ndlp);
1603 } 1726 }
1727 if ((new_state == NLP_STE_MAPPED_NODE) &&
1728 (vport->stat_data_enabled)) {
1729 /*
1730 * A new target is discovered, if there is no buffer for
1731 * statistical data collection allocate buffer.
1732 */
1733 ndlp->lat_data = kcalloc(LPFC_MAX_BUCKET_COUNT,
1734 sizeof(struct lpfc_scsicmd_bkt),
1735 GFP_KERNEL);
1736
1737 if (!ndlp->lat_data)
1738 lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
1739 "0286 lpfc_nlp_state_cleanup failed to "
1740 "allocate statistical data buffer DID "
1741 "0x%x\n", ndlp->nlp_DID);
1742 }
1604 /* 1743 /*
1605 * if we added to Mapped list, but the remote port 1744 * if we added to Mapped list, but the remote port
1606 * registration failed or assigned a target id outside 1745 * registration failed or assigned a target id outside
@@ -3029,8 +3168,10 @@ lpfc_nlp_release(struct kref *kref)
3029 spin_unlock_irqrestore(&phba->ndlp_lock, flags); 3168 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
3030 3169
3031 /* free ndlp memory for final ndlp release */ 3170 /* free ndlp memory for final ndlp release */
3032 if (NLP_CHK_FREE_REQ(ndlp)) 3171 if (NLP_CHK_FREE_REQ(ndlp)) {
3172 kfree(ndlp->lat_data);
3033 mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); 3173 mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
3174 }
3034} 3175}
3035 3176
3036/* This routine bumps the reference count for a ndlp structure to ensure 3177/* This routine bumps the reference count for a ndlp structure to ensure
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 49577d5f130f..909be3301bba 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -36,6 +36,7 @@
36 36
37#include "lpfc_hw.h" 37#include "lpfc_hw.h"
38#include "lpfc_sli.h" 38#include "lpfc_sli.h"
39#include "lpfc_nl.h"
39#include "lpfc_disc.h" 40#include "lpfc_disc.h"
40#include "lpfc_scsi.h" 41#include "lpfc_scsi.h"
41#include "lpfc.h" 42#include "lpfc.h"
@@ -815,6 +816,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
815 unsigned long temperature; 816 unsigned long temperature;
816 struct temp_event temp_event_data; 817 struct temp_event temp_event_data;
817 struct Scsi_Host *shost; 818 struct Scsi_Host *shost;
819 struct lpfc_board_event_header board_event;
818 820
819 /* If the pci channel is offline, ignore possible errors, 821 /* If the pci channel is offline, ignore possible errors,
820 * since we cannot communicate with the pci card anyway. */ 822 * since we cannot communicate with the pci card anyway. */
@@ -824,6 +826,16 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
824 if (!phba->cfg_enable_hba_reset) 826 if (!phba->cfg_enable_hba_reset)
825 return; 827 return;
826 828
829 /* Send an internal error event to mgmt application */
830 board_event.event_type = FC_REG_BOARD_EVENT;
831 board_event.subcategory = LPFC_EVENT_PORTINTERR;
832 shost = lpfc_shost_from_vport(phba->pport);
833 fc_host_post_vendor_event(shost, fc_get_event_number(),
834 sizeof(board_event),
835 (char *) &board_event,
836 SCSI_NL_VID_TYPE_PCI
837 | PCI_VENDOR_ID_EMULEX);
838
827 if (phba->work_hs & HS_FFER6) { 839 if (phba->work_hs & HS_FFER6) {
828 /* Re-establishing Link */ 840 /* Re-establishing Link */
829 lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, 841 lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
@@ -2345,6 +2357,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
2345 int i, hbq_count; 2357 int i, hbq_count;
2346 uint16_t iotag; 2358 uint16_t iotag;
2347 int bars = pci_select_bars(pdev, IORESOURCE_MEM); 2359 int bars = pci_select_bars(pdev, IORESOURCE_MEM);
2360 struct lpfc_adapter_event_header adapter_event;
2348 2361
2349 if (pci_enable_device_mem(pdev)) 2362 if (pci_enable_device_mem(pdev))
2350 goto out; 2363 goto out;
@@ -2355,6 +2368,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
2355 if (!phba) 2368 if (!phba)
2356 goto out_release_regions; 2369 goto out_release_regions;
2357 2370
2371 atomic_set(&phba->fast_event_count, 0);
2358 spin_lock_init(&phba->hbalock); 2372 spin_lock_init(&phba->hbalock);
2359 2373
2360 /* Initialize ndlp management spinlock */ 2374 /* Initialize ndlp management spinlock */
@@ -2626,6 +2640,14 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
2626 2640
2627 lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 2641 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2628 "0428 Perform SCSI scan\n"); 2642 "0428 Perform SCSI scan\n");
2643 /* Send board arrival event to upper layer */
2644 adapter_event.event_type = FC_REG_ADAPTER_EVENT;
2645 adapter_event.subcategory = LPFC_EVENT_ARRIVAL;
2646 fc_host_post_vendor_event(shost, fc_get_event_number(),
2647 sizeof(adapter_event),
2648 (char *) &adapter_event,
2649 SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
2650
2629 scsi_scan_host(shost); 2651 scsi_scan_host(shost);
2630 2652
2631 return 0; 2653 return 0;
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 65bc8e1a5f7d..7465fe746fe9 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -30,6 +30,7 @@
30 30
31#include "lpfc_hw.h" 31#include "lpfc_hw.h"
32#include "lpfc_sli.h" 32#include "lpfc_sli.h"
33#include "lpfc_nl.h"
33#include "lpfc_disc.h" 34#include "lpfc_disc.h"
34#include "lpfc_scsi.h" 35#include "lpfc_scsi.h"
35#include "lpfc.h" 36#include "lpfc.h"
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 50d9136a6e04..a4bba2069248 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -30,6 +30,7 @@
30 30
31#include "lpfc_hw.h" 31#include "lpfc_hw.h"
32#include "lpfc_sli.h" 32#include "lpfc_sli.h"
33#include "lpfc_nl.h"
33#include "lpfc_disc.h" 34#include "lpfc_disc.h"
34#include "lpfc_scsi.h" 35#include "lpfc_scsi.h"
35#include "lpfc.h" 36#include "lpfc.h"
diff --git a/drivers/scsi/lpfc/lpfc_nl.h b/drivers/scsi/lpfc/lpfc_nl.h
new file mode 100644
index 000000000000..1accb5a9f4e6
--- /dev/null
+++ b/drivers/scsi/lpfc/lpfc_nl.h
@@ -0,0 +1,163 @@
1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2008 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com *
7 * *
8 * This program is free software; you can redistribute it and/or *
9 * modify it under the terms of version 2 of the GNU General *
10 * Public License as published by the Free Software Foundation. *
11 * This program is distributed in the hope that it will be useful. *
12 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
13 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
14 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
15 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
16 * TO BE LEGALLY INVALID. See the GNU General Public License for *
17 * more details, a copy of which can be found in the file COPYING *
18 * included with this package. *
19 *******************************************************************/
20
21/* Event definitions for RegisterForEvent */
22#define FC_REG_LINK_EVENT 0x0001 /* link up / down events */
23#define FC_REG_RSCN_EVENT 0x0002 /* RSCN events */
24#define FC_REG_CT_EVENT 0x0004 /* CT request events */
25#define FC_REG_DUMP_EVENT 0x0008 /* Dump events */
26#define FC_REG_TEMPERATURE_EVENT 0x0010 /* temperature events */
27#define FC_REG_ELS_EVENT 0x0020 /* lpfc els events */
28#define FC_REG_FABRIC_EVENT 0x0040 /* lpfc fabric events */
29#define FC_REG_SCSI_EVENT 0x0080 /* lpfc scsi events */
30#define FC_REG_BOARD_EVENT 0x0100 /* lpfc board events */
31#define FC_REG_ADAPTER_EVENT 0x0200 /* lpfc adapter events */
32#define FC_REG_EVENT_MASK (FC_REG_LINK_EVENT | \
33 FC_REG_RSCN_EVENT | \
34 FC_REG_CT_EVENT | \
35 FC_REG_DUMP_EVENT | \
36 FC_REG_TEMPERATURE_EVENT | \
37 FC_REG_ELS_EVENT | \
38 FC_REG_FABRIC_EVENT | \
39 FC_REG_SCSI_EVENT | \
40 FC_REG_BOARD_EVENT | \
41 FC_REG_ADAPTER_EVENT)
42/* Temperature events */
43#define LPFC_CRIT_TEMP 0x1
44#define LPFC_THRESHOLD_TEMP 0x2
45#define LPFC_NORMAL_TEMP 0x3
46/*
47 * All net link event payloads will begin with and event type
48 * and subcategory. The event type must come first.
49 * The subcategory further defines the data that follows in the rest
50 * of the payload. Each category will have its own unique header plus
51 * any addtional data unique to the subcategory.
52 * The payload sent via the fc transport is one-way driver->application.
53 */
54
55/* els event header */
56struct lpfc_els_event_header {
57 uint32_t event_type;
58 uint32_t subcategory;
59 uint8_t wwpn[8];
60 uint8_t wwnn[8];
61};
62
63/* subcategory codes for FC_REG_ELS_EVENT */
64#define LPFC_EVENT_PLOGI_RCV 0x01
65#define LPFC_EVENT_PRLO_RCV 0x02
66#define LPFC_EVENT_ADISC_RCV 0x04
67#define LPFC_EVENT_LSRJT_RCV 0x08
68
69/* special els lsrjt event */
70struct lpfc_lsrjt_event {
71 struct lpfc_els_event_header header;
72 uint32_t command;
73 uint32_t reason_code;
74 uint32_t explanation;
75};
76
77
78/* fabric event header */
79struct lpfc_fabric_event_header {
80 uint32_t event_type;
81 uint32_t subcategory;
82 uint8_t wwpn[8];
83 uint8_t wwnn[8];
84};
85
86/* subcategory codes for FC_REG_FABRIC_EVENT */
87#define LPFC_EVENT_FABRIC_BUSY 0x01
88#define LPFC_EVENT_PORT_BUSY 0x02
89#define LPFC_EVENT_FCPRDCHKERR 0x04
90
91/* special case fabric fcprdchkerr event */
92struct lpfc_fcprdchkerr_event {
93 struct lpfc_fabric_event_header header;
94 uint32_t lun;
95 uint32_t opcode;
96 uint32_t fcpiparam;
97};
98
99
100/* scsi event header */
101struct lpfc_scsi_event_header {
102 uint32_t event_type;
103 uint32_t subcategory;
104 uint32_t lun;
105 uint8_t wwpn[8];
106 uint8_t wwnn[8];
107};
108
109/* subcategory codes for FC_REG_SCSI_EVENT */
110#define LPFC_EVENT_QFULL 0x0001
111#define LPFC_EVENT_DEVBSY 0x0002
112#define LPFC_EVENT_CHECK_COND 0x0004
113#define LPFC_EVENT_LUNRESET 0x0008
114#define LPFC_EVENT_TGTRESET 0x0010
115#define LPFC_EVENT_BUSRESET 0x0020
116#define LPFC_EVENT_VARQUEDEPTH 0x0040
117
118/* special case scsi varqueuedepth event */
119struct lpfc_scsi_varqueuedepth_event {
120 struct lpfc_scsi_event_header scsi_event;
121 uint32_t oldval;
122 uint32_t newval;
123};
124
125/* special case scsi check condition event */
126struct lpfc_scsi_check_condition_event {
127 struct lpfc_scsi_event_header scsi_event;
128 uint8_t sense_key;
129 uint8_t asc;
130 uint8_t ascq;
131};
132
133/* event codes for FC_REG_BOARD_EVENT */
134#define LPFC_EVENT_PORTINTERR 0x01
135
136/* board event header */
137struct lpfc_board_event_header {
138 uint32_t event_type;
139 uint32_t subcategory;
140};
141
142
143/* event codes for FC_REG_ADAPTER_EVENT */
144#define LPFC_EVENT_ARRIVAL 0x01
145
146/* adapter event header */
147struct lpfc_adapter_event_header {
148 uint32_t event_type;
149 uint32_t subcategory;
150};
151
152
153/* event codes for temp_event */
154#define LPFC_CRIT_TEMP 0x1
155#define LPFC_THRESHOLD_TEMP 0x2
156#define LPFC_NORMAL_TEMP 0x3
157
158struct temp_event {
159 uint32_t event_type;
160 uint32_t event_code;
161 uint32_t data;
162};
163
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 83ffa75378e5..0c25d97acb42 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -30,6 +30,7 @@
30 30
31#include "lpfc_hw.h" 31#include "lpfc_hw.h"
32#include "lpfc_sli.h" 32#include "lpfc_sli.h"
33#include "lpfc_nl.h"
33#include "lpfc_disc.h" 34#include "lpfc_disc.h"
34#include "lpfc_scsi.h" 35#include "lpfc_scsi.h"
35#include "lpfc.h" 36#include "lpfc.h"
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 7b17f52660b4..bd1867411821 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -32,6 +32,7 @@
32#include "lpfc_version.h" 32#include "lpfc_version.h"
33#include "lpfc_hw.h" 33#include "lpfc_hw.h"
34#include "lpfc_sli.h" 34#include "lpfc_sli.h"
35#include "lpfc_nl.h"
35#include "lpfc_disc.h" 36#include "lpfc_disc.h"
36#include "lpfc_scsi.h" 37#include "lpfc_scsi.h"
37#include "lpfc.h" 38#include "lpfc.h"
@@ -42,6 +43,111 @@
42#define LPFC_RESET_WAIT 2 43#define LPFC_RESET_WAIT 2
43#define LPFC_ABORT_WAIT 2 44#define LPFC_ABORT_WAIT 2
44 45
46/**
47 * lpfc_update_stats: Update statistical data for the command completion.
48 * @phba: Pointer to HBA object.
49 * @lpfc_cmd: lpfc scsi command object pointer.
50 *
51 * This function is called when there is a command completion and this
52 * function updates the statistical data for the command completion.
53 **/
54static void
55lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
56{
57 struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
58 struct lpfc_nodelist *pnode = rdata->pnode;
59 struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
60 unsigned long flags;
61 struct Scsi_Host *shost = cmd->device->host;
62 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
63 unsigned long latency;
64 int i;
65
66 if (cmd->result)
67 return;
68
69 spin_lock_irqsave(shost->host_lock, flags);
70 if (!vport->stat_data_enabled ||
71 vport->stat_data_blocked ||
72 !pnode->lat_data ||
73 (phba->bucket_type == LPFC_NO_BUCKET)) {
74 spin_unlock_irqrestore(shost->host_lock, flags);
75 return;
76 }
77 latency = jiffies_to_msecs(jiffies - lpfc_cmd->start_time);
78
79 if (phba->bucket_type == LPFC_LINEAR_BUCKET) {
80 i = (latency + phba->bucket_step - 1 - phba->bucket_base)/
81 phba->bucket_step;
82 if (i >= LPFC_MAX_BUCKET_COUNT)
83 i = LPFC_MAX_BUCKET_COUNT;
84 } else {
85 for (i = 0; i < LPFC_MAX_BUCKET_COUNT-1; i++)
86 if (latency <= (phba->bucket_base +
87 ((1<<i)*phba->bucket_step)))
88 break;
89 }
90
91 pnode->lat_data[i].cmd_count++;
92 spin_unlock_irqrestore(shost->host_lock, flags);
93}
94
95
96/**
97 * lpfc_send_sdev_queuedepth_change_event: Posts a queuedepth change
98 * event.
99 * @phba: Pointer to HBA context object.
100 * @vport: Pointer to vport object.
101 * @ndlp: Pointer to FC node associated with the target.
102 * @lun: Lun number of the scsi device.
103 * @old_val: Old value of the queue depth.
104 * @new_val: New value of the queue depth.
105 *
106 * This function sends an event to the mgmt application indicating
107 * there is a change in the scsi device queue depth.
108 **/
109static void
110lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba,
111 struct lpfc_vport *vport,
112 struct lpfc_nodelist *ndlp,
113 uint32_t lun,
114 uint32_t old_val,
115 uint32_t new_val)
116{
117 struct lpfc_fast_path_event *fast_path_evt;
118 unsigned long flags;
119
120 fast_path_evt = lpfc_alloc_fast_evt(phba);
121 if (!fast_path_evt)
122 return;
123
124 fast_path_evt->un.queue_depth_evt.scsi_event.event_type =
125 FC_REG_SCSI_EVENT;
126 fast_path_evt->un.queue_depth_evt.scsi_event.subcategory =
127 LPFC_EVENT_VARQUEDEPTH;
128
129 /* Report all luns with change in queue depth */
130 fast_path_evt->un.queue_depth_evt.scsi_event.lun = lun;
131 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
132 memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwpn,
133 &ndlp->nlp_portname, sizeof(struct lpfc_name));
134 memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwnn,
135 &ndlp->nlp_nodename, sizeof(struct lpfc_name));
136 }
137
138 fast_path_evt->un.queue_depth_evt.oldval = old_val;
139 fast_path_evt->un.queue_depth_evt.newval = new_val;
140 fast_path_evt->vport = vport;
141
142 fast_path_evt->work_evt.evt = LPFC_EVT_FASTPATH_MGMT_EVT;
143 spin_lock_irqsave(&phba->hbalock, flags);
144 list_add_tail(&fast_path_evt->work_evt.evt_listp, &phba->work_list);
145 spin_unlock_irqrestore(&phba->hbalock, flags);
146 lpfc_worker_wake_up(phba);
147
148 return;
149}
150
45/* 151/*
46 * This function is called with no lock held when there is a resource 152 * This function is called with no lock held when there is a resource
47 * error in driver or in firmware. 153 * error in driver or in firmware.
@@ -117,9 +223,10 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
117 struct lpfc_vport **vports; 223 struct lpfc_vport **vports;
118 struct Scsi_Host *shost; 224 struct Scsi_Host *shost;
119 struct scsi_device *sdev; 225 struct scsi_device *sdev;
120 unsigned long new_queue_depth; 226 unsigned long new_queue_depth, old_queue_depth;
121 unsigned long num_rsrc_err, num_cmd_success; 227 unsigned long num_rsrc_err, num_cmd_success;
122 int i; 228 int i;
229 struct lpfc_rport_data *rdata;
123 230
124 num_rsrc_err = atomic_read(&phba->num_rsrc_err); 231 num_rsrc_err = atomic_read(&phba->num_rsrc_err);
125 num_cmd_success = atomic_read(&phba->num_cmd_success); 232 num_cmd_success = atomic_read(&phba->num_cmd_success);
@@ -137,6 +244,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
137 else 244 else
138 new_queue_depth = sdev->queue_depth - 245 new_queue_depth = sdev->queue_depth -
139 new_queue_depth; 246 new_queue_depth;
247 old_queue_depth = sdev->queue_depth;
140 if (sdev->ordered_tags) 248 if (sdev->ordered_tags)
141 scsi_adjust_queue_depth(sdev, 249 scsi_adjust_queue_depth(sdev,
142 MSG_ORDERED_TAG, 250 MSG_ORDERED_TAG,
@@ -145,6 +253,13 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
145 scsi_adjust_queue_depth(sdev, 253 scsi_adjust_queue_depth(sdev,
146 MSG_SIMPLE_TAG, 254 MSG_SIMPLE_TAG,
147 new_queue_depth); 255 new_queue_depth);
256 rdata = sdev->hostdata;
257 if (rdata)
258 lpfc_send_sdev_queuedepth_change_event(
259 phba, vports[i],
260 rdata->pnode,
261 sdev->lun, old_queue_depth,
262 new_queue_depth);
148 } 263 }
149 } 264 }
150 lpfc_destroy_vport_work_array(phba, vports); 265 lpfc_destroy_vport_work_array(phba, vports);
@@ -159,6 +274,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
159 struct Scsi_Host *shost; 274 struct Scsi_Host *shost;
160 struct scsi_device *sdev; 275 struct scsi_device *sdev;
161 int i; 276 int i;
277 struct lpfc_rport_data *rdata;
162 278
163 vports = lpfc_create_vport_work_array(phba); 279 vports = lpfc_create_vport_work_array(phba);
164 if (vports != NULL) 280 if (vports != NULL)
@@ -176,6 +292,14 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
176 scsi_adjust_queue_depth(sdev, 292 scsi_adjust_queue_depth(sdev,
177 MSG_SIMPLE_TAG, 293 MSG_SIMPLE_TAG,
178 sdev->queue_depth+1); 294 sdev->queue_depth+1);
295 rdata = sdev->hostdata;
296 if (rdata)
297 lpfc_send_sdev_queuedepth_change_event(
298 phba, vports[i],
299 rdata->pnode,
300 sdev->lun,
301 sdev->queue_depth - 1,
302 sdev->queue_depth);
179 } 303 }
180 } 304 }
181 lpfc_destroy_vport_work_array(phba, vports); 305 lpfc_destroy_vport_work_array(phba, vports);
@@ -466,6 +590,97 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
466 return 0; 590 return 0;
467} 591}
468 592
593/**
594 * lpfc_send_scsi_error_event: Posts an event when there is SCSI error.
595 * @phba: Pointer to hba context object.
596 * @vport: Pointer to vport object.
597 * @lpfc_cmd: Pointer to lpfc scsi command which reported the error.
598 * @rsp_iocb: Pointer to response iocb object which reported error.
599 *
600 * This function posts an event when there is a SCSI command reporting
601 * error from the scsi device.
602 **/
603static void
604lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport,
605 struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb) {
606 struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
607 struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
608 uint32_t resp_info = fcprsp->rspStatus2;
609 uint32_t scsi_status = fcprsp->rspStatus3;
610 uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
611 struct lpfc_fast_path_event *fast_path_evt = NULL;
612 struct lpfc_nodelist *pnode = lpfc_cmd->rdata->pnode;
613 unsigned long flags;
614
615 /* If there is queuefull or busy condition send a scsi event */
616 if ((cmnd->result == SAM_STAT_TASK_SET_FULL) ||
617 (cmnd->result == SAM_STAT_BUSY)) {
618 fast_path_evt = lpfc_alloc_fast_evt(phba);
619 if (!fast_path_evt)
620 return;
621 fast_path_evt->un.scsi_evt.event_type =
622 FC_REG_SCSI_EVENT;
623 fast_path_evt->un.scsi_evt.subcategory =
624 (cmnd->result == SAM_STAT_TASK_SET_FULL) ?
625 LPFC_EVENT_QFULL : LPFC_EVENT_DEVBSY;
626 fast_path_evt->un.scsi_evt.lun = cmnd->device->lun;
627 memcpy(&fast_path_evt->un.scsi_evt.wwpn,
628 &pnode->nlp_portname, sizeof(struct lpfc_name));
629 memcpy(&fast_path_evt->un.scsi_evt.wwnn,
630 &pnode->nlp_nodename, sizeof(struct lpfc_name));
631 } else if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen &&
632 ((cmnd->cmnd[0] == READ_10) || (cmnd->cmnd[0] == WRITE_10))) {
633 fast_path_evt = lpfc_alloc_fast_evt(phba);
634 if (!fast_path_evt)
635 return;
636 fast_path_evt->un.check_cond_evt.scsi_event.event_type =
637 FC_REG_SCSI_EVENT;
638 fast_path_evt->un.check_cond_evt.scsi_event.subcategory =
639 LPFC_EVENT_CHECK_COND;
640 fast_path_evt->un.check_cond_evt.scsi_event.lun =
641 cmnd->device->lun;
642 memcpy(&fast_path_evt->un.check_cond_evt.scsi_event.wwpn,
643 &pnode->nlp_portname, sizeof(struct lpfc_name));
644 memcpy(&fast_path_evt->un.check_cond_evt.scsi_event.wwnn,
645 &pnode->nlp_nodename, sizeof(struct lpfc_name));
646 fast_path_evt->un.check_cond_evt.sense_key =
647 cmnd->sense_buffer[2] & 0xf;
648 fast_path_evt->un.check_cond_evt.asc = cmnd->sense_buffer[12];
649 fast_path_evt->un.check_cond_evt.ascq = cmnd->sense_buffer[13];
650 } else if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
651 fcpi_parm &&
652 ((be32_to_cpu(fcprsp->rspResId) != fcpi_parm) ||
653 ((scsi_status == SAM_STAT_GOOD) &&
654 !(resp_info & (RESID_UNDER | RESID_OVER))))) {
655 /*
656 * If status is good or resid does not match with fcp_param and
657 * there is valid fcpi_parm, then there is a read_check error
658 */
659 fast_path_evt = lpfc_alloc_fast_evt(phba);
660 if (!fast_path_evt)
661 return;
662 fast_path_evt->un.read_check_error.header.event_type =
663 FC_REG_FABRIC_EVENT;
664 fast_path_evt->un.read_check_error.header.subcategory =
665 LPFC_EVENT_FCPRDCHKERR;
666 memcpy(&fast_path_evt->un.read_check_error.header.wwpn,
667 &pnode->nlp_portname, sizeof(struct lpfc_name));
668 memcpy(&fast_path_evt->un.read_check_error.header.wwnn,
669 &pnode->nlp_nodename, sizeof(struct lpfc_name));
670 fast_path_evt->un.read_check_error.lun = cmnd->device->lun;
671 fast_path_evt->un.read_check_error.opcode = cmnd->cmnd[0];
672 fast_path_evt->un.read_check_error.fcpiparam =
673 fcpi_parm;
674 } else
675 return;
676
677 fast_path_evt->vport = vport;
678 spin_lock_irqsave(&phba->hbalock, flags);
679 list_add_tail(&fast_path_evt->work_evt.evt_listp, &phba->work_list);
680 spin_unlock_irqrestore(&phba->hbalock, flags);
681 lpfc_worker_wake_up(phba);
682 return;
683}
469static void 684static void
470lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) 685lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
471{ 686{
@@ -494,6 +709,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
494 uint32_t rsplen = 0; 709 uint32_t rsplen = 0;
495 uint32_t logit = LOG_FCP | LOG_FCP_ERROR; 710 uint32_t logit = LOG_FCP | LOG_FCP_ERROR;
496 711
712
497 /* 713 /*
498 * If this is a task management command, there is no 714 * If this is a task management command, there is no
499 * scsi packet associated with this lpfc_cmd. The driver 715 * scsi packet associated with this lpfc_cmd. The driver
@@ -609,6 +825,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
609 825
610 out: 826 out:
611 cmnd->result = ScsiResult(host_status, scsi_status); 827 cmnd->result = ScsiResult(host_status, scsi_status);
828 lpfc_send_scsi_error_event(vport->phba, vport, lpfc_cmd, rsp_iocb);
612} 829}
613 830
614static void 831static void
@@ -625,6 +842,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
625 struct scsi_device *sdev, *tmp_sdev; 842 struct scsi_device *sdev, *tmp_sdev;
626 int depth = 0; 843 int depth = 0;
627 unsigned long flags; 844 unsigned long flags;
845 struct lpfc_fast_path_event *fast_path_evt;
628 846
629 lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; 847 lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
630 lpfc_cmd->status = pIocbOut->iocb.ulpStatus; 848 lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
@@ -655,6 +873,30 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
655 case IOSTAT_NPORT_BSY: 873 case IOSTAT_NPORT_BSY:
656 case IOSTAT_FABRIC_BSY: 874 case IOSTAT_FABRIC_BSY:
657 cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0); 875 cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0);
876 fast_path_evt = lpfc_alloc_fast_evt(phba);
877 if (!fast_path_evt)
878 break;
879 fast_path_evt->un.fabric_evt.event_type =
880 FC_REG_FABRIC_EVENT;
881 fast_path_evt->un.fabric_evt.subcategory =
882 (lpfc_cmd->status == IOSTAT_NPORT_BSY) ?
883 LPFC_EVENT_PORT_BUSY : LPFC_EVENT_FABRIC_BUSY;
884 if (pnode && NLP_CHK_NODE_ACT(pnode)) {
885 memcpy(&fast_path_evt->un.fabric_evt.wwpn,
886 &pnode->nlp_portname,
887 sizeof(struct lpfc_name));
888 memcpy(&fast_path_evt->un.fabric_evt.wwnn,
889 &pnode->nlp_nodename,
890 sizeof(struct lpfc_name));
891 }
892 fast_path_evt->vport = vport;
893 fast_path_evt->work_evt.evt =
894 LPFC_EVT_FASTPATH_MGMT_EVT;
895 spin_lock_irqsave(&phba->hbalock, flags);
896 list_add_tail(&fast_path_evt->work_evt.evt_listp,
897 &phba->work_list);
898 spin_unlock_irqrestore(&phba->hbalock, flags);
899 lpfc_worker_wake_up(phba);
658 break; 900 break;
659 case IOSTAT_LOCAL_REJECT: 901 case IOSTAT_LOCAL_REJECT:
660 if (lpfc_cmd->result == IOERR_INVALID_RPI || 902 if (lpfc_cmd->result == IOERR_INVALID_RPI ||
@@ -687,6 +929,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
687 scsi_get_resid(cmd)); 929 scsi_get_resid(cmd));
688 } 930 }
689 931
932 lpfc_update_stats(phba, lpfc_cmd);
690 result = cmd->result; 933 result = cmd->result;
691 sdev = cmd->device; 934 sdev = cmd->device;
692 if (vport->cfg_max_scsicmpl_time && 935 if (vport->cfg_max_scsicmpl_time &&
@@ -755,6 +998,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
755 pnode->last_ramp_up_time = jiffies; 998 pnode->last_ramp_up_time = jiffies;
756 } 999 }
757 } 1000 }
1001 lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode,
1002 0xFFFFFFFF,
1003 sdev->queue_depth - 1, sdev->queue_depth);
758 } 1004 }
759 1005
760 /* 1006 /*
@@ -784,6 +1030,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
784 lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, 1030 lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
785 "0711 detected queue full - lun queue " 1031 "0711 detected queue full - lun queue "
786 "depth adjusted to %d.\n", depth); 1032 "depth adjusted to %d.\n", depth);
1033 lpfc_send_sdev_queuedepth_change_event(phba, vport,
1034 pnode, 0xFFFFFFFF,
1035 depth+1, depth);
787 } 1036 }
788 } 1037 }
789 1038
@@ -1112,6 +1361,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
1112 goto out_host_busy; 1361 goto out_host_busy;
1113 } 1362 }
1114 1363
1364 lpfc_cmd->start_time = jiffies;
1115 /* 1365 /*
1116 * Store the midlayer's command structure for the completion phase 1366 * Store the midlayer's command structure for the completion phase
1117 * and complete the command initialization. 1367 * and complete the command initialization.
@@ -1280,6 +1530,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
1280 int ret = SUCCESS; 1530 int ret = SUCCESS;
1281 int status; 1531 int status;
1282 int cnt; 1532 int cnt;
1533 struct lpfc_scsi_event_header scsi_event;
1283 1534
1284 lpfc_block_error_handler(cmnd); 1535 lpfc_block_error_handler(cmnd);
1285 /* 1536 /*
@@ -1298,6 +1549,19 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
1298 break; 1549 break;
1299 pnode = rdata->pnode; 1550 pnode = rdata->pnode;
1300 } 1551 }
1552
1553 scsi_event.event_type = FC_REG_SCSI_EVENT;
1554 scsi_event.subcategory = LPFC_EVENT_TGTRESET;
1555 scsi_event.lun = 0;
1556 memcpy(scsi_event.wwpn, &pnode->nlp_portname, sizeof(struct lpfc_name));
1557 memcpy(scsi_event.wwnn, &pnode->nlp_nodename, sizeof(struct lpfc_name));
1558
1559 fc_host_post_vendor_event(shost,
1560 fc_get_event_number(),
1561 sizeof(scsi_event),
1562 (char *)&scsi_event,
1563 SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
1564
1301 if (!rdata || pnode->nlp_state != NLP_STE_MAPPED_NODE) { 1565 if (!rdata || pnode->nlp_state != NLP_STE_MAPPED_NODE) {
1302 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, 1566 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
1303 "0721 LUN Reset rport " 1567 "0721 LUN Reset rport "
@@ -1381,6 +1645,19 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
1381 int cnt; 1645 int cnt;
1382 struct lpfc_scsi_buf * lpfc_cmd; 1646 struct lpfc_scsi_buf * lpfc_cmd;
1383 unsigned long later; 1647 unsigned long later;
1648 struct lpfc_scsi_event_header scsi_event;
1649
1650 scsi_event.event_type = FC_REG_SCSI_EVENT;
1651 scsi_event.subcategory = LPFC_EVENT_BUSRESET;
1652 scsi_event.lun = 0;
1653 memcpy(scsi_event.wwpn, &vport->fc_portname, sizeof(struct lpfc_name));
1654 memcpy(scsi_event.wwnn, &vport->fc_nodename, sizeof(struct lpfc_name));
1655
1656 fc_host_post_vendor_event(shost,
1657 fc_get_event_number(),
1658 sizeof(scsi_event),
1659 (char *)&scsi_event,
1660 SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
1384 1661
1385 lpfc_block_error_handler(cmnd); 1662 lpfc_block_error_handler(cmnd);
1386 /* 1663 /*
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index 6737cabe9a72..437f182e2322 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -107,6 +107,10 @@ struct fcp_cmnd {
107 107
108}; 108};
109 109
110struct lpfc_scsicmd_bkt {
111 uint32_t cmd_count;
112};
113
110struct lpfc_scsi_buf { 114struct lpfc_scsi_buf {
111 struct list_head list; 115 struct list_head list;
112 struct scsi_cmnd *pCmd; 116 struct scsi_cmnd *pCmd;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 2cca39e9b93d..8ab5babdeebc 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -32,6 +32,7 @@
32 32
33#include "lpfc_hw.h" 33#include "lpfc_hw.h"
34#include "lpfc_sli.h" 34#include "lpfc_sli.h"
35#include "lpfc_nl.h"
35#include "lpfc_disc.h" 36#include "lpfc_disc.h"
36#include "lpfc_scsi.h" 37#include "lpfc_scsi.h"
37#include "lpfc.h" 38#include "lpfc.h"
@@ -1611,6 +1612,17 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1611 if (cmdiocbp) { 1612 if (cmdiocbp) {
1612 if (cmdiocbp->iocb_cmpl) { 1613 if (cmdiocbp->iocb_cmpl) {
1613 /* 1614 /*
1615 * If an ELS command failed send an event to mgmt
1616 * application.
1617 */
1618 if (saveq->iocb.ulpStatus &&
1619 (pring->ringno == LPFC_ELS_RING) &&
1620 (cmdiocbp->iocb.ulpCommand ==
1621 CMD_ELS_REQUEST64_CR))
1622 lpfc_send_els_failure_event(phba,
1623 cmdiocbp, saveq);
1624
1625 /*
1614 * Post all ELS completions to the worker thread. 1626 * Post all ELS completions to the worker thread.
1615 * All other are passed to the completion callback. 1627 * All other are passed to the completion callback.
1616 */ 1628 */
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 2578d5fd9537..a7de1cc02b40 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -34,6 +34,7 @@
34#include <scsi/scsi_transport_fc.h> 34#include <scsi/scsi_transport_fc.h>
35#include "lpfc_hw.h" 35#include "lpfc_hw.h"
36#include "lpfc_sli.h" 36#include "lpfc_sli.h"
37#include "lpfc_nl.h"
37#include "lpfc_disc.h" 38#include "lpfc_disc.h"
38#include "lpfc_scsi.h" 39#include "lpfc_scsi.h"
39#include "lpfc.h" 40#include "lpfc.h"
@@ -745,3 +746,82 @@ lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports)
745 scsi_host_put(lpfc_shost_from_vport(vports[i])); 746 scsi_host_put(lpfc_shost_from_vport(vports[i]));
746 kfree(vports); 747 kfree(vports);
747} 748}
749
750
751/**
752 * lpfc_vport_reset_stat_data: Reset the statistical data for the vport.
753 * @vport: Pointer to vport object.
754 *
755 * This function resets the statistical data for the vport. This function
756 * is called with the host_lock held
757 **/
758void
759lpfc_vport_reset_stat_data(struct lpfc_vport *vport)
760{
761 struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
762
763 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
764 if (!NLP_CHK_NODE_ACT(ndlp))
765 continue;
766 if (ndlp->lat_data)
767 memset(ndlp->lat_data, 0, LPFC_MAX_BUCKET_COUNT *
768 sizeof(struct lpfc_scsicmd_bkt));
769 }
770}
771
772
773/**
774 * lpfc_alloc_bucket: Allocate data buffer required for collecting
775 * statistical data.
776 * @vport: Pointer to vport object.
777 *
778 * This function allocates data buffer required for all the FC
779 * nodes of the vport to collect statistical data.
780 **/
781void
782lpfc_alloc_bucket(struct lpfc_vport *vport)
783{
784 struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
785
786 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
787 if (!NLP_CHK_NODE_ACT(ndlp))
788 continue;
789
790 kfree(ndlp->lat_data);
791 ndlp->lat_data = NULL;
792
793 if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) {
794 ndlp->lat_data = kcalloc(LPFC_MAX_BUCKET_COUNT,
795 sizeof(struct lpfc_scsicmd_bkt),
796 GFP_ATOMIC);
797
798 if (!ndlp->lat_data)
799 lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
800 "0287 lpfc_alloc_bucket failed to "
801 "allocate statistical data buffer DID "
802 "0x%x\n", ndlp->nlp_DID);
803 }
804 }
805}
806
807/**
808 * lpfc_free_bucket: Free data buffer required for collecting
809 * statistical data.
810 * @vport: Pointer to vport object.
811 *
812 * Th function frees statistical data buffer of all the FC
813 * nodes of the vport.
814 **/
815void
816lpfc_free_bucket(struct lpfc_vport *vport)
817{
818 struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
819
820 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
821 if (!NLP_CHK_NODE_ACT(ndlp))
822 continue;
823
824 kfree(ndlp->lat_data);
825 ndlp->lat_data = NULL;
826 }
827}
diff --git a/drivers/scsi/lpfc/lpfc_vport.h b/drivers/scsi/lpfc/lpfc_vport.h
index 96c445333b69..90828340acea 100644
--- a/drivers/scsi/lpfc/lpfc_vport.h
+++ b/drivers/scsi/lpfc/lpfc_vport.h
@@ -112,4 +112,8 @@ struct vport_cmd_tag {
112void lpfc_vport_set_state(struct lpfc_vport *vport, 112void lpfc_vport_set_state(struct lpfc_vport *vport,
113 enum fc_vport_state new_state); 113 enum fc_vport_state new_state);
114 114
115void lpfc_vport_reset_stat_data(struct lpfc_vport *);
116void lpfc_alloc_bucket(struct lpfc_vport *);
117void lpfc_free_bucket(struct lpfc_vport *);
118
115#endif /* H_LPFC_VPORT */ 119#endif /* H_LPFC_VPORT */