[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Lost] [Patch] Fix für Race in rtl8139



! rtl8139: Zuerst den nächsten Tx-Deskriptor auswählen und dann senden.  
Verhindert ein Race, wenn das TOK und damit möglicherweise auch der nächste 
Send zu früh kommt.
Index: rtl8139.c
===================================================================
--- rtl8139.c	(Revision 803)
+++ rtl8139.c	(Arbeitskopie)
@@ -160,6 +160,7 @@
     (struct cdi_net_device* device, void* data, size_t size)
 {
     struct rtl8139_device* netcard = (struct rtl8139_device*) device;
+    int cur_buffer;
 
     if (size > 0x700) {
         // Spezialfall - keine Lust
@@ -167,9 +168,9 @@
         return;
     }
 
-    //DEBUG_MSG("Vor dem p()...");
-
-    if (netcard->buffer_used) {
+    if (!__sync_lock_test_and_set(&netcard->buffer_used, 1)) {
+        netcard->buffer_used = TRUE;
+    } else {
         DEBUG_MSG("Tx-Buffer ist schon besetzt");
 
         void* pending = malloc(size + sizeof(dword));
@@ -181,10 +182,10 @@
 
         return;
     }
+
     //DEBUG_MSG("Tx-Buffer reserviert");
     // Kopiere das Packet in den Puffer. Wichtig: Der Speicherbereich
     // muß physisch zusammenhängend sein.
-    netcard->buffer_used = TRUE;
     memcpy(netcard->buffer, data, size);
 
     // Falls weniger als 60 Bytes gesendet werden sollen, muss mit Nullen
@@ -195,23 +196,26 @@
     }
     //printf("Phys Buffer = %08x\n", netcard->buffer.phys);
 
+    // Die vier Deskriptoren müssen der Reihe nach verwendet werden,
+    // auch wenn wir momentan nur einen einzigen Puffer verwenden
+    // und immer warten.
+    cur_buffer = netcard->cur_buffer;
+    netcard->cur_buffer++;
+    netcard->cur_buffer %= 4;
+
+    asm volatile("");
+
     // Adresse und Größe des Buffers setzen
     // In TASD (REG_TRANSMIT_STATUS) wird das OWN-Bit gelöscht, was die
     // tatsächliche Übertragung anstößt.
-    write_register_dword(netcard, 
-        REG_TRANSMIT_ADDR0 + (4 * netcard->cur_buffer), 
+    write_register_dword(netcard,
+        REG_TRANSMIT_ADDR0 + (4 * cur_buffer),
         PHYS(netcard, buffer));
 
-    write_register_dword(netcard, 
-        REG_TRANSMIT_STATUS0 + (4 * netcard->cur_buffer), 
+    write_register_dword(netcard,
+        REG_TRANSMIT_STATUS0 + (4 * cur_buffer),
         size);
 
-    // Die vier Deskriptoren müssen der Reihe nach verwendet werden,
-    // auch wenn wir momentan nur einen einzigen Puffer verwenden
-    // und immer warten.
-    netcard->cur_buffer++;
-    netcard->cur_buffer %= 4;
-
     DEBUG_MSG("Gesendet");
 
     return;
@@ -325,6 +329,7 @@
     if (pending) {
         dword size = *((dword*) pending);
         pending += sizeof(dword);
+        DEBUG_MSG("Sende Paket aus der pending-Queue");
         rtl8139_send_packet((struct cdi_net_device*) device, pending, size);
         free(pending - sizeof(dword));
     }