[Open-FCoE] [RFC PATCH 1/4] libfcoe: move common functions/structures from fcoe

Bhanu Gollapudi bprakash at broadcom.com
Fri Jan 21 23:41:37 UTC 2011


On Thu, 2011-01-20 at 23:56 -0800, Zou, Yi wrote:

Thanks for your review comments, Yi.


> > To facilitate LLDDs to reuse the code, skb queue related functions are
> > moved to
> > libfcoe, so that both fcoe and bnx2fc drivers can use them. The common
> > structures
> > fcoe_port, fcoe_percpu_s are moved to libfcoe. fcoe_port will now have an
> > opaque pointer that points to corresponding driver's interface structure.
> 
> 
> fcoe_ctrl.c is all FIP codes, it'd make more sense to have these codes in
> a separate c file.

yes, you're right. how about using fcoe_transport.c?

> 
> >
> > Signed-off-by: Nithin Nayak Sujir <nsujir at broadcom.com>
> > Signed-off-by: Bhanu Prakash Gollapudi <bprakash at broadcom.com>
> > ---
> >  drivers/scsi/fcoe/fcoe.c      |  159 +++++------------------------------
> > -----
> >  drivers/scsi/fcoe/fcoe.h      |   45 +-----------
> >  drivers/scsi/fcoe/fcoe_ctlr.c |  138 +++++++++++++++++++++++++++++++++++
> >  include/scsi/libfcoe.h        |   45 ++++++++++++
> >  4 files changed, 205 insertions(+), 182 deletions(-)
> >
> > diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
> > index e753027..62df94e 100644
> > --- a/drivers/scsi/fcoe/fcoe.c
> > +++ b/drivers/scsi/fcoe/fcoe.c
> > @@ -72,7 +72,6 @@ static int fcoe_xmit(struct fc_lport *, struct fc_frame
> > *);
> >  static int fcoe_rcv(struct sk_buff *, struct net_device *,
> >                   struct packet_type *, struct net_device *);
> >  static int fcoe_percpu_receive_thread(void *);
> > -static void fcoe_clean_pending_queue(struct fc_lport *);
> >  static void fcoe_percpu_clean(struct fc_lport *);
> >  static int fcoe_link_speed_update(struct fc_lport *);
> >  static int fcoe_link_ok(struct fc_lport *);
> > @@ -80,7 +79,6 @@ static int fcoe_link_ok(struct fc_lport *);
> >  static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
> >  static int fcoe_hostlist_add(const struct fc_lport *);
> >
> > -static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *);
> >  static int fcoe_device_notification(struct notifier_block *, ulong, void
> > *);
> >  static void fcoe_dev_setup(void);
> >  static void fcoe_dev_cleanup(void);
> > @@ -502,7 +500,7 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip,
> > struct sk_buff *skb)
> >  static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr)
> >  {
> >       struct fcoe_port *port = lport_priv(lport);
> > -     struct fcoe_interface *fcoe = port->fcoe;
> > +     struct fcoe_interface *fcoe = port->priv;
> Is renaming 'fcoe' really necessary?

I wanted the reader knows that it is an opaque pointer.

> 
> 
> >
> >       rtnl_lock();
> >       if (!is_zero_ether_addr(port->data_src_addr))
> > @@ -558,17 +556,6 @@ static int fcoe_lport_config(struct fc_lport *lport)
> >  }
> >
> >  /**
> > - * fcoe_queue_timer() - The fcoe queue timer
> > - * @lport: The local port
> > - *
> > - * Calls fcoe_check_wait_queue on timeout
> > - */
> > -static void fcoe_queue_timer(ulong lport)
> > -{
> > -     fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
> > -}
> > -
> > -/**
> >   * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
> >   * @netdev: the associated net device
> >   * @wwn: the output WWN
> > @@ -647,7 +634,7 @@ static int fcoe_netdev_config(struct fc_lport *lport,
> > struct net_device *netdev)
> >
> >       /* Setup lport private data to point to fcoe softc */
> >       port = lport_priv(lport);
> > -     fcoe = port->fcoe;
> > +     fcoe = port->priv;
> >
> >       /*
> >        * Determine max frame size based on underlying device and optional
> > @@ -757,7 +744,7 @@ bool fcoe_oem_match(struct fc_frame *fp)
> >  static inline int fcoe_em_config(struct fc_lport *lport)
> >  {
> >       struct fcoe_port *port = lport_priv(lport);
> > -     struct fcoe_interface *fcoe = port->fcoe;
> > +     struct fcoe_interface *fcoe = port->priv;
> >       struct fcoe_interface *oldfcoe = NULL;
> >       struct net_device *old_real_dev, *cur_real_dev;
> >       u16 min_xid = FCOE_MIN_XID;
> > @@ -841,7 +828,7 @@ skip_oem:
> >  static void fcoe_if_destroy(struct fc_lport *lport)
> >  {
> >       struct fcoe_port *port = lport_priv(lport);
> > -     struct fcoe_interface *fcoe = port->fcoe;
> > +     struct fcoe_interface *fcoe = port->priv;
> >       struct net_device *netdev = fcoe->netdev;
> >
> >       FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
> > @@ -962,7 +949,7 @@ static struct fc_lport *fcoe_if_create(struct
> > fcoe_interface *fcoe,
> >       }
> >       port = lport_priv(lport);
> >       port->lport = lport;
> > -     port->fcoe = fcoe;
> > +     port->priv = fcoe;
> >       INIT_WORK(&port->destroy_work, fcoe_destroy_work);
> >
> >       /* configure a fc_lport including the exchange manager */
> > @@ -1358,50 +1345,22 @@ err2:
> >  }
> >
> >  /**
> > - * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer
> > CRC
> > + * fcoe_alloc_paged_crc_eof() - Allocate a page to be used for the
> > trailer CRC
> >   * @skb:  The packet to be transmitted
> >   * @tlen: The total length of the trailer
> >   *
> > - * This routine allocates a page for frame trailers. The page is re-used
> > if
> > - * there is enough room left on it for the current trailer. If there
> > isn't
> > - * enough buffer left a new page is allocated for the trailer. Reference
> > to
> > - * the page from this function as well as the skbs using the page
> > fragments
> > - * ensure that the page is freed at the appropriate time.
> > - *
> >   * Returns: 0 for success
> >   */
> > -static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
> > +static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen)
> >  {
> >       struct fcoe_percpu_s *fps;
> > -     struct page *page;
> > +     int rc;
> >
> >       fps = &get_cpu_var(fcoe_percpu);
> > -     page = fps->crc_eof_page;
> > -     if (!page) {
> > -             page = alloc_page(GFP_ATOMIC);
> > -             if (!page) {
> > -                     put_cpu_var(fcoe_percpu);
> > -                     return -ENOMEM;
> > -             }
> > -             fps->crc_eof_page = page;
> > -             fps->crc_eof_offset = 0;
> > -     }
> > -
> > -     get_page(page);
> > -     skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
> > -                        fps->crc_eof_offset, tlen);
> > -     skb->len += tlen;
> > -     skb->data_len += tlen;
> > -     skb->truesize += tlen;
> > -     fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
> > -
> > -     if (fps->crc_eof_offset >= PAGE_SIZE) {
> > -             fps->crc_eof_page = NULL;
> > -             fps->crc_eof_offset = 0;
> > -             put_page(page);
> > -     }
> > +     rc = fcoe_get_paged_crc_eof(skb, tlen, fps);
> >       put_cpu_var(fcoe_percpu);
> > -     return 0;
> > +
> > +     return rc;
> >  }
> >
> >  /**
> > @@ -1424,7 +1383,7 @@ int fcoe_xmit(struct fc_lport *lport, struct
> > fc_frame *fp)
> >       unsigned int tlen;              /* trailer length */
> >       unsigned int elen;              /* eth header, may include vlan */
> >       struct fcoe_port *port = lport_priv(lport);
> > -     struct fcoe_interface *fcoe = port->fcoe;
> > +     struct fcoe_interface *fcoe = port->priv;
> >       u8 sof, eof;
> >       struct fcoe_hdr *hp;
> >
> > @@ -1465,7 +1424,7 @@ int fcoe_xmit(struct fc_lport *lport, struct
> > fc_frame *fp)
> >       /* copy port crc and eof to the skb buff */
> >       if (skb_is_nonlinear(skb)) {
> >               skb_frag_t *frag;
> > -             if (fcoe_get_paged_crc_eof(skb, tlen)) {
> > +             if (fcoe_alloc_paged_crc_eof(skb, tlen)) {
> >                       kfree_skb(skb);
> >                       return -ENOMEM;
> >               }
> > @@ -1574,7 +1533,7 @@ static inline int fcoe_filter_frames(struct
> > fc_lport *lport,
> >       if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type ==
> > FC_TYPE_FCP)
> >               return 0;
> >
> > -     fcoe = ((struct fcoe_port *)lport_priv(lport))->fcoe;
> > +     fcoe = ((struct fcoe_port *)lport_priv(lport))->priv;
> >       if (is_fip_mode(&fcoe->ctlr) && fc_frame_payload_op(fp) == ELS_LOGO
> > &&
> >           ntoh24(fh->fh_s_id) == FC_FID_FLOGI) {
> >               FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n");
> > @@ -1709,64 +1668,6 @@ int fcoe_percpu_receive_thread(void *arg)
> >  }
> >
> >  /**
> > - * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
> > - * @lport: The local port whose backlog is to be cleared
> > - *
> > - * This empties the wait_queue, dequeues the head of the wait_queue
> > queue
> > - * and calls fcoe_start_io() for each packet. If all skb have been
> > - * transmitted it returns the qlen. If an error occurs it restores
> > - * wait_queue (to try again later) and returns -1.
> > - *
> > - * The wait_queue is used when the skb transmit fails. The failed skb
> > - * will go in the wait_queue which will be emptied by the timer function
> > or
> > - * by the next skb transmit.
> > - */
> > -static void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff
> > *skb)
> > -{
> > -     struct fcoe_port *port = lport_priv(lport);
> > -     int rc;
> > -
> > -     spin_lock_bh(&port->fcoe_pending_queue.lock);
> > -
> > -     if (skb)
> > -             __skb_queue_tail(&port->fcoe_pending_queue, skb);
> > -
> > -     if (port->fcoe_pending_queue_active)
> > -             goto out;
> > -     port->fcoe_pending_queue_active = 1;
> > -
> > -     while (port->fcoe_pending_queue.qlen) {
> > -             /* keep qlen > 0 until fcoe_start_io succeeds */
> > -             port->fcoe_pending_queue.qlen++;
> > -             skb = __skb_dequeue(&port->fcoe_pending_queue);
> > -
> > -             spin_unlock_bh(&port->fcoe_pending_queue.lock);
> > -             rc = fcoe_start_io(skb);
> > -             spin_lock_bh(&port->fcoe_pending_queue.lock);
> > -
> > -             if (rc) {
> > -                     __skb_queue_head(&port->fcoe_pending_queue, skb);
> > -                     /* undo temporary increment above */
> > -                     port->fcoe_pending_queue.qlen--;
> > -                     break;
> > -             }
> > -             /* undo temporary increment above */
> > -             port->fcoe_pending_queue.qlen--;
> > -     }
> > -
> > -     if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
> > -             lport->qfull = 0;
> > -     if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
> > -             mod_timer(&port->timer, jiffies + 2);
> > -     port->fcoe_pending_queue_active = 0;
> > -out:
> > -     if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
> > -             lport->qfull = 1;
> > -     spin_unlock_bh(&port->fcoe_pending_queue.lock);
> > -     return;
> > -}
> > -
> > -/**
> >   * fcoe_dev_setup() - Setup the link change notification interface
> >   */
> >  static void fcoe_dev_setup(void)
> > @@ -2104,8 +2005,7 @@ out_nodev:
> >   */
> >  int fcoe_link_speed_update(struct fc_lport *lport)
> >  {
> > -     struct fcoe_port *port = lport_priv(lport);
> > -     struct net_device *netdev = port->fcoe->netdev;
> > +     struct net_device *netdev = fcoe_netdev(lport);
> >       struct ethtool_cmd ecmd = { ETHTOOL_GSET };
> >
> >       if (!dev_ethtool_get_settings(netdev, &ecmd)) {
> > @@ -2136,8 +2036,7 @@ int fcoe_link_speed_update(struct fc_lport *lport)
> >   */
> >  int fcoe_link_ok(struct fc_lport *lport)
> >  {
> > -     struct fcoe_port *port = lport_priv(lport);
> > -     struct net_device *netdev = port->fcoe->netdev;
> > +     struct net_device *netdev = fcoe_netdev(lport);
> >
> >       if (netif_oper_up(netdev))
> >               return 0;
> > @@ -2201,24 +2100,6 @@ void fcoe_percpu_clean(struct fc_lport *lport)
> >  }
> >
> >  /**
> > - * fcoe_clean_pending_queue() - Dequeue a skb and free it
> > - * @lport: The local port to dequeue a skb on
> > - */
> > -void fcoe_clean_pending_queue(struct fc_lport *lport)
> > -{
> > -     struct fcoe_port  *port = lport_priv(lport);
> > -     struct sk_buff *skb;
> > -
> > -     spin_lock_bh(&port->fcoe_pending_queue.lock);
> > -     while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
> > -             spin_unlock_bh(&port->fcoe_pending_queue.lock);
> > -             kfree_skb(skb);
> > -             spin_lock_bh(&port->fcoe_pending_queue.lock);
> > -     }
> > -     spin_unlock_bh(&port->fcoe_pending_queue.lock);
> > -}
> > -
> > -/**
> >   * fcoe_reset() - Reset a local port
> >   * @shost: The SCSI host associated with the local port to be reset
> >   *
> > @@ -2285,7 +2166,7 @@ static int fcoe_hostlist_add(const struct fc_lport
> > *lport)
> >       fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
> >       if (!fcoe) {
> >               port = lport_priv(lport);
> > -             fcoe = port->fcoe;
> > +             fcoe = port->priv;
> >               list_add_tail(&fcoe->list, &fcoe_hostlist);
> >       }
> >       return 0;
> > @@ -2471,7 +2352,7 @@ static struct fc_seq *fcoe_elsct_send(struct
> > fc_lport *lport, u32 did,
> >                                     void *arg, u32 timeout)
> >  {
> >       struct fcoe_port *port = lport_priv(lport);
> > -     struct fcoe_interface *fcoe = port->fcoe;
> > +     struct fcoe_interface *fcoe = port->priv;
> >       struct fcoe_ctlr *fip = &fcoe->ctlr;
> >       struct fc_frame_header *fh = fc_frame_header_get(fp);
> >
> > @@ -2504,7 +2385,7 @@ static int fcoe_vport_create(struct fc_vport
> > *vport, bool disabled)
> >       struct Scsi_Host *shost = vport_to_shost(vport);
> >       struct fc_lport *n_port = shost_priv(shost);
> >       struct fcoe_port *port = lport_priv(n_port);
> > -     struct fcoe_interface *fcoe = port->fcoe;
> > +     struct fcoe_interface *fcoe = port->priv;
> >       struct net_device *netdev = fcoe->netdev;
> >       struct fc_lport *vn_port;
> >
> > @@ -2648,7 +2529,7 @@ static void fcoe_set_port_id(struct fc_lport
> > *lport,
> >                            u32 port_id, struct fc_frame *fp)
> >  {
> >       struct fcoe_port *port = lport_priv(lport);
> > -     struct fcoe_interface *fcoe = port->fcoe;
> > +     struct fcoe_interface *fcoe = port->priv;
> >
> >       if (fp && fc_frame_payload_op(fp) == ELS_FLOGI)
> >               fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp);
> > diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
> > index c69b2c5..1d02820 100644
> > --- a/drivers/scsi/fcoe/fcoe.h
> > +++ b/drivers/scsi/fcoe/fcoe.h
> > @@ -23,9 +23,6 @@
> >  #include <linux/skbuff.h>
> >  #include <linux/kthread.h>
> >
> > -#define FCOE_MAX_QUEUE_DEPTH 256
> > -#define FCOE_LOW_QUEUE_DEPTH 32
> > -
> >  #define FCOE_WORD_TO_BYTE    4
> >
> >  #define FCOE_VERSION "0.1"
> > @@ -71,21 +68,6 @@ do {
> >       \
> >                                 netdev->name, ##args);)
> >
> >  /**
> > - * struct fcoe_percpu_s - The per-CPU context for FCoE receive threads
> > - * @thread:      The thread context
> > - * @fcoe_rx_list:   The queue of pending packets to process
> > - * @page:        The memory page for calculating frame trailer CRCs
> > - * @crc_eof_offset: The offset into the CRC page pointing to available
> > - *               memory for a new trailer
> > - */
> > -struct fcoe_percpu_s {
> > -     struct task_struct *thread;
> > -     struct sk_buff_head fcoe_rx_list;
> > -     struct page *crc_eof_page;
> > -     int crc_eof_offset;
> > -};
> > -
> > -/**
> >   * struct fcoe_interface - A FCoE interface
> >   * @list:          Handle for a list of FCoE interfaces
> >   * @netdev:        The associated net device
> > @@ -108,30 +90,6 @@ struct fcoe_interface {
> >       struct kref        kref;
> >  };
> >
> > -/**
> > - * struct fcoe_port - The FCoE private structure
> > - * @fcoe:                   The associated fcoe interface
> > - * @lport:                  The associated local port
> > - * @fcoe_pending_queue:             The pending Rx queue of skbs
> > - * @fcoe_pending_queue_active: Indicates if the pending queue is active
> > - * @timer:                  The queue timer
> > - * @destroy_work:           Handle for work context
> > - *                          (to prevent RTNL deadlocks)
> > - * @data_srt_addr:          Source address for data
> > - *
> > - * An instance of this structure is to be allocated along with the
> > - * Scsi_Host and libfc fc_lport structures.
> > - */
> > -struct fcoe_port {
> > -     struct fcoe_interface *fcoe;
> > -     struct fc_lport       *lport;
> > -     struct sk_buff_head   fcoe_pending_queue;
> > -     u8                    fcoe_pending_queue_active;
> > -     struct timer_list     timer;
> > -     struct work_struct    destroy_work;
> > -     u8                    data_src_addr[ETH_ALEN];
> > -};
> > -
> >  #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface,
> > ctlr)
> >
> >  /**
> > @@ -140,7 +98,8 @@ struct fcoe_port {
> >   */
> >  static inline struct net_device *fcoe_netdev(const struct fc_lport
> > *lport)
> >  {
> > -     return ((struct fcoe_port *)lport_priv(lport))->fcoe->netdev;
> > +     return ((struct fcoe_interface *)
> > +                     ((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
> >  }
> >
> >  #endif /* _FCOE_H_ */
> > diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c
> > b/drivers/scsi/fcoe/fcoe_ctlr.c
> > index fd10037..e7b7a70 100644
> > --- a/drivers/scsi/fcoe/fcoe_ctlr.c
> > +++ b/drivers/scsi/fcoe/fcoe_ctlr.c
> > @@ -49,6 +49,8 @@
> >
> >  #define      FCOE_CTLR_MIN_FKA       500             /* min keep alive (mS) */
> >  #define      FCOE_CTLR_DEF_FKA       FIP_DEF_FKA     /* default keep alive (mS) */
> > +#define FCOE_LOW_QUEUE_DEPTH 32
> > +#define FCOE_MAX_QUEUE_DEPTH 256
> 
> This seems more LLD specific, will it be more beneficial to make them
> part of fcoe_port struct?

OK. We can do that.

> 
> Yi
> 
> >
> >  static void fcoe_ctlr_timeout(unsigned long);
> >  static void fcoe_ctlr_timer_work(struct work_struct *);
> > @@ -2743,3 +2745,139 @@ int fcoe_start_io(struct sk_buff *skb)
> >       return 0;
> >  }
> >  EXPORT_SYMBOL_GPL(fcoe_start_io);
> > +
> > +/**
> > + * fcoe_clean_pending_queue() - Dequeue a skb and free it
> > + * @lport: The local port to dequeue a skb on
> > + */
> > +void fcoe_clean_pending_queue(struct fc_lport *lport)
> > +{
> > +     struct fcoe_port  *port = lport_priv(lport);
> > +     struct sk_buff *skb;
> > +
> > +     spin_lock_bh(&port->fcoe_pending_queue.lock);
> > +     while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
> > +             spin_unlock_bh(&port->fcoe_pending_queue.lock);
> > +             kfree_skb(skb);
> > +             spin_lock_bh(&port->fcoe_pending_queue.lock);
> > +     }
> > +     spin_unlock_bh(&port->fcoe_pending_queue.lock);
> > +}
> > +EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
> > +
> > +/**
> > + * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
> > + * @lport: The local port whose backlog is to be cleared
> > + *
> > + * This empties the wait_queue, dequeues the head of the wait_queue
> > queue
> > + * and calls fcoe_start_io() for each packet. If all skb have been
> > + * transmitted it returns the qlen. If an error occurs it restores
> > + * wait_queue (to try again later) and returns -1.
> > + *
> > + * The wait_queue is used when the skb transmit fails. The failed skb
> > + * will go in the wait_queue which will be emptied by the timer function
> > or
> > + * by the next skb transmit.
> > + */
> > +void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
> > +{
> > +     struct fcoe_port *port = lport_priv(lport);
> > +     int rc;
> > +
> > +     spin_lock_bh(&port->fcoe_pending_queue.lock);
> > +
> > +     if (skb)
> > +             __skb_queue_tail(&port->fcoe_pending_queue, skb);
> > +
> > +     if (port->fcoe_pending_queue_active)
> > +             goto out;
> > +     port->fcoe_pending_queue_active = 1;
> > +
> > +     while (port->fcoe_pending_queue.qlen) {
> > +             /* keep qlen > 0 until fcoe_start_io succeeds */
> > +             port->fcoe_pending_queue.qlen++;
> > +             skb = __skb_dequeue(&port->fcoe_pending_queue);
> > +
> > +             spin_unlock_bh(&port->fcoe_pending_queue.lock);
> > +             rc = fcoe_start_io(skb);
> > +             spin_lock_bh(&port->fcoe_pending_queue.lock);
> > +
> > +             if (rc) {
> > +                     __skb_queue_head(&port->fcoe_pending_queue, skb);
> > +                     /* undo temporary increment above */
> > +                     port->fcoe_pending_queue.qlen--;
> > +                     break;
> > +             }
> > +             /* undo temporary increment above */
> > +             port->fcoe_pending_queue.qlen--;
> > +     }
> > +
> > +     if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
> > +             lport->qfull = 0;
> > +     if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
> > +             mod_timer(&port->timer, jiffies + 2);
> > +     port->fcoe_pending_queue_active = 0;
> > +out:
> > +     if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
> > +             lport->qfull = 1;
> > +     spin_unlock_bh(&port->fcoe_pending_queue.lock);
> > +}
> > +EXPORT_SYMBOL_GPL(fcoe_check_wait_queue);
> > +
> > +/**
> > + * fcoe_queue_timer() - The fcoe queue timer
> > + * @lport: The local port
> > + *
> > + * Calls fcoe_check_wait_queue on timeout
> > + */
> > +void fcoe_queue_timer(ulong lport)
> > +{
> > +     fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
> > +}
> > +EXPORT_SYMBOL_GPL(fcoe_queue_timer);
> > +
> > +/**
> > + * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer
> > CRC
> > + * @skb:  The packet to be transmitted
> > + * @tlen: The total length of the trailer
> > + * @fps:  The fcoe context
> > + *
> > + * This routine allocates a page for frame trailers. The page is re-used
> > if
> > + * there is enough room left on it for the current trailer. If there
> > isn't
> > + * enough buffer left a new page is allocated for the trailer. Reference
> > to
> > + * the page from this function as well as the skbs using the page
> > fragments
> > + * ensure that the page is freed at the appropriate time.
> > + *
> > + * Returns: 0 for success
> > + */
> > +int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
> > +                        struct fcoe_percpu_s *fps)
> > +{
> > +     struct page *page;
> > +
> > +     page = fps->crc_eof_page;
> > +     if (!page) {
> > +             page = alloc_page(GFP_ATOMIC);
> > +             if (!page)
> > +                     return -ENOMEM;
> > +
> > +             fps->crc_eof_page = page;
> > +             fps->crc_eof_offset = 0;
> > +     }
> > +
> > +     get_page(page);
> > +     skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
> > +                        fps->crc_eof_offset, tlen);
> > +     skb->len += tlen;
> > +     skb->data_len += tlen;
> > +     skb->truesize += tlen;
> > +     fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
> > +
> > +     if (fps->crc_eof_offset >= PAGE_SIZE) {
> > +             fps->crc_eof_page = NULL;
> > +             fps->crc_eof_offset = 0;
> > +             put_page(page);
> > +     }
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof);
> > diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
> > index da64ca6..17fffdf 100644
> > --- a/include/scsi/libfcoe.h
> > +++ b/include/scsi/libfcoe.h
> > @@ -264,6 +264,51 @@ struct fcoe_transport {
> >  };
> >
> >  /**
> > + * struct fcoe_percpu_s - The context for FCoE receive thread(s)
> > + * @thread:      The thread context
> > + * @fcoe_rx_list:   The queue of pending packets to process
> > + * @page:        The memory page for calculating frame trailer CRCs
> > + * @crc_eof_offset: The offset into the CRC page pointing to available
> > + *               memory for a new trailer
> > + */
> > +struct fcoe_percpu_s {
> > +     struct task_struct *thread;
> > +     struct sk_buff_head fcoe_rx_list;
> > +     struct page *crc_eof_page;
> > +     int crc_eof_offset;
> > +};
> > +
> > +/**
> > + * struct fcoe_port - The FCoE private structure
> > + * @priv:                   The associated fcoe interface. The structure is
> > + *                          defined by the low level driver
> > + * @lport:                  The associated local port
> > + * @fcoe_pending_queue:             The pending Rx queue of skbs
> > + * @fcoe_pending_queue_active: Indicates if the pending queue is active
> > + * @timer:                  The queue timer
> > + * @destroy_work:           Handle for work context
> > + *                          (to prevent RTNL deadlocks)
> > + * @data_srt_addr:          Source address for data
> > + *
> > + * An instance of this structure is to be allocated along with the
> > + * Scsi_Host and libfc fc_lport structures.
> > + */
> > +struct fcoe_port {
> > +     void                  *priv;
> > +     struct fc_lport       *lport;
> > +     struct sk_buff_head   fcoe_pending_queue;
> > +     u8                    fcoe_pending_queue_active;
> > +     struct timer_list     timer;
> > +     struct work_struct    destroy_work;
> > +     u8                    data_src_addr[ETH_ALEN];
> > +};
> > +void fcoe_clean_pending_queue(struct fc_lport *);
> > +void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb);
> > +void fcoe_queue_timer(ulong lport);
> > +int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
> > +                        struct fcoe_percpu_s *fps);
> > +
> > +/**
> >   * struct netdev_list
> >   * A mapping from netdevice to fcoe_transport
> >   */
> > --
> > 1.7.0.6
> >
> >
> >
> >
> > _______________________________________________
> > devel mailing list
> > devel at open-fcoe.org
> > https://lists.open-fcoe.org/mailman/listinfo/devel
> 






More information about the devel mailing list