@@ -263,12 +263,20 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
263263 int wait )
264264{
265265 struct devcmd2_controller * dc2c = vdev -> devcmd2 ;
266- struct devcmd2_result * result = dc2c -> result + dc2c -> next_result ;
266+ struct devcmd2_result * result = NULL ;
267267 unsigned int i ;
268268 int delay ;
269269 int err ;
270270 u32 posted ;
271+ u32 fetch_idx ;
271272 u32 new_posted ;
273+ u8 color ;
274+
275+ fetch_idx = ioread32 (& dc2c -> wq_ctrl -> fetch_index );
276+ if (fetch_idx == 0xFFFFFFFF ) { /* check for hardware gone */
277+ /* Hardware surprise removal: return error */
278+ return - ENODEV ;
279+ }
272280
273281 posted = ioread32 (& dc2c -> wq_ctrl -> posted_index );
274282
@@ -278,6 +286,13 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
278286 }
279287
280288 new_posted = (posted + 1 ) % DEVCMD2_RING_SIZE ;
289+ if (new_posted == fetch_idx ) {
290+ pr_err ("%s: wq is full while issuing devcmd2 command %d, fetch index: %u, posted index: %u\n" ,
291+ pci_name (vdev -> pdev ), _CMD_N (cmd ), fetch_idx , posted );
292+
293+ return - EBUSY ;
294+ }
295+
281296 dc2c -> cmd_ring [posted ].cmd = cmd ;
282297 dc2c -> cmd_ring [posted ].flags = 0 ;
283298
@@ -299,14 +314,22 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
299314 if (dc2c -> cmd_ring [posted ].flags & DEVCMD2_FNORESULT )
300315 return 0 ;
301316
317+ result = dc2c -> result + dc2c -> next_result ;
318+ color = dc2c -> color ;
319+
320+ /*
321+ * Increment next_result, after posting the devcmd, irrespective of
322+ * devcmd result, and it should be done only once.
323+ */
324+ dc2c -> next_result ++ ;
325+ if (dc2c -> next_result == dc2c -> result_size ) {
326+ dc2c -> next_result = 0 ;
327+ dc2c -> color = dc2c -> color ? 0 : 1 ;
328+ }
329+
302330 for (delay = 0 ; delay < wait ; delay ++ ) {
303331 udelay (100 );
304- if (result -> color == dc2c -> color ) {
305- dc2c -> next_result ++ ;
306- if (dc2c -> next_result == dc2c -> result_size ) {
307- dc2c -> next_result = 0 ;
308- dc2c -> color = dc2c -> color ? 0 : 1 ;
309- }
332+ if (result -> color == color ) {
310333 if (result -> error ) {
311334 err = (int ) result -> error ;
312335 if (err != ERR_ECMDUNKNOWN ||
@@ -317,13 +340,6 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
317340 return err ;
318341 }
319342 if (_CMD_DIR (cmd ) & _CMD_DIR_READ ) {
320- /*
321- * Adding the rmb() prevents the compiler
322- * and/or CPU from reordering the reads which
323- * would potentially result in reading stale
324- * values.
325- */
326- rmb ();
327343 for (i = 0 ; i < VNIC_DEVCMD_NARGS ; i ++ )
328344 vdev -> args [i ] = result -> results [i ];
329345 }
0 commit comments