static void adapter_sdio_rx_packet(struct net_adapter *adapter, int len)
{
	struct hw_packet_header	*hdr;
	int							rlen;
	u32			type;
	u8						*ofs;
	struct sk_buff				*rx_skb;

	rlen = len;
	ofs = (u8 *)adapter->hw.receive_buffer;

	while (rlen > 0) {
		hdr = (struct hw_packet_header *)ofs;
		type = HWPKTTYPENONE;

		/* "WD", "WC", "WP" or "WE" */
		if (unlikely(hdr->id0 != 'W')) {
			if (rlen > 4) {
				pr_debug("Wrong packet	\
				ID (%02x %02x)", hdr->id0, hdr->id1);
			}
			/* skip rest of packets */
			break;
		}

		/* check packet type */
		switch (hdr->id1) {
		case 'P': {
			u32 l = 0;
			type = HWPKTTYPEPRIVATE;

			/* process packet */
			l = process_private_cmd(adapter, ofs);

			/* shift */
			ofs += l;
			rlen -= l;

			/* process next packet */
			continue;
		}
		case 'C':
			type = HWPKTTYPECONTROL;
			break;
		case 'D':
			type = HWPKTTYPEDATA;
			break;
		case 'E':
			/* skip rest of buffer */
			break;
		default:
			pr_debug("hwParseReceivedData :	\
					Wrong packet ID [%02x %02x]",
						hdr->id0, hdr->id1);
			/* skip rest of buffer */
			break;
		}

		if (type == HWPKTTYPENONE)
			break;

		if (likely(!adapter->downloading)) {
			if (unlikely(hdr->length > WIMAX_MAX_TOTAL_SIZE
					|| ((hdr->length +
				sizeof(struct hw_packet_header)) > rlen))) {
				pr_debug("Packet length is	\
						too big (%d)", hdr->length);
				/* skip rest of packets */
				break;
			}
		}
示例#2
0
static void adapter_rx_packet(struct net_adapter *adapter,
		struct buffer_descriptor *bufdsc)
{
	struct hw_packet_header	*hdr;
	s32						rlen = bufdsc->length;
	u32						l;
	u8						*ofs;
	struct sk_buff				*rx_skb;
	ofs = (u8 *)bufdsc->buffer;

	while (rlen > 0) {
		hdr = (struct hw_packet_header *)ofs;

		/* "WD", "WC", "WP" or "WE" */
		if (unlikely(hdr->id0 != 'W')) {
			/*Ignore if it is the 4 byte allignment*/
			pr_warn("Wrong packet	\
			ID (%02x %02x) rlen = %d\n", hdr->id0, hdr->id1, rlen);
			/* skip rest of packets */
			break;
		}

		/* change offset */
		ofs += sizeof(*hdr);
		rlen -= sizeof(*hdr);

		/* check packet type */
		switch (hdr->id1) {
		case 'P': {
			/* revert offset */
			ofs -= sizeof(*hdr);
			rlen += sizeof(*hdr);
			/* process packet */
			l = process_private_cmd(adapter, ofs);
			/* shift */
			ofs += l;
			rlen -= l;

			/* process next packet */
			continue;
			}
		case 'C':
			if (!adapter->downloading) {
				ofs += 2;
				rlen -= 2;
				control_recv(adapter, (u8 *)ofs, hdr->length);
				break;
			} else {
				hdr->length -= sizeof(*hdr);
				process_indicate_packet(adapter, ofs);
				break;
			}
		case 'D':
			ofs += 2;
			rlen -= 2;

			if (hdr->length > BUFFER_DATA_SIZE) {
					pr_warn("Data packet too large");
					adapter->netstats.rx_dropped++;
					break;
				}

				if (likely(hdr->length <=
							(WIMAX_MTU_SIZE + 2))) {
					rx_skb = cmc7xx_fetch_skb(adapter);

					if (!rx_skb) {
						pr_err("unable to allocate skb");
						break;
					}
				} else {
					rx_skb = dev_alloc_skb(hdr->length +
						(ETHERNET_ADDRESS_LENGTH * 2) +
						NET_IP_ALIGN);
					if (!rx_skb) {
						pr_err("unable to allocate skb");
						break;
					}
					cmc7xx_prepare_skb(adapter, rx_skb);
				}

				memcpy(skb_put(rx_skb, hdr->length),
							(u8 *)ofs,
							hdr->length);
				rx_skb->protocol =
					eth_type_trans(rx_skb, adapter->net);
				if (netif_rx_ni(rx_skb) == NET_RX_DROP) {
					pr_debug("packet dropped!");
					adapter->netstats.rx_dropped++;
				}
				adapter->netstats.rx_packets++;
				adapter->netstats.rx_bytes +=
					(hdr->length +
					 (ETHERNET_ADDRESS_LENGTH * 2));

			break;
		case 'E':
			pr_warn("%s :Wrong packet Extended ID [%02x %02x]",
						__func__, hdr->id0, hdr->id1);
			/* skip rest of buffer */
			goto out;
		default:
			pr_warn("%s :Wrong packet ID [%02x %02x]",
						__func__, hdr->id0, hdr->id1);
			/* skip rest of buffer */
			goto out;
		}

		ofs += hdr->length;
		rlen -= hdr->length;
	}