@@ -823,6 +823,135 @@ qla83xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb)
823823 }
824824}
825825
826+ /**
827+ * qla27xx_copy_multiple_pkt() - Copy over purex/purls packets that can
828+ * span over multiple IOCBs.
829+ * @vha: SCSI driver HA context
830+ * @pkt: ELS packet
831+ * @rsp: Response queue
832+ * @is_purls: True, for Unsolicited Received FC-NVMe LS rsp IOCB
833+ * false, for Unsolicited Received ELS IOCB
834+ * @byte_order: True, to change the byte ordering of iocb payload
835+ */
836+ struct purex_item *
837+ qla27xx_copy_multiple_pkt (struct scsi_qla_host * vha , void * * pkt ,
838+ struct rsp_que * * rsp , bool is_purls ,
839+ bool byte_order )
840+ {
841+ struct purex_entry_24xx * purex = NULL ;
842+ struct pt_ls4_rx_unsol * purls = NULL ;
843+ struct rsp_que * rsp_q = * rsp ;
844+ sts_cont_entry_t * new_pkt ;
845+ uint16_t no_bytes = 0 , total_bytes = 0 , pending_bytes = 0 ;
846+ uint16_t buffer_copy_offset = 0 , payload_size = 0 ;
847+ uint16_t entry_count , entry_count_remaining ;
848+ struct purex_item * item ;
849+ void * iocb_pkt = NULL ;
850+
851+ if (is_purls ) {
852+ purls = * pkt ;
853+ total_bytes = (le16_to_cpu (purls -> frame_size ) & 0x0FFF ) -
854+ PURX_ELS_HEADER_SIZE ;
855+ entry_count = entry_count_remaining = purls -> entry_count ;
856+ payload_size = sizeof (purls -> payload );
857+ } else {
858+ purex = * pkt ;
859+ total_bytes = (le16_to_cpu (purex -> frame_size ) & 0x0FFF ) -
860+ PURX_ELS_HEADER_SIZE ;
861+ entry_count = entry_count_remaining = purex -> entry_count ;
862+ payload_size = sizeof (purex -> els_frame_payload );
863+ }
864+
865+ pending_bytes = total_bytes ;
866+ no_bytes = (pending_bytes > payload_size ) ? payload_size :
867+ pending_bytes ;
868+ ql_dbg (ql_dbg_async , vha , 0x509a ,
869+ "%s LS, frame_size 0x%x, entry count %d\n" ,
870+ (is_purls ? "PURLS" : "FPIN" ), total_bytes , entry_count );
871+
872+ item = qla24xx_alloc_purex_item (vha , total_bytes );
873+ if (!item )
874+ return item ;
875+
876+ iocb_pkt = & item -> iocb ;
877+
878+ if (is_purls )
879+ memcpy (iocb_pkt , & purls -> payload [0 ], no_bytes );
880+ else
881+ memcpy (iocb_pkt , & purex -> els_frame_payload [0 ], no_bytes );
882+ buffer_copy_offset += no_bytes ;
883+ pending_bytes -= no_bytes ;
884+ -- entry_count_remaining ;
885+
886+ if (is_purls )
887+ ((response_t * )purls )-> signature = RESPONSE_PROCESSED ;
888+ else
889+ ((response_t * )purex )-> signature = RESPONSE_PROCESSED ;
890+ wmb ();
891+
892+ do {
893+ while ((total_bytes > 0 ) && (entry_count_remaining > 0 )) {
894+ if (rsp_q -> ring_ptr -> signature == RESPONSE_PROCESSED ) {
895+ ql_dbg (ql_dbg_async , vha , 0x5084 ,
896+ "Ran out of IOCBs, partial data 0x%x\n" ,
897+ buffer_copy_offset );
898+ cpu_relax ();
899+ continue ;
900+ }
901+
902+ new_pkt = (sts_cont_entry_t * )rsp_q -> ring_ptr ;
903+ * pkt = new_pkt ;
904+
905+ if (new_pkt -> entry_type != STATUS_CONT_TYPE ) {
906+ ql_log (ql_log_warn , vha , 0x507a ,
907+ "Unexpected IOCB type, partial data 0x%x\n" ,
908+ buffer_copy_offset );
909+ break ;
910+ }
911+
912+ rsp_q -> ring_index ++ ;
913+ if (rsp_q -> ring_index == rsp_q -> length ) {
914+ rsp_q -> ring_index = 0 ;
915+ rsp_q -> ring_ptr = rsp_q -> ring ;
916+ } else {
917+ rsp_q -> ring_ptr ++ ;
918+ }
919+ no_bytes = (pending_bytes > sizeof (new_pkt -> data )) ?
920+ sizeof (new_pkt -> data ) : pending_bytes ;
921+ if ((buffer_copy_offset + no_bytes ) <= total_bytes ) {
922+ memcpy (((uint8_t * )iocb_pkt + buffer_copy_offset ),
923+ new_pkt -> data , no_bytes );
924+ buffer_copy_offset += no_bytes ;
925+ pending_bytes -= no_bytes ;
926+ -- entry_count_remaining ;
927+ } else {
928+ ql_log (ql_log_warn , vha , 0x5044 ,
929+ "Attempt to copy more that we got, optimizing..%x\n" ,
930+ buffer_copy_offset );
931+ memcpy (((uint8_t * )iocb_pkt + buffer_copy_offset ),
932+ new_pkt -> data ,
933+ total_bytes - buffer_copy_offset );
934+ }
935+
936+ ((response_t * )new_pkt )-> signature = RESPONSE_PROCESSED ;
937+ wmb ();
938+ }
939+
940+ if (pending_bytes != 0 || entry_count_remaining != 0 ) {
941+ ql_log (ql_log_fatal , vha , 0x508b ,
942+ "Dropping partial FPIN, underrun bytes = 0x%x, entry cnts 0x%x\n" ,
943+ total_bytes , entry_count_remaining );
944+ qla24xx_free_purex_item (item );
945+ return NULL ;
946+ }
947+ } while (entry_count_remaining > 0 );
948+
949+ if (byte_order )
950+ host_to_fcp_swap ((uint8_t * )& item -> iocb , total_bytes );
951+
952+ return item ;
953+ }
954+
826955int
827956qla2x00_is_a_vp_did (scsi_qla_host_t * vha , uint32_t rscn_entry )
828957{
@@ -958,7 +1087,7 @@ qla24xx_alloc_purex_item(scsi_qla_host_t *vha, uint16_t size)
9581087 return item ;
9591088}
9601089
961- static void
1090+ void
9621091qla24xx_queue_purex_item (scsi_qla_host_t * vha , struct purex_item * pkt ,
9631092 void (* process_item )(struct scsi_qla_host * vha ,
9641093 struct purex_item * pkt ))
@@ -3811,6 +3940,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
38113940 struct qla_hw_data * ha = vha -> hw ;
38123941 struct purex_entry_24xx * purex_entry ;
38133942 struct purex_item * pure_item ;
3943+ struct pt_ls4_rx_unsol * p ;
38143944 u16 rsp_in = 0 , cur_ring_index ;
38153945 int is_shadow_hba ;
38163946
@@ -3983,7 +4113,19 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
39834113 qla28xx_sa_update_iocb_entry (vha , rsp -> req ,
39844114 (struct sa_update_28xx * )pkt );
39854115 break ;
3986-
4116+ case PT_LS4_UNSOL :
4117+ p = (void * )pkt ;
4118+ if (qla_chk_cont_iocb_avail (vha , rsp , (response_t * )pkt , rsp_in )) {
4119+ rsp -> ring_ptr = (response_t * )pkt ;
4120+ rsp -> ring_index = cur_ring_index ;
4121+
4122+ ql_dbg (ql_dbg_init , vha , 0x2124 ,
4123+ "Defer processing UNSOL LS req opcode %#x...\n" ,
4124+ p -> payload [0 ]);
4125+ return ;
4126+ }
4127+ qla2xxx_process_purls_iocb ((void * * )& pkt , & rsp );
4128+ break ;
39874129 default :
39884130 /* Type Not Supported. */
39894131 ql_dbg (ql_dbg_async , vha , 0x5042 ,
0 commit comments