2009-04-18 09:33:26 +08:00
|
|
|
/*
|
|
|
|
* Copyright 2008 Cisco Systems, Inc. All rights reserved.
|
|
|
|
* Copyright 2007 Nuova 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 _FNIC_H_
|
|
|
|
#define _FNIC_H_
|
|
|
|
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/netdevice.h>
|
|
|
|
#include <linux/workqueue.h>
|
2010-08-11 09:01:26 +08:00
|
|
|
#include <linux/bitops.h>
|
2009-04-18 09:33:26 +08:00
|
|
|
#include <scsi/libfc.h>
|
2009-11-04 03:49:22 +08:00
|
|
|
#include <scsi/libfcoe.h>
|
2009-04-18 09:33:26 +08:00
|
|
|
#include "fnic_io.h"
|
|
|
|
#include "fnic_res.h"
|
2013-02-13 09:01:02 +08:00
|
|
|
#include "fnic_trace.h"
|
2009-04-18 09:33:26 +08:00
|
|
|
#include "vnic_dev.h"
|
|
|
|
#include "vnic_wq.h"
|
|
|
|
#include "vnic_rq.h"
|
|
|
|
#include "vnic_cq.h"
|
|
|
|
#include "vnic_wq_copy.h"
|
|
|
|
#include "vnic_intr.h"
|
|
|
|
#include "vnic_stats.h"
|
|
|
|
#include "vnic_scsi.h"
|
|
|
|
|
|
|
|
#define DRV_NAME "fnic"
|
|
|
|
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
|
[SCSI] fnic: BUG: sleeping function called from invalid context during probe
I hit this during driver probe with the latest fnic updates (this trace
is from a backport into a distro kernel, but the issue is the same).
> BUG: sleeping function called from invalid context at mm/slab.c:3113
> in_atomic(): 0, irqs_disabled(): 1, pid: 610, name: work_for_cpu
> INFO: lockdep is turned off.
> irq event stamp: 0
> hardirqs last enabled at (0): [<(null)>] (null)
> hardirqs last disabled at (0): [<ffffffff81070aa5>]
> copy_process+0x5e5/0x1670
> softirqs last enabled at (0): [<ffffffff81070aa5>]
> copy_process+0x5e5/0x1670
> softirqs last disabled at (0): [<(null)>] (null)
> Pid: 610, comm: work_for_cpu Not tainted
> Call Trace:
> [<ffffffff810b2d10>] ? print_irqtrace_events+0xd0/0xe0
> [<ffffffff8105c1a7>] ? __might_sleep+0xf7/0x130
> [<ffffffff81184efb>] ? kmem_cache_alloc_trace+0x20b/0x2d0
> [<ffffffff8109709e>] ? __create_workqueue_key+0x3e/0x1d0
> [<ffffffff8109709e>] ? __create_workqueue_key+0x3e/0x1d0
> [<ffffffffa00c101c>] ? fnic_probe+0x977/0x11aa [fnic]
> [<ffffffffa00c1048>] ? fnic_probe+0x9a3/0x11aa [fnic]
> [<ffffffff81096f00>] ? do_work_for_cpu+0x0/0x30
> [<ffffffff812c6da7>] ? local_pci_probe+0x17/0x20
> [<ffffffff81096f18>] ? do_work_for_cpu+0x18/0x30
> [<ffffffff8109cdc6>] ? kthread+0x96/0xa0
> [<ffffffff8100c1ca>] ? child_rip+0xa/0x20
> [<ffffffff81550f80>] ? _spin_unlock_irq+0x30/0x40
> [<ffffffff8100bb10>] ? restore_args+0x0/0x30
> [<ffffffff8109cd30>] ? kthread+0x0/0xa0
> [<ffffffff8100c1c0>] ? child_rip+0x0/0x20
The problem is in this hunk of "FIP VLAN Discovery Feature Support"
(d3c995f1dcf938f1084388d92b8fb97bec366566)
create_singlethreaded_workqueue cannot be called with irqs disabled
@@ -620,7 +634,29 @@ static int __devinit fnic_probe(struct pci_dev
*pdev,
vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0);
vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS);
vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr);
+ fnic->set_vlan = fnic_set_vlan;
fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO);
+ setup_timer(&fnic->fip_timer, fnic_fip_notify_timer,
+ (unsigned long)fnic);
+ spin_lock_init(&fnic->vlans_lock);
+ INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame);
+ INIT_WORK(&fnic->event_work, fnic_handle_event);
+ skb_queue_head_init(&fnic->fip_frame_queue);
+ spin_lock_irqsave(&fnic_list_lock, flags);
+ if (!fnic_fip_queue) {
+ fnic_fip_queue =
+ create_singlethread_workqueue("fnic_fip_q");
+ if (!fnic_fip_queue) {
+ spin_unlock_irqrestore(&fnic_list_lock, flags);
+ printk(KERN_ERR PFX "fnic FIP work queue "
+ "create failed\n");
+ err = -ENOMEM;
+ goto err_out_free_max_pool;
+ }
+ }
+ spin_unlock_irqrestore(&fnic_list_lock, flags);
+ INIT_LIST_HEAD(&fnic->evlist);
+ INIT_LIST_HEAD(&fnic->vlans);
} else {
shost_printk(KERN_INFO, fnic->lport->host,
"firmware uses non-FIP mode\n");
The attempts to make fnic_fip_queue a single instance for the driver
while it's being created in probe look awkward anyway, why is this not
created in fnic_init_module like the event workqueue?
Signed-off-by: Chris Leech <cleech@redhat.com>
Tested-by: Anantha Tungarakodi <atungara@cisco.com>
Acked-by: Hiral Patel <hiralpat@cisco.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-07-24 04:04:58 +08:00
|
|
|
#define DRV_VERSION "1.5.0.23"
|
2009-04-18 09:33:26 +08:00
|
|
|
#define PFX DRV_NAME ": "
|
|
|
|
#define DFX DRV_NAME "%d: "
|
|
|
|
|
|
|
|
#define DESC_CLEAN_LOW_WATERMARK 8
|
2013-09-10 04:31:51 +08:00
|
|
|
#define FNIC_UCSM_DFLT_THROTTLE_CNT_BLD 16 /* UCSM default throttle count */
|
|
|
|
#define FNIC_MIN_IO_REQ 256 /* Min IO throttle count */
|
2009-04-18 09:33:26 +08:00
|
|
|
#define FNIC_MAX_IO_REQ 2048 /* scsi_cmnd tag map entries */
|
|
|
|
#define FNIC_IO_LOCKS 64 /* IO locks: power of 2 */
|
|
|
|
#define FNIC_DFLT_QUEUE_DEPTH 32
|
|
|
|
#define FNIC_STATS_RATE_LIMIT 4 /* limit rate at which stats are pulled up */
|
2010-04-10 05:22:59 +08:00
|
|
|
|
2009-04-18 09:33:26 +08:00
|
|
|
/*
|
|
|
|
* Tag bits used for special requests.
|
|
|
|
*/
|
|
|
|
#define FNIC_TAG_ABORT BIT(30) /* tag bit indicating abort */
|
|
|
|
#define FNIC_TAG_DEV_RST BIT(29) /* indicates device reset */
|
|
|
|
#define FNIC_TAG_MASK (BIT(24) - 1) /* mask for lookup */
|
|
|
|
#define FNIC_NO_TAG -1
|
|
|
|
|
[SCSI] fnic: fixing issues in device and firmware reset code
1. Handling overlapped firmware resets
This fix serialize multiple firmware resets to avoid situation where fnic
device fails to come up for link up event, when firmware resets are issued
back to back. If there are overlapped firmware resets are issued,
the firmware reset operation checks whether there is any firmware reset in
progress, if so it polls for its completion in a loop with 100ms delay.
2. Handling device reset timeout
fnic_device_reset code has been modified to handle Device reset timeout:
- Issue terminate on device reset timeout.
- Introduced flags field (one of the scratch fields in scsi_cmnd).
With this, device reset request would have DEVICE_RESET flag set for other
routines to determine the type of the request.
Also modified fnic_terminate_rport_io, fnic_rport_exch_rset, completion
routines to handle SCSI commands with DEVICE_RESET flag.
3. LUN/Device Reset hangs when issued through IOCTL using utilities like
sg_reset.
Each SCSI command is associated with a valid tag, fnic uses this tag to
retrieve associated scsi command on completion. the LUN/Device Reset issued
through IOCTL resulting into a SCSI command that is not associated with a
valid tag. So fnic fails to retrieve associated scsi command on completion,
which causes hang. This fix allocates tag, associates it with the
scsi command and frees the tag, when the operation completed.
4. Preventing IOs during firmware reset.
Current fnic implementation allows IO submissions during firmware reset.
This fix synchronizes IO submissions and firmware reset operations.
It ensures that IOs issued to fnic prior to reset will be issued to the
firmware before firmware reset.
Signed-off-by: Narsimhulu Musini <nmusini@cisco.com>
Signed-off-by: Hiral Patel <hiralpat@cisco.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-02-13 09:00:58 +08:00
|
|
|
/*
|
|
|
|
* Command flags to identify the type of command and for other future
|
|
|
|
* use.
|
|
|
|
*/
|
2013-02-13 09:01:01 +08:00
|
|
|
#define FNIC_NO_FLAGS 0
|
|
|
|
#define FNIC_IO_INITIALIZED BIT(0)
|
|
|
|
#define FNIC_IO_ISSUED BIT(1)
|
|
|
|
#define FNIC_IO_DONE BIT(2)
|
|
|
|
#define FNIC_IO_REQ_NULL BIT(3)
|
|
|
|
#define FNIC_IO_ABTS_PENDING BIT(4)
|
|
|
|
#define FNIC_IO_ABORTED BIT(5)
|
|
|
|
#define FNIC_IO_ABTS_ISSUED BIT(6)
|
|
|
|
#define FNIC_IO_TERM_ISSUED BIT(7)
|
|
|
|
#define FNIC_IO_INTERNAL_TERM_ISSUED BIT(8)
|
|
|
|
#define FNIC_IO_ABT_TERM_DONE BIT(9)
|
|
|
|
#define FNIC_IO_ABT_TERM_REQ_NULL BIT(10)
|
|
|
|
#define FNIC_IO_ABT_TERM_TIMED_OUT BIT(11)
|
|
|
|
#define FNIC_DEVICE_RESET BIT(12) /* Device reset request */
|
|
|
|
#define FNIC_DEV_RST_ISSUED BIT(13)
|
|
|
|
#define FNIC_DEV_RST_TIMED_OUT BIT(14)
|
|
|
|
#define FNIC_DEV_RST_ABTS_ISSUED BIT(15)
|
|
|
|
#define FNIC_DEV_RST_TERM_ISSUED BIT(16)
|
|
|
|
#define FNIC_DEV_RST_DONE BIT(17)
|
|
|
|
#define FNIC_DEV_RST_REQ_NULL BIT(18)
|
|
|
|
#define FNIC_DEV_RST_ABTS_DONE BIT(19)
|
|
|
|
#define FNIC_DEV_RST_TERM_DONE BIT(20)
|
|
|
|
#define FNIC_DEV_RST_ABTS_PENDING BIT(21)
|
[SCSI] fnic: fixing issues in device and firmware reset code
1. Handling overlapped firmware resets
This fix serialize multiple firmware resets to avoid situation where fnic
device fails to come up for link up event, when firmware resets are issued
back to back. If there are overlapped firmware resets are issued,
the firmware reset operation checks whether there is any firmware reset in
progress, if so it polls for its completion in a loop with 100ms delay.
2. Handling device reset timeout
fnic_device_reset code has been modified to handle Device reset timeout:
- Issue terminate on device reset timeout.
- Introduced flags field (one of the scratch fields in scsi_cmnd).
With this, device reset request would have DEVICE_RESET flag set for other
routines to determine the type of the request.
Also modified fnic_terminate_rport_io, fnic_rport_exch_rset, completion
routines to handle SCSI commands with DEVICE_RESET flag.
3. LUN/Device Reset hangs when issued through IOCTL using utilities like
sg_reset.
Each SCSI command is associated with a valid tag, fnic uses this tag to
retrieve associated scsi command on completion. the LUN/Device Reset issued
through IOCTL resulting into a SCSI command that is not associated with a
valid tag. So fnic fails to retrieve associated scsi command on completion,
which causes hang. This fix allocates tag, associates it with the
scsi command and frees the tag, when the operation completed.
4. Preventing IOs during firmware reset.
Current fnic implementation allows IO submissions during firmware reset.
This fix synchronizes IO submissions and firmware reset operations.
It ensures that IOs issued to fnic prior to reset will be issued to the
firmware before firmware reset.
Signed-off-by: Narsimhulu Musini <nmusini@cisco.com>
Signed-off-by: Hiral Patel <hiralpat@cisco.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-02-13 09:00:58 +08:00
|
|
|
|
2009-04-18 09:33:26 +08:00
|
|
|
/*
|
|
|
|
* Usage of the scsi_cmnd scratchpad.
|
|
|
|
* These fields are locked by the hashed io_req_lock.
|
|
|
|
*/
|
|
|
|
#define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr)
|
|
|
|
#define CMD_STATE(Cmnd) ((Cmnd)->SCp.phase)
|
|
|
|
#define CMD_ABTS_STATUS(Cmnd) ((Cmnd)->SCp.Message)
|
|
|
|
#define CMD_LR_STATUS(Cmnd) ((Cmnd)->SCp.have_data_in)
|
|
|
|
#define CMD_TAG(Cmnd) ((Cmnd)->SCp.sent_command)
|
[SCSI] fnic: fixing issues in device and firmware reset code
1. Handling overlapped firmware resets
This fix serialize multiple firmware resets to avoid situation where fnic
device fails to come up for link up event, when firmware resets are issued
back to back. If there are overlapped firmware resets are issued,
the firmware reset operation checks whether there is any firmware reset in
progress, if so it polls for its completion in a loop with 100ms delay.
2. Handling device reset timeout
fnic_device_reset code has been modified to handle Device reset timeout:
- Issue terminate on device reset timeout.
- Introduced flags field (one of the scratch fields in scsi_cmnd).
With this, device reset request would have DEVICE_RESET flag set for other
routines to determine the type of the request.
Also modified fnic_terminate_rport_io, fnic_rport_exch_rset, completion
routines to handle SCSI commands with DEVICE_RESET flag.
3. LUN/Device Reset hangs when issued through IOCTL using utilities like
sg_reset.
Each SCSI command is associated with a valid tag, fnic uses this tag to
retrieve associated scsi command on completion. the LUN/Device Reset issued
through IOCTL resulting into a SCSI command that is not associated with a
valid tag. So fnic fails to retrieve associated scsi command on completion,
which causes hang. This fix allocates tag, associates it with the
scsi command and frees the tag, when the operation completed.
4. Preventing IOs during firmware reset.
Current fnic implementation allows IO submissions during firmware reset.
This fix synchronizes IO submissions and firmware reset operations.
It ensures that IOs issued to fnic prior to reset will be issued to the
firmware before firmware reset.
Signed-off-by: Narsimhulu Musini <nmusini@cisco.com>
Signed-off-by: Hiral Patel <hiralpat@cisco.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-02-13 09:00:58 +08:00
|
|
|
#define CMD_FLAGS(Cmnd) ((Cmnd)->SCp.Status)
|
2009-04-18 09:33:26 +08:00
|
|
|
|
|
|
|
#define FCPIO_INVALID_CODE 0x100 /* hdr_status value unused by firmware */
|
|
|
|
|
|
|
|
#define FNIC_LUN_RESET_TIMEOUT 10000 /* mSec */
|
|
|
|
#define FNIC_HOST_RESET_TIMEOUT 10000 /* mSec */
|
|
|
|
#define FNIC_RMDEVICE_TIMEOUT 1000 /* mSec */
|
|
|
|
#define FNIC_HOST_RESET_SETTLE_TIME 30 /* Sec */
|
[SCSI] fnic: fixing issues in device and firmware reset code
1. Handling overlapped firmware resets
This fix serialize multiple firmware resets to avoid situation where fnic
device fails to come up for link up event, when firmware resets are issued
back to back. If there are overlapped firmware resets are issued,
the firmware reset operation checks whether there is any firmware reset in
progress, if so it polls for its completion in a loop with 100ms delay.
2. Handling device reset timeout
fnic_device_reset code has been modified to handle Device reset timeout:
- Issue terminate on device reset timeout.
- Introduced flags field (one of the scratch fields in scsi_cmnd).
With this, device reset request would have DEVICE_RESET flag set for other
routines to determine the type of the request.
Also modified fnic_terminate_rport_io, fnic_rport_exch_rset, completion
routines to handle SCSI commands with DEVICE_RESET flag.
3. LUN/Device Reset hangs when issued through IOCTL using utilities like
sg_reset.
Each SCSI command is associated with a valid tag, fnic uses this tag to
retrieve associated scsi command on completion. the LUN/Device Reset issued
through IOCTL resulting into a SCSI command that is not associated with a
valid tag. So fnic fails to retrieve associated scsi command on completion,
which causes hang. This fix allocates tag, associates it with the
scsi command and frees the tag, when the operation completed.
4. Preventing IOs during firmware reset.
Current fnic implementation allows IO submissions during firmware reset.
This fix synchronizes IO submissions and firmware reset operations.
It ensures that IOs issued to fnic prior to reset will be issued to the
firmware before firmware reset.
Signed-off-by: Narsimhulu Musini <nmusini@cisco.com>
Signed-off-by: Hiral Patel <hiralpat@cisco.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-02-13 09:00:58 +08:00
|
|
|
#define FNIC_ABT_TERM_DELAY_TIMEOUT 500 /* mSec */
|
2009-04-18 09:33:26 +08:00
|
|
|
|
|
|
|
#define FNIC_MAX_FCP_TARGET 256
|
|
|
|
|
[SCSI] fnic: fixing issues in device and firmware reset code
1. Handling overlapped firmware resets
This fix serialize multiple firmware resets to avoid situation where fnic
device fails to come up for link up event, when firmware resets are issued
back to back. If there are overlapped firmware resets are issued,
the firmware reset operation checks whether there is any firmware reset in
progress, if so it polls for its completion in a loop with 100ms delay.
2. Handling device reset timeout
fnic_device_reset code has been modified to handle Device reset timeout:
- Issue terminate on device reset timeout.
- Introduced flags field (one of the scratch fields in scsi_cmnd).
With this, device reset request would have DEVICE_RESET flag set for other
routines to determine the type of the request.
Also modified fnic_terminate_rport_io, fnic_rport_exch_rset, completion
routines to handle SCSI commands with DEVICE_RESET flag.
3. LUN/Device Reset hangs when issued through IOCTL using utilities like
sg_reset.
Each SCSI command is associated with a valid tag, fnic uses this tag to
retrieve associated scsi command on completion. the LUN/Device Reset issued
through IOCTL resulting into a SCSI command that is not associated with a
valid tag. So fnic fails to retrieve associated scsi command on completion,
which causes hang. This fix allocates tag, associates it with the
scsi command and frees the tag, when the operation completed.
4. Preventing IOs during firmware reset.
Current fnic implementation allows IO submissions during firmware reset.
This fix synchronizes IO submissions and firmware reset operations.
It ensures that IOs issued to fnic prior to reset will be issued to the
firmware before firmware reset.
Signed-off-by: Narsimhulu Musini <nmusini@cisco.com>
Signed-off-by: Hiral Patel <hiralpat@cisco.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-02-13 09:00:58 +08:00
|
|
|
/**
|
|
|
|
* state_flags to identify host state along along with fnic's state
|
|
|
|
**/
|
|
|
|
#define __FNIC_FLAGS_FWRESET BIT(0) /* fwreset in progress */
|
|
|
|
#define __FNIC_FLAGS_BLOCK_IO BIT(1) /* IOs are blocked */
|
|
|
|
|
|
|
|
#define FNIC_FLAGS_NONE (0)
|
|
|
|
#define FNIC_FLAGS_FWRESET (__FNIC_FLAGS_FWRESET | \
|
|
|
|
__FNIC_FLAGS_BLOCK_IO)
|
|
|
|
|
|
|
|
#define FNIC_FLAGS_IO_BLOCKED (__FNIC_FLAGS_BLOCK_IO)
|
|
|
|
|
|
|
|
#define fnic_set_state_flags(fnicp, st_flags) \
|
|
|
|
__fnic_set_state_flags(fnicp, st_flags, 0)
|
|
|
|
|
|
|
|
#define fnic_clear_state_flags(fnicp, st_flags) \
|
|
|
|
__fnic_set_state_flags(fnicp, st_flags, 1)
|
|
|
|
|
2009-04-18 09:33:26 +08:00
|
|
|
extern unsigned int fnic_log_level;
|
|
|
|
|
|
|
|
#define FNIC_MAIN_LOGGING 0x01
|
|
|
|
#define FNIC_FCS_LOGGING 0x02
|
|
|
|
#define FNIC_SCSI_LOGGING 0x04
|
|
|
|
#define FNIC_ISR_LOGGING 0x08
|
|
|
|
|
|
|
|
#define FNIC_CHECK_LOGGING(LEVEL, CMD) \
|
|
|
|
do { \
|
|
|
|
if (unlikely(fnic_log_level & LEVEL)) \
|
|
|
|
do { \
|
|
|
|
CMD; \
|
|
|
|
} while (0); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define FNIC_MAIN_DBG(kern_level, host, fmt, args...) \
|
|
|
|
FNIC_CHECK_LOGGING(FNIC_MAIN_LOGGING, \
|
|
|
|
shost_printk(kern_level, host, fmt, ##args);)
|
|
|
|
|
|
|
|
#define FNIC_FCS_DBG(kern_level, host, fmt, args...) \
|
|
|
|
FNIC_CHECK_LOGGING(FNIC_FCS_LOGGING, \
|
|
|
|
shost_printk(kern_level, host, fmt, ##args);)
|
|
|
|
|
|
|
|
#define FNIC_SCSI_DBG(kern_level, host, fmt, args...) \
|
|
|
|
FNIC_CHECK_LOGGING(FNIC_SCSI_LOGGING, \
|
|
|
|
shost_printk(kern_level, host, fmt, ##args);)
|
|
|
|
|
|
|
|
#define FNIC_ISR_DBG(kern_level, host, fmt, args...) \
|
|
|
|
FNIC_CHECK_LOGGING(FNIC_ISR_LOGGING, \
|
|
|
|
shost_printk(kern_level, host, fmt, ##args);)
|
|
|
|
|
2013-09-10 04:31:45 +08:00
|
|
|
#define FNIC_MAIN_NOTE(kern_level, host, fmt, args...) \
|
|
|
|
shost_printk(kern_level, host, fmt, ##args)
|
|
|
|
|
2009-04-18 09:33:26 +08:00
|
|
|
extern const char *fnic_state_str[];
|
|
|
|
|
|
|
|
enum fnic_intx_intr_index {
|
|
|
|
FNIC_INTX_WQ_RQ_COPYWQ,
|
|
|
|
FNIC_INTX_ERR,
|
|
|
|
FNIC_INTX_NOTIFY,
|
|
|
|
FNIC_INTX_INTR_MAX,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum fnic_msix_intr_index {
|
|
|
|
FNIC_MSIX_RQ,
|
|
|
|
FNIC_MSIX_WQ,
|
|
|
|
FNIC_MSIX_WQ_COPY,
|
|
|
|
FNIC_MSIX_ERR_NOTIFY,
|
|
|
|
FNIC_MSIX_INTR_MAX,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct fnic_msix_entry {
|
|
|
|
int requested;
|
|
|
|
char devname[IFNAMSIZ];
|
|
|
|
irqreturn_t (*isr)(int, void *);
|
|
|
|
void *devid;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum fnic_state {
|
|
|
|
FNIC_IN_FC_MODE = 0,
|
|
|
|
FNIC_IN_FC_TRANS_ETH_MODE,
|
|
|
|
FNIC_IN_ETH_MODE,
|
|
|
|
FNIC_IN_ETH_TRANS_FC_MODE,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define FNIC_WQ_COPY_MAX 1
|
|
|
|
#define FNIC_WQ_MAX 1
|
|
|
|
#define FNIC_RQ_MAX 1
|
|
|
|
#define FNIC_CQ_MAX (FNIC_WQ_COPY_MAX + FNIC_WQ_MAX + FNIC_RQ_MAX)
|
|
|
|
|
|
|
|
struct mempool;
|
|
|
|
|
2013-02-26 08:18:36 +08:00
|
|
|
enum fnic_evt {
|
|
|
|
FNIC_EVT_START_VLAN_DISC = 1,
|
|
|
|
FNIC_EVT_START_FCF_DISC = 2,
|
|
|
|
FNIC_EVT_MAX,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct fnic_event {
|
|
|
|
struct list_head list;
|
|
|
|
struct fnic *fnic;
|
|
|
|
enum fnic_evt event;
|
|
|
|
};
|
|
|
|
|
2009-04-18 09:33:26 +08:00
|
|
|
/* Per-instance private data structure */
|
|
|
|
struct fnic {
|
|
|
|
struct fc_lport *lport;
|
2009-11-04 03:49:22 +08:00
|
|
|
struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */
|
2009-04-18 09:33:26 +08:00
|
|
|
struct vnic_dev_bar bar0;
|
|
|
|
|
|
|
|
struct msix_entry msix_entry[FNIC_MSIX_INTR_MAX];
|
|
|
|
struct fnic_msix_entry msix[FNIC_MSIX_INTR_MAX];
|
|
|
|
|
|
|
|
struct vnic_stats *stats;
|
|
|
|
unsigned long stats_time; /* time of stats update */
|
2013-09-10 04:31:45 +08:00
|
|
|
unsigned long stats_reset_time; /* time of stats reset */
|
2009-04-18 09:33:26 +08:00
|
|
|
struct vnic_nic_cfg *nic_cfg;
|
|
|
|
char name[IFNAMSIZ];
|
|
|
|
struct timer_list notify_timer; /* used for MSI interrupts */
|
|
|
|
|
2013-09-10 04:31:51 +08:00
|
|
|
unsigned int fnic_max_tag_id;
|
2009-04-18 09:33:26 +08:00
|
|
|
unsigned int err_intr_offset;
|
|
|
|
unsigned int link_intr_offset;
|
|
|
|
|
|
|
|
unsigned int wq_count;
|
|
|
|
unsigned int cq_count;
|
|
|
|
|
|
|
|
u32 vlan_hw_insert:1; /* let hw insert the tag */
|
|
|
|
u32 in_remove:1; /* fnic device in removal */
|
|
|
|
u32 stop_rx_link_events:1; /* stop proc. rx frames, link events */
|
|
|
|
|
|
|
|
struct completion *remove_wait; /* device remove thread blocks */
|
|
|
|
|
[SCSI] fnic: fixing issues in device and firmware reset code
1. Handling overlapped firmware resets
This fix serialize multiple firmware resets to avoid situation where fnic
device fails to come up for link up event, when firmware resets are issued
back to back. If there are overlapped firmware resets are issued,
the firmware reset operation checks whether there is any firmware reset in
progress, if so it polls for its completion in a loop with 100ms delay.
2. Handling device reset timeout
fnic_device_reset code has been modified to handle Device reset timeout:
- Issue terminate on device reset timeout.
- Introduced flags field (one of the scratch fields in scsi_cmnd).
With this, device reset request would have DEVICE_RESET flag set for other
routines to determine the type of the request.
Also modified fnic_terminate_rport_io, fnic_rport_exch_rset, completion
routines to handle SCSI commands with DEVICE_RESET flag.
3. LUN/Device Reset hangs when issued through IOCTL using utilities like
sg_reset.
Each SCSI command is associated with a valid tag, fnic uses this tag to
retrieve associated scsi command on completion. the LUN/Device Reset issued
through IOCTL resulting into a SCSI command that is not associated with a
valid tag. So fnic fails to retrieve associated scsi command on completion,
which causes hang. This fix allocates tag, associates it with the
scsi command and frees the tag, when the operation completed.
4. Preventing IOs during firmware reset.
Current fnic implementation allows IO submissions during firmware reset.
This fix synchronizes IO submissions and firmware reset operations.
It ensures that IOs issued to fnic prior to reset will be issued to the
firmware before firmware reset.
Signed-off-by: Narsimhulu Musini <nmusini@cisco.com>
Signed-off-by: Hiral Patel <hiralpat@cisco.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-02-13 09:00:58 +08:00
|
|
|
atomic_t in_flight; /* io counter */
|
|
|
|
u32 _reserved; /* fill hole */
|
|
|
|
unsigned long state_flags; /* protected by host lock */
|
2009-04-18 09:33:26 +08:00
|
|
|
enum fnic_state state;
|
|
|
|
spinlock_t fnic_lock;
|
|
|
|
|
|
|
|
u16 vlan_id; /* VLAN tag including priority */
|
|
|
|
u8 data_src_addr[ETH_ALEN];
|
|
|
|
u64 fcp_input_bytes; /* internal statistic */
|
|
|
|
u64 fcp_output_bytes; /* internal statistic */
|
|
|
|
u32 link_down_cnt;
|
|
|
|
int link_status;
|
|
|
|
|
|
|
|
struct list_head list;
|
|
|
|
struct pci_dev *pdev;
|
|
|
|
struct vnic_fc_config config;
|
|
|
|
struct vnic_dev *vdev;
|
|
|
|
unsigned int raw_wq_count;
|
|
|
|
unsigned int wq_copy_count;
|
|
|
|
unsigned int rq_count;
|
|
|
|
int fw_ack_index[FNIC_WQ_COPY_MAX];
|
|
|
|
unsigned short fw_ack_recd[FNIC_WQ_COPY_MAX];
|
|
|
|
unsigned short wq_copy_desc_low[FNIC_WQ_COPY_MAX];
|
|
|
|
unsigned int intr_count;
|
|
|
|
u32 __iomem *legacy_pba;
|
|
|
|
struct fnic_host_tag *tags;
|
|
|
|
mempool_t *io_req_pool;
|
|
|
|
mempool_t *io_sgl_pool[FNIC_SGL_NUM_CACHES];
|
|
|
|
spinlock_t io_req_lock[FNIC_IO_LOCKS]; /* locks for scsi cmnds */
|
|
|
|
|
|
|
|
struct work_struct link_work;
|
|
|
|
struct work_struct frame_work;
|
|
|
|
struct sk_buff_head frame_queue;
|
2009-11-04 03:49:22 +08:00
|
|
|
struct sk_buff_head tx_queue;
|
2009-04-18 09:33:26 +08:00
|
|
|
|
2013-02-26 08:18:36 +08:00
|
|
|
/*** FIP related data members -- start ***/
|
|
|
|
void (*set_vlan)(struct fnic *, u16 vlan);
|
|
|
|
struct work_struct fip_frame_work;
|
|
|
|
struct sk_buff_head fip_frame_queue;
|
|
|
|
struct timer_list fip_timer;
|
|
|
|
struct list_head vlans;
|
|
|
|
spinlock_t vlans_lock;
|
|
|
|
|
|
|
|
struct work_struct event_work;
|
|
|
|
struct list_head evlist;
|
|
|
|
/*** FIP related data members -- end ***/
|
|
|
|
|
2009-04-18 09:33:26 +08:00
|
|
|
/* copy work queue cache line section */
|
|
|
|
____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX];
|
|
|
|
/* completion queue cache line section */
|
|
|
|
____cacheline_aligned struct vnic_cq cq[FNIC_CQ_MAX];
|
|
|
|
|
|
|
|
spinlock_t wq_copy_lock[FNIC_WQ_COPY_MAX];
|
|
|
|
|
|
|
|
/* work queue cache line section */
|
|
|
|
____cacheline_aligned struct vnic_wq wq[FNIC_WQ_MAX];
|
|
|
|
spinlock_t wq_lock[FNIC_WQ_MAX];
|
|
|
|
|
|
|
|
/* receive queue cache line section */
|
|
|
|
____cacheline_aligned struct vnic_rq rq[FNIC_RQ_MAX];
|
|
|
|
|
|
|
|
/* interrupt resource cache line section */
|
|
|
|
____cacheline_aligned struct vnic_intr intr[FNIC_MSIX_INTR_MAX];
|
|
|
|
};
|
|
|
|
|
2009-11-04 03:49:22 +08:00
|
|
|
static inline struct fnic *fnic_from_ctlr(struct fcoe_ctlr *fip)
|
|
|
|
{
|
|
|
|
return container_of(fip, struct fnic, ctlr);
|
|
|
|
}
|
|
|
|
|
2009-04-18 09:33:26 +08:00
|
|
|
extern struct workqueue_struct *fnic_event_queue;
|
2013-02-26 08:18:36 +08:00
|
|
|
extern struct workqueue_struct *fnic_fip_queue;
|
2009-04-18 09:33:26 +08:00
|
|
|
extern struct device_attribute *fnic_attrs[];
|
|
|
|
|
|
|
|
void fnic_clear_intr_mode(struct fnic *fnic);
|
|
|
|
int fnic_set_intr_mode(struct fnic *fnic);
|
|
|
|
void fnic_free_intr(struct fnic *fnic);
|
|
|
|
int fnic_request_intr(struct fnic *fnic);
|
|
|
|
|
|
|
|
int fnic_send(struct fc_lport *, struct fc_frame *);
|
|
|
|
void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf);
|
|
|
|
void fnic_handle_frame(struct work_struct *work);
|
|
|
|
void fnic_handle_link(struct work_struct *work);
|
2013-02-26 08:18:36 +08:00
|
|
|
void fnic_handle_event(struct work_struct *work);
|
2009-04-18 09:33:26 +08:00
|
|
|
int fnic_rq_cmpl_handler(struct fnic *fnic, int);
|
|
|
|
int fnic_alloc_rq_frame(struct vnic_rq *rq);
|
|
|
|
void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf);
|
2009-11-04 03:49:22 +08:00
|
|
|
void fnic_flush_tx(struct fnic *);
|
|
|
|
void fnic_eth_send(struct fcoe_ctlr *, struct sk_buff *skb);
|
|
|
|
void fnic_set_port_id(struct fc_lport *, u32, struct fc_frame *);
|
|
|
|
void fnic_update_mac(struct fc_lport *, u8 *new);
|
|
|
|
void fnic_update_mac_locked(struct fnic *, u8 *new);
|
2009-04-18 09:33:26 +08:00
|
|
|
|
2010-11-16 15:10:29 +08:00
|
|
|
int fnic_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
|
2009-04-18 09:33:26 +08:00
|
|
|
int fnic_abort_cmd(struct scsi_cmnd *);
|
|
|
|
int fnic_device_reset(struct scsi_cmnd *);
|
|
|
|
int fnic_host_reset(struct scsi_cmnd *);
|
|
|
|
int fnic_reset(struct Scsi_Host *);
|
|
|
|
void fnic_scsi_cleanup(struct fc_lport *);
|
|
|
|
void fnic_scsi_abort_io(struct fc_lport *);
|
|
|
|
void fnic_empty_scsi_cleanup(struct fc_lport *);
|
|
|
|
void fnic_exch_mgr_reset(struct fc_lport *, u32, u32);
|
|
|
|
int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int);
|
|
|
|
int fnic_wq_cmpl_handler(struct fnic *fnic, int);
|
2009-11-04 03:49:22 +08:00
|
|
|
int fnic_flogi_reg_handler(struct fnic *fnic, u32);
|
2009-04-18 09:33:26 +08:00
|
|
|
void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
|
|
|
|
struct fcpio_host_req *desc);
|
|
|
|
int fnic_fw_reset_handler(struct fnic *fnic);
|
|
|
|
void fnic_terminate_rport_io(struct fc_rport *);
|
|
|
|
const char *fnic_state_to_str(unsigned int state);
|
|
|
|
|
|
|
|
void fnic_log_q_error(struct fnic *fnic);
|
|
|
|
void fnic_handle_link_event(struct fnic *fnic);
|
|
|
|
|
2013-02-13 09:01:00 +08:00
|
|
|
int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *);
|
|
|
|
|
2013-02-26 08:18:36 +08:00
|
|
|
void fnic_handle_fip_frame(struct work_struct *work);
|
|
|
|
void fnic_handle_fip_event(struct fnic *fnic);
|
|
|
|
void fnic_fcoe_reset_vlans(struct fnic *fnic);
|
|
|
|
void fnic_fcoe_evlist_free(struct fnic *fnic);
|
|
|
|
extern void fnic_handle_fip_timer(struct fnic *fnic);
|
|
|
|
|
[SCSI] fnic: fixing issues in device and firmware reset code
1. Handling overlapped firmware resets
This fix serialize multiple firmware resets to avoid situation where fnic
device fails to come up for link up event, when firmware resets are issued
back to back. If there are overlapped firmware resets are issued,
the firmware reset operation checks whether there is any firmware reset in
progress, if so it polls for its completion in a loop with 100ms delay.
2. Handling device reset timeout
fnic_device_reset code has been modified to handle Device reset timeout:
- Issue terminate on device reset timeout.
- Introduced flags field (one of the scratch fields in scsi_cmnd).
With this, device reset request would have DEVICE_RESET flag set for other
routines to determine the type of the request.
Also modified fnic_terminate_rport_io, fnic_rport_exch_rset, completion
routines to handle SCSI commands with DEVICE_RESET flag.
3. LUN/Device Reset hangs when issued through IOCTL using utilities like
sg_reset.
Each SCSI command is associated with a valid tag, fnic uses this tag to
retrieve associated scsi command on completion. the LUN/Device Reset issued
through IOCTL resulting into a SCSI command that is not associated with a
valid tag. So fnic fails to retrieve associated scsi command on completion,
which causes hang. This fix allocates tag, associates it with the
scsi command and frees the tag, when the operation completed.
4. Preventing IOs during firmware reset.
Current fnic implementation allows IO submissions during firmware reset.
This fix synchronizes IO submissions and firmware reset operations.
It ensures that IOs issued to fnic prior to reset will be issued to the
firmware before firmware reset.
Signed-off-by: Narsimhulu Musini <nmusini@cisco.com>
Signed-off-by: Hiral Patel <hiralpat@cisco.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
2013-02-13 09:00:58 +08:00
|
|
|
static inline int
|
|
|
|
fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
|
|
|
|
{
|
|
|
|
return ((fnic->state_flags & st_flags) == st_flags);
|
|
|
|
}
|
|
|
|
void __fnic_set_state_flags(struct fnic *, unsigned long, unsigned long);
|
2013-09-10 04:31:45 +08:00
|
|
|
void fnic_dump_fchost_stats(struct Scsi_Host *, struct fc_host_statistics *);
|
2009-04-18 09:33:26 +08:00
|
|
|
#endif /* _FNIC_H_ */
|