diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/scsi/fc/fc_fip.h | 237 | ||||
-rw-r--r-- | include/scsi/fc_transport_fcoe.h | 54 | ||||
-rw-r--r-- | include/scsi/libfc.h | 45 | ||||
-rw-r--r-- | include/scsi/libfcoe.h | 227 |
4 files changed, 395 insertions, 168 deletions
diff --git a/include/scsi/fc/fc_fip.h b/include/scsi/fc/fc_fip.h new file mode 100644 index 00000000000..0627a9ae634 --- /dev/null +++ b/include/scsi/fc/fc_fip.h @@ -0,0 +1,237 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef _FC_FIP_H_ +#define _FC_FIP_H_ + +/* + * This version is based on: + * http://www.t11.org/ftp/t11/pub/fc/bb-5/08-543v1.pdf + */ + +/* + * The FIP ethertype eventually goes in net/if_ether.h. + */ +#ifndef ETH_P_FIP +#define ETH_P_FIP 0x8914 /* FIP Ethertype */ +#endif + +#define FIP_DEF_PRI 128 /* default selection priority */ +#define FIP_DEF_FC_MAP 0x0efc00 /* default FCoE MAP (MAC OUI) value */ +#define FIP_DEF_FKA 8000 /* default FCF keep-alive/advert period (mS) */ +#define FIP_VN_KA_PERIOD 90000 /* required VN_port keep-alive period (mS) */ +#define FIP_FCF_FUZZ 100 /* random time added by FCF (mS) */ + +/* + * Multicast MAC addresses. T11-adopted. + */ +#define FIP_ALL_FCOE_MACS ((u8[6]) { 1, 0x10, 0x18, 1, 0, 0 }) +#define FIP_ALL_ENODE_MACS ((u8[6]) { 1, 0x10, 0x18, 1, 0, 1 }) +#define FIP_ALL_FCF_MACS ((u8[6]) { 1, 0x10, 0x18, 1, 0, 2 }) + +#define FIP_VER 1 /* version for fip_header */ + +struct fip_header { + __u8 fip_ver; /* upper 4 bits are the version */ + __u8 fip_resv1; /* reserved */ + __be16 fip_op; /* operation code */ + __u8 fip_resv2; /* reserved */ + __u8 fip_subcode; /* lower 4 bits are sub-code */ + __be16 fip_dl_len; /* length of descriptors in words */ + __be16 fip_flags; /* header flags */ +} __attribute__((packed)); + +#define FIP_VER_SHIFT 4 +#define FIP_VER_ENCAPS(v) ((v) << FIP_VER_SHIFT) +#define FIP_VER_DECAPS(v) ((v) >> FIP_VER_SHIFT) +#define FIP_BPW 4 /* bytes per word for lengths */ + +/* + * fip_op. + */ +enum fip_opcode { + FIP_OP_DISC = 1, /* discovery, advertisement, etc. */ + FIP_OP_LS = 2, /* Link Service request or reply */ + FIP_OP_CTRL = 3, /* Keep Alive / Link Reset */ + FIP_OP_VLAN = 4, /* VLAN discovery */ + FIP_OP_VENDOR_MIN = 0xfff8, /* min vendor-specific opcode */ + FIP_OP_VENDOR_MAX = 0xfffe, /* max vendor-specific opcode */ +}; + +/* + * Subcodes for FIP_OP_DISC. + */ +enum fip_disc_subcode { + FIP_SC_SOL = 1, /* solicitation */ + FIP_SC_ADV = 2, /* advertisement */ +}; + +/* + * Subcodes for FIP_OP_LS. + */ +enum fip_trans_subcode { + FIP_SC_REQ = 1, /* request */ + FIP_SC_REP = 2, /* reply */ +}; + +/* + * Subcodes for FIP_OP_RESET. + */ +enum fip_reset_subcode { + FIP_SC_KEEP_ALIVE = 1, /* keep-alive from VN_Port */ + FIP_SC_CLR_VLINK = 2, /* clear virtual link from VF_Port */ +}; + +/* + * Subcodes for FIP_OP_VLAN. + */ +enum fip_vlan_subcode { + FIP_SC_VL_REQ = 1, /* request */ + FIP_SC_VL_REP = 2, /* reply */ +}; + +/* + * flags in header fip_flags. + */ +enum fip_flag { + FIP_FL_FPMA = 0x8000, /* supports FPMA fabric-provided MACs */ + FIP_FL_SPMA = 0x4000, /* supports SPMA server-provided MACs */ + FIP_FL_AVAIL = 0x0004, /* available for FLOGI/ELP */ + FIP_FL_SOL = 0x0002, /* this is a solicited message */ + FIP_FL_FPORT = 0x0001, /* sent from an F port */ +}; + +/* + * Common descriptor header format. + */ +struct fip_desc { + __u8 fip_dtype; /* type - see below */ + __u8 fip_dlen; /* length - in 32-bit words */ +}; + +enum fip_desc_type { + FIP_DT_PRI = 1, /* priority for forwarder selection */ + FIP_DT_MAC = 2, /* MAC address */ + FIP_DT_MAP_OUI = 3, /* FC-MAP OUI */ + FIP_DT_NAME = 4, /* switch name or node name */ + FIP_DT_FAB = 5, /* fabric descriptor */ + FIP_DT_FCOE_SIZE = 6, /* max FCoE frame size */ + FIP_DT_FLOGI = 7, /* FLOGI request or response */ + FIP_DT_FDISC = 8, /* FDISC request or response */ + FIP_DT_LOGO = 9, /* LOGO request or response */ + FIP_DT_ELP = 10, /* ELP request or response */ + FIP_DT_VN_ID = 11, /* VN_Node Identifier */ + FIP_DT_FKA = 12, /* advertisement keep-alive period */ + FIP_DT_VENDOR = 13, /* vendor ID */ + FIP_DT_VLAN = 14, /* vlan number */ + FIP_DT_LIMIT, /* max defined desc_type + 1 */ + FIP_DT_VENDOR_BASE = 128, /* first vendor-specific desc_type */ +}; + +/* + * FIP_DT_PRI - priority descriptor. + */ +struct fip_pri_desc { + struct fip_desc fd_desc; + __u8 fd_resvd; + __u8 fd_pri; /* FCF priority: higher is better */ +} __attribute__((packed)); + +/* + * FIP_DT_MAC - MAC address descriptor. + */ +struct fip_mac_desc { + struct fip_desc fd_desc; + __u8 fd_mac[ETH_ALEN]; +} __attribute__((packed)); + +/* + * FIP_DT_MAP - descriptor. + */ +struct fip_map_desc { + struct fip_desc fd_desc; + __u8 fd_resvd[3]; + __u8 fd_map[3]; +} __attribute__((packed)); + +/* + * FIP_DT_NAME descriptor. + */ +struct fip_wwn_desc { + struct fip_desc fd_desc; + __u8 fd_resvd[2]; + __be64 fd_wwn; /* 64-bit WWN, unaligned */ +} __attribute__((packed)); + +/* + * FIP_DT_FAB descriptor. + */ +struct fip_fab_desc { + struct fip_desc fd_desc; + __be16 fd_vfid; /* virtual fabric ID */ + __u8 fd_resvd; + __u8 fd_map[3]; /* FC-MAP value */ + __be64 fd_wwn; /* fabric name, unaligned */ +} __attribute__((packed)); + +/* + * FIP_DT_FCOE_SIZE descriptor. + */ +struct fip_size_desc { + struct fip_desc fd_desc; + __be16 fd_size; +} __attribute__((packed)); + +/* + * Descriptor that encapsulates an ELS or ILS frame. + * The encapsulated frame immediately follows this header, without + * SOF, EOF, or CRC. + */ +struct fip_encaps { + struct fip_desc fd_desc; + __u8 fd_resvd[2]; +} __attribute__((packed)); + +/* + * FIP_DT_VN_ID - VN_Node Identifier descriptor. + */ +struct fip_vn_desc { + struct fip_desc fd_desc; + __u8 fd_mac[ETH_ALEN]; + __u8 fd_resvd; + __u8 fd_fc_id[3]; + __be64 fd_wwpn; /* port name, unaligned */ +} __attribute__((packed)); + +/* + * FIP_DT_FKA - Advertisement keep-alive period. + */ +struct fip_fka_desc { + struct fip_desc fd_desc; + __u8 fd_resvd[2]; + __be32 fd_fka_period; /* adv./keep-alive period in mS */ +} __attribute__((packed)); + +/* + * FIP_DT_VENDOR descriptor. + */ +struct fip_vendor_desc { + struct fip_desc fd_desc; + __u8 fd_resvd[2]; + __u8 fd_vendor_id[8]; +} __attribute__((packed)); + +#endif /* _FC_FIP_H_ */ diff --git a/include/scsi/fc_transport_fcoe.h b/include/scsi/fc_transport_fcoe.h deleted file mode 100644 index 8dca2af14ff..00000000000 --- a/include/scsi/fc_transport_fcoe.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef FC_TRANSPORT_FCOE_H -#define FC_TRANSPORT_FCOE_H - -#include <linux/device.h> -#include <linux/netdevice.h> -#include <scsi/scsi_host.h> -#include <scsi/libfc.h> - -/** - * struct fcoe_transport - FCoE transport struct for generic transport - * for Ethernet devices as well as pure HBAs - * - * @name: name for thsi transport - * @bus: physical bus type (pci_bus_type) - * @driver: physical bus driver for network device - * @create: entry create function - * @destroy: exit destroy function - * @list: list of transports - */ -struct fcoe_transport { - char *name; - unsigned short vendor; - unsigned short device; - struct bus_type *bus; - struct device_driver *driver; - int (*create)(struct net_device *device); - int (*destroy)(struct net_device *device); - bool (*match)(struct net_device *device); - struct list_head list; - struct list_head devlist; - struct mutex devlock; -}; - -/** - * MODULE_ALIAS_FCOE_PCI - * - * some care must be taken with this, vendor and device MUST be a hex value - * preceded with 0x and with letters in lower case (0x12ab, not 0x12AB or 12AB) - */ -#define MODULE_ALIAS_FCOE_PCI(vendor, device) \ - MODULE_ALIAS("fcoe-pci-" __stringify(vendor) "-" __stringify(device)) - -/* exported funcs */ -int fcoe_transport_attach(struct net_device *netdev); -int fcoe_transport_release(struct net_device *netdev); -int fcoe_transport_register(struct fcoe_transport *t); -int fcoe_transport_unregister(struct fcoe_transport *t); -int fcoe_load_transport_driver(struct net_device *netdev); -int __init fcoe_transport_init(void); -int __exit fcoe_transport_exit(void); - -/* fcow_sw is the default transport */ -extern struct fcoe_transport fcoe_sw_transport; -#endif /* FC_TRANSPORT_FCOE_H */ diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index a70eafaad08..0303a6a098c 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -22,6 +22,7 @@ #include <linux/timer.h> #include <linux/if.h> +#include <linux/percpu.h> #include <scsi/scsi_transport.h> #include <scsi/scsi_transport_fc.h> @@ -661,7 +662,8 @@ struct fc_lport { unsigned long boot_time; struct fc_host_statistics host_stats; - struct fcoe_dev_stats *dev_stats[NR_CPUS]; + struct fcoe_dev_stats *dev_stats; + u64 wwpn; u64 wwnn; u8 retry_count; @@ -694,11 +696,6 @@ struct fc_lport { /* * FC_LPORT HELPER FUNCTIONS *****************************/ -static inline void *lport_priv(const struct fc_lport *lp) -{ - return (void *)(lp + 1); -} - static inline int fc_lport_test_ready(struct fc_lport *lp) { return lp->state == LPORT_ST_READY; @@ -722,6 +719,42 @@ static inline void fc_lport_state_enter(struct fc_lport *lp, lp->state = state; } +static inline int fc_lport_init_stats(struct fc_lport *lp) +{ + /* allocate per cpu stats block */ + lp->dev_stats = alloc_percpu(struct fcoe_dev_stats); + if (!lp->dev_stats) + return -ENOMEM; + return 0; +} + +static inline void fc_lport_free_stats(struct fc_lport *lp) +{ + free_percpu(lp->dev_stats); +} + +static inline struct fcoe_dev_stats *fc_lport_get_stats(struct fc_lport *lp) +{ + return per_cpu_ptr(lp->dev_stats, smp_processor_id()); +} + +static inline void *lport_priv(const struct fc_lport *lp) +{ + return (void *)(lp + 1); +} + +/** + * libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport + * @sht: ptr to the scsi host templ + * @priv_size: size of private data after fc_lport + * + * Returns: ptr to Scsi_Host + */ +static inline struct Scsi_Host * +libfc_host_alloc(struct scsi_host_template *sht, int priv_size) +{ + return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size); +} /* * LOCAL PORT LAYER diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index c41f7d0c6ef..666cc131732 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -1,5 +1,6 @@ /* - * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. + * Copyright (c) 2008-2009 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2007-2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,134 +21,144 @@ #ifndef _LIBFCOE_H #define _LIBFCOE_H +#include <linux/etherdevice.h> +#include <linux/if_ether.h> #include <linux/netdevice.h> #include <linux/skbuff.h> +#include <linux/workqueue.h> #include <scsi/fc/fc_fcoe.h> #include <scsi/libfc.h> /* - * this percpu struct for fcoe + * FIP tunable parameters. */ -struct fcoe_percpu_s { - int cpu; - struct task_struct *thread; - struct sk_buff_head fcoe_rx_list; - struct page *crc_eof_page; - int crc_eof_offset; +#define FCOE_CTLR_START_DELAY 2000 /* mS after first adv. to choose FCF */ +#define FCOE_CTRL_SOL_TOV 2000 /* min. solicitation interval (mS) */ +#define FCOE_CTLR_FCF_LIMIT 20 /* max. number of FCF entries */ + +/** + * enum fip_state - internal state of FCoE controller. + * @FIP_ST_DISABLED: controller has been disabled or not yet enabled. + * @FIP_ST_LINK_WAIT: the physical link is down or unusable. + * @FIP_ST_AUTO: determining whether to use FIP or non-FIP mode. + * @FIP_ST_NON_FIP: non-FIP mode selected. + * @FIP_ST_ENABLED: FIP mode selected. + */ +enum fip_state { + FIP_ST_DISABLED, + FIP_ST_LINK_WAIT, + FIP_ST_AUTO, + FIP_ST_NON_FIP, + FIP_ST_ENABLED, }; -/* - * the fcoe sw transport private data +/** + * struct fcoe_ctlr - FCoE Controller and FIP state. + * @state: internal FIP state for network link and FIP or non-FIP mode. + * @lp: &fc_lport: libfc local port. + * @sel_fcf: currently selected FCF, or NULL. + * @fcfs: list of discovered FCFs. + * @fcf_count: number of discovered FCF entries. + * @sol_time: time when a multicast solicitation was last sent. + * @sel_time: time after which to select an FCF. + * @port_ka_time: time of next port keep-alive. + * @ctlr_ka_time: time of next controller keep-alive. + * @timer: timer struct used for all delayed events. + * @link_work: &work_struct for doing FCF selection. + * @recv_work: &work_struct for receiving FIP frames. + * @fip_recv_list: list of received FIP frames. + * @user_mfs: configured maximum FC frame size, including FC header. + * @flogi_oxid: exchange ID of most recent fabric login. + * @flogi_count: number of FLOGI attempts in AUTO mode. + * @link: current link status for libfc. + * @last_link: last link state reported to libfc. + * @map_dest: use the FC_MAP mode for destination MAC addresses. + * @dest_addr: MAC address of the selected FC forwarder. + * @ctl_src_addr: the native MAC address of our local port. + * @data_src_addr: the assigned MAC address for the local port after FLOGI. + * @send: LLD-supplied function to handle sending of FIP Ethernet frames. + * @update_mac: LLD-supplied function to handle changes to MAC addresses. + * @lock: lock protecting this structure. + * + * This structure is used by all FCoE drivers. It contains information + * needed by all FCoE low-level drivers (LLDs) as well as internal state + * for FIP, and fields shared with the LLDS. */ -struct fcoe_softc { - struct list_head list; +struct fcoe_ctlr { + enum fip_state state; struct fc_lport *lp; - struct net_device *real_dev; - struct net_device *phys_dev; /* device with ethtool_ops */ - struct packet_type fcoe_packet_type; - struct sk_buff_head fcoe_pending_queue; - u8 fcoe_pending_queue_active; - + struct fcoe_fcf *sel_fcf; + struct list_head fcfs; + u16 fcf_count; + unsigned long sol_time; + unsigned long sel_time; + unsigned long port_ka_time; + unsigned long ctlr_ka_time; + struct timer_list timer; + struct work_struct link_work; + struct work_struct recv_work; + struct sk_buff_head fip_recv_list; + u16 user_mfs; + u16 flogi_oxid; + u8 flogi_count; + u8 link; + u8 last_link; + u8 map_dest; u8 dest_addr[ETH_ALEN]; u8 ctl_src_addr[ETH_ALEN]; u8 data_src_addr[ETH_ALEN]; - /* - * fcoe protocol address learning related stuff - */ - u16 flogi_oxid; - u8 flogi_progress; - u8 address_mode; -}; - -static inline struct net_device *fcoe_netdev( - const struct fc_lport *lp) -{ - return ((struct fcoe_softc *)lport_priv(lp))->real_dev; -} - -static inline struct fcoe_hdr *skb_fcoe_header(const struct sk_buff *skb) -{ - return (struct fcoe_hdr *)skb_network_header(skb); -} - -static inline int skb_fcoe_offset(const struct sk_buff *skb) -{ - return skb_network_offset(skb); -} - -static inline struct fc_frame_header *skb_fc_header(const struct sk_buff *skb) -{ - return (struct fc_frame_header *)skb_transport_header(skb); -} - -static inline int skb_fc_offset(const struct sk_buff *skb) -{ - return skb_transport_offset(skb); -} -static inline void skb_reset_fc_header(struct sk_buff *skb) -{ - skb_reset_network_header(skb); - skb_set_transport_header(skb, skb_network_offset(skb) + - sizeof(struct fcoe_hdr)); -} - -static inline bool skb_fc_is_data(const struct sk_buff *skb) -{ - return skb_fc_header(skb)->fh_r_ctl == FC_RCTL_DD_SOL_DATA; -} - -static inline bool skb_fc_is_cmd(const struct sk_buff *skb) -{ - return skb_fc_header(skb)->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD; -} + void (*send)(struct fcoe_ctlr *, struct sk_buff *); + void (*update_mac)(struct fcoe_ctlr *, u8 *old, u8 *new); + spinlock_t lock; +}; -static inline bool skb_fc_has_exthdr(const struct sk_buff *skb) -{ - return (skb_fc_header(skb)->fh_r_ctl == FC_RCTL_VFTH) || - (skb_fc_header(skb)->fh_r_ctl == FC_RCTL_IFRH) || - (skb_fc_header(skb)->fh_r_ctl == FC_RCTL_ENCH); -} +/* + * struct fcoe_fcf - Fibre-Channel Forwarder. + * @list: list linkage. + * @time: system time (jiffies) when an advertisement was last received. + * @switch_name: WWN of switch from advertisement. + * @fabric_name: WWN of fabric from advertisement. + * @fc_map: FC_MAP value from advertisement. + * @fcf_mac: Ethernet address of the FCF. + * @vfid: virtual fabric ID. + * @pri: seletion priority, smaller values are better. + * @flags: flags received from advertisement. + * @fka_period: keep-alive period, in jiffies. + * + * A Fibre-Channel Forwarder (FCF) is the entity on the Ethernet that + * passes FCoE frames on to an FC fabric. This structure represents + * one FCF from which advertisements have been received. + * + * When looking up an FCF, @switch_name, @fabric_name, @fc_map, @vfid, and + * @fcf_mac together form the lookup key. + */ +struct fcoe_fcf { + struct list_head list; + unsigned long time; -static inline bool skb_fc_is_roff(const struct sk_buff *skb) -{ - return skb_fc_header(skb)->fh_f_ctl[2] & FC_FC_REL_OFF; -} + u64 switch_name; + u64 fabric_name; + u32 fc_map; + u16 vfid; + u8 fcf_mac[ETH_ALEN]; -static inline u16 skb_fc_oxid(const struct sk_buff *skb) -{ - return be16_to_cpu(skb_fc_header(skb)->fh_ox_id); -} + u8 pri; + u16 flags; + u32 fka_period; +}; -static inline u16 skb_fc_rxid(const struct sk_buff *skb) -{ - return be16_to_cpu(skb_fc_header(skb)->fh_rx_id); -} +/* FIP API functions */ +void fcoe_ctlr_init(struct fcoe_ctlr *); +void fcoe_ctlr_destroy(struct fcoe_ctlr *); +void fcoe_ctlr_link_up(struct fcoe_ctlr *); +int fcoe_ctlr_link_down(struct fcoe_ctlr *); +int fcoe_ctlr_els_send(struct fcoe_ctlr *, struct sk_buff *); +void fcoe_ctlr_recv(struct fcoe_ctlr *, struct sk_buff *); +int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_frame *fp, u8 *sa); /* libfcoe funcs */ -int fcoe_reset(struct Scsi_Host *shost); -u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], - unsigned int scheme, unsigned int port); - -u32 fcoe_fc_crc(struct fc_frame *fp); -int fcoe_xmit(struct fc_lport *, struct fc_frame *); -int fcoe_rcv(struct sk_buff *, struct net_device *, - struct packet_type *, struct net_device *); - -int fcoe_percpu_receive_thread(void *arg); -void fcoe_clean_pending_queue(struct fc_lport *lp); -void fcoe_percpu_clean(struct fc_lport *lp); -void fcoe_watchdog(ulong vp); -int fcoe_link_ok(struct fc_lport *lp); - -struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); -int fcoe_hostlist_add(const struct fc_lport *); -int fcoe_hostlist_remove(const struct fc_lport *); - -struct Scsi_Host *fcoe_host_alloc(struct scsi_host_template *, int); +u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); int fcoe_libfc_config(struct fc_lport *, struct libfc_function_template *); -/* fcoe sw hba */ -int __init fcoe_sw_init(void); -int __exit fcoe_sw_exit(void); #endif /* _LIBFCOE_H */ |