blob: 61f878b4f56c1de900d55941e42c6a63bce3e3bd [file] [log] [blame]
#include "headers.h"
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 */
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)
{
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);
}