3 * @defgroup tx_functions Transmission
8 * edge[weight=5;color=red]
10 * bcm_transmit->GetPacketQueueIndex[label="IP Packet"]
11 * GetPacketQueueIndex->IpVersion4[label="IPV4"]
12 * GetPacketQueueIndex->IpVersion6[label="IPV6"]
17 * @section De-Queueing
21 * edge[weight=5;color=red]
22 * interrupt_service_thread->transmit_packets
23 * tx_pkt_hdler->transmit_packets
24 * transmit_packets->CheckAndSendPacketFromIndex
25 * transmit_packets->UpdateTokenCount
26 * CheckAndSendPacketFromIndex->PruneQueue
27 * CheckAndSendPacketFromIndex->IsPacketAllowedForFlow
28 * CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"]
29 * SendControlPacket->bcm_cmd53
30 * CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"]
31 * SendPacketFromQueue->SetupNextSend->bcm_cmd53
39 * @ingroup ctrl_pkt_functions
40 * This function dispatches control packet to the h/w interface
41 * @return zero(success) or -ve value(failure)
43 int SendControlPacket(struct bcm_mini_adapter
*Adapter
, char *pControlPacket
)
45 struct bcm_leader
*PLeader
= (struct bcm_leader
*)pControlPacket
;
47 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "Tx");
48 if (!pControlPacket
|| !Adapter
) {
49 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "Got NULL Control Packet or Adapter");
50 return STATUS_FAILURE
;
52 if ((atomic_read(&Adapter
->CurrNumFreeTxDesc
) <
53 ((PLeader
->PLength
-1)/MAX_DEVICE_DESC_SIZE
)+1)) {
54 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
55 return STATUS_FAILURE
;
58 /* Update the netdevice statistics */
60 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "Leader Status: %x", PLeader
->Status
);
61 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "Leader VCID: %x", PLeader
->Vcid
);
62 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "Leader Length: %x", PLeader
->PLength
);
63 if (Adapter
->device_removed
)
66 if (netif_msg_pktdata(Adapter
))
67 print_hex_dump(KERN_DEBUG
, PFX
"tx control: ", DUMP_PREFIX_NONE
,
68 16, 1, pControlPacket
, PLeader
->PLength
+ LEADER_SIZE
, 0);
70 Adapter
->interface_transmit(Adapter
->pvInterfaceAdapter
,
71 pControlPacket
, (PLeader
->PLength
+ LEADER_SIZE
));
73 atomic_dec(&Adapter
->CurrNumFreeTxDesc
);
74 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "<=========");
75 return STATUS_SUCCESS
;
79 * @ingroup tx_functions
80 * This function despatches the IP packets with the given vcid
81 * to the target via the host h/w interface.
82 * @return zero(success) or -ve value(failure)
84 int SetupNextSend(struct bcm_mini_adapter
*Adapter
, struct sk_buff
*Packet
, USHORT Vcid
)
87 bool bHeaderSupressionEnabled
= false;
88 B_UINT16 uiClassifierRuleID
;
89 u16 QueueIndex
= skb_get_queue_mapping(Packet
);
90 struct bcm_leader Leader
= {0};
92 if (Packet
->len
> MAX_DEVICE_DESC_SIZE
) {
93 status
= STATUS_FAILURE
;
97 /* Get the Classifier Rule ID */
98 uiClassifierRuleID
= *((UINT32
*) (Packet
->cb
) + SKB_CB_CLASSIFICATION_OFFSET
);
100 bHeaderSupressionEnabled
= Adapter
->PackInfo
[QueueIndex
].bHeaderSuppressionEnabled
101 & Adapter
->bPHSEnabled
;
103 if (Adapter
->device_removed
) {
104 status
= STATUS_FAILURE
;
108 status
= PHSTransmit(Adapter
, &Packet
, Vcid
, uiClassifierRuleID
, bHeaderSupressionEnabled
,
109 (UINT
*)&Packet
->len
, Adapter
->PackInfo
[QueueIndex
].bEthCSSupport
);
111 if (status
!= STATUS_SUCCESS
) {
112 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, NEXT_SEND
, DBG_LVL_ALL
, "PHS Transmit failed..\n");
118 if (TCP_ACK
== *((UINT32
*) (Packet
->cb
) + SKB_CB_TCPACK_OFFSET
))
119 Leader
.Status
= LEADER_STATUS_TCP_ACK
;
121 Leader
.Status
= LEADER_STATUS
;
123 if (Adapter
->PackInfo
[QueueIndex
].bEthCSSupport
) {
124 Leader
.PLength
= Packet
->len
;
125 if (skb_headroom(Packet
) < LEADER_SIZE
) {
126 status
= skb_cow(Packet
, LEADER_SIZE
);
128 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, NEXT_SEND
, DBG_LVL_ALL
, "bcm_transmit : Failed To Increase headRoom\n");
132 skb_push(Packet
, LEADER_SIZE
);
133 memcpy(Packet
->data
, &Leader
, LEADER_SIZE
);
135 Leader
.PLength
= Packet
->len
- ETH_HLEN
;
136 memcpy((struct bcm_leader
*)skb_pull(Packet
, (ETH_HLEN
- LEADER_SIZE
)), &Leader
, LEADER_SIZE
);
139 status
= Adapter
->interface_transmit(Adapter
->pvInterfaceAdapter
,
140 Packet
->data
, (Leader
.PLength
+ LEADER_SIZE
));
142 ++Adapter
->dev
->stats
.tx_errors
;
143 if (netif_msg_tx_err(Adapter
))
144 pr_info(PFX
"%s: transmit error %d\n", Adapter
->dev
->name
,
147 struct net_device_stats
*netstats
= &Adapter
->dev
->stats
;
148 Adapter
->PackInfo
[QueueIndex
].uiTotalTxBytes
+= Leader
.PLength
;
150 netstats
->tx_bytes
+= Leader
.PLength
;
151 ++netstats
->tx_packets
;
153 Adapter
->PackInfo
[QueueIndex
].uiCurrentTokenCount
-= Leader
.PLength
<< 3;
154 Adapter
->PackInfo
[QueueIndex
].uiSentBytes
+= (Packet
->len
);
155 Adapter
->PackInfo
[QueueIndex
].uiSentPackets
++;
156 Adapter
->PackInfo
[QueueIndex
].NumOfPacketsSent
++;
158 atomic_dec(&Adapter
->PackInfo
[QueueIndex
].uiPerSFTxResourceCount
);
159 Adapter
->PackInfo
[QueueIndex
].uiThisPeriodSentBytes
+= Leader
.PLength
;
162 atomic_dec(&Adapter
->CurrNumFreeTxDesc
);
165 dev_kfree_skb(Packet
);
169 static int tx_pending(struct bcm_mini_adapter
*Adapter
)
171 return (atomic_read(&Adapter
->TxPktAvail
)
172 && MINIMUM_PENDING_DESCRIPTORS
< atomic_read(&Adapter
->CurrNumFreeTxDesc
))
173 || Adapter
->device_removed
|| (1 == Adapter
->downloadDDR
);
177 * @ingroup tx_functions
180 int tx_pkt_handler(struct bcm_mini_adapter
*Adapter
/**< pointer to adapter object*/)
184 while (!kthread_should_stop()) {
185 /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
186 if (Adapter
->LinkUpStatus
)
187 wait_event_timeout(Adapter
->tx_packet_wait_queue
,
188 tx_pending(Adapter
), msecs_to_jiffies(10));
190 wait_event_interruptible(Adapter
->tx_packet_wait_queue
,
191 tx_pending(Adapter
));
193 if (Adapter
->device_removed
)
196 if (Adapter
->downloadDDR
== 1) {
197 Adapter
->downloadDDR
+= 1;
198 status
= download_ddr_settings(Adapter
);
200 pr_err(PFX
"DDR DOWNLOAD FAILED! %d\n", status
);
204 /* Check end point for halt/stall. */
205 if (Adapter
->bEndPointHalted
== TRUE
) {
206 Bcm_clear_halt_of_endpoints(Adapter
);
207 Adapter
->bEndPointHalted
= false;
208 StartInterruptUrb((struct bcm_interface_adapter
*)(Adapter
->pvInterfaceAdapter
));
211 if (Adapter
->LinkUpStatus
&& !Adapter
->IdleMode
) {
212 if (atomic_read(&Adapter
->TotalPacketCount
))
213 update_per_sf_desc_cnts(Adapter
);
216 if (atomic_read(&Adapter
->CurrNumFreeTxDesc
) &&
217 Adapter
->LinkStatus
== SYNC_UP_REQUEST
&&
218 !Adapter
->bSyncUpRequestSent
) {
220 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Calling LinkMessage");
221 LinkMessage(Adapter
);
224 if ((Adapter
->IdleMode
|| Adapter
->bShutStatus
) && atomic_read(&Adapter
->TotalPacketCount
)) {
225 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Device in Low Power mode...waking up");
226 Adapter
->usIdleModePattern
= ABORT_IDLE_MODE
;
227 Adapter
->bWakeUpDevice
= TRUE
;
228 wake_up(&Adapter
->process_rx_cntrlpkt
);
231 transmit_packets(Adapter
);
232 atomic_set(&Adapter
->TxPktAvail
, 0);
235 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Exiting the tx thread..\n");
236 Adapter
->transmit_packet_thread
= NULL
;