diff options
Diffstat (limited to 'drivers/staging/bcm/InterfaceMisc.c')
-rw-r--r-- | drivers/staging/bcm/InterfaceMisc.c | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c new file mode 100644 index 000000000000..8fc893b37fe4 --- /dev/null +++ b/drivers/staging/bcm/InterfaceMisc.c @@ -0,0 +1,290 @@ +#include "headers.h" + +#ifndef BCM_SHM_INTERFACE + +PS_INTERFACE_ADAPTER +InterfaceAdapterGet(PMINI_ADAPTER psAdapter) +{ + if(psAdapter == NULL) + { + return NULL; + } + return (PS_INTERFACE_ADAPTER)(psAdapter->pvInterfaceAdapter); +} + +INT +InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, + UINT addr, + PVOID buff, + INT len) +{ + int retval = 0; + USHORT usRetries = 0 ; + if(psIntfAdapter == NULL ) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Interface Adapter is NULL"); + 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 ; + do { + retval = usb_control_msg(psIntfAdapter->udev, + usb_rcvctrlpipe(psIntfAdapter->udev,0), + 0x02, + 0xC2, + (addr & 0xFFFF), + ((addr >> 16) & 0xFFFF), + buff, + len, + 5000); + + usRetries++ ; + if(-ENODEV == retval) + { + psIntfAdapter->psAdapter->device_removed =TRUE; + break; + } + + }while((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES ) ); + + if(retval < 0) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval,usRetries); + psIntfAdapter->psAdapter->DeviceAccess = FALSE ; + return retval; + } + else + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval); + psIntfAdapter->psAdapter->DeviceAccess = FALSE ; + return STATUS_SUCCESS; + } +} + +INT +InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, + UINT addr, + PVOID buff, + INT len) +{ + int retval = 0; + USHORT usRetries = 0 ; + + if(psIntfAdapter == NULL ) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL"); + 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 ; + do{ + retval = usb_control_msg(psIntfAdapter->udev, + usb_sndctrlpipe(psIntfAdapter->udev,0), + 0x01, + 0x42, + (addr & 0xFFFF), + ((addr >> 16) & 0xFFFF), + buff, + len, + 5000); + + usRetries++ ; + if(-ENODEV == retval) + { + psIntfAdapter->psAdapter->device_removed = TRUE ; + break; + } + + }while((retval < 0) && ( usRetries < MAX_RDM_WRM_RETIRES)); + + if(retval < 0) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries); + 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(PVOID arg, + UINT addr, + PVOID buff, + INT len) +{ + return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); +} + +INT +BcmWRM(PVOID arg, + UINT addr, + PVOID buff, + INT len) +{ + return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); +} + + + +INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter) +{ + PS_INTERFACE_ADAPTER psIntfAdapter = (PS_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(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + struct urb *tempUrb = NULL; + UINT 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 != NULL) + { + if(psIntfAdapter->psInterruptUrb->status == -EINPROGRESS) + usb_kill_urb(psIntfAdapter->psInterruptUrb); + } + + /* Cancel All submitted TX URB's */ + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cancelling All Submitted TX Urbs \n"); + + for(i = 0; i < MAXIMUM_USB_TCB; i++) + { + tempUrb = psIntfAdapter->asUsbTcb[i].urb; + if(tempUrb) + { + if(tempUrb->status == -EINPROGRESS) + usb_kill_urb(tempUrb); + } + } + + + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cancelling All submitted Rx Urbs \n"); + + 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); + + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "TCB: used- %d cur-%d\n", atomic_read(&psIntfAdapter->uNumTcbUsed), atomic_read(&psIntfAdapter->uCurrTcb)); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "RCB: used- %d cur-%d\n", atomic_read(&psIntfAdapter->uNumRcbUsed), atomic_read(&psIntfAdapter->uCurrRcb)); + +} + +VOID putUsbSuspend(struct work_struct *work) +{ + PS_INTERFACE_ADAPTER psIntfAdapter = NULL ; + struct usb_interface *intf = NULL ; + psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER,usbSuspendWork); + intf=psIntfAdapter->interface ; + + if(psIntfAdapter->bSuspended == FALSE) + usb_autopm_put_interface(intf); + else + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Interface Resumed Completely\n"); + +} + +#endif |