@@ -79,9 +79,64 @@ void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc)
7979 sbitmap_queue_clear (& wq -> sbq , desc -> id , cpu );
8080}
8181
82+ static struct idxd_desc * list_abort_desc (struct idxd_wq * wq , struct idxd_irq_entry * ie ,
83+ struct idxd_desc * desc )
84+ {
85+ struct idxd_desc * d , * n ;
86+
87+ lockdep_assert_held (& ie -> list_lock );
88+ list_for_each_entry_safe (d , n , & ie -> work_list , list ) {
89+ if (d == desc ) {
90+ list_del (& d -> list );
91+ return d ;
92+ }
93+ }
94+
95+ /*
96+ * At this point, the desc needs to be aborted is held by the completion
97+ * handler where it has taken it off the pending list but has not added to the
98+ * work list. It will be cleaned up by the interrupt handler when it sees the
99+ * IDXD_COMP_DESC_ABORT for completion status.
100+ */
101+ return NULL ;
102+ }
103+
104+ static void llist_abort_desc (struct idxd_wq * wq , struct idxd_irq_entry * ie ,
105+ struct idxd_desc * desc )
106+ {
107+ struct idxd_desc * d , * t , * found = NULL ;
108+ struct llist_node * head ;
109+ unsigned long flags ;
110+
111+ desc -> completion -> status = IDXD_COMP_DESC_ABORT ;
112+ /*
113+ * Grab the list lock so it will block the irq thread handler. This allows the
114+ * abort code to locate the descriptor need to be aborted.
115+ */
116+ spin_lock_irqsave (& ie -> list_lock , flags );
117+ head = llist_del_all (& ie -> pending_llist );
118+ if (head ) {
119+ llist_for_each_entry_safe (d , t , head , llnode ) {
120+ if (d == desc ) {
121+ found = desc ;
122+ continue ;
123+ }
124+ list_add_tail (& desc -> list , & ie -> work_list );
125+ }
126+ }
127+
128+ if (!found )
129+ found = list_abort_desc (wq , ie , desc );
130+ spin_unlock_irqrestore (& ie -> list_lock , flags );
131+
132+ if (found )
133+ complete_desc (found , IDXD_COMPLETE_ABORT );
134+ }
135+
82136int idxd_submit_desc (struct idxd_wq * wq , struct idxd_desc * desc )
83137{
84138 struct idxd_device * idxd = wq -> idxd ;
139+ struct idxd_irq_entry * ie = NULL ;
85140 void __iomem * portal ;
86141 int rc ;
87142
@@ -99,6 +154,16 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
99154 * even on UP because the recipient is a device.
100155 */
101156 wmb ();
157+
158+ /*
159+ * Pending the descriptor to the lockless list for the irq_entry
160+ * that we designated the descriptor to.
161+ */
162+ if (desc -> hw -> flags & IDXD_OP_FLAG_RCI ) {
163+ ie = & idxd -> irq_entries [wq -> id + 1 ];
164+ llist_add (& desc -> llnode , & ie -> pending_llist );
165+ }
166+
102167 if (wq_dedicated (wq )) {
103168 iosubmit_cmds512 (portal , desc -> hw , 1 );
104169 } else {
@@ -111,18 +176,12 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
111176 rc = enqcmds (portal , desc -> hw );
112177 if (rc < 0 ) {
113178 percpu_ref_put (& wq -> wq_active );
179+ if (ie )
180+ llist_abort_desc (wq , ie , desc );
114181 return rc ;
115182 }
116183 }
117184
118185 percpu_ref_put (& wq -> wq_active );
119-
120- /*
121- * Pending the descriptor to the lockless list for the irq_entry
122- * that we designated the descriptor to.
123- */
124- if (desc -> hw -> flags & IDXD_OP_FLAG_RCI )
125- llist_add (& desc -> llnode , & idxd -> irq_entries [wq -> id + 1 ].pending_llist );
126-
127186 return 0 ;
128187}
0 commit comments