Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Mar 24-27, 2025, special US time zones
Register
Loading...
Note: File does not exist in v6.13.7.
  1#include "headers.h"
  2
  3/*this is transmit call-back(BULK OUT)*/
  4static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/)
  5{
  6	struct bcm_usb_tcb *pTcb = (struct bcm_usb_tcb *)urb->context;
  7	struct bcm_interface_adapter *psIntfAdapter = pTcb->psIntfAdapter;
  8	struct bcm_link_request *pControlMsg = (struct bcm_link_request *)urb->transfer_buffer;
  9	struct bcm_mini_adapter *psAdapter = psIntfAdapter->psAdapter;
 10	bool bpowerDownMsg = false;
 11	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 12
 13	if (unlikely(netif_msg_tx_done(Adapter)))
 14		pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name, urb->status);
 15
 16	if (urb->status != STATUS_SUCCESS) {
 17		if (urb->status == -EPIPE) {
 18			psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
 19			wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
 20		} else {
 21			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx URB has got cancelled. status :%d", urb->status);
 22		}
 23	}
 24
 25	pTcb->bUsed = false;
 26	atomic_dec(&psIntfAdapter->uNumTcbUsed);
 27
 28
 29
 30	if (TRUE == psAdapter->bPreparingForLowPowerMode) {
 31
 32		if (((pControlMsg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) &&
 33			(pControlMsg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) {
 34			bpowerDownMsg = TRUE;
 35			/* This covers the bus err while Idle Request msg sent down. */
 36			if (urb->status != STATUS_SUCCESS) {
 37				psAdapter->bPreparingForLowPowerMode = false;
 38				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Idle Mode Request msg failed to reach to Modem");
 39				/* Signalling the cntrl pkt path in Ioctl */
 40				wake_up(&psAdapter->lowpower_mode_wait_queue);
 41				StartInterruptUrb(psIntfAdapter);
 42				goto err_exit;
 43			}
 44
 45			if (psAdapter->bDoSuspend == false) {
 46				psAdapter->IdleMode = TRUE;
 47				/* since going in Idle mode completed hence making this var false */
 48				psAdapter->bPreparingForLowPowerMode = false;
 49
 50				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in Idle Mode State...");
 51				/* Signalling the cntrl pkt path in Ioctl*/
 52				wake_up(&psAdapter->lowpower_mode_wait_queue);
 53			}
 54
 55		} else if ((pControlMsg->Leader.Status == LINK_UP_CONTROL_REQ) &&
 56			(pControlMsg->szData[0] == LINK_UP_ACK) &&
 57			(pControlMsg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE)  &&
 58			(pControlMsg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER)) {
 59			/* This covers the bus err while shutdown Request msg sent down. */
 60			if (urb->status != STATUS_SUCCESS) {
 61				psAdapter->bPreparingForLowPowerMode = false;
 62				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Shutdown Request Msg failed to reach to Modem");
 63				/* Signalling the cntrl pkt path in Ioctl */
 64				wake_up(&psAdapter->lowpower_mode_wait_queue);
 65				StartInterruptUrb(psIntfAdapter);
 66				goto err_exit;
 67			}
 68
 69			bpowerDownMsg = TRUE;
 70			if (psAdapter->bDoSuspend == false) {
 71				psAdapter->bShutStatus = TRUE;
 72				/* since going in shutdown mode completed hence making this var false */
 73				psAdapter->bPreparingForLowPowerMode = false;
 74				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in shutdown Mode State...");
 75				/* Signalling the cntrl pkt path in Ioctl */
 76				wake_up(&psAdapter->lowpower_mode_wait_queue);
 77			}
 78		}
 79
 80		if (psAdapter->bDoSuspend && bpowerDownMsg) {
 81			/* issuing bus suspend request */
 82			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Issuing the Bus suspend request to USB stack");
 83			psIntfAdapter->bPreparingForBusSuspend = TRUE;
 84			schedule_work(&psIntfAdapter->usbSuspendWork);
 85
 86		}
 87
 88	}
 89
 90err_exit:
 91	usb_free_coherent(urb->dev, urb->transfer_buffer_length,
 92			urb->transfer_buffer, urb->transfer_dma);
 93}
 94
 95
 96static struct bcm_usb_tcb *GetBulkOutTcb(struct bcm_interface_adapter *psIntfAdapter)
 97{
 98	struct bcm_usb_tcb *pTcb = NULL;
 99	UINT index = 0;
100
101	if ((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) &&
102		(psIntfAdapter->psAdapter->StopAllXaction == false)) {
103		index = atomic_read(&psIntfAdapter->uCurrTcb);
104		pTcb = &psIntfAdapter->asUsbTcb[index];
105		pTcb->bUsed = TRUE;
106		pTcb->psIntfAdapter = psIntfAdapter;
107		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got Tx desc %d used %d",
108			index, atomic_read(&psIntfAdapter->uNumTcbUsed));
109		index = (index + 1) % MAXIMUM_USB_TCB;
110		atomic_set(&psIntfAdapter->uCurrTcb, index);
111		atomic_inc(&psIntfAdapter->uNumTcbUsed);
112	}
113	return pTcb;
114}
115
116static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_tcb *pTcb, PVOID data, int len)
117{
118
119	struct urb *urb = pTcb->urb;
120	int retval = 0;
121
122	urb->transfer_buffer = usb_alloc_coherent(psIntfAdapter->udev, len,
123						GFP_ATOMIC, &urb->transfer_dma);
124	if (!urb->transfer_buffer) {
125		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Error allocating memory\n");
126		return  -ENOMEM;
127	}
128	memcpy(urb->transfer_buffer, data, len);
129	urb->transfer_buffer_length = len;
130
131	BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending Bulk out packet\n");
132	/* For T3B,INT OUT end point will be used as bulk out end point */
133	if ((psIntfAdapter->psAdapter->chip_id == T3B) && (psIntfAdapter->bHighSpeedDevice == TRUE)) {
134		usb_fill_int_urb(urb, psIntfAdapter->udev,
135			psIntfAdapter->sBulkOut.bulk_out_pipe,
136			urb->transfer_buffer, len, write_bulk_callback, pTcb,
137			psIntfAdapter->sBulkOut.int_out_interval);
138	} else {
139	usb_fill_bulk_urb(urb, psIntfAdapter->udev,
140		  psIntfAdapter->sBulkOut.bulk_out_pipe,
141		  urb->transfer_buffer, len, write_bulk_callback, pTcb);
142	}
143	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* For DMA transfer */
144
145	if (false == psIntfAdapter->psAdapter->device_removed &&
146	   false == psIntfAdapter->psAdapter->bEndPointHalted &&
147	   false == psIntfAdapter->bSuspended &&
148	   false == psIntfAdapter->bPreparingForBusSuspend) {
149		retval = usb_submit_urb(urb, GFP_ATOMIC);
150		if (retval) {
151			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "failed submitting write urb, error %d", retval);
152			if (retval == -EPIPE) {
153				psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
154				wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
155			}
156		}
157	}
158	return retval;
159}
160
161int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len)
162{
163	struct bcm_usb_tcb *pTcb = NULL;
164
165	struct bcm_interface_adapter *psIntfAdapter = arg;
166	pTcb = GetBulkOutTcb(psIntfAdapter);
167	if (pTcb == NULL) {
168		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "No URB to transmit packet, dropping packet");
169		return -EFAULT;
170	}
171	return TransmitTcb(psIntfAdapter, pTcb, data, len);
172}
173
174