diff options
Diffstat (limited to 'drivers/staging/bcm/InterfaceMisc.c')
| -rw-r--r-- | drivers/staging/bcm/InterfaceMisc.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c new file mode 100644 index 00000000000..4173fd7d671 --- /dev/null +++ b/drivers/staging/bcm/InterfaceMisc.c @@ -0,0 +1,217 @@ +#include "headers.h" + +int InterfaceRDM(struct bcm_interface_adapter *psIntfAdapter, + unsigned int addr, + void *buff, + int len) +{ + int bytes; + + if (!psIntfAdapter) + return -EINVAL; + + if (psIntfAdapter->psAdapter->device_removed == TRUE) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed"); + return -ENODEV; + } + + if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus"); + return -EACCES; + } + + if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed.."); + return -EACCES; + } + psIntfAdapter->psAdapter->DeviceAccess = TRUE; + + bytes = usb_control_msg(psIntfAdapter->udev, + usb_rcvctrlpipe(psIntfAdapter->udev, 0), + 0x02, + 0xC2, + (addr & 0xFFFF), + ((addr >> 16) & 0xFFFF), + buff, + len, + 5000); + + if (-ENODEV == bytes) + psIntfAdapter->psAdapter->device_removed = TRUE; + + if (bytes < 0) + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d", bytes); + else + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes); + + psIntfAdapter->psAdapter->DeviceAccess = false; + return bytes; +} + +int InterfaceWRM(struct bcm_interface_adapter *psIntfAdapter, + unsigned int addr, + void *buff, + int len) +{ + int retval = 0; + + if (!psIntfAdapter) + return -EINVAL; + + if (psIntfAdapter->psAdapter->device_removed == TRUE) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed"); + return -ENODEV; + } + + if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus..."); + return -EACCES; + } + + if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed.."); + return -EACCES; + } + + psIntfAdapter->psAdapter->DeviceAccess = TRUE; + + retval = usb_control_msg(psIntfAdapter->udev, + usb_sndctrlpipe(psIntfAdapter->udev, 0), + 0x01, + 0x42, + (addr & 0xFFFF), + ((addr >> 16) & 0xFFFF), + buff, + len, + 5000); + + if (-ENODEV == retval) + psIntfAdapter->psAdapter->device_removed = TRUE; + + if (retval < 0) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d", retval); + psIntfAdapter->psAdapter->DeviceAccess = false; + return retval; + } else { + psIntfAdapter->psAdapter->DeviceAccess = false; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval); + return STATUS_SUCCESS; + } +} + +int BcmRDM(void *arg, + unsigned int addr, + void *buff, + int len) +{ + return InterfaceRDM((struct bcm_interface_adapter *)arg, addr, buff, len); +} + +int BcmWRM(void *arg, + unsigned int addr, + void *buff, + int len) +{ + return InterfaceWRM((struct bcm_interface_adapter *)arg, addr, buff, len); +} + +int Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter) +{ + struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter); + int status = STATUS_SUCCESS; + + /* + * usb_clear_halt - tells device to clear endpoint halt/stall condition + * @dev: device whose endpoint is halted + * @pipe: endpoint "pipe" being cleared + * @ Context: !in_interrupt () + * + * usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code. + * This is used to clear halt conditions for bulk and interrupt endpoints only. + * Control and isochronous endpoints never halts. + * + * Any URBs queued for such an endpoint should normally be unlinked by the driver + * before clearing the halt condition. + * + */ + + /* Killing all the submitted urbs to different end points. */ + Bcm_kill_all_URBs(psIntfAdapter); + + /* clear the halted/stalled state for every end point */ + status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sIntrIn.int_in_pipe); + if (status != STATUS_SUCCESS) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status); + + status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_pipe); + if (status != STATUS_SUCCESS) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status); + + status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkOut.bulk_out_pipe); + if (status != STATUS_SUCCESS) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status); + + return status; +} + +void Bcm_kill_all_URBs(struct bcm_interface_adapter *psIntfAdapter) +{ + struct urb *tempUrb = NULL; + unsigned int i; + + /* + * usb_kill_urb - cancel a transfer request and wait for it to finish + * @urb: pointer to URB describing a previously submitted request, + * returns nothing as it is void returned API. + * + * This routine cancels an in-progress request. It is guaranteed that + * upon return all completion handlers will have finished and the URB + * will be totally idle and available for reuse + * + * This routine may not be used in an interrupt context (such as a bottom + * half or a completion handler), or when holding a spinlock, or in other + * situations where the caller can't schedule(). + * + */ + + /* Cancel submitted Interrupt-URB's */ + if (psIntfAdapter->psInterruptUrb) { + if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS) + usb_kill_urb(psIntfAdapter->psInterruptUrb); + } + + /* Cancel All submitted TX URB's */ + for (i = 0; i < MAXIMUM_USB_TCB; i++) { + tempUrb = psIntfAdapter->asUsbTcb[i].urb; + if (tempUrb) { + if (tempUrb->status == -EINPROGRESS) + usb_kill_urb(tempUrb); + } + } + + for (i = 0; i < MAXIMUM_USB_RCB; i++) { + tempUrb = psIntfAdapter->asUsbRcb[i].urb; + if (tempUrb) { + if (tempUrb->status == -EINPROGRESS) + usb_kill_urb(tempUrb); + } + } + + atomic_set(&psIntfAdapter->uNumTcbUsed, 0); + atomic_set(&psIntfAdapter->uCurrTcb, 0); + + atomic_set(&psIntfAdapter->uNumRcbUsed, 0); + atomic_set(&psIntfAdapter->uCurrRcb, 0); +} + +void putUsbSuspend(struct work_struct *work) +{ + struct bcm_interface_adapter *psIntfAdapter = NULL; + struct usb_interface *intf = NULL; + psIntfAdapter = container_of(work, struct bcm_interface_adapter, usbSuspendWork); + intf = psIntfAdapter->interface; + + if (psIntfAdapter->bSuspended == false) + usb_autopm_put_interface(intf); +} + |
