示例#1
0
static int pegasus_open(struct net_device *net)
{
	pegasus_t *pegasus = (pegasus_t *) net->priv;
	int res;

	if (pegasus->rx_skb == NULL)
		pegasus->rx_skb = pull_skb(pegasus);
	/*
	 ** Note: no point to free the pool.  it is empty :-)
	 */
	if (!pegasus->rx_skb)
		return -ENOMEM;

	set_registers(pegasus, EthID, 6, net->dev_addr);
	
	usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
			  usb_rcvbulkpipe(pegasus->usb, 1),
			  pegasus->rx_skb->data, PEGASUS_MTU + 8,
			  read_bulk_callback, pegasus);
	if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL)))
		warn("%s: failed rx_urb %d", __FUNCTION__, res);
	usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
			 usb_rcvintpipe(pegasus->usb, 3),
			 pegasus->intr_buff, sizeof (pegasus->intr_buff),
			 intr_callback, pegasus, pegasus->intr_interval);
	if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)))
		warn("%s: failed intr_urb %d", __FUNCTION__, res);
	netif_start_queue(net);
	pegasus->flags |= PEGASUS_RUNNING;
	if ((res = enable_net_traffic(net, pegasus->usb))) {
		err("can't enable_net_traffic() - %d", res);
		res = -EIO;
		usb_unlink_urb(pegasus->rx_urb);
		usb_unlink_urb(pegasus->intr_urb);
		free_skb_pool(pegasus);
		goto exit;
	}
	set_carrier(net);
	res = 0;
exit:
	return res;
}
示例#2
0
static void rx_fixup(unsigned long data)
{
	pegasus_t *pegasus;
	unsigned long flags;

	pegasus = (pegasus_t *) data;
	if (pegasus->flags & PEGASUS_UNPLUG)
		return;

	spin_lock_irqsave(&pegasus->rx_pool_lock, flags);
	fill_skb_pool(pegasus);
	if (pegasus->flags & PEGASUS_RX_URB_FAIL)
		if (pegasus->rx_skb)
			goto try_again;
	if (pegasus->rx_skb == NULL) {
		pegasus->rx_skb = pull_skb(pegasus);
	}
	if (pegasus->rx_skb == NULL) {
		warn("wow, low on memory");
		tasklet_schedule(&pegasus->rx_tl);
		goto done;
	}
	usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
			  usb_rcvbulkpipe(pegasus->usb, 1),
			  pegasus->rx_skb->data, PEGASUS_MTU + 8,
			  read_bulk_callback, pegasus);
try_again:
	if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) {
		pegasus->flags |= PEGASUS_RX_URB_FAIL;
		tasklet_schedule(&pegasus->rx_tl);
	} else {
		pegasus->flags &= ~PEGASUS_RX_URB_FAIL;
	}
done:
	spin_unlock_irqrestore(&pegasus->rx_pool_lock, flags);
}
示例#3
0
static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
	pegasus_t *pegasus = urb->context;
	struct net_device *net;
	int rx_status, count = urb->actual_length;
	__u16 pkt_len;

	if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
		return;

	net = pegasus->net;
	if (!netif_device_present(net))
		return;

	switch (urb->status) {
	case 0:
		break;
	case -ETIMEDOUT:
		dbg("%s: reset MAC", net->name);
		pegasus->flags &= ~PEGASUS_RX_BUSY;
		break;
	case -EPIPE:		/* stall, or disconnect from TT */
		/* FIXME schedule work to clear the halt */
		warn("%s: no rx stall recovery", net->name);
		return;
	case -ENOENT:
	case -ECONNRESET:
	case -ESHUTDOWN:
		dbg("%s: rx unlink, %d", net->name, urb->status);
		return;
	default:
		dbg("%s: RX status %d", net->name, urb->status);
		goto goon;
	}

	if (!count)
		goto goon;

	rx_status = le32_to_cpu(*(int *) (urb->transfer_buffer + count - 4));
	if (rx_status & 0x000e0000) {
		dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
		pegasus->stats.rx_errors++;
		if (rx_status & 0x060000)
			pegasus->stats.rx_length_errors++;
		if (rx_status & 0x080000)
			pegasus->stats.rx_crc_errors++;
		if (rx_status & 0x100000)
			pegasus->stats.rx_frame_errors++;
		goto goon;
	}
	if (pegasus->chip == 0x8513) {
		pkt_len = le32_to_cpu(*(int *)urb->transfer_buffer);
		pkt_len &= 0x0fff;
		pegasus->rx_skb->data += 2;
	} else {
		pkt_len = (rx_status & 0xfff) - 8;
	}

	/*
	 * at this point we are sure pegasus->rx_skb != NULL
	 * so we go ahead and pass up the packet.
	 */
	skb_put(pegasus->rx_skb, pkt_len);
	pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net);
	netif_rx(pegasus->rx_skb);
	pegasus->stats.rx_packets++;
	pegasus->stats.rx_bytes += pkt_len;

	if (pegasus->flags & PEGASUS_UNPLUG)
		return;

	spin_lock(&pegasus->rx_pool_lock);
	pegasus->rx_skb = pull_skb(pegasus);
	spin_unlock(&pegasus->rx_pool_lock);

	if (pegasus->rx_skb == NULL)
		goto tl_sched;
goon:
	usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
			  usb_rcvbulkpipe(pegasus->usb, 1),
			  pegasus->rx_skb->data, PEGASUS_MTU + 8,
			  read_bulk_callback, pegasus);
	if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) {
		pegasus->flags |= PEGASUS_RX_URB_FAIL;
		goto tl_sched;
	} else {
		pegasus->flags &= ~PEGASUS_RX_URB_FAIL;
	}

	return;

      tl_sched:
	tasklet_schedule(&pegasus->rx_tl);
}
示例#4
0
unsigned int processSdioReceiveData(MINIPORT_ADAPTER *Adapter, void *Buffer, u_long Length, long Timeout)
{
	unsigned int offset = 0, PacketLen = 0, remain_len = 0;
	PHW_PACKET_HEADER hdr = (PHW_PACKET_HEADER)Buffer; 
	unsigned long PacketType;
	struct net_device 	*net = Adapter->net;
	u_long flags;
	
	ENTER;
	DumpDebug(RX_DPC,"Total length of packet = %lu", Length); 

	PacketType = HwPktTypeNone;
	PacketLen = Length;
#if 0		
	if(Adapter->bHaltPending)
		return 0;
#endif	

	if (hdr->Id0 != 'W') { // "WD", "WC", "WP" or "WE"
		DumpDebug(RX_DPC, "WiBro USB: Wrong packet ID (%c%c or %02x%02x)", hdr->Id0, hdr->Id1, hdr->Id0, hdr->Id1);
		// skip rest of packets
		PacketLen = 0;
	}
	// check packet type
	if ((hdr->Id0 == 'W') && (hdr->Id1 == 'P')) {
	    DumpDebug(RX_DPC, "WiBro USB: control packet (private) ");
	    // set packet type
	    PacketType = HwPktTypePrivate;
	}
	else if ((hdr->Id0 == 'W') && (hdr->Id1 == 'C')) {
	    DumpDebug(RX_DPC, "WiBro USB: CONTROL packet <<<-----------------------------------");
	    PacketType = HwPktTypeControl;
	}
	else if ((hdr->Id0 == 'W') && (hdr->Id1 == 'D')) {
	    DumpDebug(RX_DPC, "WiBro USB: DATA packet <<<-------------------------------------------------------------------");
	    PacketType = HwPktTypeData;
	}
	else
	{
		DumpDebug(RX_DPC, "WiBro USB: Wrong packet ID (%c%c or %02x%02x)", hdr->Id0, hdr->Id1, hdr->Id0, hdr->Id1);
		return 0;
	}
	
	if (PacketType != HwPktTypePrivate) 
	{
		if (!Adapter->DownloadMode) {
			if (hdr->Length > MINIPORT_MAX_TOTAL_SIZE) { 
				DumpDebug(RX_DPC,"WiBro USB: Packet length is too big (%d)", hdr->Length); 
				// skip rest of packets
				PacketLen = 0;
			}
		}
		
		if (hdr->Length)
		{
		    // change offset
		    offset += sizeof(HW_PACKET_HEADER);
#ifdef HARDWARE_USE_ALIGN_HEADER
			if(!Adapter->DownloadMode)
				offset += 2;		
#endif			
			if(PacketLen <4 ) {
				PacketLen = 0;
				return 0;		
			}

			PacketLen -= offset; /* from this line, Packet length is read data size without samsung header YHM */
		    // copy packet

#ifdef HARDWARE_USE_SUPPRESS_MAC_HEADER //sangam dbg:If suppress mac address enabled during send same applicable to receive
				memcpy((unsigned char *)Adapter->hw.ReceiveBuffer, Adapter->hw.EthHeader, MINIPORT_LENGTH_OF_ADDRESS * 2);
				memcpy((unsigned char *)Adapter->hw.ReceiveBuffer + (MINIPORT_LENGTH_OF_ADDRESS * 2),
						((unsigned char *) Buffer) + offset, PacketLen);
				PacketLen += (MINIPORT_LENGTH_OF_ADDRESS * 2);
#else
				memcpy((unsigned char *)Adapter->hw.ReceiveBuffer, ((unsigned char *) Buffer) + offset, PacketLen);
#endif				
			if(PacketType == HwPktTypeData)
			{
				if (Adapter->rx_skb == NULL)
				{
					spin_lock_irqsave(&Adapter->rx_pool_lock, flags);
					fill_skb_pool(Adapter);
					Adapter->rx_skb = pull_skb(Adapter);
					spin_unlock_irqrestore(&Adapter->rx_pool_lock, flags);
					if(Adapter->rx_skb == NULL ){
						DumpDebug(RX_DPC, "%s : Low on Memory",Adapter->net->name);
						return -ENOMEM;
					}
				}
				memcpy((unsigned char *)Adapter->rx_skb->data, (unsigned char *)Adapter->hw.ReceiveBuffer, PacketLen);
#ifdef HARDWARE_USE_SUPPRESS_MAC_HEADER
				if(hdr->Length == (PacketLen - (MINIPORT_LENGTH_OF_ADDRESS * 2))) 
#else	
				if(hdr->Length == PacketLen) 
#endif
					DumpDebug(RX_DPC,"Just one DATA packet processed and remained len is = %d",(PacketLen - hdr->Length))
				else {
					remain_len = PacketLen - hdr->Length;					
					DumpDebug(RX_DPC,"multiple DATA packet received and remained len is = %d",remain_len);
				}
			}
			else
			{			
#ifdef HARDWARE_USE_SUPPRESS_MAC_HEADER
				if(hdr->Length == (PacketLen - (MINIPORT_LENGTH_OF_ADDRESS * 2))) 
#else	
				if(hdr->Length == PacketLen) 
#endif
					DumpDebug(RX_DPC,"Just one C or P packet processed and remained len is = %d", (PacketLen - hdr->Length))
				else{
					remain_len = PacketLen - hdr->Length;					
					DumpDebug(RX_DPC,"multiple C or P packet received and remained len is = %d",remain_len);
				}				
			}
		}