@@ -2282,6 +2282,10 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
22822282 }
22832283 }
22842284
2285+ /* Process any deferred work. */
2286+ if (!list_empty (& ha -> work_list ))
2287+ start_dpc ++ ;
2288+
22852289 /* Wakeup the dpc routine for this adapter, if needed. */
22862290 if (start_dpc ||
22872291 test_bit (DPC_RESET_HA , & ha -> dpc_flags ) ||
@@ -2847,6 +2851,81 @@ void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
28472851 queue_work (ha -> dpc_thread , & ha -> dpc_work );
28482852}
28492853
2854+ static struct qla4_work_evt *
2855+ qla4xxx_alloc_work (struct scsi_qla_host * ha , uint32_t data_size ,
2856+ enum qla4_work_type type )
2857+ {
2858+ struct qla4_work_evt * e ;
2859+ uint32_t size = sizeof (struct qla4_work_evt ) + data_size ;
2860+
2861+ e = kzalloc (size , GFP_ATOMIC );
2862+ if (!e )
2863+ return NULL ;
2864+
2865+ INIT_LIST_HEAD (& e -> list );
2866+ e -> type = type ;
2867+ return e ;
2868+ }
2869+
2870+ static void qla4xxx_post_work (struct scsi_qla_host * ha ,
2871+ struct qla4_work_evt * e )
2872+ {
2873+ unsigned long flags ;
2874+
2875+ spin_lock_irqsave (& ha -> work_lock , flags );
2876+ list_add_tail (& e -> list , & ha -> work_list );
2877+ spin_unlock_irqrestore (& ha -> work_lock , flags );
2878+ qla4xxx_wake_dpc (ha );
2879+ }
2880+
2881+ int qla4xxx_post_aen_work (struct scsi_qla_host * ha ,
2882+ enum iscsi_host_event_code aen_code ,
2883+ uint32_t data_size , uint8_t * data )
2884+ {
2885+ struct qla4_work_evt * e ;
2886+
2887+ e = qla4xxx_alloc_work (ha , data_size , QLA4_EVENT_AEN );
2888+ if (!e )
2889+ return QLA_ERROR ;
2890+
2891+ e -> u .aen .code = aen_code ;
2892+ e -> u .aen .data_size = data_size ;
2893+ memcpy (e -> u .aen .data , data , data_size );
2894+
2895+ qla4xxx_post_work (ha , e );
2896+
2897+ return QLA_SUCCESS ;
2898+ }
2899+
2900+ void qla4xxx_do_work (struct scsi_qla_host * ha )
2901+ {
2902+ struct qla4_work_evt * e , * tmp ;
2903+ unsigned long flags ;
2904+ LIST_HEAD (work );
2905+
2906+ spin_lock_irqsave (& ha -> work_lock , flags );
2907+ list_splice_init (& ha -> work_list , & work );
2908+ spin_unlock_irqrestore (& ha -> work_lock , flags );
2909+
2910+ list_for_each_entry_safe (e , tmp , & work , list ) {
2911+ list_del_init (& e -> list );
2912+
2913+ switch (e -> type ) {
2914+ case QLA4_EVENT_AEN :
2915+ iscsi_post_host_event (ha -> host_no ,
2916+ & qla4xxx_iscsi_transport ,
2917+ e -> u .aen .code ,
2918+ e -> u .aen .data_size ,
2919+ e -> u .aen .data );
2920+ break ;
2921+ default :
2922+ ql4_printk (KERN_WARNING , ha , "event type: 0x%x not "
2923+ "supported" , e -> type );
2924+ }
2925+ kfree (e );
2926+ }
2927+ }
2928+
28502929/**
28512930 * qla4xxx_do_dpc - dpc routine
28522931 * @data: in our case pointer to adapter structure
@@ -2878,6 +2957,9 @@ static void qla4xxx_do_dpc(struct work_struct *work)
28782957 return ;
28792958 }
28802959
2960+ /* post events to application */
2961+ qla4xxx_do_work (ha );
2962+
28812963 if (is_qla8022 (ha )) {
28822964 if (test_bit (DPC_HA_UNRECOVERABLE , & ha -> dpc_flags )) {
28832965 qla4_8xxx_idc_lock (ha );
@@ -4450,6 +4532,9 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
44504532
44514533 spin_lock_init (& ha -> hardware_lock );
44524534
4535+ /* Initialize work list */
4536+ INIT_LIST_HEAD (& ha -> work_list );
4537+
44534538 /* Allocate dma buffers */
44544539 if (qla4xxx_mem_alloc (ha )) {
44554540 ql4_printk (KERN_WARNING , ha ,
0 commit comments