@@ -1473,7 +1473,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
1473
1473
struct ipr_hostrcb * hostrcb = ipr_cmd -> u .hostrcb ;
1474
1474
u32 ioasc = be32_to_cpu (ipr_cmd -> s .ioasa .hdr .ioasc );
1475
1475
1476
- list_del (& hostrcb -> queue );
1476
+ list_del_init (& hostrcb -> queue );
1477
1477
list_add_tail (& ipr_cmd -> queue , & ipr_cmd -> hrrq -> hrrq_free_q );
1478
1478
1479
1479
if (ioasc ) {
@@ -2552,6 +2552,23 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
2552
2552
}
2553
2553
}
2554
2554
2555
+ static struct ipr_hostrcb * ipr_get_free_hostrcb (struct ipr_ioa_cfg * ioa )
2556
+ {
2557
+ struct ipr_hostrcb * hostrcb ;
2558
+
2559
+ hostrcb = list_first_entry_or_null (& ioa -> hostrcb_free_q ,
2560
+ struct ipr_hostrcb , queue );
2561
+
2562
+ if (unlikely (!hostrcb )) {
2563
+ dev_info (& ioa -> pdev -> dev , "Reclaiming async error buffers." );
2564
+ hostrcb = list_first_entry_or_null (& ioa -> hostrcb_report_q ,
2565
+ struct ipr_hostrcb , queue );
2566
+ }
2567
+
2568
+ list_del_init (& hostrcb -> queue );
2569
+ return hostrcb ;
2570
+ }
2571
+
2555
2572
/**
2556
2573
* ipr_process_error - Op done function for an adapter error log.
2557
2574
* @ipr_cmd: ipr command struct
@@ -2569,13 +2586,14 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
2569
2586
struct ipr_hostrcb * hostrcb = ipr_cmd -> u .hostrcb ;
2570
2587
u32 ioasc = be32_to_cpu (ipr_cmd -> s .ioasa .hdr .ioasc );
2571
2588
u32 fd_ioasc ;
2589
+ char * envp [] = { "ASYNC_ERR_LOG=1" , NULL };
2572
2590
2573
2591
if (ioa_cfg -> sis64 )
2574
2592
fd_ioasc = be32_to_cpu (hostrcb -> hcam .u .error64 .fd_ioasc );
2575
2593
else
2576
2594
fd_ioasc = be32_to_cpu (hostrcb -> hcam .u .error .fd_ioasc );
2577
2595
2578
- list_del (& hostrcb -> queue );
2596
+ list_del_init (& hostrcb -> queue );
2579
2597
list_add_tail (& ipr_cmd -> queue , & ipr_cmd -> hrrq -> hrrq_free_q );
2580
2598
2581
2599
if (!ioasc ) {
@@ -2588,6 +2606,10 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
2588
2606
"Host RCB failed with IOASC: 0x%08X\n" , ioasc );
2589
2607
}
2590
2608
2609
+ list_add_tail (& hostrcb -> queue , & ioa_cfg -> hostrcb_report_q );
2610
+ hostrcb = ipr_get_free_hostrcb (ioa_cfg );
2611
+ kobject_uevent_env (& ioa_cfg -> host -> shost_dev .kobj , KOBJ_CHANGE , envp );
2612
+
2591
2613
ipr_send_hcam (ioa_cfg , IPR_HCAM_CDB_OP_CODE_LOG_DATA , hostrcb );
2592
2614
}
2593
2615
@@ -4095,6 +4117,64 @@ static struct device_attribute ipr_ioa_fw_type_attr = {
4095
4117
.show = ipr_show_fw_type
4096
4118
};
4097
4119
4120
+ static ssize_t ipr_read_async_err_log (struct file * filep , struct kobject * kobj ,
4121
+ struct bin_attribute * bin_attr , char * buf ,
4122
+ loff_t off , size_t count )
4123
+ {
4124
+ struct device * cdev = container_of (kobj , struct device , kobj );
4125
+ struct Scsi_Host * shost = class_to_shost (cdev );
4126
+ struct ipr_ioa_cfg * ioa_cfg = (struct ipr_ioa_cfg * )shost -> hostdata ;
4127
+ struct ipr_hostrcb * hostrcb ;
4128
+ unsigned long lock_flags = 0 ;
4129
+ int ret ;
4130
+
4131
+ spin_lock_irqsave (ioa_cfg -> host -> host_lock , lock_flags );
4132
+ hostrcb = list_first_entry_or_null (& ioa_cfg -> hostrcb_report_q ,
4133
+ struct ipr_hostrcb , queue );
4134
+ if (!hostrcb ) {
4135
+ spin_unlock_irqrestore (ioa_cfg -> host -> host_lock , lock_flags );
4136
+ return 0 ;
4137
+ }
4138
+ ret = memory_read_from_buffer (buf , count , & off , & hostrcb -> hcam ,
4139
+ sizeof (hostrcb -> hcam ));
4140
+ spin_unlock_irqrestore (ioa_cfg -> host -> host_lock , lock_flags );
4141
+ return ret ;
4142
+ }
4143
+
4144
+ static ssize_t ipr_next_async_err_log (struct file * filep , struct kobject * kobj ,
4145
+ struct bin_attribute * bin_attr , char * buf ,
4146
+ loff_t off , size_t count )
4147
+ {
4148
+ struct device * cdev = container_of (kobj , struct device , kobj );
4149
+ struct Scsi_Host * shost = class_to_shost (cdev );
4150
+ struct ipr_ioa_cfg * ioa_cfg = (struct ipr_ioa_cfg * )shost -> hostdata ;
4151
+ struct ipr_hostrcb * hostrcb ;
4152
+ unsigned long lock_flags = 0 ;
4153
+
4154
+ spin_lock_irqsave (ioa_cfg -> host -> host_lock , lock_flags );
4155
+ hostrcb = list_first_entry_or_null (& ioa_cfg -> hostrcb_report_q ,
4156
+ struct ipr_hostrcb , queue );
4157
+ if (!hostrcb ) {
4158
+ spin_unlock_irqrestore (ioa_cfg -> host -> host_lock , lock_flags );
4159
+ return count ;
4160
+ }
4161
+
4162
+ /* Reclaim hostrcb before exit */
4163
+ list_move_tail (& hostrcb -> queue , & ioa_cfg -> hostrcb_free_q );
4164
+ spin_unlock_irqrestore (ioa_cfg -> host -> host_lock , lock_flags );
4165
+ return count ;
4166
+ }
4167
+
4168
+ static struct bin_attribute ipr_ioa_async_err_log = {
4169
+ .attr = {
4170
+ .name = "async_err_log" ,
4171
+ .mode = S_IRUGO | S_IWUSR ,
4172
+ },
4173
+ .size = 0 ,
4174
+ .read = ipr_read_async_err_log ,
4175
+ .write = ipr_next_async_err_log
4176
+ };
4177
+
4098
4178
static struct device_attribute * ipr_ioa_attrs [] = {
4099
4179
& ipr_fw_version_attr ,
4100
4180
& ipr_log_level_attr ,
@@ -7026,8 +7106,7 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd)
7026
7106
{
7027
7107
struct ipr_ioa_cfg * ioa_cfg = ipr_cmd -> ioa_cfg ;
7028
7108
struct ipr_resource_entry * res ;
7029
- struct ipr_hostrcb * hostrcb , * temp ;
7030
- int i = 0 , j ;
7109
+ int j ;
7031
7110
7032
7111
ENTER ;
7033
7112
ioa_cfg -> in_reset_reload = 0 ;
@@ -7048,12 +7127,16 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd)
7048
7127
}
7049
7128
schedule_work (& ioa_cfg -> work_q );
7050
7129
7051
- list_for_each_entry_safe (hostrcb , temp , & ioa_cfg -> hostrcb_free_q , queue ) {
7052
- list_del (& hostrcb -> queue );
7053
- if (i ++ < IPR_NUM_LOG_HCAMS )
7054
- ipr_send_hcam (ioa_cfg , IPR_HCAM_CDB_OP_CODE_LOG_DATA , hostrcb );
7130
+ for (j = 0 ; j < IPR_NUM_HCAMS ; j ++ ) {
7131
+ list_del_init (& ioa_cfg -> hostrcb [j ]-> queue );
7132
+ if (j < IPR_NUM_LOG_HCAMS )
7133
+ ipr_send_hcam (ioa_cfg ,
7134
+ IPR_HCAM_CDB_OP_CODE_LOG_DATA ,
7135
+ ioa_cfg -> hostrcb [j ]);
7055
7136
else
7056
- ipr_send_hcam (ioa_cfg , IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE , hostrcb );
7137
+ ipr_send_hcam (ioa_cfg ,
7138
+ IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE ,
7139
+ ioa_cfg -> hostrcb [j ]);
7057
7140
}
7058
7141
7059
7142
scsi_report_bus_reset (ioa_cfg -> host , IPR_VSET_BUS );
@@ -8335,7 +8418,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
8335
8418
8336
8419
hostrcb = list_entry (ioa_cfg -> hostrcb_free_q .next ,
8337
8420
struct ipr_hostrcb , queue );
8338
- list_del (& hostrcb -> queue );
8421
+ list_del_init (& hostrcb -> queue );
8339
8422
memset (& hostrcb -> hcam , 0 , sizeof (hostrcb -> hcam ));
8340
8423
8341
8424
rc = ipr_get_ldump_data_section (ioa_cfg ,
@@ -9332,7 +9415,7 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
9332
9415
dma_free_coherent (& ioa_cfg -> pdev -> dev , ioa_cfg -> cfg_table_size ,
9333
9416
ioa_cfg -> u .cfg_table , ioa_cfg -> cfg_table_dma );
9334
9417
9335
- for (i = 0 ; i < IPR_NUM_HCAMS ; i ++ ) {
9418
+ for (i = 0 ; i < IPR_MAX_HCAMS ; i ++ ) {
9336
9419
dma_free_coherent (& ioa_cfg -> pdev -> dev ,
9337
9420
sizeof (struct ipr_hostrcb ),
9338
9421
ioa_cfg -> hostrcb [i ],
@@ -9572,7 +9655,7 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
9572
9655
if (!ioa_cfg -> u .cfg_table )
9573
9656
goto out_free_host_rrq ;
9574
9657
9575
- for (i = 0 ; i < IPR_NUM_HCAMS ; i ++ ) {
9658
+ for (i = 0 ; i < IPR_MAX_HCAMS ; i ++ ) {
9576
9659
ioa_cfg -> hostrcb [i ] = dma_alloc_coherent (& pdev -> dev ,
9577
9660
sizeof (struct ipr_hostrcb ),
9578
9661
& ioa_cfg -> hostrcb_dma [i ],
@@ -9714,6 +9797,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
9714
9797
9715
9798
INIT_LIST_HEAD (& ioa_cfg -> hostrcb_free_q );
9716
9799
INIT_LIST_HEAD (& ioa_cfg -> hostrcb_pending_q );
9800
+ INIT_LIST_HEAD (& ioa_cfg -> hostrcb_report_q );
9717
9801
INIT_LIST_HEAD (& ioa_cfg -> free_res_q );
9718
9802
INIT_LIST_HEAD (& ioa_cfg -> used_res_q );
9719
9803
INIT_WORK (& ioa_cfg -> work_q , ipr_worker_thread );
@@ -10352,6 +10436,8 @@ static void ipr_remove(struct pci_dev *pdev)
10352
10436
& ipr_trace_attr );
10353
10437
ipr_remove_dump_file (& ioa_cfg -> host -> shost_dev .kobj ,
10354
10438
& ipr_dump_attr );
10439
+ sysfs_remove_bin_file (& ioa_cfg -> host -> shost_dev .kobj ,
10440
+ & ipr_ioa_async_err_log );
10355
10441
scsi_remove_host (ioa_cfg -> host );
10356
10442
10357
10443
__ipr_remove (pdev );
@@ -10400,10 +10486,25 @@ static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
10400
10486
return rc ;
10401
10487
}
10402
10488
10489
+ rc = sysfs_create_bin_file (& ioa_cfg -> host -> shost_dev .kobj ,
10490
+ & ipr_ioa_async_err_log );
10491
+
10492
+ if (rc ) {
10493
+ ipr_remove_dump_file (& ioa_cfg -> host -> shost_dev .kobj ,
10494
+ & ipr_dump_attr );
10495
+ ipr_remove_trace_file (& ioa_cfg -> host -> shost_dev .kobj ,
10496
+ & ipr_trace_attr );
10497
+ scsi_remove_host (ioa_cfg -> host );
10498
+ __ipr_remove (pdev );
10499
+ return rc ;
10500
+ }
10501
+
10403
10502
rc = ipr_create_dump_file (& ioa_cfg -> host -> shost_dev .kobj ,
10404
10503
& ipr_dump_attr );
10405
10504
10406
10505
if (rc ) {
10506
+ sysfs_remove_bin_file (& ioa_cfg -> host -> shost_dev .kobj ,
10507
+ & ipr_ioa_async_err_log );
10407
10508
ipr_remove_trace_file (& ioa_cfg -> host -> shost_dev .kobj ,
10408
10509
& ipr_trace_attr );
10409
10510
scsi_remove_host (ioa_cfg -> host );
0 commit comments