@@ -159,7 +159,7 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
159
159
struct scatterlist * sg ;
160
160
unsigned int i , j , dmacount ;
161
161
unsigned int len ;
162
- static const unsigned int bufflen = 4096 ;
162
+ static const unsigned int bufflen = IXGBE_FCBUFF_MIN ;
163
163
unsigned int firstoff = 0 ;
164
164
unsigned int lastsize ;
165
165
unsigned int thisoff = 0 ;
@@ -254,6 +254,24 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
254
254
/* only the last buffer may have non-full bufflen */
255
255
lastsize = thisoff + thislen ;
256
256
257
+ /*
258
+ * lastsize can not be buffer len.
259
+ * If it is then adding another buffer with lastsize = 1.
260
+ */
261
+ if (lastsize == bufflen ) {
262
+ if (j >= IXGBE_BUFFCNT_MAX ) {
263
+ e_err (drv , "xid=%x:%d,%d,%d:addr=%llx "
264
+ "not enough user buffers. We need an extra "
265
+ "buffer because lastsize is bufflen.\n" ,
266
+ xid , i , j , dmacount , (u64 )addr );
267
+ goto out_noddp_free ;
268
+ }
269
+
270
+ ddp -> udl [j ] = (u64 )(fcoe -> extra_ddp_buffer_dma );
271
+ j ++ ;
272
+ lastsize = 1 ;
273
+ }
274
+
257
275
fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT );
258
276
fcbuff |= ((j & 0xff ) << IXGBE_FCBUFF_BUFFCNT_SHIFT );
259
277
fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT );
@@ -532,6 +550,24 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
532
550
e_err (drv , "failed to allocated FCoE DDP pool\n" );
533
551
534
552
spin_lock_init (& fcoe -> lock );
553
+
554
+ /* Extra buffer to be shared by all DDPs for HW work around */
555
+ fcoe -> extra_ddp_buffer = kmalloc (IXGBE_FCBUFF_MIN , GFP_ATOMIC );
556
+ if (fcoe -> extra_ddp_buffer == NULL ) {
557
+ e_err (drv , "failed to allocated extra DDP buffer\n" );
558
+ goto out_extra_ddp_buffer_alloc ;
559
+ }
560
+
561
+ fcoe -> extra_ddp_buffer_dma =
562
+ dma_map_single (& adapter -> pdev -> dev ,
563
+ fcoe -> extra_ddp_buffer ,
564
+ IXGBE_FCBUFF_MIN ,
565
+ DMA_FROM_DEVICE );
566
+ if (dma_mapping_error (& adapter -> pdev -> dev ,
567
+ fcoe -> extra_ddp_buffer_dma )) {
568
+ e_err (drv , "failed to map extra DDP buffer\n" );
569
+ goto out_extra_ddp_buffer_dma ;
570
+ }
535
571
}
536
572
537
573
/* Enable L2 eth type filter for FCoE */
@@ -581,6 +617,14 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
581
617
}
582
618
}
583
619
#endif
620
+
621
+ return ;
622
+
623
+ out_extra_ddp_buffer_dma :
624
+ kfree (fcoe -> extra_ddp_buffer );
625
+ out_extra_ddp_buffer_alloc :
626
+ pci_pool_destroy (fcoe -> pool );
627
+ fcoe -> pool = NULL ;
584
628
}
585
629
586
630
/**
@@ -600,6 +644,11 @@ void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter)
600
644
if (fcoe -> pool ) {
601
645
for (i = 0 ; i < IXGBE_FCOE_DDP_MAX ; i ++ )
602
646
ixgbe_fcoe_ddp_put (adapter -> netdev , i );
647
+ dma_unmap_single (& adapter -> pdev -> dev ,
648
+ fcoe -> extra_ddp_buffer_dma ,
649
+ IXGBE_FCBUFF_MIN ,
650
+ DMA_FROM_DEVICE );
651
+ kfree (fcoe -> extra_ddp_buffer );
603
652
pci_pool_destroy (fcoe -> pool );
604
653
fcoe -> pool = NULL ;
605
654
}
0 commit comments