⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qla_rscn.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * QLogic Fibre Channel HBA Driver * Copyright (c)  2003-2005 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */#include "qla_def.h"#include <scsi/scsi_transport_fc.h>/** * IO descriptor handle definitions. * * Signature form: * *	|31------28|27-------------------12|11-------0| *	|   Type   |   Rolling Signature   |   Index  | *	|----------|-----------------------|----------| * **/#define HDL_TYPE_SCSI		0#define HDL_TYPE_ASYNC_IOCB	0x0A#define HDL_INDEX_BITS	12#define HDL_ITER_BITS	16#define HDL_TYPE_BITS	4#define HDL_INDEX_MASK	((1UL << HDL_INDEX_BITS) - 1)#define HDL_ITER_MASK	((1UL << HDL_ITER_BITS) - 1)#define HDL_TYPE_MASK	((1UL << HDL_TYPE_BITS) - 1)#define HDL_INDEX_SHIFT	0#define HDL_ITER_SHIFT	(HDL_INDEX_SHIFT + HDL_INDEX_BITS)#define HDL_TYPE_SHIFT	(HDL_ITER_SHIFT + HDL_ITER_BITS)/* Local Prototypes. */static inline uint32_t qla2x00_to_handle(uint16_t, uint16_t, uint16_t);static inline uint16_t qla2x00_handle_to_idx(uint32_t);static inline uint32_t qla2x00_iodesc_to_handle(struct io_descriptor *);static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *,    uint32_t);static inline struct io_descriptor *qla2x00_alloc_iodesc(scsi_qla_host_t *);static inline void qla2x00_free_iodesc(struct io_descriptor *);static inline void qla2x00_init_io_descriptors(scsi_qla_host_t *);static void qla2x00_iodesc_timeout(unsigned long);static inline void qla2x00_add_iodesc_timer(struct io_descriptor *);static inline void qla2x00_remove_iodesc_timer(struct io_descriptor *);static inline void qla2x00_update_login_fcport(scsi_qla_host_t *,    struct mbx_entry *, fc_port_t *);static int qla2x00_send_abort_iocb(scsi_qla_host_t *, struct io_descriptor *,    uint32_t, int);static int qla2x00_send_abort_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,    struct mbx_entry *);static int qla2x00_send_adisc_iocb(scsi_qla_host_t *, struct io_descriptor *,    int);static int qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,    struct mbx_entry *);static int qla2x00_send_logout_iocb(scsi_qla_host_t *, struct io_descriptor *,    int);static int qla2x00_send_logout_iocb_cb(scsi_qla_host_t *,    struct io_descriptor *, struct mbx_entry *);static int qla2x00_send_login_iocb(scsi_qla_host_t *, struct io_descriptor *,    port_id_t *, int);static int qla2x00_send_login_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,    struct mbx_entry *);/** * Mailbox IOCB callback array. **/static int (*iocb_function_cb_list[LAST_IOCB_CB])	(scsi_qla_host_t *, struct io_descriptor *, struct mbx_entry *) = {	qla2x00_send_abort_iocb_cb,	qla2x00_send_adisc_iocb_cb,	qla2x00_send_logout_iocb_cb,	qla2x00_send_login_iocb_cb,};/** * Generic IO descriptor handle routines. **//** * qla2x00_to_handle() - Create a descriptor handle. * @type: descriptor type * @iter: descriptor rolling signature * @idx: index to the descriptor array * * Returns a composite handle based in the @type, @iter, and @idx. */static inline uint32_tqla2x00_to_handle(uint16_t type, uint16_t iter, uint16_t idx){	return ((uint32_t)(((uint32_t)type << HDL_TYPE_SHIFT) |	    ((uint32_t)iter << HDL_ITER_SHIFT) |	    ((uint32_t)idx << HDL_INDEX_SHIFT)));}/** * qla2x00_handle_to_idx() - Retrive the index for a given handle. * @handle: descriptor handle * * Returns the index specified by the @handle. */static inline uint16_tqla2x00_handle_to_idx(uint32_t handle){	return ((uint16_t)(((handle) >> HDL_INDEX_SHIFT) & HDL_INDEX_MASK));}/** * qla2x00_iodesc_to_handle() - Convert an IO descriptor to a unique handle. * @iodesc: io descriptor * * Returns a unique handle for @iodesc. */static inline uint32_tqla2x00_iodesc_to_handle(struct io_descriptor *iodesc){	uint32_t handle;	handle = qla2x00_to_handle(HDL_TYPE_ASYNC_IOCB,	    ++iodesc->ha->iodesc_signature, iodesc->idx);	iodesc->signature = handle;	return (handle);}/** * qla2x00_handle_to_iodesc() - Retrieve an IO descriptor given a unique handle. * @ha: HA context * @handle: handle to io descriptor * * Returns a pointer to the io descriptor, or NULL, if the io descriptor does * not exist or the io descriptors signature does not @handle. */static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *ha, uint32_t handle){	uint16_t idx;	struct io_descriptor *iodesc;	idx = qla2x00_handle_to_idx(handle);	iodesc = &ha->io_descriptors[idx];	if (iodesc)		if (iodesc->signature != handle)			iodesc = NULL;	return (iodesc);}/** * IO descriptor allocation routines. **//** * qla2x00_alloc_iodesc() - Allocate an IO descriptor from the pool. * @ha: HA context * * Returns a pointer to the allocated io descriptor, or NULL, if none available. */static inline struct io_descriptor *qla2x00_alloc_iodesc(scsi_qla_host_t *ha){	uint16_t iter;	struct io_descriptor *iodesc;	iodesc = NULL;	for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) {		if (ha->io_descriptors[iter].used)			continue;		iodesc = &ha->io_descriptors[iter];		iodesc->used = 1;		iodesc->idx = iter;		init_timer(&iodesc->timer);		iodesc->ha = ha;		iodesc->signature = qla2x00_iodesc_to_handle(iodesc);		break;	}	return (iodesc);}/** * qla2x00_free_iodesc() - Free an IO descriptor. * @iodesc: io descriptor * * NOTE: The io descriptors timer *must* be stopped before it can be free'd. */static inline voidqla2x00_free_iodesc(struct io_descriptor *iodesc){	iodesc->used = 0;	iodesc->signature = 0;}/** * qla2x00_remove_iodesc_timer() - Remove an active timer from an IO descriptor. * @iodesc: io descriptor */static inline voidqla2x00_remove_iodesc_timer(struct io_descriptor *iodesc){	if (iodesc->timer.function != NULL) {		del_timer_sync(&iodesc->timer);		iodesc->timer.data = (unsigned long) NULL;		iodesc->timer.function = NULL;	}}/** * qla2x00_init_io_descriptors() - Initialize the pool of IO descriptors. * @ha: HA context */static inline voidqla2x00_init_io_descriptors(scsi_qla_host_t *ha){	uint16_t iter;	for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) {		if (!ha->io_descriptors[iter].used)			continue;		qla2x00_remove_iodesc_timer(&ha->io_descriptors[iter]);		qla2x00_free_iodesc(&ha->io_descriptors[iter]);	}}/** * IO descriptor timer routines. **//** * qla2x00_iodesc_timeout() - Timeout IO descriptor handler. * @data: io descriptor */static voidqla2x00_iodesc_timeout(unsigned long data){	struct io_descriptor *iodesc;	iodesc = (struct io_descriptor *) data;	DEBUG14(printk("scsi(%ld): IO descriptor timeout, index=%x "	    "signature=%08x, scheduling ISP abort.\n", iodesc->ha->host_no,	    iodesc->idx, iodesc->signature));	qla2x00_free_iodesc(iodesc);	qla_printk(KERN_WARNING, iodesc->ha,	    "IO descriptor timeout. Scheduling ISP abort.\n");	set_bit(ISP_ABORT_NEEDED, &iodesc->ha->dpc_flags);}/** * qla2x00_add_iodesc_timer() - Add and start a timer for an IO descriptor. * @iodesc: io descriptor * * NOTE: * The firmware shall timeout an outstanding mailbox IOCB in 2 * R_A_TOV (in * tenths of a second) after it hits the wire.  But, if there are any request * resource contraints (i.e. during heavy I/O), exchanges can be held off for * at most R_A_TOV.  Therefore, the driver will wait 4 * R_A_TOV before * scheduling a recovery (big hammer). */static inline voidqla2x00_add_iodesc_timer(struct io_descriptor *iodesc){	unsigned long timeout;	timeout = (iodesc->ha->r_a_tov * 4) / 10;	init_timer(&iodesc->timer);	iodesc->timer.data = (unsigned long) iodesc;	iodesc->timer.expires = jiffies + (timeout * HZ);	iodesc->timer.function =	    (void (*) (unsigned long)) qla2x00_iodesc_timeout;	add_timer(&iodesc->timer);}/** * IO descriptor support routines. **//** * qla2x00_update_login_fcport() - Update fcport data after login processing. * @ha: HA context * @mbxstat: Mailbox command status IOCB * @fcport: port to update */static inline voidqla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat,    fc_port_t *fcport){	if (le16_to_cpu(mbxstat->mb1) & BIT_0) {		fcport->port_type = FCT_INITIATOR;	} else {		fcport->port_type = FCT_TARGET;		if (le16_to_cpu(mbxstat->mb1) & BIT_1) {			fcport->flags |= FCF_TAPE_PRESENT;		}	}	fcport->login_retry = 0;	fcport->port_login_retry_count = ha->port_down_retry_count *	    PORT_RETRY_TIME;	atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *	    PORT_RETRY_TIME);	fcport->flags |= FCF_FABRIC_DEVICE;	fcport->flags &= ~FCF_FAILOVER_NEEDED;	fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;	atomic_set(&fcport->state, FCS_ONLINE);	schedule_work(&fcport->rport_add_work);}/** * Mailbox IOCB commands. **//** * qla2x00_get_mbx_iocb_entry() - Retrieve an IOCB from the request queue. * @ha: HA context * @handle: handle to io descriptor * * Returns a pointer to the reqest entry, or NULL, if none were available. */static inline struct mbx_entry *qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle){	uint16_t cnt;	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;	struct mbx_entry *mbxentry;	mbxentry = NULL;	if (ha->req_q_cnt < 3) {		cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg));		if  (ha->req_ring_index < cnt)			ha->req_q_cnt = cnt - ha->req_ring_index;		else			ha->req_q_cnt = ha->request_q_length -			    (ha->req_ring_index - cnt);	}	if (ha->req_q_cnt >= 3) {		mbxentry = (struct mbx_entry *)ha->request_ring_ptr;		memset(mbxentry, 0, sizeof(struct mbx_entry));		mbxentry->entry_type = MBX_IOCB_TYPE;		mbxentry->entry_count = 1;		mbxentry->sys_define1 = SOURCE_ASYNC_IOCB;		mbxentry->handle = handle;	}	return (mbxentry);}/** * qla2x00_send_abort_iocb() - Issue an abort IOCB to the firmware. * @ha: HA context * @iodesc: io descriptor * @handle_to_abort: firmware handle to abort * @ha_locked: is function called with the hardware lock * * Returns QLA_SUCCESS if the IOCB was issued. */static intqla2x00_send_abort_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,    uint32_t handle_to_abort, int ha_locked){	unsigned long flags = 0;	struct mbx_entry *mbxentry;	/* Send marker if required. */	if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)		return (QLA_FUNCTION_FAILED);	if (!ha_locked)		spin_lock_irqsave(&ha->hardware_lock, flags);	/* Build abort mailbox IOCB. */	mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);	if (mbxentry == NULL) {		if (!ha_locked)			spin_unlock_irqrestore(&ha->hardware_lock, flags);		return (QLA_FUNCTION_FAILED);	}	mbxentry->mb0 = __constant_cpu_to_le16(MBC_ABORT_COMMAND);	mbxentry->mb1 = mbxentry->loop_id.extended =	    cpu_to_le16(iodesc->remote_fcport->loop_id);	mbxentry->mb2 = LSW(handle_to_abort);	mbxentry->mb3 = MSW(handle_to_abort);	wmb();	qla2x00_add_iodesc_timer(iodesc);	/* Issue command to ISP. */	qla2x00_isp_cmd(ha);	if (!ha_locked)		spin_unlock_irqrestore(&ha->hardware_lock, flags);	DEBUG14(printk("scsi(%ld): Sending Abort IOCB (%08x) to [%x], aborting "	    "%08x.\n", ha->host_no, iodesc->signature,	    iodesc->remote_fcport->loop_id, handle_to_abort));	return (QLA_SUCCESS);}/** * qla2x00_send_abort_iocb_cb() - Abort IOCB callback. * @ha: HA context * @iodesc: io descriptor * @mbxstat: mailbox status IOCB * * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc * will be used for a retry. */static intqla2x00_send_abort_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,    struct mbx_entry *mbxstat){	DEBUG14(printk("scsi(%ld): Abort IOCB -- sent to [%x/%02x%02x%02x], "	    "status=%x mb0=%x.\n", ha->host_no, iodesc->remote_fcport->loop_id,	    iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa,	    le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0)));	return (QLA_SUCCESS);}/** * qla2x00_send_adisc_iocb() - Issue a Get Port Database IOCB to the firmware. * @ha: HA context * @iodesc: io descriptor * @ha_locked: is function called with the hardware lock * * Returns QLA_SUCCESS if the IOCB was issued. */static intqla2x00_send_adisc_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,    int ha_locked){	unsigned long flags = 0;	struct mbx_entry *mbxentry;	/* Send marker if required. */	if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)		return (QLA_FUNCTION_FAILED);	if (!ha_locked)		spin_lock_irqsave(&ha->hardware_lock, flags);	/* Build Get Port Database IOCB. */	mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);	if (mbxentry == NULL) {		if (!ha_locked)			spin_unlock_irqrestore(&ha->hardware_lock, flags);		return (QLA_FUNCTION_FAILED);	}	mbxentry->mb0 = __constant_cpu_to_le16(MBC_GET_PORT_DATABASE);	mbxentry->mb1 = mbxentry->loop_id.extended =	    cpu_to_le16(iodesc->remote_fcport->loop_id);	mbxentry->mb2 = cpu_to_le16(MSW(LSD(ha->iodesc_pd_dma)));	mbxentry->mb3 = cpu_to_le16(LSW(LSD(ha->iodesc_pd_dma)));	mbxentry->mb6 = cpu_to_le16(MSW(MSD(ha->iodesc_pd_dma)));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -