cregit-Linux how code gets into the kernel

Release 4.14 drivers/firewire/net.c

Directory: drivers/firewire
/*
 * IPv4 over IEEE 1394, per RFC 2734
 * IPv6 over IEEE 1394, per RFC 3146
 *
 * Copyright (C) 2009 Jay Fenlason <fenlason@redhat.com>
 *
 * based on eth1394 by Ben Collins et al
 */

#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/ethtool.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/highmem.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/jiffies.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/spinlock.h>

#include <asm/unaligned.h>
#include <net/arp.h>
#include <net/firewire.h>

/* rx limits */

#define FWNET_MAX_FRAGMENTS		30 
/* arbitrary, > TX queue depth */

#define FWNET_ISO_PAGE_COUNT		(PAGE_SIZE < 16*1024 ? 4 : 2)

/* tx limits */

#define FWNET_MAX_QUEUED_DATAGRAMS	20 
/* < 64 = number of tlabels */

#define FWNET_MIN_QUEUED_DATAGRAMS	10 
/* should keep AT DMA busy enough */

#define FWNET_TX_QUEUE_LEN		FWNET_MAX_QUEUED_DATAGRAMS 
/* ? */


#define IEEE1394_BROADCAST_CHANNEL	31

#define IEEE1394_ALL_NODES		(0xffc0 | 0x003f)

#define IEEE1394_MAX_PAYLOAD_S100	512

#define FWNET_NO_FIFO_ADDR		(~0ULL)


#define IANA_SPECIFIER_ID		0x00005eU

#define RFC2734_SW_VERSION		0x000001U

#define RFC3146_SW_VERSION		0x000002U


#define IEEE1394_GASP_HDR_SIZE	8


#define RFC2374_UNFRAG_HDR_SIZE	4

#define RFC2374_FRAG_HDR_SIZE	8

#define RFC2374_FRAG_OVERHEAD	4


#define RFC2374_HDR_UNFRAG	0	
/* unfragmented         */

#define RFC2374_HDR_FIRSTFRAG	1	
/* first fragment       */

#define RFC2374_HDR_LASTFRAG	2	
/* last fragment        */

#define RFC2374_HDR_INTFRAG	3	
/* interior fragment    */


static bool fwnet_hwaddr_is_multicast(u8 *ha) { return !!(*ha & 1); }

Contributors

PersonTokensPropCommitsCommitProp
Hideaki Yoshifuji / 吉藤英明20100.00%1100.00%
Total20100.00%1100.00%

/* IPv4 and IPv6 encapsulation header */ struct rfc2734_header { u32 w0; u32 w1; }; #define fwnet_get_hdr_lf(h) (((h)->w0 & 0xc0000000) >> 30) #define fwnet_get_hdr_ether_type(h) (((h)->w0 & 0x0000ffff)) #define fwnet_get_hdr_dg_size(h) ((((h)->w0 & 0x0fff0000) >> 16) + 1) #define fwnet_get_hdr_fg_off(h) (((h)->w0 & 0x00000fff)) #define fwnet_get_hdr_dgl(h) (((h)->w1 & 0xffff0000) >> 16) #define fwnet_set_hdr_lf(lf) ((lf) << 30) #define fwnet_set_hdr_ether_type(et) (et) #define fwnet_set_hdr_dg_size(dgs) (((dgs) - 1) << 16) #define fwnet_set_hdr_fg_off(fgo) (fgo) #define fwnet_set_hdr_dgl(dgl) ((dgl) << 16)
static inline void fwnet_make_uf_hdr(struct rfc2734_header *hdr, unsigned ether_type) { hdr->w0 = fwnet_set_hdr_lf(RFC2374_HDR_UNFRAG) | fwnet_set_hdr_ether_type(ether_type); }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason2482.76%150.00%
Stefan Richter517.24%150.00%
Total29100.00%2100.00%


static inline void fwnet_make_ff_hdr(struct rfc2734_header *hdr, unsigned ether_type, unsigned dg_size, unsigned dgl) { hdr->w0 = fwnet_set_hdr_lf(RFC2374_HDR_FIRSTFRAG) | fwnet_set_hdr_dg_size(dg_size) | fwnet_set_hdr_ether_type(ether_type); hdr->w1 = fwnet_set_hdr_dgl(dgl); }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason4285.71%150.00%
Stefan Richter714.29%150.00%
Total49100.00%2100.00%


static inline void fwnet_make_sf_hdr(struct rfc2734_header *hdr, unsigned lf, unsigned dg_size, unsigned fg_off, unsigned dgl) { hdr->w0 = fwnet_set_hdr_lf(lf) | fwnet_set_hdr_dg_size(dg_size) | fwnet_set_hdr_fg_off(fg_off); hdr->w1 = fwnet_set_hdr_dgl(dgl); }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason4688.46%150.00%
Stefan Richter611.54%150.00%
Total52100.00%2100.00%

/* This list keeps track of what parts of the datagram have been filled in */ struct fwnet_fragment_info { struct list_head fi_link; u16 offset; u16 len; }; struct fwnet_partial_datagram { struct list_head pd_link; struct list_head fi_list; struct sk_buff *skb; /* FIXME Why not use skb->data? */ char *pbuf; u16 datagram_label; u16 ether_type; u16 datagram_size; }; static DEFINE_MUTEX(fwnet_device_mutex); static LIST_HEAD(fwnet_device_list); struct fwnet_device { struct list_head dev_link; spinlock_t lock; enum { FWNET_BROADCAST_ERROR, FWNET_BROADCAST_RUNNING, FWNET_BROADCAST_STOPPED, } broadcast_state; struct fw_iso_context *broadcast_rcv_context; struct fw_iso_buffer broadcast_rcv_buffer; void **broadcast_rcv_buffer_ptrs; unsigned broadcast_rcv_next_ptr; unsigned num_broadcast_rcv_ptrs; unsigned rcv_buffer_size; /* * This value is the maximum unfragmented datagram size that can be * sent by the hardware. It already has the GASP overhead and the * unfragmented datagram header overhead calculated into it. */ unsigned broadcast_xmt_max_payload; u16 broadcast_xmt_datagramlabel; /* * The CSR address that remote nodes must send datagrams to for us to * receive them. */ struct fw_address_handler handler; u64 local_fifo; /* Number of tx datagrams that have been queued but not yet acked */ int queued_datagrams; int peer_count; struct list_head peer_list; struct fw_card *card; struct net_device *netdev; }; struct fwnet_peer { struct list_head peer_link; struct fwnet_device *dev; u64 guid; /* guarded by dev->lock */ struct list_head pd_list; /* received partial datagrams */ unsigned pdg_size; /* pd_list size */ u16 datagram_label; /* outgoing datagram label */ u16 max_payload; /* includes RFC2374_FRAG_HDR_SIZE overhead */ int node_id; int generation; unsigned speed; }; /* This is our task struct. It's used for the packet complete callback. */ struct fwnet_packet_task { struct fw_transaction transaction; struct rfc2734_header hdr; struct sk_buff *skb; struct fwnet_device *dev; int outstanding_pkts; u64 fifo_addr; u16 dest_node; u16 max_payload; u8 generation; u8 speed; u8 enqueued; }; /* * Get fifo address embedded in hwaddr */
static __u64 fwnet_hwaddr_fifo(union fwnet_hwaddr *ha) { return (u64)get_unaligned_be16(&ha->uc.fifo_hi) << 32 | get_unaligned_be32(&ha->uc.fifo_lo); }

Contributors

PersonTokensPropCommitsCommitProp
Hideaki Yoshifuji / 吉藤英明37100.00%1100.00%
Total37100.00%1100.00%

/* * saddr == NULL means use device source address. * daddr == NULL means leave destination address (eg unresolved arp). */
static int fwnet_header_create(struct sk_buff *skb, struct net_device *net, unsigned short type, const void *daddr, const void *saddr, unsigned len) { struct fwnet_header *h; h = skb_push(skb, sizeof(*h)); put_unaligned_be16(type, &h->h_proto); if (net->flags & (IFF_LOOPBACK | IFF_NOARP)) { memset(h->h_dest, 0, net->addr_len); return net->hard_header_len; } if (daddr) { memcpy(h->h_dest, daddr, net->addr_len); return net->hard_header_len; } return -net->hard_header_len; }

Contributors

PersonTokensPropCommitsCommitProp
Stefan Richter6855.28%150.00%
Jay Fenlason5544.72%150.00%
Total123100.00%2100.00%


static int fwnet_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 type) { struct net_device *net; struct fwnet_header *h; if (type == cpu_to_be16(ETH_P_802_3)) return -1; net = neigh->dev; h = (struct fwnet_header *)((u8 *)hh->hh_data + HH_DATA_OFF(sizeof(*h))); h->h_proto = type; memcpy(h->h_dest, neigh->ha, net->addr_len); hh->hh_len = FWNET_HLEN; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason8480.00%125.00%
Stefan Richter1312.38%125.00%
David S. Miller54.76%125.00%
Hideaki Yoshifuji / 吉藤英明32.86%125.00%
Total105100.00%4100.00%

/* Called by Address Resolution module to notify changes in address. */
static void fwnet_header_cache_update(struct hh_cache *hh, const struct net_device *net, const unsigned char *haddr) { memcpy((u8 *)hh->hh_data + HH_DATA_OFF(FWNET_HLEN), haddr, net->addr_len); }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason3884.44%133.33%
Stefan Richter48.89%133.33%
Hideaki Yoshifuji / 吉藤英明36.67%133.33%
Total45100.00%3100.00%


static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr) { memcpy(haddr, skb->dev->dev_addr, FWNET_ALEN); return FWNET_ALEN; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason3090.91%150.00%
Stefan Richter39.09%150.00%
Total33100.00%2100.00%

static const struct header_ops fwnet_header_ops = { .create = fwnet_header_create, .cache = fwnet_header_cache, .cache_update = fwnet_header_cache_update, .parse = fwnet_header_parse, }; /* FIXME: is this correct for all cases? */
static bool fwnet_frag_overlap(struct fwnet_partial_datagram *pd, unsigned offset, unsigned len) { struct fwnet_fragment_info *fi; unsigned end = offset + len; list_for_each_entry(fi, &pd->fi_list, fi_link) if (offset < fi->offset + fi->len && end > fi->offset) return true; return false; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason5691.80%150.00%
Stefan Richter58.20%150.00%
Total61100.00%2100.00%

/* Assumes that new fragment does not overlap any existing fragments */
static struct fwnet_fragment_info *fwnet_frag_new( struct fwnet_partial_datagram *pd, unsigned offset, unsigned len) { struct fwnet_fragment_info *fi, *fi2, *new; struct list_head *list; list = &pd->fi_list; list_for_each_entry(fi, &pd->fi_list, fi_link) { if (fi->offset + fi->len == offset) { /* The new fragment can be tacked on to the end */ /* Did the new fragment plug a hole? */ fi2 = list_entry(fi->fi_link.next, struct fwnet_fragment_info, fi_link); if (fi->offset + fi->len == fi2->offset) { /* glue fragments together */ fi->len += len + fi2->len; list_del(&fi2->fi_link); kfree(fi2); } else { fi->len += len; } return fi; } if (offset + len == fi->offset) { /* The new fragment can be tacked on to the beginning */ /* Did the new fragment plug a hole? */ fi2 = list_entry(fi->fi_link.prev, struct fwnet_fragment_info, fi_link); if (fi2->offset + fi2->len == fi->offset) { /* glue fragments together */ fi2->len += fi->len + len; list_del(&fi->fi_link); kfree(fi); return fi2; } fi->offset = offset; fi->len += len; return fi; } if (offset > fi->offset + fi->len) { list = &fi->fi_link; break; } if (offset + len < fi->offset) { list = fi->fi_link.prev; break; } } new = kmalloc(sizeof(*new), GFP_ATOMIC); if (!new) return NULL; new->offset = offset; new->len = len; list_add(&new->fi_link, list); return new; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason29594.25%150.00%
Stefan Richter185.75%150.00%
Total313100.00%2100.00%


static struct fwnet_partial_datagram *fwnet_pd_new(struct net_device *net, struct fwnet_peer *peer, u16 datagram_label, unsigned dg_size, void *frag_buf, unsigned frag_off, unsigned frag_len) { struct fwnet_partial_datagram *new; struct fwnet_fragment_info *fi; new = kmalloc(sizeof(*new), GFP_ATOMIC); if (!new) goto fail; INIT_LIST_HEAD(&new->fi_list); fi = fwnet_frag_new(new, frag_off, frag_len); if (fi == NULL) goto fail_w_new; new->datagram_label = datagram_label; new->datagram_size = dg_size; new->skb = dev_alloc_skb(dg_size + LL_RESERVED_SPACE(net)); if (new->skb == NULL) goto fail_w_fi; skb_reserve(new->skb, LL_RESERVED_SPACE(net)); new->pbuf = skb_put(new->skb, dg_size); memcpy(new->pbuf + frag_off, frag_buf, frag_len); list_add_tail(&new->pd_link, &peer->pd_list); return new; fail_w_fi: kfree(fi); fail_w_new: kfree(new); fail: return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason18289.66%133.33%
Stefan Richter157.39%133.33%
Hideaki Yoshifuji / 吉藤英明62.96%133.33%
Total203100.00%3100.00%


static struct fwnet_partial_datagram *fwnet_pd_find(struct fwnet_peer *peer, u16 datagram_label) { struct fwnet_partial_datagram *pd; list_for_each_entry(pd, &peer->pd_list, pd_link) if (pd->datagram_label == datagram_label) return pd; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason3683.72%150.00%
Stefan Richter716.28%150.00%
Total43100.00%2100.00%


static void fwnet_pd_delete(struct fwnet_partial_datagram *old) { struct fwnet_fragment_info *fi, *n; list_for_each_entry_safe(fi, n, &old->fi_list, fi_link) kfree(fi); list_del(&old->pd_link); dev_kfree_skb_any(old->skb); kfree(old); }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason4888.89%150.00%
Stefan Richter611.11%150.00%
Total54100.00%2100.00%


static bool fwnet_pd_update(struct fwnet_peer *peer, struct fwnet_partial_datagram *pd, void *frag_buf, unsigned frag_off, unsigned frag_len) { if (fwnet_frag_new(pd, frag_off, frag_len) == NULL) return false; memcpy(pd->pbuf + frag_off, frag_buf, frag_len); /* * Move list entry to beginning of list so that oldest partial * datagrams percolate to the end of the list */ list_move_tail(&pd->pd_link, &peer->pd_list); return true; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason6286.11%133.33%
Stefan Richter912.50%133.33%
Lucas De Marchi11.39%133.33%
Total72100.00%3100.00%


static bool fwnet_pd_is_complete(struct fwnet_partial_datagram *pd) { struct fwnet_fragment_info *fi; fi = list_entry(pd->fi_list.next, struct fwnet_fragment_info, fi_link); return fi->len == pd->datagram_size; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason3482.93%150.00%
Stefan Richter717.07%150.00%
Total41100.00%2100.00%

/* caller must hold dev->lock */
static struct fwnet_peer *fwnet_peer_find_by_guid(struct fwnet_device *dev, u64 guid) { struct fwnet_peer *peer; list_for_each_entry(peer, &dev->peer_list, peer_link) if (peer->guid == guid) return peer; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Stefan Richter2455.81%266.67%
Jay Fenlason1944.19%133.33%
Total43100.00%3100.00%

/* caller must hold dev->lock */
static struct fwnet_peer *fwnet_peer_find_by_node_id(struct fwnet_device *dev, int node_id, int generation) { struct fwnet_peer *peer; list_for_each_entry(peer, &dev->peer_list, peer_link) if (peer->node_id == node_id && peer->generation == generation) return peer; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Stefan Richter4280.77%266.67%
Jay Fenlason1019.23%133.33%
Total52100.00%3100.00%

/* See IEEE 1394-2008 table 6-4, table 8-8, table 16-18. */
static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed) { max_rec = min(max_rec, speed + 8); max_rec = clamp(max_rec, 8U, 11U); /* 512...4096 */ return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE; }

Contributors

PersonTokensPropCommitsCommitProp
Stefan Richter3368.75%266.67%
Jay Fenlason1531.25%133.33%
Total48100.00%3100.00%


static int fwnet_finish_incoming_packet(struct net_device *net, struct sk_buff *skb, u16 source_node_id, bool is_broadcast, u16 ether_type) { struct fwnet_device *dev; int status; __be64 guid; switch (ether_type) { case ETH_P_ARP: case ETH_P_IP: #if IS_ENABLED(CONFIG_IPV6) case ETH_P_IPV6: #endif break; default: goto err; } dev = netdev_priv(net); /* Write metadata, and then pass to the receive level */ skb->dev = net; skb->ip_summed = CHECKSUM_NONE; /* * Parse the encapsulation header. This actually does the job of * converting to an ethernet-like pseudo frame header. */ guid = cpu_to_be64(dev->card->guid); if (dev_hard_header(skb, net, ether_type, is_broadcast ? net->broadcast : net->dev_addr, NULL, skb->len) >= 0) { struct fwnet_header *eth; u16 *rawp; __be16 protocol; skb_reset_mac_header(skb); skb_pull(skb, sizeof(*eth)); eth = (struct fwnet_header *)skb_mac_header(skb); if (fwnet_hwaddr_is_multicast(eth->h_dest)) { if (memcmp(eth->h_dest, net->broadcast, net->addr_len) == 0) skb->pkt_type = PACKET_BROADCAST; #if 0 else skb->pkt_type = PACKET_MULTICAST; #endif } else { if (memcmp(eth->h_dest, net->dev_addr, net->addr_len)) skb->pkt_type = PACKET_OTHERHOST; } if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) { protocol = eth->h_proto; } else { rawp = (u16 *)skb->data; if (*rawp == 0xffff) protocol = htons(ETH_P_802_3); else protocol = htons(ETH_P_802_2); } skb->protocol = protocol; } status = netif_rx(skb); if (status == NET_RX_DROP) { net->stats.rx_errors++; net->stats.rx_dropped++; } else { net->stats.rx_packets++; net->stats.rx_bytes += skb->len; } return 0; err: net->stats.rx_errors++; net->stats.rx_dropped++; dev_kfree_skb_any(skb); return -ENOENT; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason29980.38%112.50%
Hideaki Yoshifuji / 吉藤英明4111.02%450.00%
Stefan Richter318.33%225.00%
Simon Horman10.27%112.50%
Total372100.00%8100.00%


static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, int source_node_id, int generation, bool is_broadcast) { struct sk_buff *skb; struct net_device *net = dev->netdev; struct rfc2734_header hdr; unsigned lf; unsigned long flags; struct fwnet_peer *peer; struct fwnet_partial_datagram *pd; int fg_off; int dg_size; u16 datagram_label; int retval; u16 ether_type; if (len <= RFC2374_UNFRAG_HDR_SIZE) return 0; hdr.w0 = be32_to_cpu(buf[0]); lf = fwnet_get_hdr_lf(&hdr); if (lf == RFC2374_HDR_UNFRAG) { /* * An unfragmented datagram has been received by the ieee1394 * bus. Build an skbuff around it so we can pass it to the * high level network layer. */ ether_type = fwnet_get_hdr_ether_type(&hdr); buf++; len -= RFC2374_UNFRAG_HDR_SIZE; skb = dev_alloc_skb(len + LL_RESERVED_SPACE(net)); if (unlikely(!skb)) { net->stats.rx_dropped++; return -ENOMEM; } skb_reserve(skb, LL_RESERVED_SPACE(net)); skb_put_data(skb, buf, len); return fwnet_finish_incoming_packet(net, skb, source_node_id, is_broadcast, ether_type); } /* A datagram fragment has been received, now the fun begins. */ if (len <= RFC2374_FRAG_HDR_SIZE) return 0; hdr.w1 = ntohl(buf[1]); buf += 2; len -= RFC2374_FRAG_HDR_SIZE; if (lf == RFC2374_HDR_FIRSTFRAG) { ether_type = fwnet_get_hdr_ether_type(&hdr); fg_off = 0; } else { ether_type = 0; fg_off = fwnet_get_hdr_fg_off(&hdr); } datagram_label = fwnet_get_hdr_dgl(&hdr); dg_size = fwnet_get_hdr_dg_size(&hdr); if (fg_off + len > dg_size) return 0; spin_lock_irqsave(&dev->lock, flags); peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation); if (!peer) { retval = -ENOENT; goto fail; } pd = fwnet_pd_find(peer, datagram_label); if (pd == NULL) { while (peer->pdg_size >= FWNET_MAX_FRAGMENTS) { /* remove the oldest */ fwnet_pd_delete(list_first_entry(&peer->pd_list, struct fwnet_partial_datagram, pd_link)); peer->pdg_size--; } pd = fwnet_pd_new(net, peer, datagram_label, dg_size, buf, fg_off, len); if (pd == NULL) { retval = -ENOMEM; goto fail; } peer->pdg_size++; } else { if (fwnet_frag_overlap(pd, fg_off, len) || pd->datagram_size != dg_size) { /* * Differing datagram sizes or overlapping fragments, * discard old datagram and start a new one. */ fwnet_pd_delete(pd); pd = fwnet_pd_new(net, peer, datagram_label, dg_size, buf, fg_off, len); if (pd == NULL) { peer->pdg_size--; retval = -ENOMEM; goto fail; } } else { if (!fwnet_pd_update(peer, pd, buf, fg_off, len)) { /* * Couldn't save off fragment anyway * so might as well obliterate the * datagram now. */ fwnet_pd_delete(pd); peer->pdg_size--; retval = -ENOMEM; goto fail; } } } /* new datagram or add to existing one */ if (lf == RFC2374_HDR_FIRSTFRAG) pd->ether_type = ether_type; if (fwnet_pd_is_complete(pd)) { ether_type = pd->ether_type; peer->pdg_size--; skb = skb_get(pd->skb); fwnet_pd_delete(pd); spin_unlock_irqrestore(&dev->lock, flags); return fwnet_finish_incoming_packet(net, skb, source_node_id, false, ether_type); } /* * Datagram is not complete, we're done for the * moment. */ retval = 0; fail: spin_unlock_irqrestore(&dev->lock, flags); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason45374.02%112.50%
Stefan Richter15224.84%562.50%
Hideaki Yoshifuji / 吉藤英明60.98%112.50%
Johannes Berg10.16%112.50%
Total612100.00%8100.00%


static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r, int tcode, int destination, int source, int generation, unsigned long long offset, void *payload, size_t length, void *callback_data) { struct fwnet_device *dev = callback_data; int rcode; if (destination == IEEE1394_ALL_NODES) { kfree(r); return; } if (offset != dev->handler.offset) rcode = RCODE_ADDRESS_ERROR; else if (tcode != TCODE_WRITE_BLOCK_REQUEST) rcode = RCODE_TYPE_ERROR; else if (fwnet_incoming_packet(dev, payload, length, source, generation, false) != 0) { dev_err(&dev->netdev->dev, "incoming packet failure\n"); rcode = RCODE_CONFLICT_ERROR; } else rcode = RCODE_COMPLETE; fw_send_response(card, r, rcode); }

Contributors

PersonTokensPropCommitsCommitProp
Jay Fenlason8860.69%120.00%
Stefan Richter5739.31%480.00%
Total145100.00%5100.00%


static int gasp_source_id(__be32 *p) { return be32_to_cpu(p[0]) >> 16; }

Contributors

PersonTokensPropCommitsCommitProp
Stefan Richter21100.00%1100.00%
Total21100.00%1100.00%


static