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; }
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); }
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); }
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); } } }