diff options
author | Robert Love <robert.w.love@intel.com> | 2008-12-09 15:10:24 -0800 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-12-29 11:24:33 -0600 |
commit | 85b4aa4926a50210b683ac89326e338e7d131211 (patch) | |
tree | 127b6586573194f2d37b5a298e12c8b7d24a6fac /include/scsi | |
parent | 42e9a92fe6a9095bd68a379aaec7ad2be0337f7a (diff) |
[SCSI] fcoe: Fibre Channel over Ethernet
Encapsulation protocol for running Fibre Channel over Ethernet interfaces.
Creates virtual Fibre Channel host adapters using libfc.
This layer is the LLD to the scsi-ml. It allocates the Scsi_Host, utilizes
libfc for Fibre Channel protocol processing and interacts with netdev to
send/receive Ethernet packets.
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'include/scsi')
-rw-r--r-- | include/scsi/fc_transport_fcoe.h | 54 | ||||
-rw-r--r-- | include/scsi/libfcoe.h | 176 |
2 files changed, 230 insertions, 0 deletions
diff --git a/include/scsi/fc_transport_fcoe.h b/include/scsi/fc_transport_fcoe.h new file mode 100644 index 000000000000..8dca2af14ffc --- /dev/null +++ b/include/scsi/fc_transport_fcoe.h @@ -0,0 +1,54 @@ +#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/libfcoe.h b/include/scsi/libfcoe.h new file mode 100644 index 000000000000..89fdbb9a6a1b --- /dev/null +++ b/include/scsi/libfcoe.h @@ -0,0 +1,176 @@ +/* + * 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _LIBFCOE_H +#define _LIBFCOE_H + +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <scsi/fc/fc_fcoe.h> +#include <scsi/libfc.h> + +/* + * this percpu struct for fcoe + */ +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; +}; + +/* + * the fcoe sw transport private data + */ +struct fcoe_softc { + struct list_head list; + 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 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 fcoe_softc *fcoe_softc( + const struct fc_lport *lp) +{ + return (struct fcoe_softc *)lport_priv(lp); +} + +static inline struct net_device *fcoe_netdev( + const struct fc_lport *lp) +{ + return fcoe_softc(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; +} + +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); +} + +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; +} + +static inline u16 skb_fc_oxid(const struct sk_buff *skb) +{ + return be16_to_cpu(skb_fc_header(skb)->fh_ox_id); +} + +static inline u16 skb_fc_rxid(const struct sk_buff *skb) +{ + return be16_to_cpu(skb_fc_header(skb)->fh_rx_id); +} + +/* FIXME - DMA_BIDIRECTIONAL ? */ +#define skb_cb(skb) ((struct fcoe_rcv_info *)&((skb)->cb[0])) +#define skb_cmd(skb) (skb_cb(skb)->fr_cmd) +#define skb_dir(skb) (skb_cmd(skb)->sc_data_direction) +static inline bool skb_fc_is_read(const struct sk_buff *skb) +{ + if (skb_fc_is_cmd(skb) && skb_cmd(skb)) + return skb_dir(skb) == DMA_FROM_DEVICE; + return false; +} + +static inline bool skb_fc_is_write(const struct sk_buff *skb) +{ + if (skb_fc_is_cmd(skb) && skb_cmd(skb)) + return skb_dir(skb) == DMA_TO_DEVICE; + return false; +} + +/* 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); +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 */ |