usb_rndis: improve logging and error handling
- On read errors, make sure to reset the read buffer pointer and not return any more packets from the incorrectly read buffer - Fix a case where an error didn't stop the processing, and we would return a zero-byte packet to the network stack instead of an error - Make sure to use different log messages for different error cases - Use strerror where appropriate - Add some TRACE calls to be able to fully trace the code. There seem to be an error at the XHCI level where it has an "USB Transaction" error (converted to a B_DEVICE_CRC_ERROR Haiku error code). After that, despite cancelling that transfer and clearing the HALT feature, it is not possible to receive anything from the receive endpoint and the connexion is stuck (it appears sending data still works, at least from the network stack point of view). Change-Id: I58687a6eb7b19ba7e7ca594c55499b60fb8b5b26 Reviewed-on: https://review.haiku-os.org/c/haiku/+/9658 Reviewed-by: Adrien Destugues <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
b6f74b4905
commit
fc3e0e860a
@@ -251,6 +251,7 @@ status_t
|
||||
RNDISDevice::Read(uint8 *buffer, size_t *numBytes)
|
||||
{
|
||||
if (fRemoved) {
|
||||
TRACE("Reading, but device is removed\n");
|
||||
*numBytes = 0;
|
||||
return B_DEVICE_NOT_FOUND;
|
||||
}
|
||||
@@ -260,21 +261,28 @@ RNDISDevice::Read(uint8 *buffer, size_t *numBytes)
|
||||
// buffer for each Read() call before scheduling a new USB transfer. This would be more
|
||||
// efficient if the network stack had a way to read multiple frames at once.
|
||||
if (fReadHeader == NULL) {
|
||||
TRACE("Reading next packet batch\n");
|
||||
status_t result = gUSBModule->queue_bulk(fReadEndpoint, fReadBuffer, sizeof(fReadBuffer),
|
||||
_ReadCallback, this);
|
||||
if (result != B_OK) {
|
||||
TRACE_ALWAYS("failed to schedule read transfer: %s\n", strerror(result));
|
||||
fReadHeader = NULL;
|
||||
*numBytes = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
result = acquire_sem_etc(fNotifyReadSem, 1, B_CAN_INTERRUPT, 0);
|
||||
if (result < B_OK) {
|
||||
TRACE_ALWAYS("error while waiting for frame: %s\n", strerror(result));
|
||||
fReadHeader = NULL;
|
||||
*numBytes = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (fStatusRead == B_CANCELED) {
|
||||
TRACE_ALWAYS("request was cancelled: %s\n", strerror(result));
|
||||
// The transfer was canceled, so no data was actually received.
|
||||
fReadHeader = NULL;
|
||||
*numBytes = 0;
|
||||
return fStatusRead;
|
||||
}
|
||||
@@ -282,18 +290,21 @@ RNDISDevice::Read(uint8 *buffer, size_t *numBytes)
|
||||
if ((fStatusRead != B_OK) && !fRemoved) {
|
||||
// In other error cases (triggered by the device), we need to clear the "halt" feature
|
||||
// so that the next transfers will work.
|
||||
TRACE_ALWAYS("device status error 0x%08" B_PRIx32 "\n", fStatusRead);
|
||||
TRACE_ALWAYS("device read status error: %s\n", strerror(fStatusRead));
|
||||
|
||||
gUSBModule->cancel_queued_transfers(fReadEndpoint);
|
||||
|
||||
result = gUSBModule->clear_feature(fReadEndpoint, USB_FEATURE_ENDPOINT_HALT);
|
||||
if (result != B_OK) {
|
||||
TRACE_ALWAYS("failed to clear halt state on read\n");
|
||||
*numBytes = 0;
|
||||
return result;
|
||||
}
|
||||
fReadHeader = NULL;
|
||||
*numBytes = 0;
|
||||
return fStatusRead;
|
||||
}
|
||||
fReadHeader = (uint32*)fReadBuffer;
|
||||
} else {
|
||||
TRACE("Returning buffered packet\n");
|
||||
}
|
||||
|
||||
if (fReadHeader[0] != REMOTE_NDIS_PACKET_MSG) {
|
||||
@@ -418,7 +429,7 @@ RNDISDevice::Write(const uint8 *buffer, size_t *numBytes)
|
||||
}
|
||||
|
||||
if ((fStatusWrite != B_OK) && !fRemoved) {
|
||||
TRACE_ALWAYS("device status error 0x%08" B_PRIx32 "\n", fStatusWrite);
|
||||
TRACE_ALWAYS("device write status error 0x%08" B_PRIx32 "\n", fStatusWrite);
|
||||
|
||||
gUSBModule->cancel_queued_transfers(fReadEndpoint);
|
||||
|
||||
@@ -467,6 +478,11 @@ RNDISDevice::Control(uint32 op, void *buffer, size_t length)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
case ETHER_SEND_NET_BUFFER:
|
||||
case ETHER_RECEIVE_NET_BUFFER:
|
||||
// Ignored for now, we use the old read/write interface instead
|
||||
return B_DEV_INVALID_IOCTL;
|
||||
|
||||
default:
|
||||
TRACE_ALWAYS("unsupported ioctl %" B_PRIu32 "\n", op);
|
||||
}
|
||||
@@ -843,7 +859,7 @@ RNDISDevice::_NotifyCallback(void *cookie, int32 status, void *_data,
|
||||
}
|
||||
|
||||
if (status != B_OK) {
|
||||
TRACE_ALWAYS("device status error 0x%08" B_PRIx32 "\n", status);
|
||||
TRACE_ALWAYS("device notify status error 0x%08" B_PRIx32 "\n", status);
|
||||
|
||||
if (gUSBModule->clear_feature(device->fNotifyEndpoint,
|
||||
USB_FEATURE_ENDPOINT_HALT) != B_OK)
|
||||
|
||||
Reference in New Issue
Block a user