|
@@ -2231,153 +2231,6 @@ static void if_cfg_callback(struct octeon_device *oct,
|
|
|
wake_up_interruptible(&ctx->wc);
|
|
|
}
|
|
|
|
|
|
-/** Routine to push packets arriving on Octeon interface upto network layer.
|
|
|
- * @param oct_id - octeon device id.
|
|
|
- * @param skbuff - skbuff struct to be passed to network layer.
|
|
|
- * @param len - size of total data received.
|
|
|
- * @param rh - Control header associated with the packet
|
|
|
- * @param param - additional control data with the packet
|
|
|
- * @param arg - farg registered in droq_ops
|
|
|
- */
|
|
|
-static void
|
|
|
-liquidio_push_packet(u32 octeon_id __attribute__((unused)),
|
|
|
- void *skbuff,
|
|
|
- u32 len,
|
|
|
- union octeon_rh *rh,
|
|
|
- void *param,
|
|
|
- void *arg)
|
|
|
-{
|
|
|
- struct napi_struct *napi = param;
|
|
|
- struct sk_buff *skb = (struct sk_buff *)skbuff;
|
|
|
- struct skb_shared_hwtstamps *shhwtstamps;
|
|
|
- u64 ns;
|
|
|
- u16 vtag = 0;
|
|
|
- u32 r_dh_off;
|
|
|
- struct net_device *netdev = (struct net_device *)arg;
|
|
|
- struct octeon_droq *droq = container_of(param, struct octeon_droq,
|
|
|
- napi);
|
|
|
- if (netdev) {
|
|
|
- int packet_was_received;
|
|
|
- struct lio *lio = GET_LIO(netdev);
|
|
|
- struct octeon_device *oct = lio->oct_dev;
|
|
|
-
|
|
|
- /* Do not proceed if the interface is not in RUNNING state. */
|
|
|
- if (!ifstate_check(lio, LIO_IFSTATE_RUNNING)) {
|
|
|
- recv_buffer_free(skb);
|
|
|
- droq->stats.rx_dropped++;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- skb->dev = netdev;
|
|
|
-
|
|
|
- skb_record_rx_queue(skb, droq->q_no);
|
|
|
- if (likely(len > MIN_SKB_SIZE)) {
|
|
|
- struct octeon_skb_page_info *pg_info;
|
|
|
- unsigned char *va;
|
|
|
-
|
|
|
- pg_info = ((struct octeon_skb_page_info *)(skb->cb));
|
|
|
- if (pg_info->page) {
|
|
|
- /* For Paged allocation use the frags */
|
|
|
- va = page_address(pg_info->page) +
|
|
|
- pg_info->page_offset;
|
|
|
- memcpy(skb->data, va, MIN_SKB_SIZE);
|
|
|
- skb_put(skb, MIN_SKB_SIZE);
|
|
|
- skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
|
|
- pg_info->page,
|
|
|
- pg_info->page_offset +
|
|
|
- MIN_SKB_SIZE,
|
|
|
- len - MIN_SKB_SIZE,
|
|
|
- LIO_RXBUFFER_SZ);
|
|
|
- }
|
|
|
- } else {
|
|
|
- struct octeon_skb_page_info *pg_info =
|
|
|
- ((struct octeon_skb_page_info *)(skb->cb));
|
|
|
- skb_copy_to_linear_data(skb, page_address(pg_info->page)
|
|
|
- + pg_info->page_offset, len);
|
|
|
- skb_put(skb, len);
|
|
|
- put_page(pg_info->page);
|
|
|
- }
|
|
|
-
|
|
|
- r_dh_off = (rh->r_dh.len - 1) * BYTES_PER_DHLEN_UNIT;
|
|
|
-
|
|
|
- if (oct->ptp_enable) {
|
|
|
- if (rh->r_dh.has_hwtstamp) {
|
|
|
- /* timestamp is included from the hardware at
|
|
|
- * the beginning of the packet.
|
|
|
- */
|
|
|
- if (ifstate_check
|
|
|
- (lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED)) {
|
|
|
- /* Nanoseconds are in the first 64-bits
|
|
|
- * of the packet.
|
|
|
- */
|
|
|
- memcpy(&ns, (skb->data + r_dh_off),
|
|
|
- sizeof(ns));
|
|
|
- r_dh_off -= BYTES_PER_DHLEN_UNIT;
|
|
|
- shhwtstamps = skb_hwtstamps(skb);
|
|
|
- shhwtstamps->hwtstamp =
|
|
|
- ns_to_ktime(ns +
|
|
|
- lio->ptp_adjust);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (rh->r_dh.has_hash) {
|
|
|
- __be32 *hash_be = (__be32 *)(skb->data + r_dh_off);
|
|
|
- u32 hash = be32_to_cpu(*hash_be);
|
|
|
-
|
|
|
- skb_set_hash(skb, hash, PKT_HASH_TYPE_L4);
|
|
|
- r_dh_off -= BYTES_PER_DHLEN_UNIT;
|
|
|
- }
|
|
|
-
|
|
|
- skb_pull(skb, rh->r_dh.len * BYTES_PER_DHLEN_UNIT);
|
|
|
-
|
|
|
- skb->protocol = eth_type_trans(skb, skb->dev);
|
|
|
- if ((netdev->features & NETIF_F_RXCSUM) &&
|
|
|
- (((rh->r_dh.encap_on) &&
|
|
|
- (rh->r_dh.csum_verified & CNNIC_TUN_CSUM_VERIFIED)) ||
|
|
|
- (!(rh->r_dh.encap_on) &&
|
|
|
- (rh->r_dh.csum_verified & CNNIC_CSUM_VERIFIED))))
|
|
|
- /* checksum has already been verified */
|
|
|
- skb->ip_summed = CHECKSUM_UNNECESSARY;
|
|
|
- else
|
|
|
- skb->ip_summed = CHECKSUM_NONE;
|
|
|
-
|
|
|
- /* Setting Encapsulation field on basis of status received
|
|
|
- * from the firmware
|
|
|
- */
|
|
|
- if (rh->r_dh.encap_on) {
|
|
|
- skb->encapsulation = 1;
|
|
|
- skb->csum_level = 1;
|
|
|
- droq->stats.rx_vxlan++;
|
|
|
- }
|
|
|
-
|
|
|
- /* inbound VLAN tag */
|
|
|
- if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
|
|
|
- (rh->r_dh.vlan != 0)) {
|
|
|
- u16 vid = rh->r_dh.vlan;
|
|
|
- u16 priority = rh->r_dh.priority;
|
|
|
-
|
|
|
- vtag = priority << 13 | vid;
|
|
|
- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vtag);
|
|
|
- }
|
|
|
-
|
|
|
- packet_was_received = napi_gro_receive(napi, skb) != GRO_DROP;
|
|
|
-
|
|
|
- if (packet_was_received) {
|
|
|
- droq->stats.rx_bytes_received += len;
|
|
|
- droq->stats.rx_pkts_received++;
|
|
|
- } else {
|
|
|
- droq->stats.rx_dropped++;
|
|
|
- netif_info(lio, rx_err, lio->netdev,
|
|
|
- "droq:%d error rx_dropped:%llu\n",
|
|
|
- droq->q_no, droq->stats.rx_dropped);
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
- recv_buffer_free(skb);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* \brief wrapper for calling napi_schedule
|
|
|
* @param param parameters to pass to napi_schedule
|