static irqreturn_t if_cs_interrupt(int irq, void *data) { struct if_cs_card *card = data; struct lbs_private *priv = card->priv; u16 cause; lbs_deb_enter(LBS_DEB_CS); /* Ask card interrupt cause register if there is something for us */ cause = if_cs_read16(card, IF_CS_CARD_INT_CAUSE); lbs_deb_cs("cause 0x%04x\n", cause); if (cause == 0) { /* Not for us */ return IRQ_NONE; } if (cause == 0xffff) { /* Read in junk, the card has probably been removed */ card->priv->surpriseremoved = 1; return IRQ_HANDLED; } if (cause & IF_CS_BIT_RX) { struct sk_buff *skb; lbs_deb_cs("rx packet\n"); skb = if_cs_receive_data(priv); if (skb) lbs_process_rxed_packet(priv, skb); } if (cause & IF_CS_BIT_TX) { lbs_deb_cs("tx done\n"); lbs_host_to_card_done(priv); } if (cause & IF_CS_BIT_RESP) { unsigned long flags; u8 i; lbs_deb_cs("cmd resp\n"); spin_lock_irqsave(&priv->driver_lock, flags); i = (priv->resp_idx == 0) ? 1 : 0; spin_unlock_irqrestore(&priv->driver_lock, flags); BUG_ON(priv->resp_len[i]); if_cs_receive_cmdres(priv, priv->resp_buf[i], &priv->resp_len[i]); spin_lock_irqsave(&priv->driver_lock, flags); lbs_notify_command_response(priv, i); spin_unlock_irqrestore(&priv->driver_lock, flags); } if (cause & IF_CS_BIT_EVENT) { u16 status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_EVENT); lbs_queue_event(priv, (status & IF_CS_CARD_STATUS_MASK) >> 8); }
static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, struct if_usb_card *cardp, struct lbs_private *priv) { if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN || recvlength < MRVDRV_MIN_PKT_LEN) { lbs_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n"); kfree_skb(skb); return; } skb_reserve(skb, IPFIELD_ALIGN_OFFSET); skb_put(skb, recvlength); skb_pull(skb, MESSAGE_HEADER_LEN); lbs_process_rxed_packet(priv, skb); }
static int if_sdio_handle_data(struct if_sdio_card *card, u8 *buffer, unsigned size) { int ret; struct sk_buff *skb; char *data; lbs_deb_enter(LBS_DEB_SDIO); if (size > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { lbs_deb_sdio("response packet too large (%d bytes)\n", (int)size); ret = -E2BIG; goto out; } skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + NET_IP_ALIGN); if (!skb) { ret = -ENOMEM; goto out; } skb_reserve(skb, NET_IP_ALIGN); data = skb_put(skb, size); memcpy(data, buffer, size); lbs_process_rxed_packet(card->priv, skb); ret = 0; out: lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); return ret; }