Open-FCoE fixes and features for 2.6.30 merge window
Subsystems (3)
cover Open-FCoE fixes and features for 2.6.30 merge window
The following series implements a few fixes, some preparation work and the implementation of FIP.
1) Fix of CPU hotplug handling.
2) Removal of fc_transport_fcoe.[ch]. This code was written so a LLD could load a transport for Ethernet devices that support FCoE offloads. This aproach was discarded in favor of directly providing offload capabilities through netdev. FCoE offload patches have been Ack'd by netdev and are in the scsi-misc tree already. In this set we just clean up the previous and unused FCoE transport method.
3) fcoe/* reorgainzation. Since both FIP and fnic are targeting the 2.6.30 merge window we wanted to do some cleanup of the fcoe layer. We've better defined each module so that fcoe.ko will only have the netdev related SW implementation (fnic does not use) and libfcoe.ko which will have common FCoE routines available to all FCoE LLDs.
4) FIP implementation. FIP == FCoE Initialization Protocol. This is a new standard way to discover FCoE capable switches. This code becomes the majority of libfcoe.ko. These patches had previously been sent to linux-scsi. This series resends them as they've been slightly modified to better fit into the reorganization. Functionality is the same as previously posted.
This patchset is built on scsi-misc-2.6 and are intended for 2.6.30.
---
Joe Eykholt (2):
fcoe, libfcoe: Add support for FIP. FCoE discovery and keep-alive.
fcoe: Add a header file defining the FIP protocol for FCoE.
Robert Love (4):
fcoe: create/destroy fcoe Rx threads on CPU hotplug events
fcoe: Use per-CPU kernel function for dev_stats instead of an array
fcoe: Use percpu kernel funcs for struct fcoe_percpu_s
fcoe: Initialize all possilbe skb_queue(s) when module is loaded
Vasu Dev (8):
fcoe, libfc: fix double fcoe_softc memory alloc
fcoe: cleans up libfcoe.h and adds fcoe.h for fcoe module
fcoe: moves common FCoE library API functions to libfcoe module fcoe, libfc, scsi: adds libfcoe module
fcoe: renames libfcoe.c to fcoe.c as the only fcoe module file
fcoe: removes default sw transport code file fcoe_sw.c
fcoe: removes fc_transport_fcoe.[ch] code files
fcoe: prep work to completely remove fc_transport_fcoe code
drivers/scsi/Kconfig | 8 drivers/scsi/Makefile | 1 drivers/scsi/fcoe/Makefile | 8 drivers/scsi/fcoe/fc_transport_fcoe.c | 443 ------- drivers/scsi/fcoe/fcoe.c | 1865 ++++++++++++++++++++++++++++ drivers/scsi/fcoe/fcoe.h | 75 + drivers/scsi/fcoe/fcoe_sw.c | 561 -------- drivers/scsi/fcoe/libfcoe.c | 2216 +++++++++++++++------------------ drivers/scsi/libfc/fc_fcp.c | 10 drivers/scsi/libfc/fc_lport.c | 11 include/scsi/fc/fc_fip.h | 237 ++++ include/scsi/fc_transport_fcoe.h | 54 - include/scsi/libfc.h | 45 + include/scsi/libfcoe.h | 227 ++- 14 files changed, 3396 insertions(+), 2365 deletions(-) delete mode 100644 drivers/scsi/fcoe/fc_transport_fcoe.c create mode 100644 drivers/scsi/fcoe/fcoe.c create mode 100644 drivers/scsi/fcoe/fcoe.h delete mode 100644 drivers/scsi/fcoe/fcoe_sw.c create mode 100644 include/scsi/fc/fc_fip.h delete mode 100644 include/scsi/fc_transport_fcoe.h
Signature · 1 line
//Rob
PATCH 1/14 fcoe: Initialize all possilbe skb_queue(s) when module is loaded
Currently the skb_queue is initialized every time the associated CPU goes online. This patch has libfcoe initializing the skb_queue for all possible CPUs when the module is loaded.
This patch also re-orders some declarations in the fcoe_rcv() function so the structure declarations are grouped before the primitive declarations.
Lastly, this patch converts all CPU indicies to use unsigned int since CPU indicies should not be negative.
---
drivers/scsi/fcoe/libfcoe.c | 21 ++++++++++++--------- include/scsi/libfcoe.h | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-)
drivers/scsi/fcoe/libfcoe.c +12 -9
@@ -97,7 +97,7 @@ static struct notifier_block fcoe_cpu_notifier = {* * Returns: none */ -static void fcoe_create_percpu_data (int cpu) +static void fcoe_create_percpu_data (unsigned int cpu) {struct fc_lport *lp;struct fcoe_softc *fc;
@@ -121,7 +121,7 @@ static void fcoe_create_percpu_data(int cpu)* * Retuns: none */ -static void fcoe_destroy_percpu_data (int cpu) +static void fcoe_destroy_percpu_data (unsigned int cpu) {struct fc_lport *lp;struct fcoe_softc *fc;
@@ -183,9 +183,9 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,struct fcoe_softc *fc;struct fcoe_dev_stats *stats;struct fc_frame_header *fh; -unsigned short oxid; -int cpu_idx;struct fcoe_percpu_s *fps; +unsigned short oxid; +unsigned int cpu_idx; fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type); lp = fc->lp;
@@ -292,7 +292,7 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) {struct fcoe_percpu_s *fps;struct page *page; -int cpu_idx; +unsigned int cpu_idx; cpu_idx =get_cpu (); fps = fcoe_percpu[cpu_idx];
@@ -1366,10 +1366,9 @@ EXPORT_SYMBOL_GPL(fcoe_libfc_config);*/ static int __init fcoe_init (void ) { -int cpu; +unsigned int cpu;struct fcoe_percpu_s *p; -INIT_LIST_HEAD (&fcoe_hostlist);rwlock_init (&fcoe_hostlist_lock);
@@ -1377,6 +1376,12 @@ static int __init fcoe_init(void)register_cpu_notifier (&fcoe_cpu_notifier);#endif /* CONFIG_HOTPLUG_CPU */ +for_each_possible_cpu (cpu) { + p = fcoe_percpu[cpu]; + p->cpu = cpu; +skb_queue_head_init (&p->fcoe_rx_list); + } +/* * initialize per CPU interrupt thread */
@@ -1392,9 +1397,7 @@ static int __init fcoe_init(void)* initialize the semaphore and skb queue head */ if (likely (!IS_ERR (p->thread))) { - p->cpu = cpu; fcoe_percpu[cpu] = p; -skb_queue_head_init (&p->fcoe_rx_list);kthread_bind (p->thread, cpu);wake_up_process (p->thread); }else {
include/scsi/libfcoe.h +1 -1
@@ -29,7 +29,7 @@* this percpu struct for fcoe */ struct fcoe_percpu_s { -int cpu; +unsigned int cpu;struct task_struct *thread;struct sk_buff_head fcoe_rx_list;struct page *crc_eof_page;
PATCH 3/14 fcoe: Use per-CPU kernel function for dev_stats instead of an array
In reply to Robert LoveRemove the hotplug creation of dev_stats, we allocate for all possible CPUs now when we allocate the lport.
---
drivers/scsi/fcoe/fcoe_sw.c | 13 +--- drivers/scsi/fcoe/libfcoe.c | 143 +++++------------------------------------ drivers/scsi/libfc/fc_fcp.c | 8 +- drivers/scsi/libfc/fc_lport.c | 11 ++- include/scsi/libfc.h | 23 ++++++- 5 files changed, 53 insertions(+), 145 deletions(-)
drivers/scsi/fcoe/fcoe_sw.c +2 -11
@@ -113,8 +113,6 @@ static struct scsi_host_template fcoe_sw_shost_template = {*/ static int fcoe_sw_lport_config (struct fc_lport *lp) { -int i =0 ; - lp->link_up =0 ; lp->qfull =0 ; lp->max_retry_count =3 ;
@@ -123,12 +121,7 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) lp->service_params = (FCP_SPPF_INIT_FCN |FCP_SPPF_RD_XRDY_DIS |FCP_SPPF_RETRY |FCP_SPPF_CONF_COMPL ); -/* -* allocate per cpu stats block -*/ -for_each_online_cpu (i) - lp->dev_stats[i] =kzalloc (sizeof (struct fcoe_dev_stats ), -GFP_KERNEL ); +fc_lport_init_stats (lp);/* lport fc_lport related configuration */ fc_lport_config (lp);
@@ -311,7 +304,6 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp)*/ static int fcoe_sw_destroy (struct net_device *netdev) { -int cpu;struct fc_lport *lp =NULL ;struct fcoe_softc *fc;u8 flogi_maddr[ETH_ALEN ];
@@ -363,8 +355,7 @@ static int fcoe_sw_destroy(struct net_device *netdev)fcoe_clean_pending_queue (lp);/* Free memory used by statistical counters */ -for_each_online_cpu (cpu) -kfree (lp->dev_stats[cpu]); +fc_lport_free_stats (lp);/* Release the net_device and Scsi_Host */ dev_put (fc->real_dev);
drivers/scsi/fcoe/libfcoe.c +18 -125
212 lines not on this page · raw message
drivers/scsi/libfc/fc_fcp.c +5 -3
@@ -407,10 +407,12 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)if (~crc !=le32_to_cpu (fr_crc (fp))) { crc_err: - stats = lp->dev_stats[smp_processor_id ()]; + stats =fc_lport_get_stats (lp); stats->ErrorFrames++; +/* FIXME - per cpu count, not total count! */ if (stats->InvalidCRCCount++ <5 ) -FC_DBG ("CRC error on data frame\n" ); +printk (KERN_WARNING "CRC error on data frame for port (%6x)\n" , +fc_host_port_id (lp->host));/* * Assume the frame is total garbage. * We may have copied it over the good part
@@ -1752,7 +1754,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))/* * setup the data direction */ - stats = lp->dev_stats[smp_processor_id ()]; + stats =fc_lport_get_stats (lp);if (sc_cmd->sc_data_direction ==DMA_FROM_DEVICE ) { fsp->req_flags =FC_SRB_READ ; stats->InputRequests++;
drivers/scsi/libfc/fc_lport.c +6 -5
@@ -267,10 +267,10 @@ EXPORT_SYMBOL(fc_get_host_speed);struct fc_host_statistics *fc_get_host_stats (struct Scsi_Host *shost) { -int i;struct fc_host_statistics *fcoe_stats;struct fc_lport *lp =shost_priv (shost);struct timespec v0, v1; +unsigned int cpu; fcoe_stats = &lp->host_stats;memset (fcoe_stats,0 ,sizeof (struct fc_host_statistics ));
@@ -279,10 +279,11 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)jiffies_to_timespec (lp->boot_time, &v1); fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec); -for_each_online_cpu (i) { -struct fcoe_dev_stats *stats = lp->dev_stats[i]; -if (stats ==NULL ) -continue ; +for_each_possible_cpu (cpu) { +struct fcoe_dev_stats *stats; + + stats =percpu_ptr (lp->dev_stats, cpu); + fcoe_stats->tx_frames += stats->TxFrames; fcoe_stats->tx_words += stats->TxWords; fcoe_stats->rx_frames += stats->RxFrames;
include/scsi/libfc.h +22 -1
@@ -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;
@@ -722,6 +724,25 @@ 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 ()); +} +/* * LOCAL PORT LAYER
PATCH 4/14 fcoe: create/destroy fcoe Rx threads on CPU hotplug events
In reply to Robert LoveThis patch adds support for dynamically created Rx threads upon CPU hotplug events.
There were existing synchronization problems that this patch attempts to resolve. The main problem had to do with fcoe_rcv() running in a different context than the hotplug notifications. This opened the possiblity that fcoe_rcv() would target a Rx thread for a skb. However, that thread could become NULL if the CPU was made offline.
This patch uses the Rx queue's (a skb_queue) lock to protect the thread it's associated with and we use the 'thread' member of the fcoe_percpu_s to determine if the thread is ready to accept new skbs.
The patch also attempts to do a better job of cleaning up, both if hotplug registration fails as well as when the module is removed.
Contribution provided by Joe Eykholt <[email protected]> to fix incorrect use of __cpuinitdata.
---
drivers/scsi/fcoe/libfcoe.c | 246 +++++++++++++++++++++++++++++++++++-------- 1 files changed, 199 insertions(+), 47 deletions(-)
drivers/scsi/fcoe/libfcoe.c +199 -47
@@ -81,6 +81,156 @@ static struct notifier_block fcoe_notifier = { };/** +* fcoe_percpu_thread_create() - Create a receive thread for an online cpu +* @cpu: cpu index for the online cpu +*/ +static void fcoe_percpu_thread_create (unsigned int cpu) +{ +struct fcoe_percpu_s *p; +struct task_struct *thread; + + p = &per_cpu (fcoe_percpu, cpu); + + thread =kthread_create (fcoe_percpu_receive_thread, + (void *)p,"fcoethread/%d" , cpu); + +if (likely (!IS_ERR (p->thread))) { +kthread_bind (thread, cpu); +wake_up_process (thread); + +spin_lock_bh (&p->fcoe_rx_list.lock); + p->thread = thread; +spin_unlock_bh (&p->fcoe_rx_list.lock); + } +} + +/** +* fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu +* @cpu: cpu index the rx thread is to be removed +* +* Destroys a per-CPU Rx thread. Any pending skbs are moved to the +* current CPU's Rx thread. If the thread being destroyed is bound to +* the CPU processing this context the skbs will be freed. +*/ +static void fcoe_percpu_thread_destroy (unsigned int cpu) +{ +struct fcoe_percpu_s *p; +struct task_struct *thread; +struct page *crc_eof; +struct sk_buff *skb; +#ifdef CONFIG_SMP +struct fcoe_percpu_s *p0; +unsigned targ_cpu =smp_processor_id (); +#endif /* CONFIG_SMP */ + +printk (KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n" , cpu); + +/* Prevent any new skbs from being queued for this CPU. */ + p = &per_cpu (fcoe_percpu, cpu); +spin_lock_bh (&p->fcoe_rx_list.lock); + thread = p->thread; + p->thread =NULL ; + crc_eof = p->crc_eof_page; + p->crc_eof_page =NULL ; + p->crc_eof_offset =0 ; +spin_unlock_bh (&p->fcoe_rx_list.lock); + +#ifdef CONFIG_SMP +/* +* Don't bother moving the skb's if this context is running +* on the same CPU that is having its thread destroyed. This +* can easily happen when the module is removed. +*/ +if (cpu != targ_cpu) { + p0 = &per_cpu (fcoe_percpu, targ_cpu); +spin_lock_bh (&p0->fcoe_rx_list.lock); +if (p0->thread) { +FC_DBG ("Moving frames from CPU %d to CPU %d\n" , + cpu, targ_cpu); + +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +__skb_queue_tail (&p0->fcoe_rx_list, skb); +spin_unlock_bh (&p0->fcoe_rx_list.lock); + }else { +/* +* The targeted CPU is not initialized and cannot accept +* new skbs. Unlock the targeted CPU and drop the skbs +* on the CPU that is going offline. +*/ +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p0->fcoe_rx_list.lock); + } + }else { +/* +* This scenario occurs when the module is being removed +* and all threads are being destroyed. skbs will continue +* to be shifted from the CPU thread that is being removed +* to the CPU thread associated with the CPU that is processing +* the module removal. Once there is only one CPU Rx thread it +* will reach this case and we will drop all skbs and later +* stop the thread. +*/ +spin_lock_bh (&p->fcoe_rx_list.lock); +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p->fcoe_rx_list.lock); + } +#else +/* +* This a non-SMP scenario where the singluar Rx thread is +* being removed. Free all skbs and stop the thread. +*/ +spin_lock_bh (&p->fcoe_rx_list.lock); +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p->fcoe_rx_list.lock); +#endif + +if (thread) +kthread_stop (thread); + +if (crc_eof) +put_page (crc_eof); +} + +/** +* fcoe_cpu_callback() - fcoe cpu hotplug event callback +* @nfb: callback data block +* @action: event triggering the callback +* @hcpu: index for the cpu of this event +* +* This creates or destroys per cpu data for fcoe +* +* Returns NOTIFY_OK always. +*/ +static int fcoe_cpu_callback (struct notifier_block *nfb, +unsigned long action,void *hcpu) +{ +unsigned cpu = (unsigned long )hcpu; + +switch (action) { +case CPU_ONLINE : +case CPU_ONLINE_FROZEN : +FC_DBG ("CPU %x online: Create Rx thread\n" , cpu); +fcoe_percpu_thread_create (cpu); +break ; +case CPU_DEAD : +case CPU_DEAD_FROZEN : +FC_DBG ("CPU %x offline: Remove Rx thread\n" , cpu); +fcoe_percpu_thread_destroy (cpu); +break ; +default : +break ; + } +return NOTIFY_OK ; +} + +static struct notifier_block fcoe_cpu_notifier = { + .notifier_call = fcoe_cpu_callback, +}; + +/** * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ * @skb: the receive skb * @dev: associated net device
@@ -100,7 +250,7 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,struct fc_frame_header *fh;struct fcoe_percpu_s *fps;unsigned short oxid; -unsigned int cpu_idx; +unsigned int cpu =0 ; fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type); lp = fc->lp;
@@ -140,25 +290,42 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, fr =fcoe_dev_from_skb (skb); fr->fr_dev = lp; fr->ptype = ptype; - cpu_idx =0 ;#ifdef CONFIG_SMP /* * The incoming frame exchange id(oxid) is ANDed with num of online -* cpu bits to get cpu_idx and then this cpu_idx is used for selecting -* a per cpu kernel thread from fcoe_percpu. In case the cpu is -* offline or no kernel thread for derived cpu_idx then cpu_idx is -* initialize to first online cpu index. +* cpu bits to get cpu and then this cpu is used for selecting +* a per cpu kernel thread from fcoe_percpu. */ - cpu_idx = oxid & (num_online_cpus () -1 ); -if (!cpu_online (cpu_idx)) - cpu_idx =first_cpu (cpu_online_map); - + cpu = oxid & (num_online_cpus () -1 );#endif - fps = &per_cpu (fcoe_percpu, cpu_idx); - + fps = &per_cpu (fcoe_percpu, cpu);spin_lock_bh (&fps->fcoe_rx_list.lock); +if (unlikely (!fps->thread)) { +/* +* The targeted CPU is not ready, let's target +* the first CPU now. For non-SMP systems this +* will check the same CPU twice. +*/ +FC_DBG ("CPU is online, but no receive thread ready " +"for incoming skb- using first online CPU.\n" ); + +spin_unlock_bh (&fps->fcoe_rx_list.lock); + cpu =first_cpu (cpu_online_map); + fps = &per_cpu (fcoe_percpu, cpu); +spin_lock_bh (&fps->fcoe_rx_list.lock); +if (!fps->thread) { +spin_unlock_bh (&fps->fcoe_rx_list.lock); + goto err; + } + } + +/* +* We now have a valid CPU that we're targeting for +* this skb. We also have this receive thread locked, +* so we're free to queue skbs into it's queue. +*/ __skb_queue_tail (&fps->fcoe_rx_list, skb);if (fps->fcoe_rx_list.qlen ==1 )wake_up_process (fps->thread);
@@ -214,7 +381,7 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)return -ENOMEM ; } fps->crc_eof_page = page; -WARN_ON (fps->crc_eof_offset !=0 ); + fps->crc_eof_offset =0 ; }get_page (page);
@@ -1271,6 +1438,7 @@ EXPORT_SYMBOL_GPL(fcoe_libfc_config);static int __init fcoe_init (void ) {unsigned int cpu; +int rc =0 ;struct fcoe_percpu_s *p;INIT_LIST_HEAD (&fcoe_hostlist);
@@ -1281,29 +1449,15 @@ static int __init fcoe_init(void)skb_queue_head_init (&p->fcoe_rx_list); } -/* -* initialize per CPU interrupt thread -*/ -for_each_online_cpu (cpu) { - p = &per_cpu (fcoe_percpu, cpu); - p->thread =kthread_create (fcoe_percpu_receive_thread, - (void *)p,"fcoethread/%d" , cpu); +for_each_online_cpu (cpu) +fcoe_percpu_thread_create (cpu); -/* -* If there is no error then bind the thread to the CPU -* and wake it up. -*/ -if (!IS_ERR (p->thread)) { -kthread_bind (p->thread, cpu); -wake_up_process (p->thread); - }else { - p->thread =NULL ; - } - } +/* Initialize per CPU interrupt thread */ + rc =register_hotcpu_notifier (&fcoe_cpu_notifier); +if (rc) + goto out_free; -/* -* setup link change notification -*/ +/* Setup link change notification */ fcoe_dev_setup ();setup_timer (&fcoe_timer, fcoe_watchdog,0 );
@@ -1316,6 +1470,13 @@ static int __init fcoe_init(void)fcoe_sw_init ();return 0 ; + +out_free: +for_each_online_cpu (cpu) { +fcoe_percpu_thread_destroy (cpu); + } + +return rc; }module_init (fcoe_init);
@@ -1328,8 +1489,6 @@ static void __exit fcoe_exit(void) {unsigned int cpu;struct fcoe_softc *fc, *tmp; -struct fcoe_percpu_s *p; -struct sk_buff *skb;fcoe_dev_cleanup ();
@@ -1340,17 +1499,10 @@ static void __exit fcoe_exit(void)list_for_each_entry_safe (fc, tmp, &fcoe_hostlist, list)fcoe_transport_release (fc->real_dev); -for_each_possible_cpu (cpu) { - p = &per_cpu (fcoe_percpu, cpu); -if (p->thread) { -kthread_stop (p->thread); -spin_lock_bh (&p->fcoe_rx_list.lock); -while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) -kfree_skb (skb); -spin_unlock_bh (&p->fcoe_rx_list.lock); -if (p->crc_eof_page) -put_page (p->crc_eof_page); - } +unregister_hotcpu_notifier (&fcoe_cpu_notifier); + +for_each_online_cpu (cpu) { +fcoe_percpu_thread_destroy (cpu); }/* remove sw trasnport */
PATCH 2/14 fcoe: Use percpu kernel funcs for struct fcoe_percpu_s
In reply to Robert LoveConvert fcoe_percpu array to use the per-cpu variables that the kernel provides. Use the kernel's functions to access this structure.
The cpu member of the fcoe_percpu_s is no longer needed, so this patch removes it too.
---
drivers/scsi/fcoe/libfcoe.c | 94 ++++++++++++++++++++----------------------- include/scsi/libfcoe.h | 1 2 files changed, 43 insertions(+), 52 deletions(-)
drivers/scsi/fcoe/libfcoe.c +43 -51
@@ -65,7 +65,7 @@ MODULE_LICENSE("GPL");LIST_HEAD (fcoe_hostlist);DEFINE_RWLOCK (fcoe_hostlist_lock);DEFINE_TIMER (fcoe_timer,NULL ,0 ,0 ); -struct fcoe_percpu_s *fcoe_percpu[NR_CPUS ]; +DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);/* Function Prototyes */
@@ -226,6 +226,7 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, fr->fr_dev = lp; fr->ptype = ptype; cpu_idx =0 ; +#ifdef CONFIG_SMP /* * The incoming frame exchange id(oxid) is ANDed with num of online
@@ -235,10 +236,12 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,* initialize to first online cpu index. */ cpu_idx = oxid & (num_online_cpus () -1 ); -if (!fcoe_percpu[cpu_idx] || !cpu_online (cpu_idx)) +if (!cpu_online (cpu_idx)) cpu_idx =first_cpu (cpu_online_map); +#endif - fps = fcoe_percpu[cpu_idx]; + + fps = &per_cpu (fcoe_percpu, cpu_idx);spin_lock_bh (&fps->fcoe_rx_list.lock);__skb_queue_tail (&fps->fcoe_rx_list, skb);
@@ -292,15 +295,13 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) {struct fcoe_percpu_s *fps;struct page *page; -unsigned int cpu_idx; - cpu_idx =get_cpu (); - fps = fcoe_percpu[cpu_idx]; + fps = &get_cpu_var (fcoe_percpu); page = fps->crc_eof_page;if (!page) { page =alloc_page (GFP_ATOMIC );if (!page) { -put_cpu (); +put_cpu_var (fcoe_percpu);return -ENOMEM ; } fps->crc_eof_page = page;
@@ -320,7 +321,7 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) fps->crc_eof_offset =0 ;put_page (page); } -put_cpu (); +put_cpu_var (fcoe_percpu);return 0 ; }
@@ -1122,30 +1123,28 @@ EXPORT_SYMBOL_GPL(fcoe_link_ok);*/ void fcoe_percpu_clean (struct fc_lport *lp) { -int idx;struct fcoe_percpu_s *pp;struct fcoe_rcv_info *fr;struct sk_buff_head *list;struct sk_buff *skb, *next;struct sk_buff *head; +unsigned int cpu; -for (idx =0 ; idx <NR_CPUS ; idx++) { -if (fcoe_percpu[idx]) { - pp = fcoe_percpu[idx]; -spin_lock_bh (&pp->fcoe_rx_list.lock); - list = &pp->fcoe_rx_list; - head = list->next; -for (skb = head; skb != (struct sk_buff *)list; - skb = next) { - next = skb->next; - fr =fcoe_dev_from_skb (skb); -if (fr->fr_dev == lp) { -__skb_unlink (skb, list); -kfree_skb (skb); - } +for_each_possible_cpu (cpu) { + pp = &per_cpu (fcoe_percpu, cpu); +spin_lock_bh (&pp->fcoe_rx_list.lock); + list = &pp->fcoe_rx_list; + head = list->next; +for (skb = head; skb != (struct sk_buff *)list; + skb = next) { + next = skb->next; + fr =fcoe_dev_from_skb (skb); +if (fr->fr_dev == lp) { +__skb_unlink (skb, list); +kfree_skb (skb); } -spin_unlock_bh (&pp->fcoe_rx_list.lock); } +spin_unlock_bh (&pp->fcoe_rx_list.lock); } }EXPORT_SYMBOL_GPL (fcoe_percpu_clean);
@@ -1377,8 +1376,7 @@ static int __init fcoe_init(void)#endif /* CONFIG_HOTPLUG_CPU */ for_each_possible_cpu (cpu) { - p = fcoe_percpu[cpu]; - p->cpu = cpu; + p = &per_cpu (fcoe_percpu, cpu);skb_queue_head_init (&p->fcoe_rx_list); }
@@ -1386,24 +1384,19 @@ static int __init fcoe_init(void)* initialize per CPU interrupt thread */ for_each_online_cpu (cpu) { - p =kzalloc (sizeof (struct fcoe_percpu_s ),GFP_KERNEL ); -if (p) { - p->thread =kthread_create (fcoe_percpu_receive_thread, - (void *)p, -"fcoethread/%d" , cpu); + p = &per_cpu (fcoe_percpu, cpu); + p->thread =kthread_create (fcoe_percpu_receive_thread, + (void *)p,"fcoethread/%d" , cpu); -/* -* if there is no error then bind the thread to the cpu -* initialize the semaphore and skb queue head -*/ -if (likely (!IS_ERR (p->thread))) { - fcoe_percpu[cpu] = p; -kthread_bind (p->thread, cpu); -wake_up_process (p->thread); - }else { - fcoe_percpu[cpu] =NULL ; -kfree (p); - } +/* +* If there is no error then bind the thread to the CPU +* and wake it up. +*/ +if (!IS_ERR (p->thread)) { +kthread_bind (p->thread, cpu); +wake_up_process (p->thread); + }else { + p->thread =NULL ; } }
@@ -1432,7 +1425,7 @@ module_init(fcoe_init);*/ static void __exit fcoe_exit(void) { -u32 idx; +unsigned int cpu;struct fcoe_softc *fc, *tmp;struct fcoe_percpu_s *p;struct sk_buff *skb;
@@ -1454,17 +1447,16 @@ static void __exit fcoe_exit(void)list_for_each_entry_safe (fc, tmp, &fcoe_hostlist, list)fcoe_transport_release (fc->real_dev); -for (idx =0 ; idx <NR_CPUS ; idx++) { -if (fcoe_percpu[idx]) { -kthread_stop (fcoe_percpu[idx]->thread); - p = fcoe_percpu[idx]; +for_each_possible_cpu (cpu) { + p = &per_cpu (fcoe_percpu, cpu); +if (p->thread) { +kthread_stop (p->thread);spin_lock_bh (&p->fcoe_rx_list.lock);while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL )kfree_skb (skb);spin_unlock_bh (&p->fcoe_rx_list.lock); -if (fcoe_percpu[idx]->crc_eof_page) -put_page (fcoe_percpu[idx]->crc_eof_page); -kfree (fcoe_percpu[idx]); +if (p->crc_eof_page) +put_page (p->crc_eof_page); } }
include/scsi/libfcoe.h +0 -1
@@ -29,7 +29,6 @@* this percpu struct for fcoe */ struct fcoe_percpu_s { -unsigned int cpu;struct task_struct *thread;struct sk_buff_head fcoe_rx_list;struct page *crc_eof_page;
PATCH 7/14 fcoe: removes default sw transport code file fcoe_sw.c
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Moves only required code from fcoe_sw.c to libfcoe.c towards having just one source file for fcoe module, this gets rid off default sw transport code in a separate fcoe_sw.c file.
Very minor renaming along this move, dropped _sw_ or _SW_ use in names and replaced them by _if_ as a auxiliary interface functions. Now some of these funcs can be removed or merged with other func after fcoe transport is gone, but that should be in another patch to keep this patch simple.
Now the libfcoe.c file name for fcoe module doesn't go along well, so the libfcoe.c file renaming to fcoe.c as the only single fcoe module file is done in next patch to keep this patch clean and small for review.
---
drivers/scsi/fcoe/Makefile | 3 drivers/scsi/fcoe/fcoe_sw.c | 522 ------------------------------------------- drivers/scsi/fcoe/libfcoe.c | 489 ++++++++++++++++++++++++++++++++++++++++ include/scsi/libfcoe.h | 6 4 files changed, 481 insertions(+), 539 deletions(-) delete mode 100644 drivers/scsi/fcoe/fcoe_sw.c
drivers/scsi/fcoe/Makefile +1 -2
@@ -3,5 +3,4 @@ obj-$(CONFIG_FCOE) += fcoe.o fcoe-y := \ - libfcoe.o \ - fcoe_sw.o + libfcoe.o
drivers/scsi/fcoe/fcoe_sw.c deleted +0 -522
522 lines not on this page · raw message
drivers/scsi/fcoe/libfcoe.c +480 -9
532 lines not on this page · raw message
include/scsi/libfcoe.h +0 -6
@@ -145,10 +145,4 @@ 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); -int fcoe_sw_create (struct net_device *); -int fcoe_sw_destroy (struct net_device *);#endif /* _LIBFCOE_H */
PATCH 6/14 fcoe: removes fc_transport_fcoe.[ch] code files
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Remove unused fc_transport_fcoe.c and fc_transport_fcoe.h files.
---
drivers/scsi/fcoe/Makefile | 3 drivers/scsi/fcoe/fc_transport_fcoe.c | 443 --------------------------------- include/scsi/fc_transport_fcoe.h | 54 ---- 3 files changed, 1 insertions(+), 499 deletions(-) delete mode 100644 drivers/scsi/fcoe/fc_transport_fcoe.c delete mode 100644 include/scsi/fc_transport_fcoe.h
drivers/scsi/fcoe/Makefile +1 -2
@@ -4,5 +4,4 @@ obj-$(CONFIG_FCOE) += fcoe.o fcoe-y := \ libfcoe.o \ - fcoe_sw.o \ - fc_transport_fcoe.o + fcoe_sw.o
drivers/scsi/fcoe/fc_transport_fcoe.c deleted +0 -443
443 lines not on this page · raw message
include/scsi/fc_transport_fcoe.h deleted +0 -54
54 lines not on this page · raw message
PATCH 8/14 fcoe: renames libfcoe.c to fcoe.c as the only fcoe module file
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Renames libfcoe.c to fcoe.c, fcoe.c becomes the only .c file for fcoe.ko.
Also deleted "$Id: Makefile" from fcoe module Makefle.
---
drivers/scsi/fcoe/Makefile | 5 drivers/scsi/fcoe/fcoe.c | 1972 +++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/fcoe/libfcoe.c | 1972 ------------------------------------------- 3 files changed, 1972 insertions(+), 1977 deletions(-) create mode 100644 drivers/scsi/fcoe/fcoe.c delete mode 100644 drivers/scsi/fcoe/libfcoe.c
drivers/scsi/fcoe/Makefile +0 -5
@@ -1,6 +1 @@ -# $Id: Makefile - obj-$(CONFIG_FCOE) += fcoe.o - -fcoe-y := \ - libfcoe.o
drivers/scsi/fcoe/fcoe.c new file +1972 -0
1,972 lines not on this page · raw message
drivers/scsi/fcoe/libfcoe.c deleted +0 -1972
1,022 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
PATCH 5/14 fcoe: prep work to completely remove fc_transport_fcoe code
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
The fcoe transport code was added for generic FCoE transport infrastructure to allow additional offload related module loading on demand, this is not required anymore after recently added different offload approach by having offload related func ops in netdev.
This patch removes fcoe transport related code use, calls functions directly between existing libfcoe.c and fcoe_sw.c for now, for example fcoe_sw_destroy and fcoe_sw_create calling.
The fcoe_sw.c and libfcoe.c code will be further consolidated in later patches and then also the default fcoe sw transport code file fcoe_sw.c will be completely removed.
The fcoe transport code files are completely removed in next patch to keep this patch simple for reviewing.
---
drivers/scsi/fcoe/fcoe_sw.c | 38 ++++---------------------------------- drivers/scsi/fcoe/libfcoe.c | 25 ++++++------------------- include/scsi/libfcoe.h | 2 ++ 3 files changed, 12 insertions(+), 53 deletions(-)
drivers/scsi/fcoe/fcoe_sw.c +4 -34
@@ -36,7 +36,6 @@#include <scsi/libfc.h> #include <scsi/libfcoe.h> -#include <scsi/fc_transport_fcoe.h> #define FCOE_SW_VERSION "0.1"#define FCOE_SW_NAME "fcoesw"
@@ -302,7 +301,7 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp)* * Returns: 0 if link is OK for use by FCoE. */ -static int fcoe_sw_destroy (struct net_device *netdev) +int fcoe_sw_destroy (struct net_device *netdev) {struct fc_lport *lp =NULL ;struct fcoe_softc *fc;
@@ -415,7 +414,7 @@ static struct libfc_function_template fcoe_sw_libfc_fcn_templ = {* * Returns : 0 on success */ -static int fcoe_sw_create (struct net_device *netdev) +int fcoe_sw_create (struct net_device *netdev) {int rc;struct fc_lport *lp =NULL ;
@@ -494,28 +493,7 @@ out_host_put: }/** -* fcoe_sw_match() - The FCoE SW transport match function -* -* Returns : false always -*/ -static bool fcoe_sw_match (struct net_device *netdev) -{ -/* FIXME - for sw transport, always return false */ -return false; -} - -/* the sw hba fcoe transport */ -struct fcoe_transport fcoe_sw_transport = { - .name ="fcoesw" , - .create = fcoe_sw_create, - .destroy = fcoe_sw_destroy, - .match = fcoe_sw_match, - .vendor =0x0 , - .device =0xffff , -}; - -/** -* fcoe_sw_init() - Registers fcoe_sw_transport +* fcoe_sw_init() - attach to scsi transport * * Returns : 0 on success */
@@ -530,23 +508,15 @@ int __init fcoe_sw_init(void)return -ENODEV ; } -mutex_init (&fcoe_sw_transport.devlock); -INIT_LIST_HEAD (&fcoe_sw_transport.devlist); - -/* register sw transport */ -fcoe_transport_register (&fcoe_sw_transport);return 0 ; }/** -* fcoe_sw_exit() - Unregisters fcoe_sw_transport +* fcoe_sw_exit() - dummy for now * * Returns : 0 on success */ int __exit fcoe_sw_exit(void) { -/* dettach the transport */ -fc_release_transport (scsi_transport_fcoe_sw); -fcoe_transport_unregister (&fcoe_sw_transport);return 0 ; }
drivers/scsi/fcoe/libfcoe.c +6 -19
@@ -44,7 +44,6 @@#include <scsi/libfc.h> #include <scsi/fc_frame.h> #include <scsi/libfcoe.h> -#include <scsi/fc_transport_fcoe.h> static int debug_fcoe;
@@ -1081,10 +1080,9 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) rc = -ENODEV ; goto out_putdev; } -/* pass to transport */ - rc =fcoe_transport_release (netdev); + rc =fcoe_sw_destroy (netdev);if (rc) { -printk (KERN_ERR "fcoe: fcoe_transport_release(%s) failed\n" , +printk (KERN_ERR "fcoe: fcoe_sw_destroy(%s) failed\n" , netdev->name); rc = -EIO ; goto out_putdev;
@@ -1121,10 +1119,9 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) }fcoe_ethdrv_get (netdev); -/* pass to transport */ - rc =fcoe_transport_attach (netdev); + rc =fcoe_sw_create (netdev);if (rc) { -printk (KERN_ERR "fcoe: fcoe_transport_attach(%s) failed\n" , +printk (KERN_ERR "fcoe: fcoe_sw_create(%s) failed\n" , netdev->name);fcoe_ethdrv_put (netdev); rc = -EIO ;
@@ -1429,10 +1426,6 @@ EXPORT_SYMBOL_GPL(fcoe_libfc_config);/** * fcoe_init() - fcoe module loading initialization * -* Initialization routine -* 1. Will create fc transport software structure -* 2. initialize the link list of port information structure -* * Returns 0 on success, negative on failure */ static int __init fcoe_init (void )
@@ -1464,9 +1457,6 @@ static int __init fcoe_init(void)mod_timer (&fcoe_timer, jiffies + (10 *HZ )); -/* initiatlize the fcoe transport */ -fcoe_transport_init (); -fcoe_sw_init ();return 0 ;
@@ -1495,9 +1485,9 @@ static void __exit fcoe_exit(void)/* Stop the timer */ del_timer_sync (&fcoe_timer); -/* releases the associated fcoe transport for each lport */ +/* releases the associated fcoe hosts */ list_for_each_entry_safe (fc, tmp, &fcoe_hostlist, list) -fcoe_transport_release (fc->real_dev); +fcoe_sw_destroy (fc->real_dev);unregister_hotcpu_notifier (&fcoe_cpu_notifier);
@@ -1507,8 +1497,5 @@ static void __exit fcoe_exit(void)/* remove sw trasnport */ fcoe_sw_exit (); - -/* detach the transport */ -fcoe_transport_exit (); }module_exit (fcoe_exit);
include/scsi/libfcoe.h +2 -0
@@ -149,4 +149,6 @@ 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); +int fcoe_sw_create (struct net_device *); +int fcoe_sw_destroy (struct net_device *);#endif /* _LIBFCOE_H */
PATCH 9/14 fcoe, libfc, scsi: adds libfcoe module
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Just sets up build environment for libfcoe module towards a libfcoe library for libfc LLDs using FCoE as libfc transport.
Common library code to libfcoe is added in next patch.
Also, updated MODULE_LICENSE from "GPL" string to "GPL v2" for libfc, libfcoe and fcoe modules to accurately match the licenses.
---
drivers/scsi/Kconfig | 8 +++++++- drivers/scsi/Makefile | 1 + drivers/scsi/fcoe/Makefile | 1 + drivers/scsi/fcoe/fcoe.c | 2 +- drivers/scsi/fcoe/libfcoe.c | 24 ++++++++++++++++++++++++ drivers/scsi/libfc/fc_fcp.c | 2 +- 6 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 drivers/scsi/fcoe/libfcoe.c
drivers/scsi/Kconfig +7 -1
@@ -614,10 +614,16 @@ config LIBFC ---help--- Fibre Channel library module +config LIBFCOE + tristate "LibFCoE module" + select LIBFC + ---help--- + Library for Fibre Channel over Ethernet module + config FCOE tristate "FCoE module" depends on PCI - select LIBFC + select LIBFCOE ---help--- Fibre Channel over Ethernet module
drivers/scsi/Makefile +1 -0
@@ -37,6 +37,7 @@ obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o obj-$(CONFIG_SCSI_DH) += device_handler/ obj-$(CONFIG_LIBFC) += libfc/ +obj-$(CONFIG_LIBFCOE) += fcoe/ obj-$(CONFIG_FCOE) += fcoe/ obj-$(CONFIG_ISCSI_TCP) += libiscsi.o libiscsi_tcp.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o
drivers/scsi/fcoe/Makefile +1 -0
@@ -1 +1,2 @@ obj-$(CONFIG_FCOE) += fcoe.o +obj-$(CONFIG_LIBFCOE) += libfcoe.o
drivers/scsi/fcoe/fcoe.c +1 -1
@@ -70,7 +70,7 @@ static int debug_fcoe;MODULE_AUTHOR ("Open-FCoE.org" );MODULE_DESCRIPTION ("FCoE" ); -MODULE_LICENSE ("GPL" ); +MODULE_LICENSE ("GPL v2" );/* fcoe host list */ LIST_HEAD (fcoe_hostlist);
drivers/scsi/fcoe/libfcoe.c new file +24 -0
@@ -0,0 +1,24 @@ +/* +* Copyright(c) 2009 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 +*/ + +#include <linux/module.h> + +MODULE_AUTHOR ("Open-FCoE.org" ); +MODULE_DESCRIPTION ("FCoE" ); +MODULE_LICENSE ("GPL v2" );
drivers/scsi/libfc/fc_fcp.c +1 -1
@@ -41,7 +41,7 @@MODULE_AUTHOR ("Open-FCoE.org" );MODULE_DESCRIPTION ("libfc" ); -MODULE_LICENSE ("GPL" ); +MODULE_LICENSE ("GPL v2" );static int fc_fcp_debug;
PATCH 10/14 fcoe: moves common FCoE library API functions to libfcoe module
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Moves these functions as-is from fcoe.c to libfcoe.c, since they're are common routines:
- fcoe_wwn_from_mac
- fcoe_libfc_config
---
drivers/scsi/fcoe/fcoe.c | 64 ----------------------------------------- drivers/scsi/fcoe/libfcoe.c | 67 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 64 deletions(-)
drivers/scsi/fcoe/fcoe.c +0 -64
@@ -1755,47 +1755,6 @@ int fcoe_reset(struct Scsi_Host *shost)EXPORT_SYMBOL_GPL (fcoe_reset);/** -* fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN. -* @mac: mac address -* @scheme: check port -* @port: port indicator for converting -* -* Returns: u64 fc world wide name -*/ -u64 fcoe_wwn_from_mac (unsigned char mac[MAX_ADDR_LEN ], -unsigned int scheme,unsigned int port) -{ -u64 wwn; -u64 host_mac; - -/* The MAC is in NO, so flip only the low 48 bits */ - host_mac = ((u64 ) mac[0 ] <<40 ) | - ((u64 ) mac[1 ] <<32 ) | - ((u64 ) mac[2 ] <<24 ) | - ((u64 ) mac[3 ] <<16 ) | - ((u64 ) mac[4 ] <<8 ) | - (u64 ) mac[5 ]; - -WARN_ON (host_mac >= (1ULL <<48 )); - wwn = host_mac | ((u64 ) scheme <<60 ); -switch (scheme) { -case 1 : -WARN_ON (port !=0 ); -break ; -case 2 : -WARN_ON (port >=0xfff ); - wwn |= (u64 ) port <<48 ; -break ; -default : -WARN_ON (1 ); -break ; - } - -return wwn; -} -EXPORT_SYMBOL_GPL (fcoe_wwn_from_mac); - -/** * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device * @device: this is currently ptr to net_device *
@@ -1875,29 +1834,6 @@ int fcoe_hostlist_remove(const struct fc_lport *lp)EXPORT_SYMBOL_GPL (fcoe_hostlist_remove);/** -* fcoe_libfc_config() - sets up libfc related properties for lport -* @lp: ptr to the fc_lport -* @tt: libfc function template -* -* Returns : 0 for success -*/ -int fcoe_libfc_config (struct fc_lport *lp,struct libfc_function_template *tt) -{ -/* Set the function pointers set by the LLDD */ -memcpy (&lp->tt, tt,sizeof (*tt)); -if (fc_fcp_init (lp)) -return -ENOMEM ; -fc_exch_init (lp); -fc_elsct_init (lp); -fc_lport_init (lp); -fc_rport_init (lp); -fc_disc_init (lp); - -return 0 ; -} -EXPORT_SYMBOL_GPL (fcoe_libfc_config); - -/** * fcoe_init() - fcoe module loading initialization * * Returns 0 on success, negative on failure
drivers/scsi/fcoe/libfcoe.c +67 -0
74 lines not on this page · raw message
PATCH 11/14 fcoe: cleans up libfcoe.h and adds fcoe.h for fcoe module
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Removes no where used several inline functions prefixed with skb_* and be16_to_cpu.
Moves fcoe module specific func prototypes to fcoe.c from libfcoe.h, moved only need for build.
Adds fcoe module header file fcoe.h and then moves fcoe module specific fcoe_percpu_s and fcoe_softc to fcoe.h from libfcoe.h.
Moves all defines from fcoe.c to fcoe.h since now fcoe module has its own header file fcoe.h.
---
drivers/scsi/fcoe/fcoe.c | 42 +++++++--------- drivers/scsi/fcoe/fcoe.h | 86 +++++++++++++++++++++++++++++++++ include/scsi/libfcoe.h | 120 +--------------------------------------------- 3 files changed, 105 insertions(+), 143 deletions(-) create mode 100644 drivers/scsi/fcoe/fcoe.h
drivers/scsi/fcoe/fcoe.c +17 -25
@@ -19,15 +19,12 @@#include <linux/module.h> #include <linux/version.h> -#include <linux/kernel.h> #include <linux/spinlock.h> -#include <linux/skbuff.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/if_ether.h> #include <linux/if_vlan.h> -#include <linux/kthread.h> #include <linux/crc32.h> #include <linux/cpu.h> #include <linux/fs.h>
@@ -45,28 +42,9 @@#include <scsi/fc_frame.h> #include <scsi/libfcoe.h> -static int debug_fcoe; - -#define FCOE_MAX_QUEUE_DEPTH 256 -#define FCOE_LOW_QUEUE_DEPTH 32 - -/* destination address mode */ -#define FCOE_GW_ADDR_MODE 0x00 -#define FCOE_FCOUI_ADDR_MODE 0x01 - -#define FCOE_WORD_TO_BYTE 4 - -#define FCOE_VERSION "0.1" -#define FCOE_NAME "fcoe" -#define FCOE_VENDOR "Open-FCoE.org" - -#define FCOE_MAX_LUN 255 -#define FCOE_MAX_FCP_TARGET 256 +#include "fcoe.h" -#define FCOE_MAX_OUTSTANDING_COMMANDS 1024 - -#define FCOE_MIN_XID 0x0001/* the min xid supported by fcoe_sw */ -#define FCOE_MAX_XID 0x07ef/* the max xid supported by fcoe_sw */ +static int debug_fcoe;MODULE_AUTHOR ("Open-FCoE.org" );MODULE_DESCRIPTION ("FCoE" );
@@ -78,8 +56,22 @@ DEFINE_RWLOCK(fcoe_hostlist_lock);DEFINE_TIMER (fcoe_timer,NULL ,0 ,0 ); DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); -/* Function Prototyes */ +static int fcoe_reset (struct Scsi_Host *shost); +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 *arg); +static void fcoe_clean_pending_queue (struct fc_lport *lp); +static void fcoe_percpu_clean (struct fc_lport *lp); +static int fcoe_link_ok (struct fc_lport *lp); + +static struct fc_lport *fcoe_hostlist_lookup (const struct net_device *); +static int fcoe_hostlist_add (const struct fc_lport *); +static int fcoe_hostlist_remove (const struct fc_lport *); + +static struct Scsi_Host *fcoe_host_alloc (struct scsi_host_template *,int ); +static int fcoe_check_wait_queue (struct fc_lport *);static void fcoe_recv_flogi (struct fcoe_softc *,struct fc_frame *,u8 *);static int fcoe_device_notification (struct notifier_block *,ulong ,void *);
drivers/scsi/fcoe/fcoe.h new file +86 -0
86 lines not on this page · raw message
include/scsi/libfcoe.h +2 -118
126 lines not on this page · raw message
PATCH 12/14 fcoe, libfc: fix double fcoe_softc memory alloc
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
The foce_softc mem was reserved by libfc_host_alloc as well as by fcoe_host_alloc.
Removes one liner fcoe_host_alloc completely, instead directly calls libfc_host_alloc to alloc scsi_host with libfc for just one fcoe_softc as fcoe private data.
Moves libfc_host_alloc to libfc.h since it is a libfc API, placed lport_priv API adjacent to libfc_host_alloc since this is related to scsi_host priv data.
---
drivers/scsi/fcoe/fcoe.c | 33 ++------------------------------- include/scsi/libfc.h | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 36 deletions(-)
drivers/scsi/fcoe/fcoe.c +2 -31
@@ -70,8 +70,6 @@ static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);static int fcoe_hostlist_add (const struct fc_lport *);static int fcoe_hostlist_remove (const struct fc_lport *); -static struct Scsi_Host *fcoe_host_alloc (struct scsi_host_template *,int ); -static int fcoe_check_wait_queue (struct fc_lport *);static void fcoe_recv_flogi (struct fcoe_softc *,struct fc_frame *,u8 *);static int fcoe_device_notification (struct notifier_block *,ulong ,void *);
@@ -464,8 +462,8 @@ static int fcoe_if_create(struct net_device *netdev)if (lp)return -EEXIST ; - shost =fcoe_host_alloc (&fcoe_shost_template, -sizeof (struct fcoe_softc )); + shost =libfc_host_alloc (&fcoe_shost_template, +sizeof (struct fcoe_softc ));if (!shost) {FC_DBG ("Could not allocate host structure\n" );return -ENOMEM ;
@@ -1706,33 +1704,6 @@ void fcoe_clean_pending_queue(struct fc_lport *lp)EXPORT_SYMBOL_GPL (fcoe_clean_pending_queue);/** -* 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 -* TODO: to libfc? -*/ -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); -} - -/** -* fcoe_host_alloc() - Allocate a Scsi_Host with room for the fcoe_softc -* @sht: ptr to the scsi host templ -* @priv_size: size of private data after fc_lport -* -* Returns: ptr to Scsi_Host -*/ -struct Scsi_Host *fcoe_host_alloc (struct scsi_host_template *sht,int priv_size) -{ -return libfc_host_alloc (sht,sizeof (struct fcoe_softc ) + priv_size); -} -EXPORT_SYMBOL_GPL (fcoe_host_alloc); - -/** * fcoe_reset() - Resets the fcoe * @shost: shost the reset is from *
include/scsi/libfc.h +17 -5
@@ -696,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 ;
@@ -743,6 +738,23 @@ 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
PATCH 13/14 fcoe: Add a header file defining the FIP protocol for FCoE.
In reply to Robert LoveFrom: Joe Eykholt <[email protected]>
Adds include/scsi/fc/fc_fip.h for FIP protocol definitions.
---
include/scsi/fc/fc_fip.h | 237 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 237 insertions(+), 0 deletions(-) create mode 100644 include/scsi/fc/fc_fip.h
include/scsi/fc/fc_fip.h new file +237 -0
@@ -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_ */
PATCH 14/14 fcoe, libfcoe: Add support for FIP. FCoE discovery and keep-alive.
In reply to Robert LoveFrom: Joe Eykholt <[email protected]>
FIP is the new standard way to discover Fibre-Channel Forwarders (FCFs) by sending solicitations and listening for advertisements from FCFs.
It also provides for keep-alives and period advertisements so that both parties know they have connectivity. If the FCF loses connectivity to the storage fabric, it can send a Link Reset to inform the E_node.
This version is also compatible with pre-FIP implementations, so no configured selection between FIP mode and non-FIP mode is required.
We wait a couple seconds after sending the initial solicitation and then send an old-style FLOGI. If we receive any FIP frames, we use FIP only mode. If the old FLOGI receives a response, we disable FIP mode. After every reset or link up, this determination is repeated.
---
drivers/scsi/fcoe/fcoe.c | 232 ++++---- drivers/scsi/fcoe/fcoe.h | 19 - drivers/scsi/fcoe/libfcoe.c | 1251 +++++++++++++++++++++++++++++++++++++++++++ include/scsi/libfcoe.h | 134 +++++ 4 files changed, 1499 insertions(+), 137 deletions(-)
drivers/scsi/fcoe/fcoe.c +113 -119
@@ -37,6 +37,7 @@#include <net/rtnetlink.h> #include <scsi/fc/fc_encaps.h> +#include <scsi/fc/fc_fip.h> #include <scsi/libfc.h> #include <scsi/fc_frame.h>
@@ -71,7 +72,6 @@ static int fcoe_hostlist_add(const struct fc_lport *);static int fcoe_hostlist_remove (const struct fc_lport *);static int fcoe_check_wait_queue (struct fc_lport *); -static void fcoe_recv_flogi (struct fcoe_softc *,struct fc_frame *,u8 *);static int fcoe_device_notification (struct notifier_block *,ulong ,void *);static void fcoe_dev_setup (void );static void fcoe_dev_cleanup (void );
@@ -185,7 +185,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)/* Setup lport private data to point to fcoe softc */ fc =lport_priv (lp); - fc->lp = lp; + fc->ctlr.lp = lp; fc->real_dev = netdev; fc->phys_dev = netdev;
@@ -210,9 +210,6 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)if (fc_set_mfs (lp, mfs))return -EINVAL ; -if (!fcoe_link_ok (lp)) - lp->link_up =1 ; -/* offload features support */ if (fc->real_dev->features &NETIF_F_SG ) lp->sg_supp =1 ;
@@ -242,7 +239,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) fc->fcoe_pending_queue_active =0 ;/* setup Source Mac Address */ -memcpy (fc->ctl_src_addr, fc->real_dev->dev_addr, +memcpy (fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, fc->real_dev->addr_len); wwnn =fcoe_wwn_from_mac (fc->real_dev->dev_addr,1 ,0 );
@@ -358,6 +355,8 @@ static int fcoe_if_destroy(struct net_device *netdev)/* Don't listen for Ethernet packets anymore */ dev_remove_pack (&fc->fcoe_packet_type); +dev_remove_pack (&fc->fip_packet_type); +fcoe_ctlr_destroy (&fc->ctlr);/* Cleanup the fc_lport */ fc_lport_destroy (lp);
@@ -375,8 +374,10 @@ static int fcoe_if_destroy(struct net_device *netdev)rtnl_lock ();memcpy (flogi_maddr, (u8 [6 ])FC_FCOE_FLOGI_MAC ,ETH_ALEN );dev_unicast_delete (fc->real_dev, flogi_maddr,ETH_ALEN ); -if (compare_ether_addr (fc->data_src_addr, (u8 [6 ]) {0 })) -dev_unicast_delete (fc->real_dev, fc->data_src_addr,ETH_ALEN ); +if (!is_zero_ether_addr (fc->ctlr.data_src_addr)) +dev_unicast_delete (fc->real_dev, + fc->ctlr.data_src_addr,ETH_ALEN ); +dev_mc_delete (fc->real_dev,FIP_ALL_ENODE_MACS ,ETH_ALEN ,0 );rtnl_unlock ();/* Free the per-CPU revieve threads */
@@ -438,6 +439,58 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { };/** +* fcoe_fip_recv - handle a received FIP frame. +* @skb: the receive skb +* @dev: associated &net_device +* @ptype: the &packet_type structure which was used to register this handler. +* @orig_dev: original receive &net_device, in case @dev is a bond. +* +* Returns: 0 for success +*/ +static int fcoe_fip_recv (struct sk_buff *skb,struct net_device *dev, +struct packet_type *ptype, +struct net_device *orig_dev) +{ +struct fcoe_softc *fc; + + fc = container_of(ptype, struct fcoe_softc, fip_packet_type); +fcoe_ctlr_recv (&fc->ctlr, skb); +return 0 ; +} + +/** +* fcoe_fip_send() - send an Ethernet-encapsulated FIP frame. +* @fip: FCoE controller. +* @skb: FIP Packet. +*/ +static void fcoe_fip_send (struct fcoe_ctlr *fip,struct sk_buff *skb) +{ + skb->dev =fcoe_from_ctlr (fip)->real_dev; +dev_queue_xmit (skb); +} + +/** +* fcoe_update_src_mac() - Update Ethernet MAC filters. +* @fip: FCoE controller. +* @old: Unicast MAC address to delete if the MAC is non-zero. +* @new: Unicast MAC address to add. +* +* Remove any previously-set unicast MAC filter. +* Add secondary FCoE MAC address filter for our OUI. +*/ +static void fcoe_update_src_mac (struct fcoe_ctlr *fip,u8 *old,u8 *new) +{ +struct fcoe_softc *fc; + + fc =fcoe_from_ctlr (fip); +rtnl_lock (); +if (!is_zero_ether_addr (old)) +dev_unicast_delete (fc->real_dev, old,ETH_ALEN ); +dev_unicast_add (fc->real_dev, new,ETH_ALEN ); +rtnl_unlock (); +} + +/** * fcoe_if_create() - this function creates the fcoe interface * @netdev: pointer the associated netdevice *
@@ -485,6 +538,18 @@ static int fcoe_if_create(struct net_device *netdev) goto out_host_put; } +/* +* Initialize FIP. +*/ +fcoe_ctlr_init (&fc->ctlr); + fc->ctlr.send = fcoe_fip_send; + fc->ctlr.update_mac = fcoe_update_src_mac; + + fc->fip_packet_type.func = fcoe_fip_recv; + fc->fip_packet_type.type =htons (ETH_P_FIP ); + fc->fip_packet_type.dev = fc->real_dev; +dev_add_pack (&fc->fip_packet_type); +/* configure lport scsi host properties */ rc =fcoe_shost_config (lp, shost, &netdev->dev);if (rc) {
@@ -513,6 +578,9 @@ static int fcoe_if_create(struct net_device *netdev)fc_fabric_login (lp); +if (!fcoe_link_ok (lp)) +fcoe_ctlr_link_up (&fc->ctlr); +dev_hold (netdev);return rc;
@@ -716,11 +784,13 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,unsigned int cpu =0 ; fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type); - lp = fc->lp; + lp = fc->ctlr.lp;if (unlikely (lp ==NULL )) {FC_DBG ("cannot find hba structure" ); goto err2; } +if (!lp->link_up) + goto err2;if (unlikely (debug_fcoe)) { FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p "
@@ -919,7 +989,6 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)unsigned int hlen;/* header length implies the version */ unsigned int tlen;/* trailer length */ unsigned int elen;/* eth header, may include vlan */ -int flogi_in_progress =0 ;struct fcoe_softc *fc;u8 sof, eof;struct fcoe_hdr *hp;
@@ -927,31 +996,19 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)WARN_ON ((fr_len (fp) %sizeof (u32)) !=0 ); fc =lport_priv (lp); -/* -* if it is a flogi then we need to learn gw-addr -* and my own fcid -*/ fh =fc_frame_header_get (fp); -if (unlikely (fh->fh_r_ctl ==FC_RCTL_ELS_REQ )) { -if (fc_frame_payload_op (fp) ==ELS_FLOGI ) { - fc->flogi_oxid =ntohs (fh->fh_ox_id); - fc->address_mode =FCOE_FCOUI_ADDR_MODE ; - fc->flogi_progress =1 ; - flogi_in_progress =1 ; - }else if (fc->flogi_progress &&ntoh24 (fh->fh_s_id) !=0 ) { -/* -* Here we must've gotten an SID by accepting an FLOGI -* from a point-to-point connection. Switch to using -* the source mac based on the SID. The destination -* MAC in this case would have been set by receving the -* FLOGI. -*/ -fc_fcoe_set_mac (fc->data_src_addr, fh->fh_s_id); - fc->flogi_progress =0 ; - } + skb =fp_skb (fp); + wlen = skb->len /FCOE_WORD_TO_BYTE ; + +if (!lp->link_up) { +kfree (skb); +return 0 ; } - skb =fp_skb (fp); +if (unlikely (fh->fh_r_ctl ==FC_RCTL_ELS_REQ ) && +fcoe_ctlr_els_send (&fc->ctlr, skb)) +return 0 ; + sof =fr_sof (fp); eof =fr_eof (fp);
@@ -1006,16 +1063,16 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)/* fill up mac and fcoe headers */ eh =eth_hdr (skb); eh->h_proto =htons (ETH_P_FCOE ); -if (fc->address_mode ==FCOE_FCOUI_ADDR_MODE ) +if (fc->ctlr.map_dest)fc_fcoe_set_mac (eh->h_dest, fh->fh_d_id);else /* insert GW address */ -memcpy (eh->h_dest, fc->dest_addr,ETH_ALEN ); +memcpy (eh->h_dest, fc->ctlr.dest_addr,ETH_ALEN ); -if (unlikely (flogi_in_progress)) -memcpy (eh->h_source, fc->ctl_src_addr,ETH_ALEN ); +if (unlikely (fc->ctlr.flogi_oxid !=FC_XID_UNKNOWN )) +memcpy (eh->h_source, fc->ctlr.ctl_src_addr,ETH_ALEN );else -memcpy (eh->h_source, fc->data_src_addr,ETH_ALEN ); +memcpy (eh->h_source, fc->ctlr.data_src_addr,ETH_ALEN ); hp = (struct fcoe_hdr *)(eh +1 );memset (hp,0 ,sizeof (*hp));
@@ -1115,11 +1172,9 @@ int fcoe_percpu_receive_thread(void *arg)* Save source MAC address before discarding header. */ fc =lport_priv (lp); -if (unlikely (fc->flogi_progress)) - mac =eth_hdr (skb)->h_source; -if (skb_is_nonlinear (skb))skb_linearize (skb);/* not ideal */ + mac =eth_hdr (skb)->h_source;/* * Frame length checks and setting up the header pointers
@@ -1194,72 +1249,17 @@ int fcoe_percpu_receive_thread(void *arg) }fr_flags (fp) &= ~FCPHF_CRC_UNCHECKED ; } -/* non flogi and non data exchanges are handled here */ -if (unlikely (fc->flogi_progress)) -fcoe_recv_flogi (fc, fp, mac); +if (unlikely (fc->ctlr.flogi_oxid !=FC_XID_UNKNOWN ) && +fcoe_ctlr_recv_flogi (&fc->ctlr, fp, mac)) { +fc_frame_free (fp); +continue ; + }fc_exch_recv (lp, lp->emp, fp); }return 0 ; }/** -* fcoe_recv_flogi() - flogi receive function -* @fc: associated fcoe_softc -* @fp: the recieved frame -* @sa: the source address of this flogi -* -* This is responsible to parse the flogi response and sets the corresponding -* mac address for the initiator, eitehr OUI based or GW based. -* -* Returns: none -*/ -static void fcoe_recv_flogi (struct fcoe_softc *fc,struct fc_frame *fp,u8 *sa) -{ -struct fc_frame_header *fh; -u8 op; - - fh =fc_frame_header_get (fp); -if (fh->fh_type !=FC_TYPE_ELS ) -return ; - op =fc_frame_payload_op (fp); -if (op ==ELS_LS_ACC && fh->fh_r_ctl ==FC_RCTL_ELS_REP && - fc->flogi_oxid ==ntohs (fh->fh_ox_id)) { -/* -* FLOGI accepted. -* If the src mac addr is FC_OUI-based, then we mark the -* address_mode flag to use FC_OUI-based Ethernet DA. -* Otherwise we use the FCoE gateway addr -*/ -if (!compare_ether_addr (sa, (u8 [6 ])FC_FCOE_FLOGI_MAC )) { - fc->address_mode =FCOE_FCOUI_ADDR_MODE ; - }else { -memcpy (fc->dest_addr, sa,ETH_ALEN ); - fc->address_mode =FCOE_GW_ADDR_MODE ; - } - -/* -* Remove any previously-set unicast MAC filter. -* Add secondary FCoE MAC address filter for our OUI. -*/ -rtnl_lock (); -if (compare_ether_addr (fc->data_src_addr, (u8 [6 ]) {0 })) -dev_unicast_delete (fc->real_dev, fc->data_src_addr, -ETH_ALEN ); -fc_fcoe_set_mac (fc->data_src_addr, fh->fh_d_id); -dev_unicast_add (fc->real_dev, fc->data_src_addr,ETH_ALEN ); -rtnl_unlock (); - - fc->flogi_progress =0 ; - }else if (op ==ELS_FLOGI && fh->fh_r_ctl ==FC_RCTL_ELS_REQ && sa) { -/* -* Save source MAC for point-to-point responses. -*/ -memcpy (fc->dest_addr, sa,ETH_ALEN ); - fc->address_mode =FCOE_GW_ADDR_MODE ; - } -} - -/** * fcoe_watchdog() - fcoe timer callback * @vp: *
@@ -1275,8 +1275,8 @@ void fcoe_watchdog(ulong vp)read_lock (&fcoe_hostlist_lock);list_for_each_entry (fc, &fcoe_hostlist, list) { -if (fc->lp) -fcoe_check_wait_queue (fc->lp); +if (fc->ctlr.lp) +fcoe_check_wait_queue (fc->ctlr.lp); }read_unlock (&fcoe_hostlist_lock);
@@ -1377,14 +1377,14 @@ static int fcoe_device_notification(struct notifier_block *notifier,struct net_device *real_dev = ptr;struct fcoe_softc *fc;struct fcoe_dev_stats *stats; -u32 new_link_up; +u32 link_possible =1 ;u32 mfs;int rc =NOTIFY_OK ;read_lock (&fcoe_hostlist_lock);list_for_each_entry (fc, &fcoe_hostlist, list) {if (fc->real_dev == real_dev) { - lp = fc->lp; + lp = fc->ctlr.lp;break ; } }
@@ -1394,15 +1394,13 @@ static int fcoe_device_notification(struct notifier_block *notifier, goto out; } - new_link_up = lp->link_up;switch (event) {case NETDEV_DOWN :case NETDEV_GOING_DOWN : - new_link_up =0 ; + link_possible =0 ;break ;case NETDEV_UP :case NETDEV_CHANGE : - new_link_up = !fcoe_link_ok (lp);break ;case NETDEV_CHANGEMTU : mfs = fc->real_dev->mtu -
@@ -1410,22 +1408,18 @@ static int fcoe_device_notification(struct notifier_block *notifier, sizeof(struct fcoe_crc_eof));if (mfs >=FC_MIN_MAX_FRAME )fc_set_mfs (lp, mfs); - new_link_up = !fcoe_link_ok (lp);break ;case NETDEV_REGISTER :break ;default : -FC_DBG ("unknown event %ld call" , event); +FC_DBG ("Unknown event %ld from netdev netlink\n" , event); } -if (lp->link_up != new_link_up) { -if (new_link_up) -fc_linkup (lp); -else { - stats =fc_lport_get_stats (lp); - stats->LinkFailureCount++; -fc_linkdown (lp); -fcoe_clean_pending_queue (lp); - } +if (link_possible && !fcoe_link_ok (lp)) +fcoe_ctlr_link_up (&fc->ctlr); +else if (fcoe_ctlr_link_down (&fc->ctlr)) { + stats =fc_lport_get_stats (lp); + stats->LinkFailureCount++; +fcoe_clean_pending_queue (lp); } out:return rc;
@@ -1751,7 +1745,7 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) fc =fcoe_hostlist_lookup_softc (netdev); -return (fc) ? fc->lp :NULL ; +return (fc) ? fc->ctlr.lp :NULL ; }EXPORT_SYMBOL_GPL (fcoe_hostlist_lookup);
drivers/scsi/fcoe/fcoe.h +4 -15
@@ -26,10 +26,6 @@#define FCOE_MAX_QUEUE_DEPTH 256#define FCOE_LOW_QUEUE_DEPTH 32 -/* destination address mode */ -#define FCOE_GW_ADDR_MODE 0x00 -#define FCOE_FCOUI_ADDR_MODE 0x01 -#define FCOE_WORD_TO_BYTE 4#define FCOE_VERSION "0.1"
@@ -59,24 +55,17 @@ struct fcoe_percpu_s {*/ 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 packet_type fip_packet_type;struct sk_buff_head fcoe_pending_queue;u8 fcoe_pending_queue_active; - -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; +struct fcoe_ctlr ctlr; }; +#define fcoe_from_ctlr (fc) container_of(fc, struct fcoe_softc, ctlr) +static inline struct net_device *fcoe_netdev (const struct fc_lport *lp) {
drivers/scsi/fcoe/libfcoe.c +1249 -2
1,269 lines not on this page · raw message
include/scsi/libfcoe.h +133 -1
149 lines not on this page · raw message
James Bottomley
maintainerRe: [PATCH 04/14] fcoe: create/destroy fcoe Rx threads on CPU hotplug events
In reply to Robert LoveQuoted 135 lines · Robert Love
This patch adds support for dynamically created Rx threads upon CPU hotplug events.
There were existing synchronization problems that this patch attempts to resolve. The main problem had to do with
fcoe_rcv()running in a different context than the hotplug notifications. This opened the possiblity thatfcoe_rcv()would target a Rx thread for a skb. However, that thread could become NULL if the CPU was made offline.This patch uses the Rx queue's (a
skb_queue) lock to protect the thread it's associated with and we use the 'thread' member of thefcoe_percpu_sto determine if the thread is ready to accept new skbs.The patch also attempts to do a better job of cleaning up, both if hotplug registration fails as well as when the module is removed.
Contribution provided by Joe Eykholt <[email protected]> to fix incorrect use of
__cpuinitdata.Signed-off-by Yi Zou <[email protected]>Signed-off-by Robert Love <[email protected]>---
drivers/scsi/fcoe/libfcoe.c | 246 +++++++++++++++++++++++++++++++++++-------- 1 files changed, 199 insertions(+), 47 deletions(-)drivers/scsi/fcoe/libfcoe.c +98
-0@@ -81,6 +81,156 @@ static struct notifier_block fcoe_notifier = { };/** +* fcoe_percpu_thread_create() - Create a receive thread for an online cpu +* @cpu: cpu index for the online cpu +*/ +static void fcoe_percpu_thread_create (unsigned int cpu) +{ +struct fcoe_percpu_s *p; +struct task_struct *thread; + + p = &per_cpu (fcoe_percpu, cpu); + + thread =kthread_create (fcoe_percpu_receive_thread, + (void *)p,"fcoethread/%d" , cpu); + +if (likely (!IS_ERR (p->thread))) { +kthread_bind (thread, cpu); +wake_up_process (thread); + +spin_lock_bh (&p->fcoe_rx_list.lock); + p->thread = thread; +spin_unlock_bh (&p->fcoe_rx_list.lock); + } +} + +/** +* fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu +* @cpu: cpu index the rx thread is to be removed +* +* Destroys a per-CPU Rx thread. Any pending skbs are moved to the +* current CPU's Rx thread. If the thread being destroyed is bound to +* the CPU processing this context the skbs will be freed. +*/ +static void fcoe_percpu_thread_destroy (unsigned int cpu) +{ +struct fcoe_percpu_s *p; +struct task_struct *thread; +struct page *crc_eof; +struct sk_buff *skb; +#ifdef CONFIG_SMP +struct fcoe_percpu_s *p0; +unsigned targ_cpu =smp_processor_id (); +#endif /* CONFIG_SMP */ + +printk (KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n" , cpu); + +/* Prevent any new skbs from being queued for this CPU. */ + p = &per_cpu (fcoe_percpu, cpu); +spin_lock_bh (&p->fcoe_rx_list.lock); + thread = p->thread; + p->thread =NULL ; + crc_eof = p->crc_eof_page; + p->crc_eof_page =NULL ; + p->crc_eof_offset =0 ; +spin_unlock_bh (&p->fcoe_rx_list.lock); + +#ifdef CONFIG_SMP +/* +* Don't bother moving the skb's if this context is running +* on the same CPU that is having its thread destroyed. This +* can easily happen when the module is removed. +*/ +if (cpu != targ_cpu) { + p0 = &per_cpu (fcoe_percpu, targ_cpu); +spin_lock_bh (&p0->fcoe_rx_list.lock); +if (p0->thread) { +FC_DBG ("Moving frames from CPU %d to CPU %d\n" , + cpu, targ_cpu); + +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +__skb_queue_tail (&p0->fcoe_rx_list, skb); +spin_unlock_bh (&p0->fcoe_rx_list.lock); + }else { +/* +* The targeted CPU is not initialized and cannot accept +* new skbs. Unlock the targeted CPU and drop the skbs +* on the CPU that is going offline. +*/ +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p0->fcoe_rx_list.lock); + } + }else { +/* +* This scenario occurs when the module is being removed +* and all threads are being destroyed. skbs will continue +* to be shifted from the CPU thread that is being removed +* to the CPU thread associated with the CPU that is processing +* the module removal. Once there is only one CPU Rx thread it +* will reach this case and we will drop all skbs and later +* stop the thread. +*/ +spin_lock_bh (&p->fcoe_rx_list.lock); +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p->fcoe_rx_list.lock); + } +#else +/* +* This a non-SMP scenario where the singluar Rx thread is
drivers/scsi/fcoe/libfcoe.c static struct notifier_block fcoe_notifier = { · line 191
Quoted 10 lines
drivers/scsi/fcoe/libfcoe.c +10
-0+* being removed. Free all skbs and stop the thread. +*/ +spin_lock_bh (&p->fcoe_rx_list.lock); +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p->fcoe_rx_list.lock); +#endif + +if (thread) +kthread_stop (thread);
Don't you need a kthread_unbind() somewhere in here? Under most of your calling conditions (CPU_DEAD events) the bound CPU is toast, so the thread isn't going to be able to wake up on it.
James
Re: [PATCH 04/14] fcoe: create/destroy fcoe Rx threads on CPU hotplug events
Quoted 142 lines · James Bottomley
Quoted 141 lines · Robert Love
This patch adds support for dynamically created Rx threads upon CPU hotplug events.
There were existing synchronization problems that this patch attempts to resolve. The main problem had to do with
fcoe_rcv()running in a different context than the hotplug notifications. This opened the possiblity thatfcoe_rcv()would target a Rx thread for a skb. However, that thread could become NULL if the CPU was made offline.This patch uses the Rx queue's (a
skb_queue) lock to protect the thread it's associated with and we use the 'thread' member of thefcoe_percpu_sto determine if the thread is ready to accept new skbs.The patch also attempts to do a better job of cleaning up, both if hotplug registration fails as well as when the module is removed.
Contribution provided by Joe Eykholt <[email protected]> to fix incorrect use of
__cpuinitdata.Signed-off-by Yi Zou <[email protected]>Signed-off-by Robert Love <[email protected]>---
drivers/scsi/fcoe/libfcoe.c | 246 +++++++++++++++++++++++++++++++++++-------- 1 files changed, 199 insertions(+), 47 deletions(-)drivers/scsi/fcoe/libfcoe.c +104
-0@@ -81,6 +81,156 @@ static struct notifier_block fcoe_notifier = { };/** +* fcoe_percpu_thread_create() - Create a receive thread for an online cpu +* @cpu: cpu index for the online cpu +*/ +static void fcoe_percpu_thread_create (unsigned int cpu) +{ +struct fcoe_percpu_s *p; +struct task_struct *thread; + + p = &per_cpu (fcoe_percpu, cpu); + + thread =kthread_create (fcoe_percpu_receive_thread, + (void *)p,"fcoethread/%d" , cpu); + +if (likely (!IS_ERR (p->thread))) { +kthread_bind (thread, cpu); +wake_up_process (thread); + +spin_lock_bh (&p->fcoe_rx_list.lock); + p->thread = thread; +spin_unlock_bh (&p->fcoe_rx_list.lock); + } +} + +/** +* fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu +* @cpu: cpu index the rx thread is to be removed +* +* Destroys a per-CPU Rx thread. Any pending skbs are moved to the +* current CPU's Rx thread. If the thread being destroyed is bound to +* the CPU processing this context the skbs will be freed. +*/ +static void fcoe_percpu_thread_destroy (unsigned int cpu) +{ +struct fcoe_percpu_s *p; +struct task_struct *thread; +struct page *crc_eof; +struct sk_buff *skb; +#ifdef CONFIG_SMP +struct fcoe_percpu_s *p0; +unsigned targ_cpu =smp_processor_id (); +#endif /* CONFIG_SMP */ + +printk (KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n" , cpu); + +/* Prevent any new skbs from being queued for this CPU. */ + p = &per_cpu (fcoe_percpu, cpu); +spin_lock_bh (&p->fcoe_rx_list.lock); + thread = p->thread; + p->thread =NULL ; + crc_eof = p->crc_eof_page; + p->crc_eof_page =NULL ; + p->crc_eof_offset =0 ; +spin_unlock_bh (&p->fcoe_rx_list.lock); + +#ifdef CONFIG_SMP +/* +* Don't bother moving the skb's if this context is running +* on the same CPU that is having its thread destroyed. This +* can easily happen when the module is removed. +*/ +if (cpu != targ_cpu) { + p0 = &per_cpu (fcoe_percpu, targ_cpu); +spin_lock_bh (&p0->fcoe_rx_list.lock); +if (p0->thread) { +FC_DBG ("Moving frames from CPU %d to CPU %d\n" , + cpu, targ_cpu); + +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +__skb_queue_tail (&p0->fcoe_rx_list, skb); +spin_unlock_bh (&p0->fcoe_rx_list.lock); + }else { +/* +* The targeted CPU is not initialized and cannot accept +* new skbs. Unlock the targeted CPU and drop the skbs +* on the CPU that is going offline. +*/ +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p0->fcoe_rx_list.lock); + } + }else { +/* +* This scenario occurs when the module is being removed +* and all threads are being destroyed. skbs will continue +* to be shifted from the CPU thread that is being removed +* to the CPU thread associated with the CPU that is processing +* the module removal. Once there is only one CPU Rx thread it +* will reach this case and we will drop all skbs and later +* stop the thread. +*/ +spin_lock_bh (&p->fcoe_rx_list.lock); +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p->fcoe_rx_list.lock); + } +#else +/* +* This a non-SMP scenario where the singluar Rx thread is +* being removed. Free all skbs and stop the thread. +*/ +spin_lock_bh (&p->fcoe_rx_list.lock); +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p->fcoe_rx_list.lock);
Quoted 9 lines
drivers/scsi/fcoe/libfcoe.c static struct notifier_block fcoe_notifier = { · line 191
Quoted 4 lines
drivers/scsi/fcoe/libfcoe.c +4
-0+#endif + +if (thread) +kthread_stop (thread);Don't you need a
kthread_unbind()somewhere in here? Under most of your calling conditions (CPU_DEADevents) the bound CPU is toast, so the thread isn't going to be able to wake up on it.
Is there a kthread_unbind()? I can't find it, maybe it was removed recently.
This function should be moving all work off of the CPU that's going away and should also prevent any new work from being scheduled to it (by setting p->thread = NULL), so I'm not expecting this thread to wake up and do something.
James Bottomley
maintainerRe: [PATCH 04/14] fcoe: create/destroy fcoe Rx threads on CPU hotplug events
Quoted 152 lines · Robert Love
Quoted 142 lines · James Bottomley
Quoted 141 lines · Robert Love
This patch adds support for dynamically created Rx threads upon CPU hotplug events.
There were existing synchronization problems that this patch attempts to resolve. The main problem had to do with
fcoe_rcv()running in a different context than the hotplug notifications. This opened the possiblity thatfcoe_rcv()would target a Rx thread for a skb. However, that thread could become NULL if the CPU was made offline.This patch uses the Rx queue's (a
skb_queue) lock to protect the thread it's associated with and we use the 'thread' member of thefcoe_percpu_sto determine if the thread is ready to accept new skbs.The patch also attempts to do a better job of cleaning up, both if hotplug registration fails as well as when the module is removed.
Contribution provided by Joe Eykholt <[email protected]> to fix incorrect use of
__cpuinitdata.Signed-off-by Yi Zou <[email protected]>Signed-off-by Robert Love <[email protected]>---
drivers/scsi/fcoe/libfcoe.c | 246 +++++++++++++++++++++++++++++++++++-------- 1 files changed, 199 insertions(+), 47 deletions(-)drivers/scsi/fcoe/libfcoe.c +104
-0@@ -81,6 +81,156 @@ static struct notifier_block fcoe_notifier = { };/** +* fcoe_percpu_thread_create() - Create a receive thread for an online cpu +* @cpu: cpu index for the online cpu +*/ +static void fcoe_percpu_thread_create (unsigned int cpu) +{ +struct fcoe_percpu_s *p; +struct task_struct *thread; + + p = &per_cpu (fcoe_percpu, cpu); + + thread =kthread_create (fcoe_percpu_receive_thread, + (void *)p,"fcoethread/%d" , cpu); + +if (likely (!IS_ERR (p->thread))) { +kthread_bind (thread, cpu); +wake_up_process (thread); + +spin_lock_bh (&p->fcoe_rx_list.lock); + p->thread = thread; +spin_unlock_bh (&p->fcoe_rx_list.lock); + } +} + +/** +* fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu +* @cpu: cpu index the rx thread is to be removed +* +* Destroys a per-CPU Rx thread. Any pending skbs are moved to the +* current CPU's Rx thread. If the thread being destroyed is bound to +* the CPU processing this context the skbs will be freed. +*/ +static void fcoe_percpu_thread_destroy (unsigned int cpu) +{ +struct fcoe_percpu_s *p; +struct task_struct *thread; +struct page *crc_eof; +struct sk_buff *skb; +#ifdef CONFIG_SMP +struct fcoe_percpu_s *p0; +unsigned targ_cpu =smp_processor_id (); +#endif /* CONFIG_SMP */ + +printk (KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n" , cpu); + +/* Prevent any new skbs from being queued for this CPU. */ + p = &per_cpu (fcoe_percpu, cpu); +spin_lock_bh (&p->fcoe_rx_list.lock); + thread = p->thread; + p->thread =NULL ; + crc_eof = p->crc_eof_page; + p->crc_eof_page =NULL ; + p->crc_eof_offset =0 ; +spin_unlock_bh (&p->fcoe_rx_list.lock); + +#ifdef CONFIG_SMP +/* +* Don't bother moving the skb's if this context is running +* on the same CPU that is having its thread destroyed. This +* can easily happen when the module is removed. +*/ +if (cpu != targ_cpu) { + p0 = &per_cpu (fcoe_percpu, targ_cpu); +spin_lock_bh (&p0->fcoe_rx_list.lock); +if (p0->thread) { +FC_DBG ("Moving frames from CPU %d to CPU %d\n" , + cpu, targ_cpu); + +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +__skb_queue_tail (&p0->fcoe_rx_list, skb); +spin_unlock_bh (&p0->fcoe_rx_list.lock); + }else { +/* +* The targeted CPU is not initialized and cannot accept +* new skbs. Unlock the targeted CPU and drop the skbs +* on the CPU that is going offline. +*/ +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p0->fcoe_rx_list.lock); + } + }else { +/* +* This scenario occurs when the module is being removed +* and all threads are being destroyed. skbs will continue +* to be shifted from the CPU thread that is being removed +* to the CPU thread associated with the CPU that is processing +* the module removal. Once there is only one CPU Rx thread it +* will reach this case and we will drop all skbs and later +* stop the thread. +*/ +spin_lock_bh (&p->fcoe_rx_list.lock); +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p->fcoe_rx_list.lock); + } +#else +/* +* This a non-SMP scenario where the singluar Rx thread is +* being removed. Free all skbs and stop the thread. +*/ +spin_lock_bh (&p->fcoe_rx_list.lock); +while ((skb =__skb_dequeue (&p->fcoe_rx_list)) !=NULL ) +kfree_skb (skb); +spin_unlock_bh (&p->fcoe_rx_list.lock);Quoted 9 lines
drivers/scsi/fcoe/libfcoe.c static struct notifier_block fcoe_notifier = { · line 191
Quoted 4 lines
drivers/scsi/fcoe/libfcoe.c +4
-0+#endif + +if (thread) +kthread_stop (thread);Don't you need a
kthread_unbind()somewhere in here? Under most of your calling conditions (CPU_DEADevents) the bound CPU is toast, so the thread isn't going to be able to wake up on it.
Quoted 7 lines
Is there a
kthread_unbind()? I can't find it, maybe it was removed recently.This function should be moving all work off of the CPU that's going away and should also prevent any new work from being scheduled to it (by setting
p->thread= NULL), so I'm not expecting this thread to wake up and do something.
Yes, sorry, it looks like the API is kthread_bind(task, cpumask_any(cpu_online_mask) ... although some in kernel users do this and some don't ... I suspect it's not something that's often tested.
James
PATCH 1/1 fcoe: prep work to completely remove fc_transport_fcoe code
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
The fcoe transport code was added for generic FCoE transport infrastructure to allow additional offload related module loading on demand, this is not required anymore after recently added different offload approach by having offload related func ops in netdev.
This patch removes fcoe transport related code use, calls functions directly between existing libfcoe.c and fcoe_sw.c for now, for example fcoe_sw_destroy and fcoe_sw_create calling.
The fcoe_sw.c and libfcoe.c code will be further consolidated in later patches and then also the default fcoe sw transport code file fcoe_sw.c will be completely removed.
The fcoe transport code files are completely removed in next patch to keep this patch simple for reviewing.
--
This patch is an update to a previous patch. This update resolves a build error as well as fixes a defect related to not calling fc_release_transport().
The following updates to the other patches in the series are just adjustments to the changes this update introduces.
---
drivers/scsi/fcoe/Makefile | 3 +-- drivers/scsi/fcoe/fcoe_sw.c | 37 ++++--------------------------------- drivers/scsi/fcoe/libfcoe.c | 25 ++++++------------------- include/scsi/libfcoe.h | 2 ++ 4 files changed, 13 insertions(+), 54 deletions(-)
drivers/scsi/fcoe/Makefile +1 -2
@@ -4,5 +4,4 @@ obj-$(CONFIG_FCOE) += fcoe.o fcoe-y := \ libfcoe.o \ - fcoe_sw.o \ - fc_transport_fcoe.o + fcoe_sw.o
drivers/scsi/fcoe/fcoe_sw.c +4 -33
@@ -36,7 +36,6 @@#include <scsi/libfc.h> #include <scsi/libfcoe.h> -#include <scsi/fc_transport_fcoe.h> #define FCOE_SW_VERSION "0.1"#define FCOE_SW_NAME "fcoesw"
@@ -302,7 +301,7 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp)* * Returns: 0 if link is OK for use by FCoE. */ -static int fcoe_sw_destroy (struct net_device *netdev) +int fcoe_sw_destroy (struct net_device *netdev) {struct fc_lport *lp =NULL ;struct fcoe_softc *fc;
@@ -415,7 +414,7 @@ static struct libfc_function_template fcoe_sw_libfc_fcn_templ = {* * Returns : 0 on success */ -static int fcoe_sw_create (struct net_device *netdev) +int fcoe_sw_create (struct net_device *netdev) {int rc;struct fc_lport *lp =NULL ;
@@ -494,28 +493,7 @@ out_host_put: }/** -* fcoe_sw_match() - The FCoE SW transport match function -* -* Returns : false always -*/ -static bool fcoe_sw_match (struct net_device *netdev) -{ -/* FIXME - for sw transport, always return false */ -return false; -} - -/* the sw hba fcoe transport */ -struct fcoe_transport fcoe_sw_transport = { - .name ="fcoesw" , - .create = fcoe_sw_create, - .destroy = fcoe_sw_destroy, - .match = fcoe_sw_match, - .vendor =0x0 , - .device =0xffff , -}; - -/** -* fcoe_sw_init() - Registers fcoe_sw_transport +* fcoe_sw_init() - attach to scsi transport * * Returns : 0 on success */
@@ -530,23 +508,16 @@ int __init fcoe_sw_init(void)return -ENODEV ; } -mutex_init (&fcoe_sw_transport.devlock); -INIT_LIST_HEAD (&fcoe_sw_transport.devlist); - -/* register sw transport */ -fcoe_transport_register (&fcoe_sw_transport);return 0 ; }/** -* fcoe_sw_exit() - Unregisters fcoe_sw_transport +* fcoe_sw_exit() - detach from scsi transport * * Returns : 0 on success */ int __exit fcoe_sw_exit(void) { -/* dettach the transport */ fc_release_transport (scsi_transport_fcoe_sw); -fcoe_transport_unregister (&fcoe_sw_transport);return 0 ; }
drivers/scsi/fcoe/libfcoe.c +6 -19
@@ -44,7 +44,6 @@#include <scsi/libfc.h> #include <scsi/fc_frame.h> #include <scsi/libfcoe.h> -#include <scsi/fc_transport_fcoe.h> static int debug_fcoe;
@@ -1081,10 +1080,9 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) rc = -ENODEV ; goto out_putdev; } -/* pass to transport */ - rc =fcoe_transport_release (netdev); + rc =fcoe_sw_destroy (netdev);if (rc) { -printk (KERN_ERR "fcoe: fcoe_transport_release(%s) failed\n" , +printk (KERN_ERR "fcoe: fcoe_sw_destroy(%s) failed\n" , netdev->name); rc = -EIO ; goto out_putdev;
@@ -1121,10 +1119,9 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) }fcoe_ethdrv_get (netdev); -/* pass to transport */ - rc =fcoe_transport_attach (netdev); + rc =fcoe_sw_create (netdev);if (rc) { -printk (KERN_ERR "fcoe: fcoe_transport_attach(%s) failed\n" , +printk (KERN_ERR "fcoe: fcoe_sw_create(%s) failed\n" , netdev->name);fcoe_ethdrv_put (netdev); rc = -EIO ;
@@ -1429,10 +1426,6 @@ EXPORT_SYMBOL_GPL(fcoe_libfc_config);/** * fcoe_init() - fcoe module loading initialization * -* Initialization routine -* 1. Will create fc transport software structure -* 2. initialize the link list of port information structure -* * Returns 0 on success, negative on failure */ static int __init fcoe_init (void )
@@ -1464,9 +1457,6 @@ static int __init fcoe_init(void)mod_timer (&fcoe_timer, jiffies + (10 *HZ )); -/* initiatlize the fcoe transport */ -fcoe_transport_init (); -fcoe_sw_init ();return 0 ;
@@ -1495,9 +1485,9 @@ static void __exit fcoe_exit(void)/* Stop the timer */ del_timer_sync (&fcoe_timer); -/* releases the associated fcoe transport for each lport */ +/* releases the associated fcoe hosts */ list_for_each_entry_safe (fc, tmp, &fcoe_hostlist, list) -fcoe_transport_release (fc->real_dev); +fcoe_sw_destroy (fc->real_dev);unregister_hotcpu_notifier (&fcoe_cpu_notifier);
@@ -1507,8 +1497,5 @@ static void __exit fcoe_exit(void)/* remove sw trasnport */ fcoe_sw_exit (); - -/* detach the transport */ -fcoe_transport_exit (); }module_exit (fcoe_exit);
include/scsi/libfcoe.h +2 -0
@@ -149,4 +149,6 @@ 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); +int fcoe_sw_create (struct net_device *); +int fcoe_sw_destroy (struct net_device *);#endif /* _LIBFCOE_H */
PATCH 1/1 fcoe: removes fc_transport_fcoe.[ch] code files
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Remove unused fc_transport_fcoe.c and fc_transport_fcoe.h files.
---
drivers/scsi/fcoe/fc_transport_fcoe.c | 443 --------------------------------- include/scsi/fc_transport_fcoe.h | 54 ---- 2 files changed, 0 insertions(+), 497 deletions(-) delete mode 100644 drivers/scsi/fcoe/fc_transport_fcoe.c delete mode 100644 include/scsi/fc_transport_fcoe.h
drivers/scsi/fcoe/fc_transport_fcoe.c deleted +0 -443
@@ -1,443 +0,0 @@ -/* -* 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 -*/ - -#include <linux/pci.h> -#include <scsi/libfcoe.h> -#include <scsi/fc_transport_fcoe.h> - -/* internal fcoe transport */ -struct fcoe_transport_internal { -struct fcoe_transport *t; -struct net_device *netdev; -struct list_head list; -}; - -/* fcoe transports list and its lock */ -static LIST_HEAD (fcoe_transports); -static DEFINE_MUTEX (fcoe_transports_lock); - -/** -* fcoe_transport_default() - Returns ptr to the default transport fcoe_sw -*/ -struct fcoe_transport *fcoe_transport_default (void ) -{ -return &fcoe_sw_transport; -} - -/** -* fcoe_transport_to_pcidev() - get the pci dev from a netdev -* @netdev: the netdev that pci dev will be retrived from -* -* Returns: NULL or the corrsponding pci_dev -*/ -struct pci_dev *fcoe_transport_pcidev (const struct net_device *netdev) -{ -if (!netdev->dev.parent) -return NULL ; -return to_pci_dev (netdev->dev.parent); -} - -/** -* fcoe_transport_device_lookup() - Lookup a transport -* @netdev: the netdev the transport to be attached to -* -* This will look for existing offload driver, if not found, it falls back to -* the default sw hba (fcoe_sw) as its fcoe transport. -* -* Returns: 0 for success -*/ -static struct fcoe_transport_internal * -fcoe_transport_device_lookup (struct fcoe_transport *t, -struct net_device *netdev) -{ -struct fcoe_transport_internal *ti; - -/* assign the transpor to this device */ -mutex_lock (&t->devlock); -list_for_each_entry (ti, &t->devlist, list) { -if (ti->netdev == netdev) { -mutex_unlock (&t->devlock); -return ti; - } - } -mutex_unlock (&t->devlock); -return NULL ; -} -/** -* fcoe_transport_device_add() - Assign a transport to a device -* @netdev: the netdev the transport to be attached to -* -* This will look for existing offload driver, if not found, it falls back to -* the default sw hba (fcoe_sw) as its fcoe transport. -* -* Returns: 0 for success -*/ -static int fcoe_transport_device_add (struct fcoe_transport *t, -struct net_device *netdev) -{ -struct fcoe_transport_internal *ti; - - ti =fcoe_transport_device_lookup (t, netdev); -if (ti) { -printk (KERN_DEBUG "fcoe_transport_device_add:" -"device %s is already added to transport %s\n" , - netdev->name, t->name); -return -EEXIST ; - } -/* allocate an internal struct to host the netdev and the list */ - ti =kzalloc (sizeof (*ti),GFP_KERNEL ); -if (!ti) -return -ENOMEM ; - - ti->t = t; - ti->netdev = netdev; -INIT_LIST_HEAD (&ti->list); -dev_hold (ti->netdev); - -mutex_lock (&t->devlock); -list_add (&ti->list, &t->devlist); -mutex_unlock (&t->devlock); - -printk (KERN_DEBUG "fcoe_transport_device_add:" -"device %s added to transport %s\n" , - netdev->name, t->name); - -return 0 ; -} - -/** -* fcoe_transport_device_remove() - Remove a device from its transport -* @netdev: the netdev the transport to be attached to -* -* This removes the device from the transport so the given transport will -* not manage this device any more -* -* Returns: 0 for success -*/ -static int fcoe_transport_device_remove (struct fcoe_transport *t, -struct net_device *netdev) -{ -struct fcoe_transport_internal *ti; - - ti =fcoe_transport_device_lookup (t, netdev); -if (!ti) { -printk (KERN_DEBUG "fcoe_transport_device_remove:" -"device %s is not managed by transport %s\n" , - netdev->name, t->name); -return -ENODEV ; - } -mutex_lock (&t->devlock); -list_del (&ti->list); -mutex_unlock (&t->devlock); -printk (KERN_DEBUG "fcoe_transport_device_remove:" -"device %s removed from transport %s\n" , - netdev->name, t->name); -dev_put (ti->netdev); -kfree (ti); -return 0 ; -} - -/** -* fcoe_transport_device_remove_all() - Remove all from transport devlist -* -* This removes the device from the transport so the given transport will -* not manage this device any more -* -* Returns: 0 for success -*/ -static void fcoe_transport_device_remove_all (struct fcoe_transport *t) -{ -struct fcoe_transport_internal *ti, *tmp; - -mutex_lock (&t->devlock); -list_for_each_entry_safe (ti, tmp, &t->devlist, list) { -list_del (&ti->list); -kfree (ti); - } -mutex_unlock (&t->devlock); -} - -/** -* fcoe_transport_match() - Use the bus device match function to match the hw -* @t: The fcoe transport to check -* @netdev: The netdev to match against -* -* This function is used to check if the given transport wants to manage the -* input netdev. if the transports implements the match function, it will be -* called, o.w. we just compare the pci vendor and device id. -* -* Returns: true for match up -*/ -static bool fcoe_transport_match (struct fcoe_transport *t, -struct net_device *netdev) -{ -/* match transport by vendor and device id */ -struct pci_dev *pci; - - pci =fcoe_transport_pcidev (netdev); - -if (pci) { -printk (KERN_DEBUG "fcoe_transport_match:" -"%s:%x:%x -- %s:%x:%x\n" , - t->name, t->vendor, t->device, - netdev->name, pci->vendor, pci->device); - -/* if transport supports match */ -if (t->match) -return t->match (netdev); - -/* else just compare the vendor and device id: pci only */ -return (t->vendor == pci->vendor) && (t->device == pci->device); - } -return false; -} - -/** -* fcoe_transport_lookup() - Check if the transport is already registered -* @t: the transport to be looked up -* -* This compares the parent device (pci) vendor and device id -* -* Returns: NULL if not found -* -* TODO: return default sw transport if no other transport is found -*/ -static struct fcoe_transport * -fcoe_transport_lookup (struct net_device *netdev) -{ -struct fcoe_transport *t; - -mutex_lock (&fcoe_transports_lock); -list_for_each_entry (t, &fcoe_transports, list) { -if (fcoe_transport_match (t, netdev)) { -mutex_unlock (&fcoe_transports_lock); -return t; - } - } -mutex_unlock (&fcoe_transports_lock); - -printk (KERN_DEBUG "fcoe_transport_lookup:" -"use default transport for %s\n" , netdev->name); -return fcoe_transport_default (); -} - -/** -* fcoe_transport_register() - Adds a fcoe transport to the fcoe transports list -* @t: ptr to the fcoe transport to be added -* -* Returns: 0 for success -*/ -int fcoe_transport_register (struct fcoe_transport *t) -{ -struct fcoe_transport *tt; - -/* TODO - add fcoe_transport specific initialization here */ -mutex_lock (&fcoe_transports_lock); -list_for_each_entry (tt, &fcoe_transports, list) { -if (tt == t) { -mutex_unlock (&fcoe_transports_lock); -return -EEXIST ; - } - } -list_add_tail (&t->list, &fcoe_transports); -mutex_unlock (&fcoe_transports_lock); - -printk (KERN_DEBUG "fcoe_transport_register:%s\n" , t->name); - -return 0 ; -} -EXPORT_SYMBOL_GPL (fcoe_transport_register); - -/** -* fcoe_transport_unregister() - Remove the tranport fro the fcoe transports list -* @t: ptr to the fcoe transport to be removed -* -* Returns: 0 for success -*/ -int fcoe_transport_unregister (struct fcoe_transport *t) -{ -struct fcoe_transport *tt, *tmp; - -mutex_lock (&fcoe_transports_lock); -list_for_each_entry_safe (tt, tmp, &fcoe_transports, list) { -if (tt == t) { -list_del (&t->list); -mutex_unlock (&fcoe_transports_lock); -fcoe_transport_device_remove_all (t); -printk (KERN_DEBUG "fcoe_transport_unregister:%s\n" , - t->name); -return 0 ; - } - } -mutex_unlock (&fcoe_transports_lock); -return -ENODEV ; -} -EXPORT_SYMBOL_GPL (fcoe_transport_unregister); - -/** -* fcoe_load_transport_driver() - Load an offload driver by alias name -* @netdev: the target net device -* -* Requests for an offload driver module as the fcoe transport, if fails, it -* falls back to use the SW HBA (fcoe_sw) as its transport -* -* TODO - -* 1. supports only PCI device -* 2. needs fix for VLAn and bonding -* 3. pure hw fcoe hba may not have netdev -* -* Returns: 0 for success -*/ -int fcoe_load_transport_driver (struct net_device *netdev) -{ -struct pci_dev *pci; -struct device *dev = netdev->dev.parent; - -if (fcoe_transport_lookup (netdev)) { -/* load default transport */ -printk (KERN_DEBUG "fcoe: already loaded transport for %s\n" , - netdev->name); -return -EEXIST ; - } - - pci =to_pci_dev (dev); -if (dev->bus != &pci_bus_type) { -printk (KERN_DEBUG "fcoe: support noly PCI device\n" ); -return -ENODEV ; - } -printk (KERN_DEBUG "fcoe: loading driver fcoe-pci-0x%04x-0x%04x\n" , - pci->vendor, pci->device); - -return request_module ("fcoe-pci-0x%04x-0x%04x" , - pci->vendor, pci->device); - -} -EXPORT_SYMBOL_GPL (fcoe_load_transport_driver); - -/** -* fcoe_transport_attach() - Load transport to fcoe -* @netdev: the netdev the transport to be attached to -* -* This will look for existing offload driver, if not found, it falls back to -* the default sw hba (fcoe_sw) as its fcoe transport. -* -* Returns: 0 for success -*/ -int fcoe_transport_attach (struct net_device *netdev) -{ -struct fcoe_transport *t; - -/* find the corresponding transport */ - t =fcoe_transport_lookup (netdev); -if (!t) { -printk (KERN_DEBUG "fcoe_transport_attach" -":no transport for %s:use %s\n" , - netdev->name, t->name); -return -ENODEV ; - } -/* add to the transport */ -if (fcoe_transport_device_add (t, netdev)) { -printk (KERN_DEBUG "fcoe_transport_attach" -":failed to add %s to tramsport %s\n" , - netdev->name, t->name); -return -EIO ; - } -/* transport create function */ -if (t->create) - t->create (netdev); - -printk (KERN_DEBUG "fcoe_transport_attach:transport %s for %s\n" , - t->name, netdev->name); -return 0 ; -} -EXPORT_SYMBOL_GPL (fcoe_transport_attach); - -/** -* fcoe_transport_release() - Unload transport from fcoe -* @netdev: the net device on which fcoe is to be released -* -* Returns: 0 for success -*/ -int fcoe_transport_release (struct net_device *netdev) -{ -struct fcoe_transport *t; - -/* find the corresponding transport */ - t =fcoe_transport_lookup (netdev); -if (!t) { -printk (KERN_DEBUG "fcoe_transport_release:" -"no transport for %s:use %s\n" , - netdev->name, t->name); -return -ENODEV ; - } -/* remove the device from the transport */ -if (fcoe_transport_device_remove (t, netdev)) { -printk (KERN_DEBUG "fcoe_transport_release:" -"failed to add %s to tramsport %s\n" , - netdev->name, t->name); -return -EIO ; - } -/* transport destroy function */ -if (t->destroy) - t->destroy (netdev); - -printk (KERN_DEBUG "fcoe_transport_release:" -"device %s dettached from transport %s\n" , - netdev->name, t->name); - -return 0 ; -} -EXPORT_SYMBOL_GPL (fcoe_transport_release); - -/** -* fcoe_transport_init() - Initializes fcoe transport layer -* -* This prepares for the fcoe transport layer -* -* Returns: none -*/ -int __init fcoe_transport_init (void ) -{ -INIT_LIST_HEAD (&fcoe_transports); -mutex_init (&fcoe_transports_lock); -return 0 ; -} - -/** -* fcoe_transport_exit() - Cleans up the fcoe transport layer -* -* This cleans up the fcoe transport layer. removing any transport on the list, -* note that the transport destroy func is not called here. -* -* Returns: none -*/ -int __exit fcoe_transport_exit(void) -{ -struct fcoe_transport *t, *tmp; - -mutex_lock (&fcoe_transports_lock); -list_for_each_entry_safe (t, tmp, &fcoe_transports, list) { -list_del (&t->list); -mutex_unlock (&fcoe_transports_lock); -fcoe_transport_device_remove_all (t); -mutex_lock (&fcoe_transports_lock); - } -mutex_unlock (&fcoe_transports_lock); -return 0 ; -}
include/scsi/fc_transport_fcoe.h deleted +0 -54
54 lines not on this page · raw message
PATCH 1/1 fcoe: removes default sw transport code file fcoe_sw.c
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Moves only required code from fcoe_sw.c to libfcoe.c towards having just one source file for fcoe module, this gets rid off default sw transport code in a separate fcoe_sw.c file.
Very minor renaming along this move, dropped _sw_ or _SW_ use in names and replaced them by _if_ as a auxiliary interface functions. Now some of these funcs can be removed or merged with other func after fcoe transport is gone, but that should be in another patch to keep this patch simple.
Now the libfcoe.c file name for fcoe module doesn't go along well, so the libfcoe.c file renaming to fcoe.c as the only single fcoe module file is done in next patch to keep this patch clean and small for review.
---
drivers/scsi/fcoe/Makefile | 3 drivers/scsi/fcoe/fcoe_sw.c | 523 ------------------------------------------- drivers/scsi/fcoe/libfcoe.c | 501 +++++++++++++++++++++++++++++++++++++++++ include/scsi/libfcoe.h | 6 4 files changed, 494 insertions(+), 539 deletions(-) delete mode 100644 drivers/scsi/fcoe/fcoe_sw.c
drivers/scsi/fcoe/Makefile +1 -2
@@ -3,5 +3,4 @@ obj-$(CONFIG_FCOE) += fcoe.o fcoe-y := \ - libfcoe.o \ - fcoe_sw.o + libfcoe.o
drivers/scsi/fcoe/fcoe_sw.c deleted +0 -523
523 lines not on this page · raw message
drivers/scsi/fcoe/libfcoe.c +493 -8
544 lines not on this page · raw message
include/scsi/libfcoe.h +0 -6
@@ -145,10 +145,4 @@ 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); -int fcoe_sw_create (struct net_device *); -int fcoe_sw_destroy (struct net_device *);#endif /* _LIBFCOE_H */
PATCH 1/1 fcoe: renames libfcoe.c to fcoe.c as the only fcoe module file
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Renames libfcoe.c to fcoe.c, fcoe.c becomes the only .c file for fcoe.ko.
Also deleted "$Id: Makefile" from fcoe module Makefle.
---
drivers/scsi/fcoe/Makefile | 5 drivers/scsi/fcoe/fcoe.c | 1986 +++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/fcoe/libfcoe.c | 1986 ------------------------------------------- 3 files changed, 1986 insertions(+), 1991 deletions(-) create mode 100644 drivers/scsi/fcoe/fcoe.c delete mode 100644 drivers/scsi/fcoe/libfcoe.c
drivers/scsi/fcoe/Makefile +0 -5
@@ -1,6 +1 @@ -# $Id: Makefile - obj-$(CONFIG_FCOE) += fcoe.o - -fcoe-y := \ - libfcoe.o
drivers/scsi/fcoe/fcoe.c new file +1986 -0
1,986 lines not on this page · raw message
drivers/scsi/fcoe/libfcoe.c deleted +0 -1986
1,008 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
PATCH 1/1 PM port setting and attached SATA port selector in discover
In reply to Robert LoveQuoted 1 line
From
9937ccded1e182b50f1128e80d70768b16d2b5e7Mon Sep 17 00:00:00 2001
From: Andy Yan <[email protected]>
Date: Thu, 26 Mar 2009 18:32:31 +0800
Subject: [PATCH] PM port setting and attached SATA port selector in discover
Default PM port should be set 0 other than 1.For most SATA disk, it is ignored,
But I got that some expander reports attached SATA port selector 1 and won't clear it. Host should pass this check and send command with PMport 0.
--- drivers/scsi/libsas/sas_ata.c | 2 +- drivers/scsi/libsas/sas_expander.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
(quoted diff) +0 -0
b/drivers/scsi/libsas/sas_ata.c
index e155011..bea3deb 100644
drivers/scsi/libsas/sas_ata.c +0 -0
@@ -174,7 +174,7 @@ static unsigned int sas_ata_qc_issue(struct
ata_queued_cmd *qc)
qc->tf.nsect = 0;
}
- ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);
+ ata_tf_to_fis(&qc->tf, 0, 0, (u8*)&task->ata_task.fis);
task->uldd_task = qc;
if (ata_is_atapi(qc->tf.protocol)) {
memcpy(task->ata_task.atapi_packet, qc->cdb,qc->dev->cdb_len);
(quoted diff) +0 -0
b/drivers/scsi/libsas/sas_expander.c
index 3da02e4..75ca00b 100644
drivers/scsi/libsas/sas_expander.c +0 -0
@@ -642,7 +642,7 @@ static struct domain_device
*sas_ex_discover_end_dev(
struct sas_rphy *rphy;
int res;
- if (phy->attached_sata_host || phy->attached_sata_ps)
+ if (phy->attached_sata_host)
return NULL;
child = kzalloc(sizeof(*child), GFP_KERNEL);
Signature · 1 line
1.6.2.1
PATCH 1/1 fcoe: prep work to completely remove fc_transport_fcoe code
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
The fcoe transport code was added for generic FCoE transport infrastructure to allow additional offload related module loading on demand, this is not required anymore after recently added different offload approach by having offload related func ops in netdev.
This patch removes fcoe transport related code use, calls functions directly between existing libfcoe.c and fcoe_sw.c for now, for example fcoe_sw_destroy and fcoe_sw_create calling.
The fcoe_sw.c and libfcoe.c code will be further consolidated in later patches and then also the default fcoe sw transport code file fcoe_sw.c will be completely removed.
The fcoe transport code files are completely removed in next patch to keep this patch simple for reviewing.
--
This patch is an update to a previous patch. This update resolves a build error as well as fixes a defect related to not calling fc_release_transport().
The following updates to the other patches in the series are just adjustments to the changes this update introduces.
---
drivers/scsi/fcoe/Makefile | 3 +-- drivers/scsi/fcoe/fcoe_sw.c | 37 ++++--------------------------------- drivers/scsi/fcoe/libfcoe.c | 25 ++++++------------------- include/scsi/libfcoe.h | 2 ++ 4 files changed, 13 insertions(+), 54 deletions(-)
drivers/scsi/fcoe/Makefile +1 -2
@@ -4,5 +4,4 @@ obj-$(CONFIG_FCOE) += fcoe.o fcoe-y := \ libfcoe.o \ - fcoe_sw.o \ - fc_transport_fcoe.o + fcoe_sw.o
drivers/scsi/fcoe/fcoe_sw.c +4 -33
@@ -36,7 +36,6 @@#include <scsi/libfc.h> #include <scsi/libfcoe.h> -#include <scsi/fc_transport_fcoe.h> #define FCOE_SW_VERSION "0.1"#define FCOE_SW_NAME "fcoesw"
@@ -302,7 +301,7 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp)* * Returns: 0 if link is OK for use by FCoE. */ -static int fcoe_sw_destroy (struct net_device *netdev) +int fcoe_sw_destroy (struct net_device *netdev) {struct fc_lport *lp =NULL ;struct fcoe_softc *fc;
@@ -415,7 +414,7 @@ static struct libfc_function_template fcoe_sw_libfc_fcn_templ = {* * Returns : 0 on success */ -static int fcoe_sw_create (struct net_device *netdev) +int fcoe_sw_create (struct net_device *netdev) {int rc;struct fc_lport *lp =NULL ;
@@ -494,28 +493,7 @@ out_host_put: }/** -* fcoe_sw_match() - The FCoE SW transport match function -* -* Returns : false always -*/ -static bool fcoe_sw_match (struct net_device *netdev) -{ -/* FIXME - for sw transport, always return false */ -return false; -} - -/* the sw hba fcoe transport */ -struct fcoe_transport fcoe_sw_transport = { - .name ="fcoesw" , - .create = fcoe_sw_create, - .destroy = fcoe_sw_destroy, - .match = fcoe_sw_match, - .vendor =0x0 , - .device =0xffff , -}; - -/** -* fcoe_sw_init() - Registers fcoe_sw_transport +* fcoe_sw_init() - attach to scsi transport * * Returns : 0 on success */
@@ -530,23 +508,16 @@ int __init fcoe_sw_init(void)return -ENODEV ; } -mutex_init (&fcoe_sw_transport.devlock); -INIT_LIST_HEAD (&fcoe_sw_transport.devlist); - -/* register sw transport */ -fcoe_transport_register (&fcoe_sw_transport);return 0 ; }/** -* fcoe_sw_exit() - Unregisters fcoe_sw_transport +* fcoe_sw_exit() - detach from scsi transport * * Returns : 0 on success */ int __exit fcoe_sw_exit(void) { -/* dettach the transport */ fc_release_transport (scsi_transport_fcoe_sw); -fcoe_transport_unregister (&fcoe_sw_transport);return 0 ; }
drivers/scsi/fcoe/libfcoe.c +6 -19
@@ -44,7 +44,6 @@#include <scsi/libfc.h> #include <scsi/fc_frame.h> #include <scsi/libfcoe.h> -#include <scsi/fc_transport_fcoe.h> static int debug_fcoe;
@@ -1081,10 +1080,9 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) rc = -ENODEV ; goto out_putdev; } -/* pass to transport */ - rc =fcoe_transport_release (netdev); + rc =fcoe_sw_destroy (netdev);if (rc) { -printk (KERN_ERR "fcoe: fcoe_transport_release(%s) failed\n" , +printk (KERN_ERR "fcoe: fcoe_sw_destroy(%s) failed\n" , netdev->name); rc = -EIO ; goto out_putdev;
@@ -1121,10 +1119,9 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) }fcoe_ethdrv_get (netdev); -/* pass to transport */ - rc =fcoe_transport_attach (netdev); + rc =fcoe_sw_create (netdev);if (rc) { -printk (KERN_ERR "fcoe: fcoe_transport_attach(%s) failed\n" , +printk (KERN_ERR "fcoe: fcoe_sw_create(%s) failed\n" , netdev->name);fcoe_ethdrv_put (netdev); rc = -EIO ;
@@ -1429,10 +1426,6 @@ EXPORT_SYMBOL_GPL(fcoe_libfc_config);/** * fcoe_init() - fcoe module loading initialization * -* Initialization routine -* 1. Will create fc transport software structure -* 2. initialize the link list of port information structure -* * Returns 0 on success, negative on failure */ static int __init fcoe_init (void )
@@ -1464,9 +1457,6 @@ static int __init fcoe_init(void)mod_timer (&fcoe_timer, jiffies + (10 *HZ )); -/* initiatlize the fcoe transport */ -fcoe_transport_init (); -fcoe_sw_init ();return 0 ;
@@ -1495,9 +1485,9 @@ static void __exit fcoe_exit(void)/* Stop the timer */ del_timer_sync (&fcoe_timer); -/* releases the associated fcoe transport for each lport */ +/* releases the associated fcoe hosts */ list_for_each_entry_safe (fc, tmp, &fcoe_hostlist, list) -fcoe_transport_release (fc->real_dev); +fcoe_sw_destroy (fc->real_dev);unregister_hotcpu_notifier (&fcoe_cpu_notifier);
@@ -1507,8 +1497,5 @@ static void __exit fcoe_exit(void)/* remove sw trasnport */ fcoe_sw_exit (); - -/* detach the transport */ -fcoe_transport_exit (); }module_exit (fcoe_exit);
include/scsi/libfcoe.h +2 -0
@@ -149,4 +149,6 @@ 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); +int fcoe_sw_create (struct net_device *); +int fcoe_sw_destroy (struct net_device *);#endif /* _LIBFCOE_H */
PATCH 1/1 fcoe: removes fc_transport_fcoe.[ch] code files
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Remove unused fc_transport_fcoe.c and fc_transport_fcoe.h files.
---
drivers/scsi/fcoe/fc_transport_fcoe.c | 443 --------------------------------- include/scsi/fc_transport_fcoe.h | 54 ---- 2 files changed, 0 insertions(+), 497 deletions(-) delete mode 100644 drivers/scsi/fcoe/fc_transport_fcoe.c delete mode 100644 include/scsi/fc_transport_fcoe.h
drivers/scsi/fcoe/fc_transport_fcoe.c deleted +0 -443
@@ -1,443 +0,0 @@ -/* -* 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 -*/ - -#include <linux/pci.h> -#include <scsi/libfcoe.h> -#include <scsi/fc_transport_fcoe.h> - -/* internal fcoe transport */ -struct fcoe_transport_internal { -struct fcoe_transport *t; -struct net_device *netdev; -struct list_head list; -}; - -/* fcoe transports list and its lock */ -static LIST_HEAD (fcoe_transports); -static DEFINE_MUTEX (fcoe_transports_lock); - -/** -* fcoe_transport_default() - Returns ptr to the default transport fcoe_sw -*/ -struct fcoe_transport *fcoe_transport_default (void ) -{ -return &fcoe_sw_transport; -} - -/** -* fcoe_transport_to_pcidev() - get the pci dev from a netdev -* @netdev: the netdev that pci dev will be retrived from -* -* Returns: NULL or the corrsponding pci_dev -*/ -struct pci_dev *fcoe_transport_pcidev (const struct net_device *netdev) -{ -if (!netdev->dev.parent) -return NULL ; -return to_pci_dev (netdev->dev.parent); -} - -/** -* fcoe_transport_device_lookup() - Lookup a transport -* @netdev: the netdev the transport to be attached to -* -* This will look for existing offload driver, if not found, it falls back to -* the default sw hba (fcoe_sw) as its fcoe transport. -* -* Returns: 0 for success -*/ -static struct fcoe_transport_internal * -fcoe_transport_device_lookup (struct fcoe_transport *t, -struct net_device *netdev) -{ -struct fcoe_transport_internal *ti; - -/* assign the transpor to this device */ -mutex_lock (&t->devlock); -list_for_each_entry (ti, &t->devlist, list) { -if (ti->netdev == netdev) { -mutex_unlock (&t->devlock); -return ti; - } - } -mutex_unlock (&t->devlock); -return NULL ; -} -/** -* fcoe_transport_device_add() - Assign a transport to a device -* @netdev: the netdev the transport to be attached to -* -* This will look for existing offload driver, if not found, it falls back to -* the default sw hba (fcoe_sw) as its fcoe transport. -* -* Returns: 0 for success -*/ -static int fcoe_transport_device_add (struct fcoe_transport *t, -struct net_device *netdev) -{ -struct fcoe_transport_internal *ti; - - ti =fcoe_transport_device_lookup (t, netdev); -if (ti) { -printk (KERN_DEBUG "fcoe_transport_device_add:" -"device %s is already added to transport %s\n" , - netdev->name, t->name); -return -EEXIST ; - } -/* allocate an internal struct to host the netdev and the list */ - ti =kzalloc (sizeof (*ti),GFP_KERNEL ); -if (!ti) -return -ENOMEM ; - - ti->t = t; - ti->netdev = netdev; -INIT_LIST_HEAD (&ti->list); -dev_hold (ti->netdev); - -mutex_lock (&t->devlock); -list_add (&ti->list, &t->devlist); -mutex_unlock (&t->devlock); - -printk (KERN_DEBUG "fcoe_transport_device_add:" -"device %s added to transport %s\n" , - netdev->name, t->name); - -return 0 ; -} - -/** -* fcoe_transport_device_remove() - Remove a device from its transport -* @netdev: the netdev the transport to be attached to -* -* This removes the device from the transport so the given transport will -* not manage this device any more -* -* Returns: 0 for success -*/ -static int fcoe_transport_device_remove (struct fcoe_transport *t, -struct net_device *netdev) -{ -struct fcoe_transport_internal *ti; - - ti =fcoe_transport_device_lookup (t, netdev); -if (!ti) { -printk (KERN_DEBUG "fcoe_transport_device_remove:" -"device %s is not managed by transport %s\n" , - netdev->name, t->name); -return -ENODEV ; - } -mutex_lock (&t->devlock); -list_del (&ti->list); -mutex_unlock (&t->devlock); -printk (KERN_DEBUG "fcoe_transport_device_remove:" -"device %s removed from transport %s\n" , - netdev->name, t->name); -dev_put (ti->netdev); -kfree (ti); -return 0 ; -} - -/** -* fcoe_transport_device_remove_all() - Remove all from transport devlist -* -* This removes the device from the transport so the given transport will -* not manage this device any more -* -* Returns: 0 for success -*/ -static void fcoe_transport_device_remove_all (struct fcoe_transport *t) -{ -struct fcoe_transport_internal *ti, *tmp; - -mutex_lock (&t->devlock); -list_for_each_entry_safe (ti, tmp, &t->devlist, list) { -list_del (&ti->list); -kfree (ti); - } -mutex_unlock (&t->devlock); -} - -/** -* fcoe_transport_match() - Use the bus device match function to match the hw -* @t: The fcoe transport to check -* @netdev: The netdev to match against -* -* This function is used to check if the given transport wants to manage the -* input netdev. if the transports implements the match function, it will be -* called, o.w. we just compare the pci vendor and device id. -* -* Returns: true for match up -*/ -static bool fcoe_transport_match (struct fcoe_transport *t, -struct net_device *netdev) -{ -/* match transport by vendor and device id */ -struct pci_dev *pci; - - pci =fcoe_transport_pcidev (netdev); - -if (pci) { -printk (KERN_DEBUG "fcoe_transport_match:" -"%s:%x:%x -- %s:%x:%x\n" , - t->name, t->vendor, t->device, - netdev->name, pci->vendor, pci->device); - -/* if transport supports match */ -if (t->match) -return t->match (netdev); - -/* else just compare the vendor and device id: pci only */ -return (t->vendor == pci->vendor) && (t->device == pci->device); - } -return false; -} - -/** -* fcoe_transport_lookup() - Check if the transport is already registered -* @t: the transport to be looked up -* -* This compares the parent device (pci) vendor and device id -* -* Returns: NULL if not found -* -* TODO: return default sw transport if no other transport is found -*/ -static struct fcoe_transport * -fcoe_transport_lookup (struct net_device *netdev) -{ -struct fcoe_transport *t; - -mutex_lock (&fcoe_transports_lock); -list_for_each_entry (t, &fcoe_transports, list) { -if (fcoe_transport_match (t, netdev)) { -mutex_unlock (&fcoe_transports_lock); -return t; - } - } -mutex_unlock (&fcoe_transports_lock); - -printk (KERN_DEBUG "fcoe_transport_lookup:" -"use default transport for %s\n" , netdev->name); -return fcoe_transport_default (); -} - -/** -* fcoe_transport_register() - Adds a fcoe transport to the fcoe transports list -* @t: ptr to the fcoe transport to be added -* -* Returns: 0 for success -*/ -int fcoe_transport_register (struct fcoe_transport *t) -{ -struct fcoe_transport *tt; - -/* TODO - add fcoe_transport specific initialization here */ -mutex_lock (&fcoe_transports_lock); -list_for_each_entry (tt, &fcoe_transports, list) { -if (tt == t) { -mutex_unlock (&fcoe_transports_lock); -return -EEXIST ; - } - } -list_add_tail (&t->list, &fcoe_transports); -mutex_unlock (&fcoe_transports_lock); - -printk (KERN_DEBUG "fcoe_transport_register:%s\n" , t->name); - -return 0 ; -} -EXPORT_SYMBOL_GPL (fcoe_transport_register); - -/** -* fcoe_transport_unregister() - Remove the tranport fro the fcoe transports list -* @t: ptr to the fcoe transport to be removed -* -* Returns: 0 for success -*/ -int fcoe_transport_unregister (struct fcoe_transport *t) -{ -struct fcoe_transport *tt, *tmp; - -mutex_lock (&fcoe_transports_lock); -list_for_each_entry_safe (tt, tmp, &fcoe_transports, list) { -if (tt == t) { -list_del (&t->list); -mutex_unlock (&fcoe_transports_lock); -fcoe_transport_device_remove_all (t); -printk (KERN_DEBUG "fcoe_transport_unregister:%s\n" , - t->name); -return 0 ; - } - } -mutex_unlock (&fcoe_transports_lock); -return -ENODEV ; -} -EXPORT_SYMBOL_GPL (fcoe_transport_unregister); - -/** -* fcoe_load_transport_driver() - Load an offload driver by alias name -* @netdev: the target net device -* -* Requests for an offload driver module as the fcoe transport, if fails, it -* falls back to use the SW HBA (fcoe_sw) as its transport -* -* TODO - -* 1. supports only PCI device -* 2. needs fix for VLAn and bonding -* 3. pure hw fcoe hba may not have netdev -* -* Returns: 0 for success -*/ -int fcoe_load_transport_driver (struct net_device *netdev) -{ -struct pci_dev *pci; -struct device *dev = netdev->dev.parent; - -if (fcoe_transport_lookup (netdev)) { -/* load default transport */ -printk (KERN_DEBUG "fcoe: already loaded transport for %s\n" , - netdev->name); -return -EEXIST ; - } - - pci =to_pci_dev (dev); -if (dev->bus != &pci_bus_type) { -printk (KERN_DEBUG "fcoe: support noly PCI device\n" ); -return -ENODEV ; - } -printk (KERN_DEBUG "fcoe: loading driver fcoe-pci-0x%04x-0x%04x\n" , - pci->vendor, pci->device); - -return request_module ("fcoe-pci-0x%04x-0x%04x" , - pci->vendor, pci->device); - -} -EXPORT_SYMBOL_GPL (fcoe_load_transport_driver); - -/** -* fcoe_transport_attach() - Load transport to fcoe -* @netdev: the netdev the transport to be attached to -* -* This will look for existing offload driver, if not found, it falls back to -* the default sw hba (fcoe_sw) as its fcoe transport. -* -* Returns: 0 for success -*/ -int fcoe_transport_attach (struct net_device *netdev) -{ -struct fcoe_transport *t; - -/* find the corresponding transport */ - t =fcoe_transport_lookup (netdev); -if (!t) { -printk (KERN_DEBUG "fcoe_transport_attach" -":no transport for %s:use %s\n" , - netdev->name, t->name); -return -ENODEV ; - } -/* add to the transport */ -if (fcoe_transport_device_add (t, netdev)) { -printk (KERN_DEBUG "fcoe_transport_attach" -":failed to add %s to tramsport %s\n" , - netdev->name, t->name); -return -EIO ; - } -/* transport create function */ -if (t->create) - t->create (netdev); - -printk (KERN_DEBUG "fcoe_transport_attach:transport %s for %s\n" , - t->name, netdev->name); -return 0 ; -} -EXPORT_SYMBOL_GPL (fcoe_transport_attach); - -/** -* fcoe_transport_release() - Unload transport from fcoe -* @netdev: the net device on which fcoe is to be released -* -* Returns: 0 for success -*/ -int fcoe_transport_release (struct net_device *netdev) -{ -struct fcoe_transport *t; - -/* find the corresponding transport */ - t =fcoe_transport_lookup (netdev); -if (!t) { -printk (KERN_DEBUG "fcoe_transport_release:" -"no transport for %s:use %s\n" , - netdev->name, t->name); -return -ENODEV ; - } -/* remove the device from the transport */ -if (fcoe_transport_device_remove (t, netdev)) { -printk (KERN_DEBUG "fcoe_transport_release:" -"failed to add %s to tramsport %s\n" , - netdev->name, t->name); -return -EIO ; - } -/* transport destroy function */ -if (t->destroy) - t->destroy (netdev); - -printk (KERN_DEBUG "fcoe_transport_release:" -"device %s dettached from transport %s\n" , - netdev->name, t->name); - -return 0 ; -} -EXPORT_SYMBOL_GPL (fcoe_transport_release); - -/** -* fcoe_transport_init() - Initializes fcoe transport layer -* -* This prepares for the fcoe transport layer -* -* Returns: none -*/ -int __init fcoe_transport_init (void ) -{ -INIT_LIST_HEAD (&fcoe_transports); -mutex_init (&fcoe_transports_lock); -return 0 ; -} - -/** -* fcoe_transport_exit() - Cleans up the fcoe transport layer -* -* This cleans up the fcoe transport layer. removing any transport on the list, -* note that the transport destroy func is not called here. -* -* Returns: none -*/ -int __exit fcoe_transport_exit(void) -{ -struct fcoe_transport *t, *tmp; - -mutex_lock (&fcoe_transports_lock); -list_for_each_entry_safe (t, tmp, &fcoe_transports, list) { -list_del (&t->list); -mutex_unlock (&fcoe_transports_lock); -fcoe_transport_device_remove_all (t); -mutex_lock (&fcoe_transports_lock); - } -mutex_unlock (&fcoe_transports_lock); -return 0 ; -}
include/scsi/fc_transport_fcoe.h deleted +0 -54
54 lines not on this page · raw message
PATCH 1/1 fcoe: removes default sw transport code file fcoe_sw.c
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Moves only required code from fcoe_sw.c to libfcoe.c towards having just one source file for fcoe module, this gets rid off default sw transport code in a separate fcoe_sw.c file.
Very minor renaming along this move, dropped _sw_ or _SW_ use in names and replaced them by _if_ as a auxiliary interface functions. Now some of these funcs can be removed or merged with other func after fcoe transport is gone, but that should be in another patch to keep this patch simple.
Now the libfcoe.c file name for fcoe module doesn't go along well, so the libfcoe.c file renaming to fcoe.c as the only single fcoe module file is done in next patch to keep this patch clean and small for review.
---
drivers/scsi/fcoe/Makefile | 3 drivers/scsi/fcoe/fcoe_sw.c | 523 ------------------------------------------- drivers/scsi/fcoe/libfcoe.c | 501 +++++++++++++++++++++++++++++++++++++++++ include/scsi/libfcoe.h | 6 4 files changed, 494 insertions(+), 539 deletions(-) delete mode 100644 drivers/scsi/fcoe/fcoe_sw.c
drivers/scsi/fcoe/Makefile +1 -2
@@ -3,5 +3,4 @@ obj-$(CONFIG_FCOE) += fcoe.o fcoe-y := \ - libfcoe.o \ - fcoe_sw.o + libfcoe.o
drivers/scsi/fcoe/fcoe_sw.c deleted +0 -523
523 lines not on this page · raw message
drivers/scsi/fcoe/libfcoe.c +493 -8
544 lines not on this page · raw message
include/scsi/libfcoe.h +0 -6
@@ -145,10 +145,4 @@ 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); -int fcoe_sw_create (struct net_device *); -int fcoe_sw_destroy (struct net_device *);#endif /* _LIBFCOE_H */
PATCH 1/1 fcoe: renames libfcoe.c to fcoe.c as the only fcoe module file
In reply to Robert LoveFrom: Vasu Dev <[email protected]>
Renames libfcoe.c to fcoe.c, fcoe.c becomes the only .c file for fcoe.ko.
Also deleted "$Id: Makefile" from fcoe module Makefle.
---
drivers/scsi/fcoe/Makefile | 5 drivers/scsi/fcoe/fcoe.c | 1986 +++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/fcoe/libfcoe.c | 1986 ------------------------------------------- 3 files changed, 1986 insertions(+), 1991 deletions(-) create mode 100644 drivers/scsi/fcoe/fcoe.c delete mode 100644 drivers/scsi/fcoe/libfcoe.c
drivers/scsi/fcoe/Makefile +0 -5
@@ -1,6 +1 @@ -# $Id: Makefile - obj-$(CONFIG_FCOE) += fcoe.o - -fcoe-y := \ - libfcoe.o
drivers/scsi/fcoe/fcoe.c new file +1986 -0
1,986 lines not on this page · raw message
drivers/scsi/fcoe/libfcoe.c deleted +0 -1986
1,008 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
RE: [PATCH] fcoe: prep work to completely remove fc_transport_fcoe code
In reply to Robert LoveQuoted 25 lines · Robert Love
From: Vasu Dev <[email protected]>
The fcoe transport code was added for generic FCoE transport infrastructure to allow additional offload related module loading on demand, this is not required anymore after recently added different offload approach by having offload related func ops in netdev.
This patch removes fcoe transport related code use, calls functions directly between existing
libfcoe.candfcoe_sw.cfor now, for examplefcoe_sw_destroyandfcoe_sw_createcalling.The
fcoe_sw.candlibfcoe.ccode will be further consolidated in later patches and then also the default fcoe sw transport code filefcoe_sw.cwill be completely removed.The fcoe transport code files are completely removed in next patch to keep this patch simple for reviewing.
--
This patch is an update to a previous patch. This update resolves a build error as well as fixes a defect related to not calling
fc_release_transport().
Quoted 7 lines
The following updates to the other patches in the series are just adjustments to the changes this update introduces.
Signed-off-by Vasu Dev <[email protected]>Signed-off-by Robert Love <[email protected]>---
Nothing has changed since these 4 updated pathces made it to linux-scsi two days ago. I just misspelled James' e-mail address in when I originally sent them.
James Bottomley
maintainerRe: [PATCH] PM port setting and attached SATA port selector in discover
In reply to Andy YanQuoted 39 lines · Andy Yan
Quoted 1 line
From
9937ccded1e182b50f1128e80d70768b16d2b5e7Mon Sep 17 00:00:00 2001From: Andy Yan <[email protected]>
Date: Thu, 26 Mar 2009 18:32:31 +0800
Subject: [PATCH] PM port setting and attached SATA port selector in discoverDefault PM port should be set 0 other than 1.For most SATA disk, it is ignored,
But I got that some expander reports attached SATA port selector 1 and won't clear it. Host should pass this check and send command with PMport 0.--- drivers/scsi/libsas/sas_ata.c | 2 +- drivers/scsi/libsas/sas_expander.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)drivers/scsi/libsas/sas_ata.c +1
-1@@ -174,7 +174,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) qc->tf.nsect = 0; } -ata_tf_to_fis (&qc->tf,1 ,0 , (u8 *)&task->ata_task.fis); +ata_tf_to_fis (&qc->tf,0 ,0 , (u8 *)&task->ata_task.fis); task->uldd_task = qc;if (ata_is_atapi (qc->tf.protocol)) {memcpy(task->ata_task.atapi_packet,
qc->cdb,qc->dev->cdb_len);drivers/scsi/libsas/sas_expander.c +0
-0
drivers/scsi/libsas/sas_expander.c static struct domain_device · line 646
Quoted 6 lines
drivers/scsi/libsas/sas_expander.c +1
-1@@ -642,7 +642,7 @@ static struct domain_device *sas_ex_discover_end_dev ( struct sas_rphy *rphy;int res; -if (phy->attached_sata_host || phy->attached_sata_ps) +if (phy->attached_sata_host)
In general this looks OK. What it's going to cause to happen is that we now try to discover SATA port selectors, which aren't supported in libsas ... can you check that nothing nasty happens when libsas finds one?
James
PATCH v2 3/14 fcoe: Use per-CPU kernel function for dev_stats instead of an array
In reply to Robert LoveRemove the hotplug creation of dev_stats, we allocate for all possible CPUs now when we allocate the lport.
v2: Durring the 2.6.30 merge window, before these patches were comitted, 'percpu_ptr' was renamed 'per_cpu_ptr'. This latest update updates this patch for the name change.
---
drivers/scsi/fcoe/fcoe_sw.c | 13 +--- drivers/scsi/fcoe/libfcoe.c | 143 +++++------------------------------------ drivers/scsi/libfc/fc_fcp.c | 8 +- drivers/scsi/libfc/fc_lport.c | 11 ++- include/scsi/libfc.h | 23 ++++++- 5 files changed, 53 insertions(+), 145 deletions(-)
drivers/scsi/fcoe/fcoe_sw.c +2 -11
@@ -113,8 +113,6 @@ static struct scsi_host_template fcoe_sw_shost_template = {*/ static int fcoe_sw_lport_config (struct fc_lport *lp) { -int i =0 ; - lp->link_up =0 ; lp->qfull =0 ; lp->max_retry_count =3 ;
@@ -123,12 +121,7 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) lp->service_params = (FCP_SPPF_INIT_FCN |FCP_SPPF_RD_XRDY_DIS |FCP_SPPF_RETRY |FCP_SPPF_CONF_COMPL ); -/* -* allocate per cpu stats block -*/ -for_each_online_cpu (i) - lp->dev_stats[i] =kzalloc (sizeof (struct fcoe_dev_stats ), -GFP_KERNEL ); +fc_lport_init_stats (lp);/* lport fc_lport related configuration */ fc_lport_config (lp);
@@ -311,7 +304,6 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp)*/ static int fcoe_sw_destroy (struct net_device *netdev) { -int cpu;struct fc_lport *lp =NULL ;struct fcoe_softc *fc;u8 flogi_maddr[ETH_ALEN ];
@@ -363,8 +355,7 @@ static int fcoe_sw_destroy(struct net_device *netdev)fcoe_clean_pending_queue (lp);/* Free memory used by statistical counters */ -for_each_online_cpu (cpu) -kfree (lp->dev_stats[cpu]); +fc_lport_free_stats (lp);/* Release the net_device and Scsi_Host */ dev_put (fc->real_dev);
drivers/scsi/fcoe/libfcoe.c +18 -125
212 lines not on this page · raw message
drivers/scsi/libfc/fc_fcp.c +5 -3
@@ -407,10 +407,12 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)if (~crc !=le32_to_cpu (fr_crc (fp))) { crc_err: - stats = lp->dev_stats[smp_processor_id ()]; + stats =fc_lport_get_stats (lp); stats->ErrorFrames++; +/* FIXME - per cpu count, not total count! */ if (stats->InvalidCRCCount++ <5 ) -FC_DBG ("CRC error on data frame\n" ); +printk (KERN_WARNING "CRC error on data frame for port (%6x)\n" , +fc_host_port_id (lp->host));/* * Assume the frame is total garbage. * We may have copied it over the good part
@@ -1752,7 +1754,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))/* * setup the data direction */ - stats = lp->dev_stats[smp_processor_id ()]; + stats =fc_lport_get_stats (lp);if (sc_cmd->sc_data_direction ==DMA_FROM_DEVICE ) { fsp->req_flags =FC_SRB_READ ; stats->InputRequests++;
drivers/scsi/libfc/fc_lport.c +6 -5
@@ -267,10 +267,10 @@ EXPORT_SYMBOL(fc_get_host_speed);struct fc_host_statistics *fc_get_host_stats (struct Scsi_Host *shost) { -int i;struct fc_host_statistics *fcoe_stats;struct fc_lport *lp =shost_priv (shost);struct timespec v0, v1; +unsigned int cpu; fcoe_stats = &lp->host_stats;memset (fcoe_stats,0 ,sizeof (struct fc_host_statistics ));
@@ -279,10 +279,11 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)jiffies_to_timespec (lp->boot_time, &v1); fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec); -for_each_online_cpu (i) { -struct fcoe_dev_stats *stats = lp->dev_stats[i]; -if (stats ==NULL ) -continue ; +for_each_possible_cpu (cpu) { +struct fcoe_dev_stats *stats; + + stats =per_cpu_ptr (lp->dev_stats, cpu); + fcoe_stats->tx_frames += stats->TxFrames; fcoe_stats->tx_words += stats->TxWords; fcoe_stats->rx_frames += stats->RxFrames;
include/scsi/libfc.h +22 -1
@@ -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;
@@ -722,6 +724,25 @@ 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 ()); +} +/* * LOCAL PORT LAYER