SCSI updates on 20120118
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iQEcBAABAgAGBQJPFnpKAAoJEDeqqVYsXL0MJZMH/06MxLWMkXrZJBgFMZs0UwcO 8vdTsQFR5HxGbj1WzARL9BeMbllCnTyG3xqdKp5iDANg0sUBJLqTuTLl+avvI3nc rKrlS6zImBs3BccxH+wtEqllUgoEto7AmxHPLqY/jf6O8/hxP/AH9uuZpcJCZqpw 1bbd/5x1aa7V6Y9omgx8+HdAohhDt/3JqTn7/PMOz6tHXnyeMx9yGl7tCzzWjmtT KeRblzn8jIApnC3yxV35MlKTFqT72csI0pHsJsKNt6OI93mLKEoJH5DxCVtQWqKo 8KzRw8mq6D0dksYfKKt78WC0ykmrft2GXMrSaUgnQgLd63qwcB7vwfynP0uqo24= =jjU7 -----END PGP SIGNATURE----- Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6 SCSI updates on 20120118 * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (49 commits) [SCSI] libfc: remove redundant timer init for fcp [SCSI] fcoe: Move fcoe_debug_logging from fcoe.h to fcoe.c [SCSI] libfc: Declare local functions static [SCSI] fcoe: fix regression on offload em matching function for initiator/target [SCSI] qla4xxx: Update driver version to 5.02.00-k12 [SCSI] qla4xxx: Cleanup modinfo display [SCSI] qla4xxx: Update license [SCSI] qla4xxx: Clear the RISC interrupt bit during FW init [SCSI] qla4xxx: Added error logging for firmware abort [SCSI] qla4xxx: Disable generating pause frames in case of FW hung [SCSI] qla4xxx: Temperature monitoring for ISP82XX core. [SCSI] megaraid: fix sparse warnings [SCSI] sg: convert to kstrtoul_from_user() [SCSI] don't change sdev starvation list order without request dispatched [SCSI] isci: fix, prevent port from getting stuck in the 'configuring' state [SCSI] isci: fix start OOB [SCSI] isci: fix io failures while wide port links are coming up [SCSI] isci: allow more time for wide port targets [SCSI] isci: enable wide port targets [SCSI] isci: Fix IO fails when pull cable from phy in x4 wideport in MPC mode. ...
This commit is contained in:
Коммит
d71f5be276
|
@ -1,3 +1,13 @@
|
|||
Release Date : Fri. Jan 6, 2012 17:00:00 PST 2010 -
|
||||
(emaild-id:megaraidlinux@lsi.com)
|
||||
Adam Radford
|
||||
Current Version : 00.00.06.14-rc1
|
||||
Old Version : 00.00.06.12-rc1
|
||||
1. Fix reglockFlags for degraded raid5/6 for MR 9360/9380.
|
||||
2. Mask off flags in ioctl path to prevent memory scribble with older
|
||||
MegaCLI versions.
|
||||
3. Remove poll_mode_io module paramater, sysfs node, and associated code.
|
||||
-------------------------------------------------------------------------------
|
||||
Release Date : Wed. Oct 5, 2011 17:00:00 PST 2010 -
|
||||
(emaild-id:megaraidlinux@lsi.com)
|
||||
Adam Radford
|
||||
|
|
|
@ -1,32 +1,11 @@
|
|||
Copyright (c) 2003-2011 QLogic Corporation
|
||||
QLogic Linux iSCSI HBA Driver
|
||||
QLogic Linux iSCSI Driver
|
||||
|
||||
This program includes a device driver for Linux 3.x.
|
||||
You may modify and redistribute the device driver code under the
|
||||
GNU General Public License (a copy of which is attached hereto as
|
||||
Exhibit A) published by the Free Software Foundation (version 2).
|
||||
|
||||
REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
|
||||
THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
|
||||
CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
|
||||
OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
|
||||
TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
|
||||
ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
|
||||
COMBINATION WITH THIS PROGRAM.
|
||||
|
||||
|
||||
EXHIBIT A
|
||||
|
||||
|
|
|
@ -7200,7 +7200,7 @@ S: Maintained
|
|||
F: drivers/net/vmxnet3/
|
||||
|
||||
VMware PVSCSI driver
|
||||
M: Alok Kataria <akataria@vmware.com>
|
||||
M: Arvind Kumar <arvindkumar@vmware.com>
|
||||
M: VMware PV-Drivers <pv-drivers@vmware.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
|
@ -830,16 +830,11 @@ config SCSI_ISCI
|
|||
tristate "Intel(R) C600 Series Chipset SAS Controller"
|
||||
depends on PCI && SCSI
|
||||
depends on X86
|
||||
# (temporary): known alpha quality driver
|
||||
depends on EXPERIMENTAL
|
||||
select SCSI_SAS_LIBSAS
|
||||
select SCSI_SAS_HOST_SMP
|
||||
---help---
|
||||
This driver supports the 6Gb/s SAS capabilities of the storage
|
||||
control unit found in the Intel(R) C600 series chipset.
|
||||
|
||||
The experimental tag will be removed after the driver exits alpha
|
||||
|
||||
config SCSI_GENERIC_NCR5380
|
||||
tristate "Generic NCR5380/53c400 SCSI PIO support"
|
||||
depends on ISA && SCSI
|
||||
|
|
|
@ -673,12 +673,7 @@ struct bfa_itnim_iostats_s {
|
|||
u32 tm_iocdowns; /* TM cleaned-up due to IOC down */
|
||||
u32 tm_cleanups; /* TM cleanup requests */
|
||||
u32 tm_cleanup_comps; /* TM cleanup completions */
|
||||
u32 lm_lun_across_sg; /* LM lun is across sg data buf */
|
||||
u32 lm_lun_not_sup; /* LM lun not supported */
|
||||
u32 lm_rpl_data_changed; /* LM report-lun data changed */
|
||||
u32 lm_wire_residue_changed; /* LM report-lun rsp residue changed */
|
||||
u32 lm_small_buf_addresidue; /* LM buf smaller than reported cnt */
|
||||
u32 lm_lun_not_rdy; /* LM lun not ready */
|
||||
u32 rsvd[6];
|
||||
};
|
||||
|
||||
/* Modify char* port_stt[] in bfal_port.c if a new state was added */
|
||||
|
|
|
@ -56,161 +56,6 @@ struct scsi_cdb_s {
|
|||
|
||||
#define SCSI_MAX_ALLOC_LEN 0xFF /* maximum allocarion length */
|
||||
|
||||
#define SCSI_SENSE_CUR_ERR 0x70
|
||||
#define SCSI_SENSE_DEF_ERR 0x71
|
||||
|
||||
/*
|
||||
* SCSI additional sense codes
|
||||
*/
|
||||
#define SCSI_ASC_LUN_NOT_READY 0x04
|
||||
#define SCSI_ASC_LUN_NOT_SUPPORTED 0x25
|
||||
#define SCSI_ASC_TOCC 0x3F
|
||||
|
||||
/*
|
||||
* SCSI additional sense code qualifiers
|
||||
*/
|
||||
#define SCSI_ASCQ_MAN_INTR_REQ 0x03 /* manual intervention req */
|
||||
#define SCSI_ASCQ_RL_DATA_CHANGED 0x0E /* report luns data changed */
|
||||
|
||||
/*
|
||||
* Methods of reporting informational exceptions
|
||||
*/
|
||||
#define SCSI_MP_IEC_UNIT_ATTN 0x2 /* generate unit attention */
|
||||
|
||||
struct scsi_report_luns_data_s {
|
||||
u32 lun_list_length; /* length of LUN list length */
|
||||
u32 reserved;
|
||||
struct scsi_lun lun[1]; /* first LUN in lun list */
|
||||
};
|
||||
|
||||
struct scsi_inquiry_vendor_s {
|
||||
u8 vendor_id[8];
|
||||
};
|
||||
|
||||
struct scsi_inquiry_prodid_s {
|
||||
u8 product_id[16];
|
||||
};
|
||||
|
||||
struct scsi_inquiry_prodrev_s {
|
||||
u8 product_rev[4];
|
||||
};
|
||||
|
||||
struct scsi_inquiry_data_s {
|
||||
#ifdef __BIG_ENDIAN
|
||||
u8 peripheral_qual:3; /* peripheral qualifier */
|
||||
u8 device_type:5; /* peripheral device type */
|
||||
u8 rmb:1; /* removable medium bit */
|
||||
u8 device_type_mod:7; /* device type modifier */
|
||||
u8 version;
|
||||
u8 aenc:1; /* async evt notification capability */
|
||||
u8 trm_iop:1; /* terminate I/O process */
|
||||
u8 norm_aca:1; /* normal ACA supported */
|
||||
u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */
|
||||
u8 rsp_data_format:4;
|
||||
u8 additional_len;
|
||||
u8 sccs:1;
|
||||
u8 reserved1:7;
|
||||
u8 reserved2:1;
|
||||
u8 enc_serv:1; /* enclosure service component */
|
||||
u8 reserved3:1;
|
||||
u8 multi_port:1; /* multi-port device */
|
||||
u8 m_chngr:1; /* device in medium transport element */
|
||||
u8 ack_req_q:1; /* SIP specific bit */
|
||||
u8 addr32:1; /* SIP specific bit */
|
||||
u8 addr16:1; /* SIP specific bit */
|
||||
u8 rel_adr:1; /* relative address */
|
||||
u8 w_bus32:1;
|
||||
u8 w_bus16:1;
|
||||
u8 synchronous:1;
|
||||
u8 linked_commands:1;
|
||||
u8 trans_dis:1;
|
||||
u8 cmd_queue:1; /* command queueing supported */
|
||||
u8 soft_reset:1; /* soft reset alternative (VS) */
|
||||
#else
|
||||
u8 device_type:5; /* peripheral device type */
|
||||
u8 peripheral_qual:3; /* peripheral qualifier */
|
||||
u8 device_type_mod:7; /* device type modifier */
|
||||
u8 rmb:1; /* removable medium bit */
|
||||
u8 version;
|
||||
u8 rsp_data_format:4;
|
||||
u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */
|
||||
u8 norm_aca:1; /* normal ACA supported */
|
||||
u8 terminate_iop:1;/* terminate I/O process */
|
||||
u8 aenc:1; /* async evt notification capability */
|
||||
u8 additional_len;
|
||||
u8 reserved1:7;
|
||||
u8 sccs:1;
|
||||
u8 addr16:1; /* SIP specific bit */
|
||||
u8 addr32:1; /* SIP specific bit */
|
||||
u8 ack_req_q:1; /* SIP specific bit */
|
||||
u8 m_chngr:1; /* device in medium transport element */
|
||||
u8 multi_port:1; /* multi-port device */
|
||||
u8 reserved3:1; /* TBD - Vendor Specific */
|
||||
u8 enc_serv:1; /* enclosure service component */
|
||||
u8 reserved2:1;
|
||||
u8 soft_seset:1; /* soft reset alternative (VS) */
|
||||
u8 cmd_queue:1; /* command queueing supported */
|
||||
u8 trans_dis:1;
|
||||
u8 linked_commands:1;
|
||||
u8 synchronous:1;
|
||||
u8 w_bus16:1;
|
||||
u8 w_bus32:1;
|
||||
u8 rel_adr:1; /* relative address */
|
||||
#endif
|
||||
struct scsi_inquiry_vendor_s vendor_id;
|
||||
struct scsi_inquiry_prodid_s product_id;
|
||||
struct scsi_inquiry_prodrev_s product_rev;
|
||||
u8 vendor_specific[20];
|
||||
u8 reserved4[40];
|
||||
};
|
||||
|
||||
/*
|
||||
* SCSI sense data format
|
||||
*/
|
||||
struct scsi_sense_s {
|
||||
#ifdef __BIG_ENDIAN
|
||||
u8 valid:1;
|
||||
u8 rsp_code:7;
|
||||
#else
|
||||
u8 rsp_code:7;
|
||||
u8 valid:1;
|
||||
#endif
|
||||
u8 seg_num;
|
||||
#ifdef __BIG_ENDIAN
|
||||
u8 file_mark:1;
|
||||
u8 eom:1; /* end of media */
|
||||
u8 ili:1; /* incorrect length indicator */
|
||||
u8 reserved:1;
|
||||
u8 sense_key:4;
|
||||
#else
|
||||
u8 sense_key:4;
|
||||
u8 reserved:1;
|
||||
u8 ili:1; /* incorrect length indicator */
|
||||
u8 eom:1; /* end of media */
|
||||
u8 file_mark:1;
|
||||
#endif
|
||||
u8 information[4]; /* device-type or cmd specific info */
|
||||
u8 add_sense_length; /* additional sense length */
|
||||
u8 command_info[4];/* command specific information */
|
||||
u8 asc; /* additional sense code */
|
||||
u8 ascq; /* additional sense code qualifier */
|
||||
u8 fru_code; /* field replaceable unit code */
|
||||
#ifdef __BIG_ENDIAN
|
||||
u8 sksv:1; /* sense key specific valid */
|
||||
u8 c_d:1; /* command/data bit */
|
||||
u8 res1:2;
|
||||
u8 bpv:1; /* bit pointer valid */
|
||||
u8 bpointer:3; /* bit pointer */
|
||||
#else
|
||||
u8 bpointer:3; /* bit pointer */
|
||||
u8 bpv:1; /* bit pointer valid */
|
||||
u8 res1:2;
|
||||
u8 c_d:1; /* command/data bit */
|
||||
u8 sksv:1; /* sense key specific valid */
|
||||
#endif
|
||||
u8 fpointer[2]; /* field pointer */
|
||||
};
|
||||
|
||||
/*
|
||||
* Fibre Channel Header Structure (FCHS) definition
|
||||
*/
|
||||
|
|
|
@ -24,8 +24,6 @@ BFA_TRC_FILE(HAL, FCPIM);
|
|||
* BFA ITNIM Related definitions
|
||||
*/
|
||||
static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
|
||||
static bfa_boolean_t bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim);
|
||||
static bfa_boolean_t bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim);
|
||||
static void bfa_ioim_lm_init(struct bfa_s *bfa);
|
||||
|
||||
#define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \
|
||||
|
@ -60,14 +58,6 @@ static void bfa_ioim_lm_init(struct bfa_s *bfa);
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define bfa_ioim_rp_wwn(__ioim) \
|
||||
(((struct bfa_fcs_rport_s *) \
|
||||
(__ioim)->itnim->rport->rport_drv)->pwwn)
|
||||
|
||||
#define bfa_ioim_lp_wwn(__ioim) \
|
||||
((BFA_LPS_FROM_TAG(BFA_LPS_MOD((__ioim)->bfa), \
|
||||
(__ioim)->itnim->rport->rport_info.lp_tag))->pwwn) \
|
||||
|
||||
#define bfa_itnim_sler_cb(__itnim) do { \
|
||||
if ((__itnim)->bfa->fcs) \
|
||||
bfa_cb_itnim_sler((__itnim)->ditn); \
|
||||
|
@ -77,13 +67,6 @@ static void bfa_ioim_lm_init(struct bfa_s *bfa);
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
enum bfa_ioim_lm_status {
|
||||
BFA_IOIM_LM_PRESENT = 1,
|
||||
BFA_IOIM_LM_LUN_NOT_SUP = 2,
|
||||
BFA_IOIM_LM_RPL_DATA_CHANGED = 3,
|
||||
BFA_IOIM_LM_LUN_NOT_RDY = 4,
|
||||
};
|
||||
|
||||
enum bfa_ioim_lm_ua_status {
|
||||
BFA_IOIM_LM_UA_RESET = 0,
|
||||
BFA_IOIM_LM_UA_SET = 1,
|
||||
|
@ -145,9 +128,6 @@ enum bfa_ioim_event {
|
|||
BFA_IOIM_SM_TMDONE = 16, /* IO cleanup from tskim */
|
||||
BFA_IOIM_SM_HWFAIL = 17, /* IOC h/w failure event */
|
||||
BFA_IOIM_SM_IOTOV = 18, /* ITN offline TOV */
|
||||
BFA_IOIM_SM_LM_LUN_NOT_SUP = 19,/* lunmask lun not supported */
|
||||
BFA_IOIM_SM_LM_RPL_DC = 20, /* lunmask report-lun data changed */
|
||||
BFA_IOIM_SM_LM_LUN_NOT_RDY = 21,/* lunmask lun not ready */
|
||||
};
|
||||
|
||||
|
||||
|
@ -245,9 +225,6 @@ static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
|
|||
static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
|
||||
static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
|
||||
static bfa_boolean_t bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
|
||||
static void __bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete);
|
||||
static void __bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete);
|
||||
static void __bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete);
|
||||
|
||||
/*
|
||||
* forward declaration of BFA IO state machine
|
||||
|
@ -445,12 +422,6 @@ bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
|
|||
bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
|
||||
bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
|
||||
bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
|
||||
bfa_fcpim_add_iostats(lstats, rstats, lm_lun_across_sg);
|
||||
bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_sup);
|
||||
bfa_fcpim_add_iostats(lstats, rstats, lm_rpl_data_changed);
|
||||
bfa_fcpim_add_iostats(lstats, rstats, lm_wire_residue_changed);
|
||||
bfa_fcpim_add_iostats(lstats, rstats, lm_small_buf_addresidue);
|
||||
bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_rdy);
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
|
@ -1580,27 +1551,6 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
|
|||
__bfa_cb_ioim_abort, ioim);
|
||||
break;
|
||||
|
||||
case BFA_IOIM_SM_LM_LUN_NOT_SUP:
|
||||
bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
|
||||
bfa_ioim_move_to_comp_q(ioim);
|
||||
bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
|
||||
__bfa_cb_ioim_lm_lun_not_sup, ioim);
|
||||
break;
|
||||
|
||||
case BFA_IOIM_SM_LM_RPL_DC:
|
||||
bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
|
||||
bfa_ioim_move_to_comp_q(ioim);
|
||||
bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
|
||||
__bfa_cb_ioim_lm_rpl_dc, ioim);
|
||||
break;
|
||||
|
||||
case BFA_IOIM_SM_LM_LUN_NOT_RDY:
|
||||
bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
|
||||
bfa_ioim_move_to_comp_q(ioim);
|
||||
bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
|
||||
__bfa_cb_ioim_lm_lun_not_rdy, ioim);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_sm_fault(ioim->bfa, event);
|
||||
}
|
||||
|
@ -2160,243 +2110,6 @@ bfa_ioim_lm_init(struct bfa_s *bfa)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate LUN for LUN masking
|
||||
*/
|
||||
static enum bfa_ioim_lm_status
|
||||
bfa_ioim_lm_check(struct bfa_ioim_s *ioim, struct bfa_lps_s *lps,
|
||||
struct bfa_rport_s *rp, struct scsi_lun lun)
|
||||
{
|
||||
u8 i;
|
||||
struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
|
||||
struct scsi_cdb_s *cdb = (struct scsi_cdb_s *)cmnd->cmnd;
|
||||
|
||||
if ((cdb->scsi_cdb[0] == REPORT_LUNS) &&
|
||||
(scsilun_to_int((struct scsi_lun *)&lun) == 0)) {
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data;
|
||||
return BFA_IOIM_LM_PRESENT;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
|
||||
|
||||
if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
|
||||
continue;
|
||||
|
||||
if ((scsilun_to_int((struct scsi_lun *)&lun_list[i].lun) ==
|
||||
scsilun_to_int((struct scsi_lun *)&lun))
|
||||
&& (rp->rport_tag == lun_list[i].rp_tag)
|
||||
&& ((u8)ioim->itnim->rport->rport_info.lp_tag ==
|
||||
lun_list[i].lp_tag)) {
|
||||
bfa_trc(ioim->bfa, lun_list[i].rp_tag);
|
||||
bfa_trc(ioim->bfa, lun_list[i].lp_tag);
|
||||
bfa_trc(ioim->bfa, scsilun_to_int(
|
||||
(struct scsi_lun *)&lun_list[i].lun));
|
||||
|
||||
if ((lun_list[i].ua == BFA_IOIM_LM_UA_SET) &&
|
||||
((cdb->scsi_cdb[0] != INQUIRY) ||
|
||||
(cdb->scsi_cdb[0] != REPORT_LUNS))) {
|
||||
lun_list[i].ua = BFA_IOIM_LM_UA_RESET;
|
||||
return BFA_IOIM_LM_RPL_DATA_CHANGED;
|
||||
}
|
||||
|
||||
if (cdb->scsi_cdb[0] == REPORT_LUNS)
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data;
|
||||
|
||||
return BFA_IOIM_LM_PRESENT;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cdb->scsi_cdb[0] == INQUIRY) &&
|
||||
(scsilun_to_int((struct scsi_lun *)&lun) == 0)) {
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_inq_data;
|
||||
return BFA_IOIM_LM_PRESENT;
|
||||
}
|
||||
|
||||
if (cdb->scsi_cdb[0] == TEST_UNIT_READY)
|
||||
return BFA_IOIM_LM_LUN_NOT_RDY;
|
||||
|
||||
return BFA_IOIM_LM_LUN_NOT_SUP;
|
||||
}
|
||||
|
||||
static bfa_boolean_t
|
||||
bfa_ioim_lm_proc_rsp_data_dummy(struct bfa_ioim_s *ioim)
|
||||
{
|
||||
return BFA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_ioim_lm_fetch_lun(struct bfa_ioim_s *ioim, u8 *rl_data, int offset,
|
||||
int buf_lun_cnt)
|
||||
{
|
||||
struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
|
||||
struct scsi_lun *lun_data = (struct scsi_lun *)(rl_data + offset);
|
||||
struct scsi_lun lun;
|
||||
int i, j;
|
||||
|
||||
bfa_trc(ioim->bfa, buf_lun_cnt);
|
||||
for (j = 0; j < buf_lun_cnt; j++) {
|
||||
lun = *((struct scsi_lun *)(lun_data + j));
|
||||
for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
|
||||
if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
|
||||
continue;
|
||||
if ((lun_list[i].rp_wwn == bfa_ioim_rp_wwn(ioim)) &&
|
||||
(lun_list[i].lp_wwn == bfa_ioim_lp_wwn(ioim)) &&
|
||||
(scsilun_to_int((struct scsi_lun *)&lun_list[i].lun)
|
||||
== scsilun_to_int((struct scsi_lun *)&lun))) {
|
||||
lun_list[i].state = BFA_IOIM_LUN_MASK_FETCHED;
|
||||
break;
|
||||
}
|
||||
} /* next lun in mask DB */
|
||||
} /* next lun in buf */
|
||||
}
|
||||
|
||||
static int
|
||||
bfa_ioim_lm_update_lun_sg(struct bfa_ioim_s *ioim, u32 *pgdlen,
|
||||
struct scsi_report_luns_data_s *rl)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
|
||||
struct scatterlist *sg = scsi_sglist(cmnd);
|
||||
struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
|
||||
struct scsi_lun *prev_rl_data = NULL, *base_rl_data;
|
||||
int i, j, sgeid, lun_fetched_cnt = 0, prev_sg_len = 0, base_count;
|
||||
int lun_across_sg_bytes, bytes_from_next_buf;
|
||||
u64 last_lun, temp_last_lun;
|
||||
|
||||
/* fetch luns from the first sg element */
|
||||
bfa_ioim_lm_fetch_lun(ioim, (u8 *)(rl->lun), 0,
|
||||
(sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1);
|
||||
|
||||
/* fetch luns from multiple sg elements */
|
||||
scsi_for_each_sg(cmnd, sg, scsi_sg_count(cmnd), sgeid) {
|
||||
if (sgeid == 0) {
|
||||
prev_sg_len = sg_dma_len(sg);
|
||||
prev_rl_data = (struct scsi_lun *)
|
||||
phys_to_virt(sg_dma_address(sg));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if the buf is having more data */
|
||||
lun_across_sg_bytes = prev_sg_len % sizeof(struct scsi_lun);
|
||||
if (lun_across_sg_bytes) {
|
||||
bfa_trc(ioim->bfa, lun_across_sg_bytes);
|
||||
bfa_stats(ioim->itnim, lm_lun_across_sg);
|
||||
bytes_from_next_buf = sizeof(struct scsi_lun) -
|
||||
lun_across_sg_bytes;
|
||||
|
||||
/* from next buf take higher bytes */
|
||||
temp_last_lun = *((u64 *)
|
||||
phys_to_virt(sg_dma_address(sg)));
|
||||
last_lun |= temp_last_lun >>
|
||||
(lun_across_sg_bytes * BITS_PER_BYTE);
|
||||
|
||||
/* from prev buf take higher bytes */
|
||||
temp_last_lun = *((u64 *)(prev_rl_data +
|
||||
(prev_sg_len - lun_across_sg_bytes)));
|
||||
temp_last_lun >>= bytes_from_next_buf * BITS_PER_BYTE;
|
||||
last_lun = last_lun | (temp_last_lun <<
|
||||
(bytes_from_next_buf * BITS_PER_BYTE));
|
||||
|
||||
bfa_ioim_lm_fetch_lun(ioim, (u8 *)&last_lun, 0, 1);
|
||||
} else
|
||||
bytes_from_next_buf = 0;
|
||||
|
||||
*pgdlen += sg_dma_len(sg);
|
||||
prev_sg_len = sg_dma_len(sg);
|
||||
prev_rl_data = (struct scsi_lun *)
|
||||
phys_to_virt(sg_dma_address(sg));
|
||||
bfa_ioim_lm_fetch_lun(ioim, (u8 *)prev_rl_data,
|
||||
bytes_from_next_buf,
|
||||
sg_dma_len(sg) / sizeof(struct scsi_lun));
|
||||
}
|
||||
|
||||
/* update the report luns data - based on fetched luns */
|
||||
sg = scsi_sglist(cmnd);
|
||||
base_rl_data = (struct scsi_lun *)rl->lun;
|
||||
base_count = (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1;
|
||||
for (i = 0, j = 0; i < MAX_LUN_MASK_CFG; i++) {
|
||||
if (lun_list[i].state == BFA_IOIM_LUN_MASK_FETCHED) {
|
||||
base_rl_data[j] = lun_list[i].lun;
|
||||
lun_list[i].state = BFA_IOIM_LUN_MASK_ACTIVE;
|
||||
j++;
|
||||
lun_fetched_cnt++;
|
||||
}
|
||||
|
||||
if (j > base_count) {
|
||||
j = 0;
|
||||
sg = sg_next(sg);
|
||||
base_rl_data = (struct scsi_lun *)
|
||||
phys_to_virt(sg_dma_address(sg));
|
||||
base_count = sg_dma_len(sg) / sizeof(struct scsi_lun);
|
||||
}
|
||||
}
|
||||
|
||||
bfa_trc(ioim->bfa, lun_fetched_cnt);
|
||||
return lun_fetched_cnt;
|
||||
}
|
||||
|
||||
static bfa_boolean_t
|
||||
bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim)
|
||||
{
|
||||
struct scsi_inquiry_data_s *inq;
|
||||
struct scatterlist *sg = scsi_sglist((struct scsi_cmnd *)ioim->dio);
|
||||
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
|
||||
inq = (struct scsi_inquiry_data_s *)phys_to_virt(sg_dma_address(sg));
|
||||
|
||||
bfa_trc(ioim->bfa, inq->device_type);
|
||||
inq->peripheral_qual = SCSI_INQ_PQ_NOT_CON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bfa_boolean_t
|
||||
bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
|
||||
struct scatterlist *sg = scsi_sglist(cmnd);
|
||||
struct bfi_ioim_rsp_s *m;
|
||||
struct scsi_report_luns_data_s *rl = NULL;
|
||||
int lun_count = 0, lun_fetched_cnt = 0;
|
||||
u32 residue, pgdlen = 0;
|
||||
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
|
||||
if (bfa_get_lun_mask_status(ioim->bfa) != BFA_LUNMASK_ENABLED)
|
||||
return BFA_TRUE;
|
||||
|
||||
m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
|
||||
if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION)
|
||||
return BFA_TRUE;
|
||||
|
||||
pgdlen = sg_dma_len(sg);
|
||||
bfa_trc(ioim->bfa, pgdlen);
|
||||
rl = (struct scsi_report_luns_data_s *)phys_to_virt(sg_dma_address(sg));
|
||||
lun_count = cpu_to_be32(rl->lun_list_length) / sizeof(struct scsi_lun);
|
||||
lun_fetched_cnt = bfa_ioim_lm_update_lun_sg(ioim, &pgdlen, rl);
|
||||
|
||||
if (lun_count == lun_fetched_cnt)
|
||||
return BFA_TRUE;
|
||||
|
||||
bfa_trc(ioim->bfa, lun_count);
|
||||
bfa_trc(ioim->bfa, lun_fetched_cnt);
|
||||
bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length));
|
||||
|
||||
if (be32_to_cpu(rl->lun_list_length) <= pgdlen)
|
||||
rl->lun_list_length = be32_to_cpu(lun_fetched_cnt) *
|
||||
sizeof(struct scsi_lun);
|
||||
else
|
||||
bfa_stats(ioim->itnim, lm_small_buf_addresidue);
|
||||
|
||||
bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length));
|
||||
bfa_trc(ioim->bfa, be32_to_cpu(m->residue));
|
||||
|
||||
residue = be32_to_cpu(m->residue);
|
||||
residue += (lun_count - lun_fetched_cnt) * sizeof(struct scsi_lun);
|
||||
bfa_stats(ioim->itnim, lm_wire_residue_changed);
|
||||
m->residue = be32_to_cpu(residue);
|
||||
bfa_trc(ioim->bfa, ioim->nsges);
|
||||
return BFA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
|
@ -2454,83 +2167,6 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
|
|||
m->scsi_status, sns_len, snsinfo, residue);
|
||||
}
|
||||
|
||||
static void
|
||||
__bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_ioim_s *ioim = cbarg;
|
||||
int sns_len = 0xD;
|
||||
u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
|
||||
struct scsi_sense_s *snsinfo;
|
||||
|
||||
if (!complete) {
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
|
||||
return;
|
||||
}
|
||||
|
||||
snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(
|
||||
ioim->fcpim->fcp, ioim->iotag);
|
||||
snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
|
||||
snsinfo->add_sense_length = 0xa;
|
||||
snsinfo->asc = SCSI_ASC_LUN_NOT_SUPPORTED;
|
||||
snsinfo->sense_key = ILLEGAL_REQUEST;
|
||||
bfa_trc(ioim->bfa, residue);
|
||||
bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
|
||||
SCSI_STATUS_CHECK_CONDITION, sns_len,
|
||||
(u8 *)snsinfo, residue);
|
||||
}
|
||||
|
||||
static void
|
||||
__bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_ioim_s *ioim = cbarg;
|
||||
int sns_len = 0xD;
|
||||
u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
|
||||
struct scsi_sense_s *snsinfo;
|
||||
|
||||
if (!complete) {
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
|
||||
return;
|
||||
}
|
||||
|
||||
snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp,
|
||||
ioim->iotag);
|
||||
snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
|
||||
snsinfo->sense_key = SCSI_MP_IEC_UNIT_ATTN;
|
||||
snsinfo->asc = SCSI_ASC_TOCC;
|
||||
snsinfo->add_sense_length = 0x6;
|
||||
snsinfo->ascq = SCSI_ASCQ_RL_DATA_CHANGED;
|
||||
bfa_trc(ioim->bfa, residue);
|
||||
bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
|
||||
SCSI_STATUS_CHECK_CONDITION, sns_len,
|
||||
(u8 *)snsinfo, residue);
|
||||
}
|
||||
|
||||
static void
|
||||
__bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_ioim_s *ioim = cbarg;
|
||||
int sns_len = 0xD;
|
||||
u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
|
||||
struct scsi_sense_s *snsinfo;
|
||||
|
||||
if (!complete) {
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
|
||||
return;
|
||||
}
|
||||
|
||||
snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(
|
||||
ioim->fcpim->fcp, ioim->iotag);
|
||||
snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
|
||||
snsinfo->add_sense_length = 0xa;
|
||||
snsinfo->sense_key = NOT_READY;
|
||||
snsinfo->asc = SCSI_ASC_LUN_NOT_READY;
|
||||
snsinfo->ascq = SCSI_ASCQ_MAN_INTR_REQ;
|
||||
bfa_trc(ioim->bfa, residue);
|
||||
bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
|
||||
SCSI_STATUS_CHECK_CONDITION, sns_len,
|
||||
(u8 *)snsinfo, residue);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn,
|
||||
u16 rp_tag, u8 lp_tag)
|
||||
|
@ -2647,7 +2283,8 @@ bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
|
|||
if (port) {
|
||||
*pwwn = port->port_cfg.pwwn;
|
||||
rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
|
||||
rp = rp_fcs->bfa_rport;
|
||||
if (rp_fcs)
|
||||
rp = rp_fcs->bfa_rport;
|
||||
}
|
||||
|
||||
lunm_list = bfa_get_lun_mask_list(bfa);
|
||||
|
@ -2715,7 +2352,8 @@ bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
|
|||
if (port) {
|
||||
*pwwn = port->port_cfg.pwwn;
|
||||
rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
|
||||
rp = rp_fcs->bfa_rport;
|
||||
if (rp_fcs)
|
||||
rp = rp_fcs->bfa_rport;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2757,7 +2395,6 @@ __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
|
|||
return;
|
||||
}
|
||||
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
|
||||
bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
|
||||
0, 0, NULL, 0);
|
||||
}
|
||||
|
@ -2773,7 +2410,6 @@ __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
|
|||
return;
|
||||
}
|
||||
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
|
||||
bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
|
||||
0, 0, NULL, 0);
|
||||
}
|
||||
|
@ -2788,7 +2424,6 @@ __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
|
|||
return;
|
||||
}
|
||||
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
|
||||
bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
|
||||
}
|
||||
|
||||
|
@ -3132,7 +2767,6 @@ bfa_ioim_attach(struct bfa_fcpim_s *fcpim)
|
|||
ioim->bfa = fcpim->bfa;
|
||||
ioim->fcpim = fcpim;
|
||||
ioim->iosp = iosp;
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
|
||||
INIT_LIST_HEAD(&ioim->sgpg_q);
|
||||
bfa_reqq_winit(&ioim->iosp->reqq_wait,
|
||||
bfa_ioim_qresume, ioim);
|
||||
|
@ -3170,7 +2804,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
|
|||
evt = BFA_IOIM_SM_DONE;
|
||||
else
|
||||
evt = BFA_IOIM_SM_COMP;
|
||||
ioim->proc_rsp_data(ioim);
|
||||
break;
|
||||
|
||||
case BFI_IOIM_STS_TIMEDOUT:
|
||||
|
@ -3206,7 +2839,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
|
|||
if (rsp->abort_tag != ioim->abort_tag) {
|
||||
bfa_trc(ioim->bfa, rsp->abort_tag);
|
||||
bfa_trc(ioim->bfa, ioim->abort_tag);
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3225,7 +2857,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
|
|||
WARN_ON(1);
|
||||
}
|
||||
|
||||
ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
|
||||
bfa_sm_send_event(ioim, evt);
|
||||
}
|
||||
|
||||
|
@ -3244,15 +2875,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
|
|||
|
||||
bfa_ioim_cb_profile_comp(fcpim, ioim);
|
||||
|
||||
if (bfa_get_lun_mask_status(bfa) != BFA_LUNMASK_ENABLED) {
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ioim->proc_rsp_data(ioim) == BFA_TRUE)
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
|
||||
else
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP);
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3364,35 +2987,6 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)
|
|||
void
|
||||
bfa_ioim_start(struct bfa_ioim_s *ioim)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
|
||||
struct bfa_lps_s *lps;
|
||||
enum bfa_ioim_lm_status status;
|
||||
struct scsi_lun scsilun;
|
||||
|
||||
if (bfa_get_lun_mask_status(ioim->bfa) == BFA_LUNMASK_ENABLED) {
|
||||
lps = BFA_IOIM_TO_LPS(ioim);
|
||||
int_to_scsilun(cmnd->device->lun, &scsilun);
|
||||
status = bfa_ioim_lm_check(ioim, lps,
|
||||
ioim->itnim->rport, scsilun);
|
||||
if (status == BFA_IOIM_LM_LUN_NOT_RDY) {
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_RDY);
|
||||
bfa_stats(ioim->itnim, lm_lun_not_rdy);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == BFA_IOIM_LM_LUN_NOT_SUP) {
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_SUP);
|
||||
bfa_stats(ioim->itnim, lm_lun_not_sup);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == BFA_IOIM_LM_RPL_DATA_CHANGED) {
|
||||
bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_RPL_DC);
|
||||
bfa_stats(ioim->itnim, lm_rpl_data_changed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
|
||||
|
||||
/*
|
||||
|
|
|
@ -110,7 +110,6 @@ struct bfad_ioim_s;
|
|||
struct bfad_tskim_s;
|
||||
|
||||
typedef void (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
|
||||
typedef bfa_boolean_t (*bfa_ioim_lm_proc_rsp_data_t) (struct bfa_ioim_s *ioim);
|
||||
|
||||
struct bfa_fcpim_s {
|
||||
struct bfa_s *bfa;
|
||||
|
@ -124,7 +123,6 @@ struct bfa_fcpim_s {
|
|||
u32 path_tov;
|
||||
u16 q_depth;
|
||||
u8 reqq; /* Request queue to be used */
|
||||
u8 lun_masking_pending;
|
||||
struct list_head itnim_q; /* queue of active itnim */
|
||||
struct list_head ioim_resfree_q; /* IOs waiting for f/w */
|
||||
struct list_head ioim_comp_q; /* IO global comp Q */
|
||||
|
@ -181,7 +179,6 @@ struct bfa_ioim_s {
|
|||
u8 reqq; /* Request queue for I/O */
|
||||
u8 mode; /* IO is passthrough or not */
|
||||
u64 start_time; /* IO's Profile start val */
|
||||
bfa_ioim_lm_proc_rsp_data_t proc_rsp_data; /* RSP data adjust */
|
||||
};
|
||||
|
||||
struct bfa_ioim_sp_s {
|
||||
|
@ -261,10 +258,6 @@ struct bfa_itnim_s {
|
|||
(__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET; \
|
||||
} while (0)
|
||||
|
||||
#define BFA_IOIM_TO_LPS(__ioim) \
|
||||
BFA_LPS_FROM_TAG(BFA_LPS_MOD(__ioim->bfa), \
|
||||
__ioim->itnim->rport->rport_info.lp_tag)
|
||||
|
||||
static inline bfa_boolean_t
|
||||
bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)
|
||||
{
|
||||
|
|
|
@ -582,11 +582,6 @@ void bfa_cb_rport_qos_scn_prio(void *rport,
|
|||
#define BFA_LP_TAG_INVALID 0xff
|
||||
void bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
|
||||
void bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
|
||||
bfa_boolean_t bfa_rport_lunmask_active(struct bfa_rport_s *rp);
|
||||
wwn_t bfa_rport_get_pwwn(struct bfa_s *bfa, struct bfa_rport_s *rp);
|
||||
struct bfa_rport_s *bfa_rport_get_by_wwn(struct bfa_s *bfa, u16 vf_id,
|
||||
wwn_t *lpwwn, wwn_t rpwwn);
|
||||
void *bfa_cb_get_rp_by_wwn(void *arg, u16 vf_id, wwn_t *lpwwn, wwn_t rpwwn);
|
||||
|
||||
/*
|
||||
* bfa fcxp API functions
|
||||
|
|
|
@ -674,6 +674,7 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
|
|||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
bfa_fcs_vport_start(&vport->fcs_vport);
|
||||
list_add_tail(&vport->list_entry, &bfad->vport_list);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
|
@ -1404,6 +1405,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
bfad->ref_count = 0;
|
||||
bfad->pport.bfad = bfad;
|
||||
INIT_LIST_HEAD(&bfad->pbc_vport_list);
|
||||
INIT_LIST_HEAD(&bfad->vport_list);
|
||||
|
||||
/* Setup the debugfs node for this bfad */
|
||||
if (bfa_debugfs_enable)
|
||||
|
|
|
@ -491,7 +491,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport)
|
|||
|
||||
free_scsi_host:
|
||||
bfad_scsi_host_free(bfad, im_port);
|
||||
|
||||
list_del(&vport->list_entry);
|
||||
kfree(vport);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -2394,6 +2394,21 @@ out:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Function to reset the LUN SCAN mode */
|
||||
static void
|
||||
bfad_iocmd_lunmask_reset_lunscan_mode(struct bfad_s *bfad, int lunmask_cfg)
|
||||
{
|
||||
struct bfad_im_port_s *pport_im = bfad->pport.im_port;
|
||||
struct bfad_vport_s *vport = NULL;
|
||||
|
||||
/* Set the scsi device LUN SCAN flags for base port */
|
||||
bfad_reset_sdev_bflags(pport_im, lunmask_cfg);
|
||||
|
||||
/* Set the scsi device LUN SCAN flags for the vports */
|
||||
list_for_each_entry(vport, &bfad->vport_list, list_entry)
|
||||
bfad_reset_sdev_bflags(vport->drv_port.im_port, lunmask_cfg);
|
||||
}
|
||||
|
||||
int
|
||||
bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
|
||||
{
|
||||
|
@ -2401,11 +2416,17 @@ bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE)
|
||||
if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) {
|
||||
iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE);
|
||||
else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE)
|
||||
/* Set the LUN Scanning mode to be Sequential scan */
|
||||
if (iocmd->status == BFA_STATUS_OK)
|
||||
bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_TRUE);
|
||||
} else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) {
|
||||
iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE);
|
||||
else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR)
|
||||
/* Set the LUN Scanning mode to default REPORT_LUNS scan */
|
||||
if (iocmd->status == BFA_STATUS_OK)
|
||||
bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_FALSE);
|
||||
} else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR)
|
||||
iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
return 0;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <scsi/scsi_transport_fc.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_bsg_fc.h>
|
||||
#include <scsi/scsi_devinfo.h>
|
||||
|
||||
#include "bfa_modules.h"
|
||||
#include "bfa_fcs.h"
|
||||
|
@ -227,6 +228,7 @@ struct bfad_s {
|
|||
struct list_head active_aen_q;
|
||||
struct bfa_aen_entry_s aen_list[BFA_AEN_MAX_ENTRY];
|
||||
spinlock_t bfad_aen_spinlock;
|
||||
struct list_head vport_list;
|
||||
};
|
||||
|
||||
/* BFAD state machine events */
|
||||
|
|
|
@ -917,6 +917,37 @@ bfad_get_itnim(struct bfad_im_port_s *im_port, int id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function is invoked from the SCSI Host Template slave_alloc() entry point.
|
||||
* Has the logic to query the LUN Mask database to check if this LUN needs to
|
||||
* be made visible to the SCSI mid-layer or not.
|
||||
*
|
||||
* Returns BFA_STATUS_OK if this LUN needs to be added to the OS stack.
|
||||
* Returns -ENXIO to notify SCSI mid-layer to not add this LUN to the OS stack.
|
||||
*/
|
||||
static int
|
||||
bfad_im_check_if_make_lun_visible(struct scsi_device *sdev,
|
||||
struct fc_rport *rport)
|
||||
{
|
||||
struct bfad_itnim_data_s *itnim_data =
|
||||
(struct bfad_itnim_data_s *) rport->dd_data;
|
||||
struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
|
||||
struct bfa_rport_s *bfa_rport = itnim_data->itnim->bfa_itnim->rport;
|
||||
struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(bfa);
|
||||
int i = 0, ret = -ENXIO;
|
||||
|
||||
for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
|
||||
if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE &&
|
||||
scsilun_to_int(&lun_list[i].lun) == sdev->lun &&
|
||||
lun_list[i].rp_tag == bfa_rport->rport_tag &&
|
||||
lun_list[i].lp_tag == (u8)bfa_rport->rport_info.lp_tag) {
|
||||
ret = BFA_STATUS_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scsi_Host template entry slave_alloc
|
||||
*/
|
||||
|
@ -924,10 +955,33 @@ static int
|
|||
bfad_im_slave_alloc(struct scsi_device *sdev)
|
||||
{
|
||||
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
|
||||
struct bfad_itnim_data_s *itnim_data =
|
||||
(struct bfad_itnim_data_s *) rport->dd_data;
|
||||
struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
|
||||
|
||||
if (!rport || fc_remote_port_chkready(rport))
|
||||
return -ENXIO;
|
||||
|
||||
if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) {
|
||||
/*
|
||||
* We should not mask LUN 0 - since this will translate
|
||||
* to no LUN / TARGET for SCSI ml resulting no scan.
|
||||
*/
|
||||
if (sdev->lun == 0) {
|
||||
sdev->sdev_bflags |= BLIST_NOREPORTLUN |
|
||||
BLIST_SPARSELUN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Query LUN Mask configuration - to expose this LUN
|
||||
* to the SCSI mid-layer or to mask it.
|
||||
*/
|
||||
if (bfad_im_check_if_make_lun_visible(sdev, rport) !=
|
||||
BFA_STATUS_OK)
|
||||
return -ENXIO;
|
||||
}
|
||||
done:
|
||||
sdev->hostdata = rport->dd_data;
|
||||
|
||||
return 0;
|
||||
|
@ -1037,6 +1091,8 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim)
|
|||
&& (fc_rport->scsi_target_id < MAX_FCP_TARGET))
|
||||
itnim->scsi_tgt_id = fc_rport->scsi_target_id;
|
||||
|
||||
itnim->channel = fc_rport->channel;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ struct bfad_itnim_s {
|
|||
struct fc_rport *fc_rport;
|
||||
struct bfa_itnim_s *bfa_itnim;
|
||||
u16 scsi_tgt_id;
|
||||
u16 channel;
|
||||
u16 queue_work;
|
||||
unsigned long last_ramp_up_time;
|
||||
unsigned long last_queue_full_time;
|
||||
|
@ -166,4 +167,30 @@ irqreturn_t bfad_intx(int irq, void *dev_id);
|
|||
int bfad_im_bsg_request(struct fc_bsg_job *job);
|
||||
int bfad_im_bsg_timeout(struct fc_bsg_job *job);
|
||||
|
||||
/*
|
||||
* Macro to set the SCSI device sdev_bflags - sdev_bflags are used by the
|
||||
* SCSI mid-layer to choose LUN Scanning mode REPORT_LUNS vs. Sequential Scan
|
||||
*
|
||||
* Internally iterate's over all the ITNIM's part of the im_port & set's the
|
||||
* sdev_bflags for the scsi_device associated with LUN #0.
|
||||
*/
|
||||
#define bfad_reset_sdev_bflags(__im_port, __lunmask_cfg) do { \
|
||||
struct scsi_device *__sdev = NULL; \
|
||||
struct bfad_itnim_s *__itnim = NULL; \
|
||||
u32 scan_flags = BLIST_NOREPORTLUN | BLIST_SPARSELUN; \
|
||||
list_for_each_entry(__itnim, &((__im_port)->itnim_mapped_list), \
|
||||
list_entry) { \
|
||||
__sdev = scsi_device_lookup((__im_port)->shost, \
|
||||
__itnim->channel, \
|
||||
__itnim->scsi_tgt_id, 0); \
|
||||
if (__sdev) { \
|
||||
if ((__lunmask_cfg) == BFA_TRUE) \
|
||||
__sdev->sdev_bflags |= scan_flags; \
|
||||
else \
|
||||
__sdev->sdev_bflags &= ~scan_flags; \
|
||||
scsi_device_put(__sdev); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1868,8 +1868,9 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
|
|||
|
||||
tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC);
|
||||
if (!tdata->skb) {
|
||||
pr_warn("alloc skb %u+%u, opcode 0x%x failed.\n",
|
||||
cdev->skb_tx_rsvd, headroom, opcode);
|
||||
struct cxgbi_sock *csk = cconn->cep->csk;
|
||||
struct net_device *ndev = cdev->ports[csk->port_id];
|
||||
ndev->stats.tx_dropped++;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
|
@ -466,6 +466,11 @@ static int alua_check_sense(struct scsi_device *sdev,
|
|||
* Power On, Reset, or Bus Device Reset, just retry.
|
||||
*/
|
||||
return ADD_TO_MLQUEUE;
|
||||
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01)
|
||||
/*
|
||||
* Mode Parameters Changed
|
||||
*/
|
||||
return ADD_TO_MLQUEUE;
|
||||
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06)
|
||||
/*
|
||||
* ALUA state changed
|
||||
|
|
|
@ -953,6 +953,8 @@ static int __init rdac_init(void)
|
|||
if (!kmpath_rdacd) {
|
||||
scsi_unregister_device_handler(&rdac_dh);
|
||||
printk(KERN_ERR "kmpath_rdacd creation failed.\n");
|
||||
|
||||
r = -EINVAL;
|
||||
}
|
||||
done:
|
||||
return r;
|
||||
|
|
|
@ -58,7 +58,11 @@ module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR);
|
|||
MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \
|
||||
"Direct Data Placement (DDP).");
|
||||
|
||||
DEFINE_MUTEX(fcoe_config_mutex);
|
||||
unsigned int fcoe_debug_logging;
|
||||
module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
|
||||
|
||||
static DEFINE_MUTEX(fcoe_config_mutex);
|
||||
|
||||
static struct workqueue_struct *fcoe_wq;
|
||||
|
||||
|
@ -67,8 +71,8 @@ static DECLARE_COMPLETION(fcoe_flush_completion);
|
|||
|
||||
/* fcoe host list */
|
||||
/* must only by accessed under the RTNL mutex */
|
||||
LIST_HEAD(fcoe_hostlist);
|
||||
DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
|
||||
static LIST_HEAD(fcoe_hostlist);
|
||||
static DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
|
||||
|
||||
/* Function Prototypes */
|
||||
static int fcoe_reset(struct Scsi_Host *);
|
||||
|
@ -157,7 +161,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
|
|||
.lport_set_port_id = fcoe_set_port_id,
|
||||
};
|
||||
|
||||
struct fc_function_template fcoe_nport_fc_functions = {
|
||||
static struct fc_function_template fcoe_nport_fc_functions = {
|
||||
.show_host_node_name = 1,
|
||||
.show_host_port_name = 1,
|
||||
.show_host_supported_classes = 1,
|
||||
|
@ -197,7 +201,7 @@ struct fc_function_template fcoe_nport_fc_functions = {
|
|||
.bsg_request = fc_lport_bsg_request,
|
||||
};
|
||||
|
||||
struct fc_function_template fcoe_vport_fc_functions = {
|
||||
static struct fc_function_template fcoe_vport_fc_functions = {
|
||||
.show_host_node_name = 1,
|
||||
.show_host_port_name = 1,
|
||||
.show_host_supported_classes = 1,
|
||||
|
@ -433,7 +437,7 @@ static inline void fcoe_interface_put(struct fcoe_interface *fcoe)
|
|||
*
|
||||
* Caller must be holding the RTNL mutex
|
||||
*/
|
||||
void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
|
||||
static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
|
||||
{
|
||||
struct net_device *netdev = fcoe->netdev;
|
||||
struct fcoe_ctlr *fip = &fcoe->ctlr;
|
||||
|
@ -748,7 +752,7 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev)
|
|||
*
|
||||
* Returns: True for read types I/O, otherwise returns false.
|
||||
*/
|
||||
bool fcoe_oem_match(struct fc_frame *fp)
|
||||
static bool fcoe_oem_match(struct fc_frame *fp)
|
||||
{
|
||||
struct fc_frame_header *fh = fc_frame_header_get(fp);
|
||||
struct fcp_cmnd *fcp;
|
||||
|
@ -756,11 +760,12 @@ bool fcoe_oem_match(struct fc_frame *fp)
|
|||
if (fc_fcp_is_read(fr_fsp(fp)) &&
|
||||
(fr_fsp(fp)->data_len > fcoe_ddp_min))
|
||||
return true;
|
||||
else if (!(ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)) {
|
||||
else if ((fr_fsp(fp) == NULL) &&
|
||||
(fh->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD) &&
|
||||
(ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN)) {
|
||||
fcp = fc_frame_payload_get(fp, sizeof(*fcp));
|
||||
if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN &&
|
||||
fcp && (ntohl(fcp->fc_dl) > fcoe_ddp_min) &&
|
||||
(fcp->fc_flags & FCP_CFL_WRDATA))
|
||||
if ((fcp->fc_flags & FCP_CFL_WRDATA) &&
|
||||
(ntohl(fcp->fc_dl) > fcoe_ddp_min))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1106,7 +1111,7 @@ static int __init fcoe_if_init(void)
|
|||
*
|
||||
* Returns: 0 on success
|
||||
*/
|
||||
int __exit fcoe_if_exit(void)
|
||||
static int __exit fcoe_if_exit(void)
|
||||
{
|
||||
fc_release_transport(fcoe_nport_scsi_transport);
|
||||
fc_release_transport(fcoe_vport_scsi_transport);
|
||||
|
@ -1295,7 +1300,7 @@ static inline unsigned int fcoe_select_cpu(void)
|
|||
*
|
||||
* Returns: 0 for success
|
||||
*/
|
||||
int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
|
||||
static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
|
||||
struct packet_type *ptype, struct net_device *olddev)
|
||||
{
|
||||
struct fc_lport *lport;
|
||||
|
@ -1451,7 +1456,7 @@ static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen)
|
|||
*
|
||||
* Return: 0 for success
|
||||
*/
|
||||
int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
|
||||
static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
|
||||
{
|
||||
int wlen;
|
||||
u32 crc;
|
||||
|
@ -1671,8 +1676,7 @@ static void fcoe_recv_frame(struct sk_buff *skb)
|
|||
skb->dev ? skb->dev->name : "<NULL>");
|
||||
|
||||
port = lport_priv(lport);
|
||||
if (skb_is_nonlinear(skb))
|
||||
skb_linearize(skb); /* not ideal */
|
||||
skb_linearize(skb); /* check for skb_is_nonlinear is within skb_linearize */
|
||||
|
||||
/*
|
||||
* Frame length checks and setting up the header pointers
|
||||
|
@ -1728,7 +1732,7 @@ drop:
|
|||
*
|
||||
* Return: 0 for success
|
||||
*/
|
||||
int fcoe_percpu_receive_thread(void *arg)
|
||||
static int fcoe_percpu_receive_thread(void *arg)
|
||||
{
|
||||
struct fcoe_percpu_s *p = arg;
|
||||
struct sk_buff *skb;
|
||||
|
@ -2146,7 +2150,7 @@ out_nortnl:
|
|||
* Returns: 0 if the ethtool query was successful
|
||||
* -1 if the ethtool query failed
|
||||
*/
|
||||
int fcoe_link_speed_update(struct fc_lport *lport)
|
||||
static int fcoe_link_speed_update(struct fc_lport *lport)
|
||||
{
|
||||
struct net_device *netdev = fcoe_netdev(lport);
|
||||
struct ethtool_cmd ecmd;
|
||||
|
@ -2180,7 +2184,7 @@ int fcoe_link_speed_update(struct fc_lport *lport)
|
|||
* Returns: 0 if link is UP and OK, -1 if not
|
||||
*
|
||||
*/
|
||||
int fcoe_link_ok(struct fc_lport *lport)
|
||||
static int fcoe_link_ok(struct fc_lport *lport)
|
||||
{
|
||||
struct net_device *netdev = fcoe_netdev(lport);
|
||||
|
||||
|
@ -2200,7 +2204,7 @@ int fcoe_link_ok(struct fc_lport *lport)
|
|||
* there no packets that will be handled by the lport, but also that any
|
||||
* threads already handling packet have returned.
|
||||
*/
|
||||
void fcoe_percpu_clean(struct fc_lport *lport)
|
||||
static void fcoe_percpu_clean(struct fc_lport *lport)
|
||||
{
|
||||
struct fcoe_percpu_s *pp;
|
||||
struct fcoe_rcv_info *fr;
|
||||
|
@ -2251,7 +2255,7 @@ void fcoe_percpu_clean(struct fc_lport *lport)
|
|||
*
|
||||
* Returns: Always 0 (return value required by FC transport template)
|
||||
*/
|
||||
int fcoe_reset(struct Scsi_Host *shost)
|
||||
static int fcoe_reset(struct Scsi_Host *shost)
|
||||
{
|
||||
struct fc_lport *lport = shost_priv(shost);
|
||||
struct fcoe_port *port = lport_priv(lport);
|
||||
|
|
|
@ -40,9 +40,7 @@
|
|||
#define FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */
|
||||
#define FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */
|
||||
|
||||
unsigned int fcoe_debug_logging;
|
||||
module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
|
||||
extern unsigned int fcoe_debug_logging;
|
||||
|
||||
#define FCOE_LOGGING 0x01 /* General logging, not categorized */
|
||||
#define FCOE_NETDEV_LOGGING 0x02 /* Netdevice logging */
|
||||
|
|
|
@ -4271,7 +4271,9 @@ static void stop_controller_lockup_detector(struct ctlr_info *h)
|
|||
remove_ctlr_from_lockup_detector_list(h);
|
||||
/* If the list of ctlr's to monitor is empty, stop the thread */
|
||||
if (list_empty(&hpsa_ctlr_list)) {
|
||||
spin_unlock_irqrestore(&lockup_detector_lock, flags);
|
||||
kthread_stop(hpsa_lockup_detector);
|
||||
spin_lock_irqsave(&lockup_detector_lock, flags);
|
||||
hpsa_lockup_detector = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&lockup_detector_lock, flags);
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
# Makefile for create_fw
|
||||
#
|
||||
CC=gcc
|
||||
CFLAGS=-c -Wall -O2 -g
|
||||
LDFLAGS=
|
||||
SOURCES=create_fw.c
|
||||
OBJECTS=$(SOURCES:.cpp=.o)
|
||||
EXECUTABLE=create_fw
|
||||
|
||||
all: $(SOURCES) $(EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $< -O $@
|
||||
|
||||
clean:
|
||||
rm -f *.o $(EXECUTABLE)
|
|
@ -1,36 +0,0 @@
|
|||
This defines the temporary binary blow we are to pass to the SCU
|
||||
driver to emulate the binary firmware that we will eventually be
|
||||
able to access via NVRAM on the SCU controller.
|
||||
|
||||
The current size of the binary blob is expected to be 149 bytes or larger
|
||||
|
||||
Header Types:
|
||||
0x1: Phy Masks
|
||||
0x2: Phy Gens
|
||||
0x3: SAS Addrs
|
||||
0xff: End of Data
|
||||
|
||||
ID string - u8[12]: "#SCU MAGIC#\0"
|
||||
Version - u8: 1
|
||||
SubVersion - u8: 0
|
||||
|
||||
Header Type - u8: 0x1
|
||||
Size - u8: 8
|
||||
Phy Mask - u32[8]
|
||||
|
||||
Header Type - u8: 0x2
|
||||
Size - u8: 8
|
||||
Phy Gen - u32[8]
|
||||
|
||||
Header Type - u8: 0x3
|
||||
Size - u8: 8
|
||||
Sas Addr - u64[8]
|
||||
|
||||
Header Type - u8: 0xf
|
||||
|
||||
|
||||
==============================================================================
|
||||
|
||||
Place isci_firmware.bin in /lib/firmware
|
||||
Be sure to recreate the initramfs image to include the firmware.
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <asm/types.h>
|
||||
#include <strings.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "create_fw.h"
|
||||
#include "../probe_roms.h"
|
||||
|
||||
int write_blob(struct isci_orom *isci_orom)
|
||||
{
|
||||
FILE *fd;
|
||||
int err;
|
||||
size_t count;
|
||||
|
||||
fd = fopen(blob_name, "w+");
|
||||
if (!fd) {
|
||||
perror("Open file for write failed");
|
||||
fclose(fd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
count = fwrite(isci_orom, sizeof(struct isci_orom), 1, fd);
|
||||
if (count != 1) {
|
||||
perror("Write data failed");
|
||||
fclose(fd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_binary_values(struct isci_orom *isci_orom)
|
||||
{
|
||||
int ctrl_idx, phy_idx, port_idx;
|
||||
|
||||
/* setting OROM signature */
|
||||
strncpy(isci_orom->hdr.signature, sig, strlen(sig));
|
||||
isci_orom->hdr.version = version;
|
||||
isci_orom->hdr.total_block_length = sizeof(struct isci_orom);
|
||||
isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr);
|
||||
isci_orom->hdr.num_elements = num_elements;
|
||||
|
||||
for (ctrl_idx = 0; ctrl_idx < 2; ctrl_idx++) {
|
||||
isci_orom->ctrl[ctrl_idx].controller.mode_type = mode_type;
|
||||
isci_orom->ctrl[ctrl_idx].controller.max_concurrent_dev_spin_up =
|
||||
max_num_concurrent_dev_spin_up;
|
||||
isci_orom->ctrl[ctrl_idx].controller.do_enable_ssc =
|
||||
enable_ssc;
|
||||
|
||||
for (port_idx = 0; port_idx < 4; port_idx++)
|
||||
isci_orom->ctrl[ctrl_idx].ports[port_idx].phy_mask =
|
||||
phy_mask[ctrl_idx][port_idx];
|
||||
|
||||
for (phy_idx = 0; phy_idx < 4; phy_idx++) {
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.high =
|
||||
(__u32)(sas_addr[ctrl_idx][phy_idx] >> 32);
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low =
|
||||
(__u32)(sas_addr[ctrl_idx][phy_idx]);
|
||||
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control0 =
|
||||
afe_tx_amp_control0;
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control1 =
|
||||
afe_tx_amp_control1;
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control2 =
|
||||
afe_tx_amp_control2;
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control3 =
|
||||
afe_tx_amp_control3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err;
|
||||
struct isci_orom *isci_orom;
|
||||
|
||||
isci_orom = malloc(sizeof(struct isci_orom));
|
||||
memset(isci_orom, 0, sizeof(struct isci_orom));
|
||||
|
||||
set_binary_values(isci_orom);
|
||||
|
||||
err = write_blob(isci_orom);
|
||||
if (err < 0) {
|
||||
free(isci_orom);
|
||||
return err;
|
||||
}
|
||||
|
||||
free(isci_orom);
|
||||
return 0;
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
#ifndef _CREATE_FW_H_
|
||||
#define _CREATE_FW_H_
|
||||
#include "../probe_roms.h"
|
||||
|
||||
|
||||
/* we are configuring for 2 SCUs */
|
||||
static const int num_elements = 2;
|
||||
|
||||
/*
|
||||
* For all defined arrays:
|
||||
* elements 0-3 are for SCU0, ports 0-3
|
||||
* elements 4-7 are for SCU1, ports 0-3
|
||||
*
|
||||
* valid configurations for one SCU are:
|
||||
* P0 P1 P2 P3
|
||||
* ----------------
|
||||
* 0xF,0x0,0x0,0x0 # 1 x4 port
|
||||
* 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
|
||||
* # ports
|
||||
* 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
|
||||
* # port
|
||||
* 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
|
||||
* 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
|
||||
*
|
||||
* if there is a port/phy on which you do not wish to override the default
|
||||
* values, use the value assigned to UNINIT_PARAM (255).
|
||||
*/
|
||||
|
||||
/* discovery mode type (port auto config mode by default ) */
|
||||
|
||||
/*
|
||||
* if there is a port/phy on which you do not wish to override the default
|
||||
* values, use the value "0000000000000000". SAS address of zero's is
|
||||
* considered invalid and will not be used.
|
||||
*/
|
||||
#ifdef MPC
|
||||
static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
|
||||
static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
|
||||
{1, 2, 4, 8} };
|
||||
static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000001ULL,
|
||||
0x5FCFFFFFF0000002ULL,
|
||||
0x5FCFFFFFF0000003ULL,
|
||||
0x5FCFFFFFF0000004ULL },
|
||||
{ 0x5FCFFFFFF0000005ULL,
|
||||
0x5FCFFFFFF0000006ULL,
|
||||
0x5FCFFFFFF0000007ULL,
|
||||
0x5FCFFFFFF0000008ULL } };
|
||||
#else /* APC (default) */
|
||||
static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
|
||||
static const __u8 phy_mask[2][4];
|
||||
static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFF00000001ULL,
|
||||
0x5FCFFFFF00000001ULL,
|
||||
0x5FCFFFFF00000001ULL,
|
||||
0x5FCFFFFF00000001ULL },
|
||||
{ 0x5FCFFFFF00000002ULL,
|
||||
0x5FCFFFFF00000002ULL,
|
||||
0x5FCFFFFF00000002ULL,
|
||||
0x5FCFFFFF00000002ULL } };
|
||||
#endif
|
||||
|
||||
/* Maximum number of concurrent device spin up */
|
||||
static const int max_num_concurrent_dev_spin_up = 1;
|
||||
|
||||
/* enable of ssc operation */
|
||||
static const int enable_ssc;
|
||||
|
||||
/* AFE_TX_AMP_CONTROL */
|
||||
static const unsigned int afe_tx_amp_control0 = 0x000bdd08;
|
||||
static const unsigned int afe_tx_amp_control1 = 0x000ffc00;
|
||||
static const unsigned int afe_tx_amp_control2 = 0x000b7c09;
|
||||
static const unsigned int afe_tx_amp_control3 = 0x000afc6e;
|
||||
|
||||
static const char blob_name[] = "isci_firmware.bin";
|
||||
static const char sig[] = "ISCUOEMB";
|
||||
static const unsigned char version = 0x10;
|
||||
|
||||
#endif
|
|
@ -899,7 +899,8 @@ static enum sci_status sci_controller_start_next_phy(struct isci_host *ihost)
|
|||
*/
|
||||
if ((iphy->is_in_link_training == false && state == SCI_PHY_INITIAL) ||
|
||||
(iphy->is_in_link_training == false && state == SCI_PHY_STOPPED) ||
|
||||
(iphy->is_in_link_training == true && is_phy_starting(iphy))) {
|
||||
(iphy->is_in_link_training == true && is_phy_starting(iphy)) ||
|
||||
(ihost->port_agent.phy_ready_mask != ihost->port_agent.phy_configured_mask)) {
|
||||
is_controller_start_complete = false;
|
||||
break;
|
||||
}
|
||||
|
@ -1666,6 +1667,9 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
|
|||
/* Default to no SSC operation. */
|
||||
ihost->oem_parameters.controller.do_enable_ssc = false;
|
||||
|
||||
/* Default to short cables on all phys. */
|
||||
ihost->oem_parameters.controller.cable_selection_mask = 0;
|
||||
|
||||
/* Initialize all of the port parameter information to narrow ports. */
|
||||
for (index = 0; index < SCI_MAX_PORTS; index++) {
|
||||
ihost->oem_parameters.ports[index].phy_mask = 0;
|
||||
|
@ -1673,8 +1677,9 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
|
|||
|
||||
/* Initialize all of the phy parameter information. */
|
||||
for (index = 0; index < SCI_MAX_PHYS; index++) {
|
||||
/* Default to 6G (i.e. Gen 3) for now. */
|
||||
ihost->user_parameters.phys[index].max_speed_generation = 3;
|
||||
/* Default to 3G (i.e. Gen 2). */
|
||||
ihost->user_parameters.phys[index].max_speed_generation =
|
||||
SCIC_SDS_PARM_GEN2_SPEED;
|
||||
|
||||
/* the frequencies cannot be 0 */
|
||||
ihost->user_parameters.phys[index].align_insertion_frequency = 0x7f;
|
||||
|
@ -1694,7 +1699,7 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
|
|||
ihost->user_parameters.ssp_inactivity_timeout = 5;
|
||||
ihost->user_parameters.stp_max_occupancy_timeout = 5;
|
||||
ihost->user_parameters.ssp_max_occupancy_timeout = 20;
|
||||
ihost->user_parameters.no_outbound_task_timeout = 20;
|
||||
ihost->user_parameters.no_outbound_task_timeout = 2;
|
||||
}
|
||||
|
||||
static void controller_timeout(unsigned long data)
|
||||
|
@ -1759,7 +1764,7 @@ static enum sci_status sci_controller_construct(struct isci_host *ihost,
|
|||
return sci_controller_reset(ihost);
|
||||
}
|
||||
|
||||
int sci_oem_parameters_validate(struct sci_oem_params *oem)
|
||||
int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1791,18 +1796,61 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem)
|
|||
oem->controller.max_concurr_spin_up < 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (oem->controller.do_enable_ssc) {
|
||||
if (version < ISCI_ROM_VER_1_1 && oem->controller.do_enable_ssc != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (version >= ISCI_ROM_VER_1_1) {
|
||||
u8 test = oem->controller.ssc_sata_tx_spread_level;
|
||||
|
||||
switch (test) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 3:
|
||||
case 6:
|
||||
case 7:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
test = oem->controller.ssc_sas_tx_spread_level;
|
||||
if (oem->controller.ssc_sas_tx_type == 0) {
|
||||
switch (test) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (oem->controller.ssc_sas_tx_type == 1) {
|
||||
switch (test) {
|
||||
case 0:
|
||||
case 3:
|
||||
case 6:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum sci_status sci_oem_parameters_set(struct isci_host *ihost)
|
||||
{
|
||||
u32 state = ihost->sm.current_state_id;
|
||||
struct isci_pci_info *pci_info = to_pci_info(ihost->pdev);
|
||||
|
||||
if (state == SCIC_RESET ||
|
||||
state == SCIC_INITIALIZING ||
|
||||
state == SCIC_INITIALIZED) {
|
||||
|
||||
if (sci_oem_parameters_validate(&ihost->oem_parameters))
|
||||
if (sci_oem_parameters_validate(&ihost->oem_parameters,
|
||||
pci_info->orom->hdr.version))
|
||||
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
||||
|
||||
return SCI_SUCCESS;
|
||||
|
@ -1857,6 +1905,31 @@ static void power_control_timeout(unsigned long data)
|
|||
ihost->power_control.phys_waiting--;
|
||||
ihost->power_control.phys_granted_power++;
|
||||
sci_phy_consume_power_handler(iphy);
|
||||
|
||||
if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
|
||||
u8 j;
|
||||
|
||||
for (j = 0; j < SCI_MAX_PHYS; j++) {
|
||||
struct isci_phy *requester = ihost->power_control.requesters[j];
|
||||
|
||||
/*
|
||||
* Search the power_control queue to see if there are other phys
|
||||
* attached to the same remote device. If found, take all of
|
||||
* them out of await_sas_power state.
|
||||
*/
|
||||
if (requester != NULL && requester != iphy) {
|
||||
u8 other = memcmp(requester->frame_rcvd.iaf.sas_addr,
|
||||
iphy->frame_rcvd.iaf.sas_addr,
|
||||
sizeof(requester->frame_rcvd.iaf.sas_addr));
|
||||
|
||||
if (other == 0) {
|
||||
ihost->power_control.requesters[j] = NULL;
|
||||
ihost->power_control.phys_waiting--;
|
||||
sci_phy_consume_power_handler(requester);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1891,9 +1964,34 @@ void sci_controller_power_control_queue_insert(struct isci_host *ihost,
|
|||
ihost->power_control.timer_started = true;
|
||||
|
||||
} else {
|
||||
/* Add the phy in the waiting list */
|
||||
ihost->power_control.requesters[iphy->phy_index] = iphy;
|
||||
ihost->power_control.phys_waiting++;
|
||||
/*
|
||||
* There are phys, attached to the same sas address as this phy, are
|
||||
* already in READY state, this phy don't need wait.
|
||||
*/
|
||||
u8 i;
|
||||
struct isci_phy *current_phy;
|
||||
|
||||
for (i = 0; i < SCI_MAX_PHYS; i++) {
|
||||
u8 other;
|
||||
current_phy = &ihost->phys[i];
|
||||
|
||||
other = memcmp(current_phy->frame_rcvd.iaf.sas_addr,
|
||||
iphy->frame_rcvd.iaf.sas_addr,
|
||||
sizeof(current_phy->frame_rcvd.iaf.sas_addr));
|
||||
|
||||
if (current_phy->sm.current_state_id == SCI_PHY_READY &&
|
||||
current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS &&
|
||||
other == 0) {
|
||||
sci_phy_consume_power_handler(iphy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == SCI_MAX_PHYS) {
|
||||
/* Add the phy in the waiting list */
|
||||
ihost->power_control.requesters[iphy->phy_index] = iphy;
|
||||
ihost->power_control.phys_waiting++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1908,162 +2006,250 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost,
|
|||
ihost->power_control.requesters[iphy->phy_index] = NULL;
|
||||
}
|
||||
|
||||
static int is_long_cable(int phy, unsigned char selection_byte)
|
||||
{
|
||||
return !!(selection_byte & (1 << phy));
|
||||
}
|
||||
|
||||
static int is_medium_cable(int phy, unsigned char selection_byte)
|
||||
{
|
||||
return !!(selection_byte & (1 << (phy + 4)));
|
||||
}
|
||||
|
||||
static enum cable_selections decode_selection_byte(
|
||||
int phy,
|
||||
unsigned char selection_byte)
|
||||
{
|
||||
return ((selection_byte & (1 << phy)) ? 1 : 0)
|
||||
+ (selection_byte & (1 << (phy + 4)) ? 2 : 0);
|
||||
}
|
||||
|
||||
static unsigned char *to_cable_select(struct isci_host *ihost)
|
||||
{
|
||||
if (is_cable_select_overridden())
|
||||
return ((unsigned char *)&cable_selection_override)
|
||||
+ ihost->id;
|
||||
else
|
||||
return &ihost->oem_parameters.controller.cable_selection_mask;
|
||||
}
|
||||
|
||||
enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy)
|
||||
{
|
||||
return decode_selection_byte(phy, *to_cable_select(ihost));
|
||||
}
|
||||
|
||||
char *lookup_cable_names(enum cable_selections selection)
|
||||
{
|
||||
static char *cable_names[] = {
|
||||
[short_cable] = "short",
|
||||
[long_cable] = "long",
|
||||
[medium_cable] = "medium",
|
||||
[undefined_cable] = "<undefined, assumed long>" /* bit 0==1 */
|
||||
};
|
||||
return (selection <= undefined_cable) ? cable_names[selection]
|
||||
: cable_names[undefined_cable];
|
||||
}
|
||||
|
||||
#define AFE_REGISTER_WRITE_DELAY 10
|
||||
|
||||
/* Initialize the AFE for this phy index. We need to read the AFE setup from
|
||||
* the OEM parameters
|
||||
*/
|
||||
static void sci_controller_afe_initialization(struct isci_host *ihost)
|
||||
{
|
||||
struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe;
|
||||
const struct sci_oem_params *oem = &ihost->oem_parameters;
|
||||
struct pci_dev *pdev = ihost->pdev;
|
||||
u32 afe_status;
|
||||
u32 phy_id;
|
||||
unsigned char cable_selection_mask = *to_cable_select(ihost);
|
||||
|
||||
/* Clear DFX Status registers */
|
||||
writel(0x0081000f, &ihost->scu_registers->afe.afe_dfx_master_control0);
|
||||
writel(0x0081000f, &afe->afe_dfx_master_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
if (is_b0(pdev)) {
|
||||
if (is_b0(pdev) || is_c0(pdev) || is_c1(pdev)) {
|
||||
/* PM Rx Equalization Save, PM SPhy Rx Acknowledgement
|
||||
* Timer, PM Stagger Timer */
|
||||
writel(0x0007BFFF, &ihost->scu_registers->afe.afe_pmsn_master_control2);
|
||||
* Timer, PM Stagger Timer
|
||||
*/
|
||||
writel(0x0007FFFF, &afe->afe_pmsn_master_control2);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
}
|
||||
|
||||
/* Configure bias currents to normal */
|
||||
if (is_a2(pdev))
|
||||
writel(0x00005A00, &ihost->scu_registers->afe.afe_bias_control);
|
||||
writel(0x00005A00, &afe->afe_bias_control);
|
||||
else if (is_b0(pdev) || is_c0(pdev))
|
||||
writel(0x00005F00, &ihost->scu_registers->afe.afe_bias_control);
|
||||
writel(0x00005F00, &afe->afe_bias_control);
|
||||
else if (is_c1(pdev))
|
||||
writel(0x00005500, &afe->afe_bias_control);
|
||||
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
/* Enable PLL */
|
||||
if (is_b0(pdev) || is_c0(pdev))
|
||||
writel(0x80040A08, &ihost->scu_registers->afe.afe_pll_control0);
|
||||
else
|
||||
writel(0x80040908, &ihost->scu_registers->afe.afe_pll_control0);
|
||||
if (is_a2(pdev))
|
||||
writel(0x80040908, &afe->afe_pll_control0);
|
||||
else if (is_b0(pdev) || is_c0(pdev))
|
||||
writel(0x80040A08, &afe->afe_pll_control0);
|
||||
else if (is_c1(pdev)) {
|
||||
writel(0x80000B08, &afe->afe_pll_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
writel(0x00000B08, &afe->afe_pll_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
writel(0x80000B08, &afe->afe_pll_control0);
|
||||
}
|
||||
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
/* Wait for the PLL to lock */
|
||||
do {
|
||||
afe_status = readl(&ihost->scu_registers->afe.afe_common_block_status);
|
||||
afe_status = readl(&afe->afe_common_block_status);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
} while ((afe_status & 0x00001000) == 0);
|
||||
|
||||
if (is_a2(pdev)) {
|
||||
/* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */
|
||||
writel(0x7bcc96ad, &ihost->scu_registers->afe.afe_pmsn_master_control0);
|
||||
/* Shorten SAS SNW lock time (RxLock timer value from 76
|
||||
* us to 50 us)
|
||||
*/
|
||||
writel(0x7bcc96ad, &afe->afe_pmsn_master_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
}
|
||||
|
||||
for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {
|
||||
struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_id];
|
||||
const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];
|
||||
int cable_length_long =
|
||||
is_long_cable(phy_id, cable_selection_mask);
|
||||
int cable_length_medium =
|
||||
is_medium_cable(phy_id, cable_selection_mask);
|
||||
|
||||
if (is_b0(pdev)) {
|
||||
/* Configure transmitter SSC parameters */
|
||||
writel(0x00030000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
|
||||
if (is_a2(pdev)) {
|
||||
/* All defaults, except the Receive Word
|
||||
* Alignament/Comma Detect Enable....(0xe800)
|
||||
*/
|
||||
writel(0x00004512, &xcvr->afe_xcvr_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(0x0050100F, &xcvr->afe_xcvr_control1);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
} else if (is_b0(pdev)) {
|
||||
/* Configure transmitter SSC parameters */
|
||||
writel(0x00030000, &xcvr->afe_tx_ssc_control);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
} else if (is_c0(pdev)) {
|
||||
/* Configure transmitter SSC parameters */
|
||||
writel(0x0003000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
|
||||
/* Configure transmitter SSC parameters */
|
||||
writel(0x00010202, &xcvr->afe_tx_ssc_control);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
/*
|
||||
* All defaults, except the Receive Word Alignament/Comma Detect
|
||||
* Enable....(0xe800) */
|
||||
writel(0x00004500, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
|
||||
/* All defaults, except the Receive Word
|
||||
* Alignament/Comma Detect Enable....(0xe800)
|
||||
*/
|
||||
writel(0x00014500, &xcvr->afe_xcvr_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
} else {
|
||||
/*
|
||||
* All defaults, except the Receive Word Alignament/Comma Detect
|
||||
* Enable....(0xe800) */
|
||||
writel(0x00004512, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
|
||||
} else if (is_c1(pdev)) {
|
||||
/* Configure transmitter SSC parameters */
|
||||
writel(0x00010202, &xcvr->afe_tx_ssc_control);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(0x0050100F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1);
|
||||
/* All defaults, except the Receive Word
|
||||
* Alignament/Comma Detect Enable....(0xe800)
|
||||
*/
|
||||
writel(0x0001C500, &xcvr->afe_xcvr_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
|
||||
* & increase TX int & ext bias 20%....(0xe85c) */
|
||||
/* Power up TX and RX out from power down (PWRDNTX and
|
||||
* PWRDNRX) & increase TX int & ext bias 20%....(0xe85c)
|
||||
*/
|
||||
if (is_a2(pdev))
|
||||
writel(0x000003F0, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
||||
writel(0x000003F0, &xcvr->afe_channel_control);
|
||||
else if (is_b0(pdev)) {
|
||||
/* Power down TX and RX (PWRDNTX and PWRDNRX) */
|
||||
writel(0x000003D7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
||||
writel(0x000003D7, &xcvr->afe_channel_control);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
/*
|
||||
* Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
|
||||
* & increase TX int & ext bias 20%....(0xe85c) */
|
||||
writel(0x000003D4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
||||
} else {
|
||||
writel(0x000001E7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
||||
writel(0x000003D4, &xcvr->afe_channel_control);
|
||||
} else if (is_c0(pdev)) {
|
||||
writel(0x000001E7, &xcvr->afe_channel_control);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
/*
|
||||
* Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
|
||||
* & increase TX int & ext bias 20%....(0xe85c) */
|
||||
writel(0x000001E4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
||||
writel(0x000001E4, &xcvr->afe_channel_control);
|
||||
} else if (is_c1(pdev)) {
|
||||
writel(cable_length_long ? 0x000002F7 : 0x000001F7,
|
||||
&xcvr->afe_channel_control);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(cable_length_long ? 0x000002F4 : 0x000001F4,
|
||||
&xcvr->afe_channel_control);
|
||||
}
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
if (is_a2(pdev)) {
|
||||
/* Enable TX equalization (0xe824) */
|
||||
writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
|
||||
writel(0x00040000, &xcvr->afe_tx_control);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
}
|
||||
|
||||
/*
|
||||
* RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
|
||||
* RDD=0x0(RX Detect Enabled) ....(0xe800) */
|
||||
writel(0x00004100, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
|
||||
if (is_a2(pdev) || is_b0(pdev))
|
||||
/* RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0,
|
||||
* TPD=0x0(TX Power On), RDD=0x0(RX Detect
|
||||
* Enabled) ....(0xe800)
|
||||
*/
|
||||
writel(0x00004100, &xcvr->afe_xcvr_control0);
|
||||
else if (is_c0(pdev))
|
||||
writel(0x00014100, &xcvr->afe_xcvr_control0);
|
||||
else if (is_c1(pdev))
|
||||
writel(0x0001C100, &xcvr->afe_xcvr_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
/* Leave DFE/FFE on */
|
||||
if (is_a2(pdev))
|
||||
writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
|
||||
writel(0x3F11103F, &xcvr->afe_rx_ssc_control0);
|
||||
else if (is_b0(pdev)) {
|
||||
writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
|
||||
writel(0x3F11103F, &xcvr->afe_rx_ssc_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
/* Enable TX equalization (0xe824) */
|
||||
writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
|
||||
} else {
|
||||
writel(0x0140DF0F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control1);
|
||||
writel(0x00040000, &xcvr->afe_tx_control);
|
||||
} else if (is_c0(pdev)) {
|
||||
writel(0x01400C0F, &xcvr->afe_rx_ssc_control1);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(0x3F6F103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
|
||||
writel(0x3F6F103F, &xcvr->afe_rx_ssc_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
/* Enable TX equalization (0xe824) */
|
||||
writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
|
||||
writel(0x00040000, &xcvr->afe_tx_control);
|
||||
} else if (is_c1(pdev)) {
|
||||
writel(cable_length_long ? 0x01500C0C :
|
||||
cable_length_medium ? 0x01400C0D : 0x02400C0D,
|
||||
&xcvr->afe_xcvr_control1);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(0x000003E0, &xcvr->afe_dfx_rx_control1);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(cable_length_long ? 0x33091C1F :
|
||||
cable_length_medium ? 0x3315181F : 0x2B17161F,
|
||||
&xcvr->afe_rx_ssc_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
/* Enable TX equalization (0xe824) */
|
||||
writel(0x00040000, &xcvr->afe_tx_control);
|
||||
}
|
||||
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(oem_phy->afe_tx_amp_control0,
|
||||
&ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0);
|
||||
writel(oem_phy->afe_tx_amp_control0, &xcvr->afe_tx_amp_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(oem_phy->afe_tx_amp_control1,
|
||||
&ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1);
|
||||
writel(oem_phy->afe_tx_amp_control1, &xcvr->afe_tx_amp_control1);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(oem_phy->afe_tx_amp_control2,
|
||||
&ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2);
|
||||
writel(oem_phy->afe_tx_amp_control2, &xcvr->afe_tx_amp_control2);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
|
||||
writel(oem_phy->afe_tx_amp_control3,
|
||||
&ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3);
|
||||
writel(oem_phy->afe_tx_amp_control3, &xcvr->afe_tx_amp_control3);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
}
|
||||
|
||||
/* Transfer control to the PEs */
|
||||
writel(0x00010f00, &ihost->scu_registers->afe.afe_dfx_master_control0);
|
||||
writel(0x00010f00, &afe->afe_dfx_master_control0);
|
||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||
}
|
||||
|
||||
|
|
|
@ -435,11 +435,36 @@ static inline bool is_b0(struct pci_dev *pdev)
|
|||
|
||||
static inline bool is_c0(struct pci_dev *pdev)
|
||||
{
|
||||
if (pdev->revision >= 5)
|
||||
if (pdev->revision == 5)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool is_c1(struct pci_dev *pdev)
|
||||
{
|
||||
if (pdev->revision >= 6)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
enum cable_selections {
|
||||
short_cable = 0,
|
||||
long_cable = 1,
|
||||
medium_cable = 2,
|
||||
undefined_cable = 3
|
||||
};
|
||||
|
||||
#define CABLE_OVERRIDE_DISABLED (0x10000)
|
||||
|
||||
static inline int is_cable_select_overridden(void)
|
||||
{
|
||||
return cable_selection_override < CABLE_OVERRIDE_DISABLED;
|
||||
}
|
||||
|
||||
enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy);
|
||||
void validate_cable_selections(struct isci_host *ihost);
|
||||
char *lookup_cable_names(enum cable_selections);
|
||||
|
||||
/* set hw control for 'activity', even though active enclosures seem to drive
|
||||
* the activity led on their own. Skip setting FSENG control on 'status' due
|
||||
* to unexpected operation and 'error' due to not being a supported automatic
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
#include "probe_roms.h"
|
||||
|
||||
#define MAJ 1
|
||||
#define MIN 0
|
||||
#define MIN 1
|
||||
#define BUILD 0
|
||||
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
|
||||
__stringify(BUILD)
|
||||
|
@ -94,7 +94,7 @@ MODULE_DEVICE_TABLE(pci, isci_id_table);
|
|||
|
||||
/* linux isci specific settings */
|
||||
|
||||
unsigned char no_outbound_task_to = 20;
|
||||
unsigned char no_outbound_task_to = 2;
|
||||
module_param(no_outbound_task_to, byte, 0);
|
||||
MODULE_PARM_DESC(no_outbound_task_to, "No Outbound Task Timeout (1us incr)");
|
||||
|
||||
|
@ -114,7 +114,7 @@ u16 stp_inactive_to = 5;
|
|||
module_param(stp_inactive_to, ushort, 0);
|
||||
MODULE_PARM_DESC(stp_inactive_to, "STP inactivity timeout (100us incr)");
|
||||
|
||||
unsigned char phy_gen = 3;
|
||||
unsigned char phy_gen = SCIC_SDS_PARM_GEN2_SPEED;
|
||||
module_param(phy_gen, byte, 0);
|
||||
MODULE_PARM_DESC(phy_gen, "PHY generation (1: 1.5Gbps 2: 3.0Gbps 3: 6.0Gbps)");
|
||||
|
||||
|
@ -122,6 +122,14 @@ unsigned char max_concurr_spinup;
|
|||
module_param(max_concurr_spinup, byte, 0);
|
||||
MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup");
|
||||
|
||||
uint cable_selection_override = CABLE_OVERRIDE_DISABLED;
|
||||
module_param(cable_selection_override, uint, 0);
|
||||
|
||||
MODULE_PARM_DESC(cable_selection_override,
|
||||
"This field indicates length of the SAS/SATA cable between "
|
||||
"host and device. If any bits > 15 are set (default) "
|
||||
"indicates \"use platform defaults\"");
|
||||
|
||||
static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev);
|
||||
|
@ -412,6 +420,14 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
|
|||
return NULL;
|
||||
isci_host->shost = shost;
|
||||
|
||||
dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: "
|
||||
"{%s, %s, %s, %s}\n",
|
||||
(is_cable_select_overridden() ? "* " : ""), isci_host->id,
|
||||
lookup_cable_names(decode_cable_selection(isci_host, 3)),
|
||||
lookup_cable_names(decode_cable_selection(isci_host, 2)),
|
||||
lookup_cable_names(decode_cable_selection(isci_host, 1)),
|
||||
lookup_cable_names(decode_cable_selection(isci_host, 0)));
|
||||
|
||||
err = isci_host_init(isci_host);
|
||||
if (err)
|
||||
goto err_shost;
|
||||
|
@ -466,7 +482,8 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
|
|||
orom = isci_request_oprom(pdev);
|
||||
|
||||
for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
|
||||
if (sci_oem_parameters_validate(&orom->ctrl[i])) {
|
||||
if (sci_oem_parameters_validate(&orom->ctrl[i],
|
||||
orom->hdr.version)) {
|
||||
dev_warn(&pdev->dev,
|
||||
"[%d]: invalid oem parameters detected, falling back to firmware\n", i);
|
||||
devm_kfree(&pdev->dev, orom);
|
||||
|
|
|
@ -480,6 +480,7 @@ extern u16 ssp_inactive_to;
|
|||
extern u16 stp_inactive_to;
|
||||
extern unsigned char phy_gen;
|
||||
extern unsigned char max_concurr_spinup;
|
||||
extern uint cable_selection_override;
|
||||
|
||||
irqreturn_t isci_msix_isr(int vec, void *data);
|
||||
irqreturn_t isci_intx_isr(int vec, void *data);
|
||||
|
|
|
@ -91,22 +91,23 @@ sci_phy_transport_layer_initialization(struct isci_phy *iphy,
|
|||
|
||||
static enum sci_status
|
||||
sci_phy_link_layer_initialization(struct isci_phy *iphy,
|
||||
struct scu_link_layer_registers __iomem *reg)
|
||||
struct scu_link_layer_registers __iomem *llr)
|
||||
{
|
||||
struct isci_host *ihost = iphy->owning_port->owning_controller;
|
||||
struct sci_phy_user_params *phy_user;
|
||||
struct sci_phy_oem_params *phy_oem;
|
||||
int phy_idx = iphy->phy_index;
|
||||
struct sci_phy_user_params *phy_user = &ihost->user_parameters.phys[phy_idx];
|
||||
struct sci_phy_oem_params *phy_oem =
|
||||
&ihost->oem_parameters.phys[phy_idx];
|
||||
u32 phy_configuration;
|
||||
struct sci_phy_cap phy_cap;
|
||||
u32 phy_configuration;
|
||||
u32 parity_check = 0;
|
||||
u32 parity_count = 0;
|
||||
u32 llctl, link_rate;
|
||||
u32 clksm_value = 0;
|
||||
u32 sp_timeouts = 0;
|
||||
|
||||
iphy->link_layer_registers = reg;
|
||||
phy_user = &ihost->user_parameters.phys[phy_idx];
|
||||
phy_oem = &ihost->oem_parameters.phys[phy_idx];
|
||||
iphy->link_layer_registers = llr;
|
||||
|
||||
/* Set our IDENTIFY frame data */
|
||||
#define SCI_END_DEVICE 0x01
|
||||
|
@ -116,32 +117,26 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
|
|||
SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) |
|
||||
SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) |
|
||||
SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE),
|
||||
&iphy->link_layer_registers->transmit_identification);
|
||||
&llr->transmit_identification);
|
||||
|
||||
/* Write the device SAS Address */
|
||||
writel(0xFEDCBA98,
|
||||
&iphy->link_layer_registers->sas_device_name_high);
|
||||
writel(phy_idx, &iphy->link_layer_registers->sas_device_name_low);
|
||||
writel(0xFEDCBA98, &llr->sas_device_name_high);
|
||||
writel(phy_idx, &llr->sas_device_name_low);
|
||||
|
||||
/* Write the source SAS Address */
|
||||
writel(phy_oem->sas_address.high,
|
||||
&iphy->link_layer_registers->source_sas_address_high);
|
||||
writel(phy_oem->sas_address.low,
|
||||
&iphy->link_layer_registers->source_sas_address_low);
|
||||
writel(phy_oem->sas_address.high, &llr->source_sas_address_high);
|
||||
writel(phy_oem->sas_address.low, &llr->source_sas_address_low);
|
||||
|
||||
/* Clear and Set the PHY Identifier */
|
||||
writel(0, &iphy->link_layer_registers->identify_frame_phy_id);
|
||||
writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx),
|
||||
&iphy->link_layer_registers->identify_frame_phy_id);
|
||||
writel(0, &llr->identify_frame_phy_id);
|
||||
writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), &llr->identify_frame_phy_id);
|
||||
|
||||
/* Change the initial state of the phy configuration register */
|
||||
phy_configuration =
|
||||
readl(&iphy->link_layer_registers->phy_configuration);
|
||||
phy_configuration = readl(&llr->phy_configuration);
|
||||
|
||||
/* Hold OOB state machine in reset */
|
||||
phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
|
||||
writel(phy_configuration,
|
||||
&iphy->link_layer_registers->phy_configuration);
|
||||
writel(phy_configuration, &llr->phy_configuration);
|
||||
|
||||
/* Configure the SNW capabilities */
|
||||
phy_cap.all = 0;
|
||||
|
@ -149,15 +144,64 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
|
|||
phy_cap.gen3_no_ssc = 1;
|
||||
phy_cap.gen2_no_ssc = 1;
|
||||
phy_cap.gen1_no_ssc = 1;
|
||||
if (ihost->oem_parameters.controller.do_enable_ssc == true) {
|
||||
if (ihost->oem_parameters.controller.do_enable_ssc) {
|
||||
struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe;
|
||||
struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_idx];
|
||||
struct isci_pci_info *pci_info = to_pci_info(ihost->pdev);
|
||||
bool en_sas = false;
|
||||
bool en_sata = false;
|
||||
u32 sas_type = 0;
|
||||
u32 sata_spread = 0x2;
|
||||
u32 sas_spread = 0x2;
|
||||
|
||||
phy_cap.gen3_ssc = 1;
|
||||
phy_cap.gen2_ssc = 1;
|
||||
phy_cap.gen1_ssc = 1;
|
||||
|
||||
if (pci_info->orom->hdr.version < ISCI_ROM_VER_1_1)
|
||||
en_sas = en_sata = true;
|
||||
else {
|
||||
sata_spread = ihost->oem_parameters.controller.ssc_sata_tx_spread_level;
|
||||
sas_spread = ihost->oem_parameters.controller.ssc_sas_tx_spread_level;
|
||||
|
||||
if (sata_spread)
|
||||
en_sata = true;
|
||||
|
||||
if (sas_spread) {
|
||||
en_sas = true;
|
||||
sas_type = ihost->oem_parameters.controller.ssc_sas_tx_type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (en_sas) {
|
||||
u32 reg;
|
||||
|
||||
reg = readl(&xcvr->afe_xcvr_control0);
|
||||
reg |= (0x00100000 | (sas_type << 19));
|
||||
writel(reg, &xcvr->afe_xcvr_control0);
|
||||
|
||||
reg = readl(&xcvr->afe_tx_ssc_control);
|
||||
reg |= sas_spread << 8;
|
||||
writel(reg, &xcvr->afe_tx_ssc_control);
|
||||
}
|
||||
|
||||
if (en_sata) {
|
||||
u32 reg;
|
||||
|
||||
reg = readl(&xcvr->afe_tx_ssc_control);
|
||||
reg |= sata_spread;
|
||||
writel(reg, &xcvr->afe_tx_ssc_control);
|
||||
|
||||
reg = readl(&llr->stp_control);
|
||||
reg |= 1 << 12;
|
||||
writel(reg, &llr->stp_control);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The SAS specification indicates that the phy_capabilities that
|
||||
* are transmitted shall have an even parity. Calculate the parity. */
|
||||
/* The SAS specification indicates that the phy_capabilities that
|
||||
* are transmitted shall have an even parity. Calculate the parity.
|
||||
*/
|
||||
parity_check = phy_cap.all;
|
||||
while (parity_check != 0) {
|
||||
if (parity_check & 0x1)
|
||||
|
@ -165,20 +209,20 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
|
|||
parity_check >>= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If parity indicates there are an odd number of bits set, then
|
||||
* set the parity bit to 1 in the phy capabilities. */
|
||||
/* If parity indicates there are an odd number of bits set, then
|
||||
* set the parity bit to 1 in the phy capabilities.
|
||||
*/
|
||||
if ((parity_count % 2) != 0)
|
||||
phy_cap.parity = 1;
|
||||
|
||||
writel(phy_cap.all, &iphy->link_layer_registers->phy_capabilities);
|
||||
writel(phy_cap.all, &llr->phy_capabilities);
|
||||
|
||||
/* Set the enable spinup period but disable the ability to send
|
||||
* notify enable spinup
|
||||
*/
|
||||
writel(SCU_ENSPINUP_GEN_VAL(COUNT,
|
||||
phy_user->notify_enable_spin_up_insertion_frequency),
|
||||
&iphy->link_layer_registers->notify_enable_spinup_control);
|
||||
&llr->notify_enable_spinup_control);
|
||||
|
||||
/* Write the ALIGN Insertion Ferequency for connected phy and
|
||||
* inpendent of connected state
|
||||
|
@ -189,11 +233,13 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
|
|||
clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL,
|
||||
phy_user->align_insertion_frequency);
|
||||
|
||||
writel(clksm_value, &iphy->link_layer_registers->clock_skew_management);
|
||||
writel(clksm_value, &llr->clock_skew_management);
|
||||
|
||||
/* @todo Provide a way to write this register correctly */
|
||||
writel(0x02108421,
|
||||
&iphy->link_layer_registers->afe_lookup_table_control);
|
||||
if (is_c0(ihost->pdev) || is_c1(ihost->pdev)) {
|
||||
writel(0x04210400, &llr->afe_lookup_table_control);
|
||||
writel(0x020A7C05, &llr->sas_primitive_timeout);
|
||||
} else
|
||||
writel(0x02108421, &llr->afe_lookup_table_control);
|
||||
|
||||
llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT,
|
||||
(u8)ihost->user_parameters.no_outbound_task_timeout);
|
||||
|
@ -210,9 +256,9 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
|
|||
break;
|
||||
}
|
||||
llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate);
|
||||
writel(llctl, &iphy->link_layer_registers->link_layer_control);
|
||||
writel(llctl, &llr->link_layer_control);
|
||||
|
||||
sp_timeouts = readl(&iphy->link_layer_registers->sas_phy_timeouts);
|
||||
sp_timeouts = readl(&llr->sas_phy_timeouts);
|
||||
|
||||
/* Clear the default 0x36 (54us) RATE_CHANGE timeout value. */
|
||||
sp_timeouts &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF);
|
||||
|
@ -222,20 +268,23 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
|
|||
*/
|
||||
sp_timeouts |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B);
|
||||
|
||||
writel(sp_timeouts, &iphy->link_layer_registers->sas_phy_timeouts);
|
||||
writel(sp_timeouts, &llr->sas_phy_timeouts);
|
||||
|
||||
if (is_a2(ihost->pdev)) {
|
||||
/* Program the max ARB time for the PHY to 700us so we inter-operate with
|
||||
* the PMC expander which shuts down PHYs if the expander PHY generates too
|
||||
* many breaks. This time value will guarantee that the initiator PHY will
|
||||
* generate the break.
|
||||
/* Program the max ARB time for the PHY to 700us so we
|
||||
* inter-operate with the PMC expander which shuts down
|
||||
* PHYs if the expander PHY generates too many breaks.
|
||||
* This time value will guarantee that the initiator PHY
|
||||
* will generate the break.
|
||||
*/
|
||||
writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME,
|
||||
&iphy->link_layer_registers->maximum_arbitration_wait_timer_timeout);
|
||||
&llr->maximum_arbitration_wait_timer_timeout);
|
||||
}
|
||||
|
||||
/* Disable link layer hang detection, rely on the OS timeout for I/O timeouts. */
|
||||
writel(0, &iphy->link_layer_registers->link_layer_hang_detection_timeout);
|
||||
/* Disable link layer hang detection, rely on the OS timeout for
|
||||
* I/O timeouts.
|
||||
*/
|
||||
writel(0, &llr->link_layer_hang_detection_timeout);
|
||||
|
||||
/* We can exit the initial state to the stopped state */
|
||||
sci_change_state(&iphy->sm, SCI_PHY_STOPPED);
|
||||
|
@ -1049,24 +1098,25 @@ static void scu_link_layer_stop_protocol_engine(
|
|||
writel(enable_spinup_value, &iphy->link_layer_registers->notify_enable_spinup_control);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This method will start the OOB/SN state machine for this struct isci_phy object.
|
||||
*/
|
||||
static void scu_link_layer_start_oob(
|
||||
struct isci_phy *iphy)
|
||||
static void scu_link_layer_start_oob(struct isci_phy *iphy)
|
||||
{
|
||||
u32 scu_sas_pcfg_value;
|
||||
struct scu_link_layer_registers __iomem *ll = iphy->link_layer_registers;
|
||||
u32 val;
|
||||
|
||||
scu_sas_pcfg_value =
|
||||
readl(&iphy->link_layer_registers->phy_configuration);
|
||||
scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
|
||||
scu_sas_pcfg_value &=
|
||||
~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |
|
||||
SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
|
||||
writel(scu_sas_pcfg_value,
|
||||
&iphy->link_layer_registers->phy_configuration);
|
||||
/** Reset OOB sequence - start */
|
||||
val = readl(&ll->phy_configuration);
|
||||
val &= ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |
|
||||
SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
|
||||
writel(val, &ll->phy_configuration);
|
||||
readl(&ll->phy_configuration); /* flush */
|
||||
/** Reset OOB sequence - end */
|
||||
|
||||
/** Start OOB sequence - start */
|
||||
val = readl(&ll->phy_configuration);
|
||||
val |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
|
||||
writel(val, &ll->phy_configuration);
|
||||
readl(&ll->phy_configuration); /* flush */
|
||||
/** Start OOB sequence - end */
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -114,7 +114,7 @@ static u32 sci_port_get_phys(struct isci_port *iport)
|
|||
* value is returned if the specified port is not valid. When this value is
|
||||
* returned, no data is copied to the properties output parameter.
|
||||
*/
|
||||
static enum sci_status sci_port_get_properties(struct isci_port *iport,
|
||||
enum sci_status sci_port_get_properties(struct isci_port *iport,
|
||||
struct sci_port_properties *prop)
|
||||
{
|
||||
if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT)
|
||||
|
@ -647,19 +647,26 @@ void sci_port_setup_transports(struct isci_port *iport, u32 device_id)
|
|||
}
|
||||
}
|
||||
|
||||
static void sci_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy,
|
||||
bool do_notify_user)
|
||||
static void sci_port_resume_phy(struct isci_port *iport, struct isci_phy *iphy)
|
||||
{
|
||||
sci_phy_resume(iphy);
|
||||
iport->enabled_phy_mask |= 1 << iphy->phy_index;
|
||||
}
|
||||
|
||||
static void sci_port_activate_phy(struct isci_port *iport,
|
||||
struct isci_phy *iphy,
|
||||
u8 flags)
|
||||
{
|
||||
struct isci_host *ihost = iport->owning_controller;
|
||||
|
||||
if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA)
|
||||
if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA && (flags & PF_RESUME))
|
||||
sci_phy_resume(iphy);
|
||||
|
||||
iport->active_phy_mask |= 1 << iphy->phy_index;
|
||||
|
||||
sci_controller_clear_invalid_phy(ihost, iphy);
|
||||
|
||||
if (do_notify_user == true)
|
||||
if (flags & PF_NOTIFY)
|
||||
isci_port_link_up(ihost, iport, iphy);
|
||||
}
|
||||
|
||||
|
@ -669,14 +676,19 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
|
|||
struct isci_host *ihost = iport->owning_controller;
|
||||
|
||||
iport->active_phy_mask &= ~(1 << iphy->phy_index);
|
||||
iport->enabled_phy_mask &= ~(1 << iphy->phy_index);
|
||||
if (!iport->active_phy_mask)
|
||||
iport->last_active_phy = iphy->phy_index;
|
||||
|
||||
iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
|
||||
|
||||
/* Re-assign the phy back to the LP as if it were a narrow port */
|
||||
writel(iphy->phy_index,
|
||||
&iport->port_pe_configuration_register[iphy->phy_index]);
|
||||
/* Re-assign the phy back to the LP as if it were a narrow port for APC
|
||||
* mode. For MPC mode, the phy will remain in the port.
|
||||
*/
|
||||
if (iport->owning_controller->oem_parameters.controller.mode_type ==
|
||||
SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
|
||||
writel(iphy->phy_index,
|
||||
&iport->port_pe_configuration_register[iphy->phy_index]);
|
||||
|
||||
if (do_notify_user == true)
|
||||
isci_port_link_down(ihost, iphy, iport);
|
||||
|
@ -701,18 +713,16 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i
|
|||
* sci_port_general_link_up_handler - phy can be assigned to port?
|
||||
* @sci_port: sci_port object for which has a phy that has gone link up.
|
||||
* @sci_phy: This is the struct isci_phy object that has gone link up.
|
||||
* @do_notify_user: This parameter specifies whether to inform the user (via
|
||||
* sci_port_link_up()) as to the fact that a new phy as become ready.
|
||||
* @flags: PF_RESUME, PF_NOTIFY to sci_port_activate_phy
|
||||
*
|
||||
* Determine if this phy can be assigned to this
|
||||
* port . If the phy is not a valid PHY for
|
||||
* this port then the function will notify the user. A PHY can only be
|
||||
* part of a port if it's attached SAS ADDRESS is the same as all other PHYs in
|
||||
* the same port. none
|
||||
* Determine if this phy can be assigned to this port . If the phy is
|
||||
* not a valid PHY for this port then the function will notify the user.
|
||||
* A PHY can only be part of a port if it's attached SAS ADDRESS is the
|
||||
* same as all other PHYs in the same port.
|
||||
*/
|
||||
static void sci_port_general_link_up_handler(struct isci_port *iport,
|
||||
struct isci_phy *iphy,
|
||||
bool do_notify_user)
|
||||
struct isci_phy *iphy,
|
||||
u8 flags)
|
||||
{
|
||||
struct sci_sas_address port_sas_address;
|
||||
struct sci_sas_address phy_sas_address;
|
||||
|
@ -730,7 +740,7 @@ static void sci_port_general_link_up_handler(struct isci_port *iport,
|
|||
iport->active_phy_mask == 0) {
|
||||
struct sci_base_state_machine *sm = &iport->sm;
|
||||
|
||||
sci_port_activate_phy(iport, iphy, do_notify_user);
|
||||
sci_port_activate_phy(iport, iphy, flags);
|
||||
if (sm->current_state_id == SCI_PORT_RESETTING)
|
||||
port_state_machine_change(iport, SCI_PORT_READY);
|
||||
} else
|
||||
|
@ -781,11 +791,16 @@ bool sci_port_link_detected(
|
|||
struct isci_phy *iphy)
|
||||
{
|
||||
if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) &&
|
||||
(iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) &&
|
||||
sci_port_is_wide(iport)) {
|
||||
sci_port_invalid_link_up(iport, iphy);
|
||||
|
||||
return false;
|
||||
(iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)) {
|
||||
if (sci_port_is_wide(iport)) {
|
||||
sci_port_invalid_link_up(iport, iphy);
|
||||
return false;
|
||||
} else {
|
||||
struct isci_host *ihost = iport->owning_controller;
|
||||
struct isci_port *dst_port = &(ihost->ports[iphy->phy_index]);
|
||||
writel(iphy->phy_index,
|
||||
&dst_port->port_pe_configuration_register[iphy->phy_index]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -975,6 +990,13 @@ static void sci_port_ready_substate_waiting_enter(struct sci_base_state_machine
|
|||
}
|
||||
}
|
||||
|
||||
static void scic_sds_port_ready_substate_waiting_exit(
|
||||
struct sci_base_state_machine *sm)
|
||||
{
|
||||
struct isci_port *iport = container_of(sm, typeof(*iport), sm);
|
||||
sci_port_resume_port_task_scheduler(iport);
|
||||
}
|
||||
|
||||
static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm)
|
||||
{
|
||||
u32 index;
|
||||
|
@ -988,13 +1010,13 @@ static void sci_port_ready_substate_operational_enter(struct sci_base_state_mach
|
|||
writel(iport->physical_port_index,
|
||||
&iport->port_pe_configuration_register[
|
||||
iport->phy_table[index]->phy_index]);
|
||||
if (((iport->active_phy_mask^iport->enabled_phy_mask) & (1 << index)) != 0)
|
||||
sci_port_resume_phy(iport, iport->phy_table[index]);
|
||||
}
|
||||
}
|
||||
|
||||
sci_port_update_viit_entry(iport);
|
||||
|
||||
sci_port_resume_port_task_scheduler(iport);
|
||||
|
||||
/*
|
||||
* Post the dummy task for the port so the hardware can schedule
|
||||
* io correctly
|
||||
|
@ -1061,20 +1083,9 @@ static void sci_port_ready_substate_configuring_enter(struct sci_base_state_mach
|
|||
if (iport->active_phy_mask == 0) {
|
||||
isci_port_not_ready(ihost, iport);
|
||||
|
||||
port_state_machine_change(iport,
|
||||
SCI_PORT_SUB_WAITING);
|
||||
} else if (iport->started_request_count == 0)
|
||||
port_state_machine_change(iport,
|
||||
SCI_PORT_SUB_OPERATIONAL);
|
||||
}
|
||||
|
||||
static void sci_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm)
|
||||
{
|
||||
struct isci_port *iport = container_of(sm, typeof(*iport), sm);
|
||||
|
||||
sci_port_suspend_port_task_scheduler(iport);
|
||||
if (iport->ready_exit)
|
||||
sci_port_invalidate_dummy_remote_node(iport);
|
||||
port_state_machine_change(iport, SCI_PORT_SUB_WAITING);
|
||||
} else
|
||||
port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL);
|
||||
}
|
||||
|
||||
enum sci_status sci_port_start(struct isci_port *iport)
|
||||
|
@ -1252,7 +1263,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport,
|
|||
if (status != SCI_SUCCESS)
|
||||
return status;
|
||||
|
||||
sci_port_general_link_up_handler(iport, iphy, true);
|
||||
sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
|
||||
iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
|
||||
port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING);
|
||||
|
||||
|
@ -1262,7 +1273,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport,
|
|||
|
||||
if (status != SCI_SUCCESS)
|
||||
return status;
|
||||
sci_port_general_link_up_handler(iport, iphy, true);
|
||||
sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY);
|
||||
|
||||
/* Re-enter the configuring state since this may be the last phy in
|
||||
* the port.
|
||||
|
@ -1338,13 +1349,13 @@ enum sci_status sci_port_link_up(struct isci_port *iport,
|
|||
/* Since this is the first phy going link up for the port we
|
||||
* can just enable it and continue
|
||||
*/
|
||||
sci_port_activate_phy(iport, iphy, true);
|
||||
sci_port_activate_phy(iport, iphy, PF_NOTIFY|PF_RESUME);
|
||||
|
||||
port_state_machine_change(iport,
|
||||
SCI_PORT_SUB_OPERATIONAL);
|
||||
return SCI_SUCCESS;
|
||||
case SCI_PORT_SUB_OPERATIONAL:
|
||||
sci_port_general_link_up_handler(iport, iphy, true);
|
||||
sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
|
||||
return SCI_SUCCESS;
|
||||
case SCI_PORT_RESETTING:
|
||||
/* TODO We should make sure that the phy that has gone
|
||||
|
@ -1361,7 +1372,7 @@ enum sci_status sci_port_link_up(struct isci_port *iport,
|
|||
/* In the resetting state we don't notify the user regarding
|
||||
* link up and link down notifications.
|
||||
*/
|
||||
sci_port_general_link_up_handler(iport, iphy, false);
|
||||
sci_port_general_link_up_handler(iport, iphy, PF_RESUME);
|
||||
return SCI_SUCCESS;
|
||||
default:
|
||||
dev_warn(sciport_to_dev(iport),
|
||||
|
@ -1584,14 +1595,14 @@ static const struct sci_base_state sci_port_state_table[] = {
|
|||
},
|
||||
[SCI_PORT_SUB_WAITING] = {
|
||||
.enter_state = sci_port_ready_substate_waiting_enter,
|
||||
.exit_state = scic_sds_port_ready_substate_waiting_exit,
|
||||
},
|
||||
[SCI_PORT_SUB_OPERATIONAL] = {
|
||||
.enter_state = sci_port_ready_substate_operational_enter,
|
||||
.exit_state = sci_port_ready_substate_operational_exit
|
||||
},
|
||||
[SCI_PORT_SUB_CONFIGURING] = {
|
||||
.enter_state = sci_port_ready_substate_configuring_enter,
|
||||
.exit_state = sci_port_ready_substate_configuring_exit
|
||||
.enter_state = sci_port_ready_substate_configuring_enter
|
||||
},
|
||||
[SCI_PORT_RESETTING] = {
|
||||
.exit_state = sci_port_resetting_state_exit
|
||||
|
@ -1609,6 +1620,7 @@ void sci_port_construct(struct isci_port *iport, u8 index,
|
|||
iport->logical_port_index = SCIC_SDS_DUMMY_PORT;
|
||||
iport->physical_port_index = index;
|
||||
iport->active_phy_mask = 0;
|
||||
iport->enabled_phy_mask = 0;
|
||||
iport->last_active_phy = 0;
|
||||
iport->ready_exit = false;
|
||||
|
||||
|
|
|
@ -63,6 +63,9 @@
|
|||
|
||||
#define SCIC_SDS_DUMMY_PORT 0xFF
|
||||
|
||||
#define PF_NOTIFY (1 << 0)
|
||||
#define PF_RESUME (1 << 1)
|
||||
|
||||
struct isci_phy;
|
||||
struct isci_host;
|
||||
|
||||
|
@ -83,6 +86,8 @@ enum isci_status {
|
|||
* @logical_port_index: software port index
|
||||
* @physical_port_index: hardware port index
|
||||
* @active_phy_mask: identifies phy members
|
||||
* @enabled_phy_mask: phy mask for the port
|
||||
* that are already part of the port
|
||||
* @reserved_tag:
|
||||
* @reserved_rni: reserver for port task scheduler workaround
|
||||
* @started_request_count: reference count for outstanding commands
|
||||
|
@ -104,6 +109,7 @@ struct isci_port {
|
|||
u8 logical_port_index;
|
||||
u8 physical_port_index;
|
||||
u8 active_phy_mask;
|
||||
u8 enabled_phy_mask;
|
||||
u8 last_active_phy;
|
||||
u16 reserved_rni;
|
||||
u16 reserved_tag;
|
||||
|
@ -250,6 +256,10 @@ bool sci_port_link_detected(
|
|||
struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
enum sci_status sci_port_get_properties(
|
||||
struct isci_port *iport,
|
||||
struct sci_port_properties *prop);
|
||||
|
||||
enum sci_status sci_port_link_up(struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
enum sci_status sci_port_link_down(struct isci_port *iport,
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10)
|
||||
#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10)
|
||||
#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100)
|
||||
#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (250)
|
||||
|
||||
enum SCIC_SDS_APC_ACTIVITY {
|
||||
SCIC_SDS_APC_SKIP_PHY,
|
||||
|
@ -466,6 +466,23 @@ sci_apc_agent_validate_phy_configuration(struct isci_host *ihost,
|
|||
return sci_port_configuration_agent_validate_ports(ihost, port_agent);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine will restart the automatic port configuration timeout
|
||||
* timer for the next time period. This could be caused by either a link
|
||||
* down event or a link up event where we can not yet tell to which a phy
|
||||
* belongs.
|
||||
*/
|
||||
static void sci_apc_agent_start_timer(
|
||||
struct sci_port_configuration_agent *port_agent,
|
||||
u32 timeout)
|
||||
{
|
||||
if (port_agent->timer_pending)
|
||||
sci_del_timer(&port_agent->timer);
|
||||
|
||||
port_agent->timer_pending = true;
|
||||
sci_mod_timer(&port_agent->timer, timeout);
|
||||
}
|
||||
|
||||
static void sci_apc_agent_configure_ports(struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent,
|
||||
struct isci_phy *iphy,
|
||||
|
@ -565,17 +582,8 @@ static void sci_apc_agent_configure_ports(struct isci_host *ihost,
|
|||
break;
|
||||
|
||||
case SCIC_SDS_APC_START_TIMER:
|
||||
/*
|
||||
* This can occur for either a link down event, or a link
|
||||
* up event where we cannot yet tell the port to which a
|
||||
* phy belongs.
|
||||
*/
|
||||
if (port_agent->timer_pending)
|
||||
sci_del_timer(&port_agent->timer);
|
||||
|
||||
port_agent->timer_pending = true;
|
||||
sci_mod_timer(&port_agent->timer,
|
||||
SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
|
||||
sci_apc_agent_start_timer(port_agent,
|
||||
SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
|
||||
break;
|
||||
|
||||
case SCIC_SDS_APC_SKIP_PHY:
|
||||
|
@ -607,7 +615,8 @@ static void sci_apc_agent_link_up(struct isci_host *ihost,
|
|||
if (!iport) {
|
||||
/* the phy is not the part of this port */
|
||||
port_agent->phy_ready_mask |= 1 << phy_index;
|
||||
sci_apc_agent_configure_ports(ihost, port_agent, iphy, true);
|
||||
sci_apc_agent_start_timer(port_agent,
|
||||
SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
|
||||
} else {
|
||||
/* the phy is already the part of the port */
|
||||
u32 port_state = iport->sm.current_state_id;
|
||||
|
|
|
@ -147,7 +147,7 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw
|
|||
|
||||
memcpy(orom, fw->data, fw->size);
|
||||
|
||||
if (is_c0(pdev))
|
||||
if (is_c0(pdev) || is_c1(pdev))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
|
|
|
@ -152,7 +152,7 @@ struct sci_user_parameters {
|
|||
#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4
|
||||
|
||||
struct sci_oem_params;
|
||||
int sci_oem_parameters_validate(struct sci_oem_params *oem);
|
||||
int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version);
|
||||
|
||||
struct isci_orom;
|
||||
struct isci_orom *isci_request_oprom(struct pci_dev *pdev);
|
||||
|
@ -191,6 +191,11 @@ struct isci_oem_hdr {
|
|||
0x1a, 0x04, 0xc6)
|
||||
#define ISCI_EFI_VAR_NAME "RstScuO"
|
||||
|
||||
#define ISCI_ROM_VER_1_0 0x10
|
||||
#define ISCI_ROM_VER_1_1 0x11
|
||||
#define ISCI_ROM_VER_1_3 0x13
|
||||
#define ISCI_ROM_VER_LATEST ISCI_ROM_VER_1_3
|
||||
|
||||
/* Allowed PORT configuration modes APC Automatic PORT configuration mode is
|
||||
* defined by the OEM configuration parameters providing no PHY_MASK parameters
|
||||
* for any PORT. i.e. There are no phys assigned to any of the ports at start.
|
||||
|
@ -220,8 +225,86 @@ struct sci_oem_params {
|
|||
struct {
|
||||
uint8_t mode_type;
|
||||
uint8_t max_concurr_spin_up;
|
||||
uint8_t do_enable_ssc;
|
||||
uint8_t reserved;
|
||||
/*
|
||||
* This bitfield indicates the OEM's desired default Tx
|
||||
* Spread Spectrum Clocking (SSC) settings for SATA and SAS.
|
||||
* NOTE: Default SSC Modulation Frequency is 31.5KHz.
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
/*
|
||||
* NOTE: Max spread for SATA is +0 / -5000 PPM.
|
||||
* Down-spreading SSC (only method allowed for SATA):
|
||||
* SATA SSC Tx Disabled = 0x0
|
||||
* SATA SSC Tx at +0 / -1419 PPM Spread = 0x2
|
||||
* SATA SSC Tx at +0 / -2129 PPM Spread = 0x3
|
||||
* SATA SSC Tx at +0 / -4257 PPM Spread = 0x6
|
||||
* SATA SSC Tx at +0 / -4967 PPM Spread = 0x7
|
||||
*/
|
||||
uint8_t ssc_sata_tx_spread_level:4;
|
||||
/*
|
||||
* SAS SSC Tx Disabled = 0x0
|
||||
*
|
||||
* NOTE: Max spread for SAS down-spreading +0 /
|
||||
* -2300 PPM
|
||||
* Down-spreading SSC:
|
||||
* SAS SSC Tx at +0 / -1419 PPM Spread = 0x2
|
||||
* SAS SSC Tx at +0 / -2129 PPM Spread = 0x3
|
||||
*
|
||||
* NOTE: Max spread for SAS center-spreading +2300 /
|
||||
* -2300 PPM
|
||||
* Center-spreading SSC:
|
||||
* SAS SSC Tx at +1064 / -1064 PPM Spread = 0x3
|
||||
* SAS SSC Tx at +2129 / -2129 PPM Spread = 0x6
|
||||
*/
|
||||
uint8_t ssc_sas_tx_spread_level:3;
|
||||
/*
|
||||
* NOTE: Refer to the SSC section of the SAS 2.x
|
||||
* Specification for proper setting of this field.
|
||||
* For standard SAS Initiator SAS PHY operation it
|
||||
* should be 0 for Down-spreading.
|
||||
* SAS SSC Tx spread type:
|
||||
* Down-spreading SSC = 0
|
||||
* Center-spreading SSC = 1
|
||||
*/
|
||||
uint8_t ssc_sas_tx_type:1;
|
||||
};
|
||||
uint8_t do_enable_ssc;
|
||||
};
|
||||
/*
|
||||
* This field indicates length of the SAS/SATA cable between
|
||||
* host and device.
|
||||
* This field is used make relationship between analog
|
||||
* parameters of the phy in the silicon and length of the cable.
|
||||
* Supported cable attenuation levels:
|
||||
* "short"- up to 3m, "medium"-3m to 6m, and "long"- more than
|
||||
* 6m.
|
||||
*
|
||||
* This is bit mask field:
|
||||
*
|
||||
* BIT: (MSB) 7 6 5 4
|
||||
* ASSIGNMENT: <phy3><phy2><phy1><phy0> - Medium cable
|
||||
* length assignment
|
||||
* BIT: 3 2 1 0 (LSB)
|
||||
* ASSIGNMENT: <phy3><phy2><phy1><phy0> - Long cable length
|
||||
* assignment
|
||||
*
|
||||
* BITS 7-4 are set when the cable length is assigned to medium
|
||||
* BITS 3-0 are set when the cable length is assigned to long
|
||||
*
|
||||
* The BIT positions are clear when the cable length is
|
||||
* assigned to short.
|
||||
*
|
||||
* Setting the bits for both long and medium cable length is
|
||||
* undefined.
|
||||
*
|
||||
* A value of 0x84 would assign
|
||||
* phy3 - medium
|
||||
* phy2 - long
|
||||
* phy1 - short
|
||||
* phy0 - short
|
||||
*/
|
||||
uint8_t cable_selection_mask;
|
||||
} controller;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <scsi/sas.h>
|
||||
#include <linux/bitops.h>
|
||||
#include "isci.h"
|
||||
#include "port.h"
|
||||
#include "remote_device.h"
|
||||
|
@ -1101,6 +1102,7 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
|
|||
struct isci_remote_device *idev)
|
||||
{
|
||||
enum sci_status status;
|
||||
struct sci_port_properties properties;
|
||||
struct domain_device *dev = idev->domain_dev;
|
||||
|
||||
sci_remote_device_construct(iport, idev);
|
||||
|
@ -1110,6 +1112,11 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
|
|||
* entries will be needed to store the remote node.
|
||||
*/
|
||||
idev->is_direct_attached = true;
|
||||
|
||||
sci_port_get_properties(iport, &properties);
|
||||
/* Get accurate port width from port's phy mask for a DA device. */
|
||||
idev->device_port_width = hweight32(properties.phy_mask);
|
||||
|
||||
status = sci_controller_allocate_remote_node_context(iport->owning_controller,
|
||||
idev,
|
||||
&idev->rnc.remote_node_index);
|
||||
|
@ -1125,9 +1132,6 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
|
|||
|
||||
idev->connection_rate = sci_port_get_max_allowed_speed(iport);
|
||||
|
||||
/* / @todo Should I assign the port width by reading all of the phys on the port? */
|
||||
idev->device_port_width = 1;
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -496,7 +496,7 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
|
|||
}
|
||||
}
|
||||
|
||||
isci_print_tmf(tmf);
|
||||
isci_print_tmf(ihost, tmf);
|
||||
|
||||
if (tmf->status == SCI_SUCCESS)
|
||||
ret = TMF_RESP_FUNC_COMPLETE;
|
||||
|
|
|
@ -106,7 +106,6 @@ struct isci_tmf {
|
|||
} resp;
|
||||
unsigned char lun[8];
|
||||
u16 io_tag;
|
||||
struct isci_remote_device *device;
|
||||
enum isci_tmf_function_codes tmf_code;
|
||||
int status;
|
||||
|
||||
|
@ -120,10 +119,10 @@ struct isci_tmf {
|
|||
|
||||
};
|
||||
|
||||
static inline void isci_print_tmf(struct isci_tmf *tmf)
|
||||
static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf)
|
||||
{
|
||||
if (SAS_PROTOCOL_SATA == tmf->proto)
|
||||
dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
|
||||
dev_dbg(&ihost->pdev->dev,
|
||||
"%s: status = %x\n"
|
||||
"tmf->resp.d2h_fis.status = %x\n"
|
||||
"tmf->resp.d2h_fis.error = %x\n",
|
||||
|
@ -132,7 +131,7 @@ static inline void isci_print_tmf(struct isci_tmf *tmf)
|
|||
tmf->resp.d2h_fis.status,
|
||||
tmf->resp.d2h_fis.error);
|
||||
else
|
||||
dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
|
||||
dev_dbg(&ihost->pdev->dev,
|
||||
"%s: status = %x\n"
|
||||
"tmf->resp.resp_iu.data_present = %x\n"
|
||||
"tmf->resp.resp_iu.status = %x\n"
|
||||
|
|
|
@ -61,7 +61,7 @@ static void fc_disc_restart(struct fc_disc *);
|
|||
* Locking Note: This function expects that the lport mutex is locked before
|
||||
* calling it.
|
||||
*/
|
||||
void fc_disc_stop_rports(struct fc_disc *disc)
|
||||
static void fc_disc_stop_rports(struct fc_disc *disc)
|
||||
{
|
||||
struct fc_lport *lport;
|
||||
struct fc_rport_priv *rdata;
|
||||
|
@ -682,7 +682,7 @@ static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp)
|
|||
* fc_disc_stop() - Stop discovery for a given lport
|
||||
* @lport: The local port that discovery should stop on
|
||||
*/
|
||||
void fc_disc_stop(struct fc_lport *lport)
|
||||
static void fc_disc_stop(struct fc_lport *lport)
|
||||
{
|
||||
struct fc_disc *disc = &lport->disc;
|
||||
|
||||
|
@ -698,7 +698,7 @@ void fc_disc_stop(struct fc_lport *lport)
|
|||
* This function will block until discovery has been
|
||||
* completely stopped and all rports have been deleted.
|
||||
*/
|
||||
void fc_disc_stop_final(struct fc_lport *lport)
|
||||
static void fc_disc_stop_final(struct fc_lport *lport)
|
||||
{
|
||||
fc_disc_stop(lport);
|
||||
lport->tt.rport_flush_queue();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <scsi/fc/fc_els.h>
|
||||
#include <scsi/libfc.h>
|
||||
#include <scsi/fc_encode.h>
|
||||
#include "fc_libfc.h"
|
||||
|
||||
/**
|
||||
* fc_elsct_send() - Send an ELS or CT frame
|
||||
|
|
|
@ -91,7 +91,7 @@ struct fc_exch_pool {
|
|||
* It manages the allocation of exchange IDs.
|
||||
*/
|
||||
struct fc_exch_mgr {
|
||||
struct fc_exch_pool *pool;
|
||||
struct fc_exch_pool __percpu *pool;
|
||||
mempool_t *ep_pool;
|
||||
enum fc_class class;
|
||||
struct kref kref;
|
||||
|
|
|
@ -155,6 +155,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp)
|
|||
fsp->xfer_ddp = FC_XID_UNKNOWN;
|
||||
atomic_set(&fsp->ref_cnt, 1);
|
||||
init_timer(&fsp->timer);
|
||||
fsp->timer.data = (unsigned long)fsp;
|
||||
INIT_LIST_HEAD(&fsp->list);
|
||||
spin_lock_init(&fsp->scsi_pkt_lock);
|
||||
}
|
||||
|
@ -1850,9 +1851,6 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd)
|
|||
}
|
||||
put_cpu();
|
||||
|
||||
init_timer(&fsp->timer);
|
||||
fsp->timer.data = (unsigned long)fsp;
|
||||
|
||||
/*
|
||||
* send it to the lower layer
|
||||
* if we get -1 return then put the request in the pending
|
||||
|
|
|
@ -677,7 +677,8 @@ EXPORT_SYMBOL(fc_set_mfs);
|
|||
* @lport: The local port receiving the event
|
||||
* @event: The discovery event
|
||||
*/
|
||||
void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
|
||||
static void fc_lport_disc_callback(struct fc_lport *lport,
|
||||
enum fc_disc_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case DISC_EV_SUCCESS:
|
||||
|
@ -1568,7 +1569,7 @@ EXPORT_SYMBOL(fc_lport_flogi_resp);
|
|||
* Locking Note: The lport lock is expected to be held before calling
|
||||
* this routine.
|
||||
*/
|
||||
void fc_lport_enter_flogi(struct fc_lport *lport)
|
||||
static void fc_lport_enter_flogi(struct fc_lport *lport)
|
||||
{
|
||||
struct fc_frame *fp;
|
||||
|
||||
|
|
|
@ -391,7 +391,7 @@ static void fc_rport_work(struct work_struct *work)
|
|||
* If it appears we are already logged in, ADISC is used to verify
|
||||
* the setup.
|
||||
*/
|
||||
int fc_rport_login(struct fc_rport_priv *rdata)
|
||||
static int fc_rport_login(struct fc_rport_priv *rdata)
|
||||
{
|
||||
mutex_lock(&rdata->rp_mutex);
|
||||
|
||||
|
@ -451,7 +451,7 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
|
|||
* function will hold the rport lock, call an _enter_*
|
||||
* function and then unlock the rport.
|
||||
*/
|
||||
int fc_rport_logoff(struct fc_rport_priv *rdata)
|
||||
static int fc_rport_logoff(struct fc_rport_priv *rdata)
|
||||
{
|
||||
mutex_lock(&rdata->rp_mutex);
|
||||
|
||||
|
@ -653,8 +653,8 @@ static int fc_rport_login_complete(struct fc_rport_priv *rdata,
|
|||
* @fp: The FLOGI response frame
|
||||
* @rp_arg: The remote port that received the FLOGI response
|
||||
*/
|
||||
void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
|
||||
void *rp_arg)
|
||||
static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
|
||||
void *rp_arg)
|
||||
{
|
||||
struct fc_rport_priv *rdata = rp_arg;
|
||||
struct fc_lport *lport = rdata->local_port;
|
||||
|
@ -1520,7 +1520,7 @@ reject:
|
|||
*
|
||||
* Locking Note: Called with the lport lock held.
|
||||
*/
|
||||
void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
|
||||
static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
|
||||
{
|
||||
struct fc_seq_els_data els_data;
|
||||
|
||||
|
|
|
@ -306,19 +306,22 @@ mega_query_adapter(adapter_t *adapter)
|
|||
adapter->host->sg_tablesize = adapter->sglen;
|
||||
|
||||
|
||||
/* use HP firmware and bios version encoding */
|
||||
/* use HP firmware and bios version encoding
|
||||
Note: fw_version[0|1] and bios_version[0|1] were originally shifted
|
||||
right 8 bits making them zero. This 0 value was hardcoded to fix
|
||||
sparse warnings. */
|
||||
if (adapter->product_info.subsysvid == HP_SUBSYS_VID) {
|
||||
sprintf (adapter->fw_version, "%c%d%d.%d%d",
|
||||
adapter->product_info.fw_version[2],
|
||||
adapter->product_info.fw_version[1] >> 8,
|
||||
0,
|
||||
adapter->product_info.fw_version[1] & 0x0f,
|
||||
adapter->product_info.fw_version[0] >> 8,
|
||||
0,
|
||||
adapter->product_info.fw_version[0] & 0x0f);
|
||||
sprintf (adapter->bios_version, "%c%d%d.%d%d",
|
||||
adapter->product_info.bios_version[2],
|
||||
adapter->product_info.bios_version[1] >> 8,
|
||||
0,
|
||||
adapter->product_info.bios_version[1] & 0x0f,
|
||||
adapter->product_info.bios_version[0] >> 8,
|
||||
0,
|
||||
adapter->product_info.bios_version[0] & 0x0f);
|
||||
} else {
|
||||
memcpy(adapter->fw_version,
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
/*
|
||||
* MegaRAID SAS Driver meta data
|
||||
*/
|
||||
#define MEGASAS_VERSION "00.00.06.12-rc1"
|
||||
#define MEGASAS_RELDATE "Oct. 5, 2011"
|
||||
#define MEGASAS_EXT_VERSION "Wed. Oct. 5 17:00:00 PDT 2011"
|
||||
#define MEGASAS_VERSION "00.00.06.14-rc1"
|
||||
#define MEGASAS_RELDATE "Jan. 6, 2012"
|
||||
#define MEGASAS_EXT_VERSION "Fri. Jan. 6 17:00:00 PDT 2012"
|
||||
|
||||
/*
|
||||
* Device IDs
|
||||
|
@ -773,7 +773,6 @@ struct megasas_ctrl_info {
|
|||
|
||||
#define MFI_OB_INTR_STATUS_MASK 0x00000002
|
||||
#define MFI_POLL_TIMEOUT_SECS 60
|
||||
#define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10)
|
||||
|
||||
#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
|
||||
#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001
|
||||
|
@ -1353,7 +1352,6 @@ struct megasas_instance {
|
|||
u32 mfiStatus;
|
||||
u32 last_seq_num;
|
||||
|
||||
struct timer_list io_completion_timer;
|
||||
struct list_head internal_reset_pending_q;
|
||||
|
||||
/* Ptr to hba specific information */
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* FILE: megaraid_sas_base.c
|
||||
* Version : v00.00.06.12-rc1
|
||||
* Version : v00.00.06.14-rc1
|
||||
*
|
||||
* Authors: LSI Corporation
|
||||
* Sreenivas Bagalkote
|
||||
|
@ -58,14 +58,6 @@
|
|||
#include "megaraid_sas_fusion.h"
|
||||
#include "megaraid_sas.h"
|
||||
|
||||
/*
|
||||
* poll_mode_io:1- schedule complete completion from q cmd
|
||||
*/
|
||||
static unsigned int poll_mode_io;
|
||||
module_param_named(poll_mode_io, poll_mode_io, int, 0);
|
||||
MODULE_PARM_DESC(poll_mode_io,
|
||||
"Complete cmds from IO path, (default=0)");
|
||||
|
||||
/*
|
||||
* Number of sectors per IO command
|
||||
* Will be set in megasas_init_mfi if user does not provide
|
||||
|
@ -1439,11 +1431,6 @@ megasas_build_and_issue_cmd(struct megasas_instance *instance,
|
|||
|
||||
instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
|
||||
cmd->frame_count-1, instance->reg_set);
|
||||
/*
|
||||
* Check if we have pend cmds to be completed
|
||||
*/
|
||||
if (poll_mode_io && atomic_read(&instance->fw_outstanding))
|
||||
tasklet_schedule(&instance->isr_tasklet);
|
||||
|
||||
return 0;
|
||||
out_return_cmd:
|
||||
|
@ -3370,47 +3357,6 @@ fail_fw_init:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* megasas_start_timer - Initializes a timer object
|
||||
* @instance: Adapter soft state
|
||||
* @timer: timer object to be initialized
|
||||
* @fn: timer function
|
||||
* @interval: time interval between timer function call
|
||||
*/
|
||||
static inline void
|
||||
megasas_start_timer(struct megasas_instance *instance,
|
||||
struct timer_list *timer,
|
||||
void *fn, unsigned long interval)
|
||||
{
|
||||
init_timer(timer);
|
||||
timer->expires = jiffies + interval;
|
||||
timer->data = (unsigned long)instance;
|
||||
timer->function = fn;
|
||||
add_timer(timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* megasas_io_completion_timer - Timer fn
|
||||
* @instance_addr: Address of adapter soft state
|
||||
*
|
||||
* Schedules tasklet for cmd completion
|
||||
* if poll_mode_io is set
|
||||
*/
|
||||
static void
|
||||
megasas_io_completion_timer(unsigned long instance_addr)
|
||||
{
|
||||
struct megasas_instance *instance =
|
||||
(struct megasas_instance *)instance_addr;
|
||||
|
||||
if (atomic_read(&instance->fw_outstanding))
|
||||
tasklet_schedule(&instance->isr_tasklet);
|
||||
|
||||
/* Restart timer */
|
||||
if (poll_mode_io)
|
||||
mod_timer(&instance->io_completion_timer,
|
||||
jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
|
||||
}
|
||||
|
||||
static u32
|
||||
megasas_init_adapter_mfi(struct megasas_instance *instance)
|
||||
{
|
||||
|
@ -3638,11 +3584,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
|
||||
(unsigned long)instance);
|
||||
|
||||
/* Initialize the cmd completion timer */
|
||||
if (poll_mode_io)
|
||||
megasas_start_timer(instance, &instance->io_completion_timer,
|
||||
megasas_io_completion_timer,
|
||||
MEGASAS_COMPLETION_TIMER_INTERVAL);
|
||||
return 0;
|
||||
|
||||
fail_init_adapter:
|
||||
|
@ -4369,9 +4310,6 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
host = instance->host;
|
||||
instance->unload = 1;
|
||||
|
||||
if (poll_mode_io)
|
||||
del_timer_sync(&instance->io_completion_timer);
|
||||
|
||||
megasas_flush_cache(instance);
|
||||
megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
|
||||
|
||||
|
@ -4511,12 +4449,6 @@ megasas_resume(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
instance->instancet->enable_intr(instance->reg_set);
|
||||
|
||||
/* Initialize the cmd completion timer */
|
||||
if (poll_mode_io)
|
||||
megasas_start_timer(instance, &instance->io_completion_timer,
|
||||
megasas_io_completion_timer,
|
||||
MEGASAS_COMPLETION_TIMER_INTERVAL);
|
||||
instance->unload = 0;
|
||||
|
||||
/*
|
||||
|
@ -4570,9 +4502,6 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
|
|||
host = instance->host;
|
||||
fusion = instance->ctrl_context;
|
||||
|
||||
if (poll_mode_io)
|
||||
del_timer_sync(&instance->io_completion_timer);
|
||||
|
||||
scsi_remove_host(instance->host);
|
||||
megasas_flush_cache(instance);
|
||||
megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
|
||||
|
@ -4773,6 +4702,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
|
|||
memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
|
||||
cmd->frame->hdr.context = cmd->index;
|
||||
cmd->frame->hdr.pad_0 = 0;
|
||||
cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
|
||||
MFI_FRAME_SENSE64);
|
||||
|
||||
/*
|
||||
* The management interface between applications and the fw uses
|
||||
|
@ -5219,60 +5150,6 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun
|
|||
static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
|
||||
megasas_sysfs_set_dbg_lvl);
|
||||
|
||||
static ssize_t
|
||||
megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", poll_mode_io);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int retval = count;
|
||||
int tmp = poll_mode_io;
|
||||
int i;
|
||||
struct megasas_instance *instance;
|
||||
|
||||
if (sscanf(buf, "%u", &poll_mode_io) < 1) {
|
||||
printk(KERN_ERR "megasas: could not set poll_mode_io\n");
|
||||
retval = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if poll_mode_io is already set or is same as previous value
|
||||
*/
|
||||
if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
|
||||
goto out;
|
||||
|
||||
if (poll_mode_io) {
|
||||
/*
|
||||
* Start timers for all adapters
|
||||
*/
|
||||
for (i = 0; i < megasas_mgmt_info.max_index; i++) {
|
||||
instance = megasas_mgmt_info.instance[i];
|
||||
if (instance) {
|
||||
megasas_start_timer(instance,
|
||||
&instance->io_completion_timer,
|
||||
megasas_io_completion_timer,
|
||||
MEGASAS_COMPLETION_TIMER_INTERVAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Delete timers for all adapters
|
||||
*/
|
||||
for (i = 0; i < megasas_mgmt_info.max_index; i++) {
|
||||
instance = megasas_mgmt_info.instance[i];
|
||||
if (instance)
|
||||
del_timer_sync(&instance->io_completion_timer);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
megasas_aen_polling(struct work_struct *work)
|
||||
{
|
||||
|
@ -5502,11 +5379,6 @@ megasas_aen_polling(struct work_struct *work)
|
|||
kfree(ev);
|
||||
}
|
||||
|
||||
|
||||
static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
|
||||
megasas_sysfs_show_poll_mode_io,
|
||||
megasas_sysfs_set_poll_mode_io);
|
||||
|
||||
/**
|
||||
* megasas_init - Driver load entry point
|
||||
*/
|
||||
|
@ -5565,11 +5437,6 @@ static int __init megasas_init(void)
|
|||
&driver_attr_dbg_lvl);
|
||||
if (rval)
|
||||
goto err_dcf_dbg_lvl;
|
||||
rval = driver_create_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_poll_mode_io);
|
||||
if (rval)
|
||||
goto err_dcf_poll_mode_io;
|
||||
|
||||
rval = driver_create_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_support_device_change);
|
||||
if (rval)
|
||||
|
@ -5578,10 +5445,6 @@ static int __init megasas_init(void)
|
|||
return rval;
|
||||
|
||||
err_dcf_support_device_change:
|
||||
driver_remove_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_poll_mode_io);
|
||||
|
||||
err_dcf_poll_mode_io:
|
||||
driver_remove_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_dbg_lvl);
|
||||
err_dcf_dbg_lvl:
|
||||
|
@ -5606,8 +5469,6 @@ err_pcidrv:
|
|||
*/
|
||||
static void __exit megasas_exit(void)
|
||||
{
|
||||
driver_remove_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_poll_mode_io);
|
||||
driver_remove_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_dbg_lvl);
|
||||
driver_remove_file(&megasas_pci_driver.driver,
|
||||
|
|
|
@ -282,7 +282,9 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
|
|||
else {
|
||||
*pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
|
||||
if ((raid->level >= 5) &&
|
||||
(instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER))
|
||||
((instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER &&
|
||||
raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))
|
||||
pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
|
||||
else if (raid->level == 1) {
|
||||
/* Get alternate Pd. */
|
||||
|
|
|
@ -150,6 +150,8 @@
|
|||
#define QL4_SESS_RECOVERY_TMO 120 /* iSCSI session */
|
||||
/* recovery timeout */
|
||||
|
||||
#define MSB(x) ((uint8_t)((uint16_t)(x) >> 8))
|
||||
#define LSW(x) ((uint16_t)(x))
|
||||
#define LSDW(x) ((u32)((u64)(x)))
|
||||
#define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
|
||||
|
||||
|
@ -671,6 +673,7 @@ struct scsi_qla_host {
|
|||
uint16_t pri_ddb_idx;
|
||||
uint16_t sec_ddb_idx;
|
||||
int is_reset;
|
||||
uint16_t temperature;
|
||||
};
|
||||
|
||||
struct ql4_task_data {
|
||||
|
|
|
@ -697,6 +697,9 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha)
|
|||
writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
|
||||
&ha->reg->ctrl_status);
|
||||
readl(&ha->reg->ctrl_status);
|
||||
writel(set_rmask(CSR_SCSI_COMPLETION_INTR),
|
||||
&ha->reg->ctrl_status);
|
||||
readl(&ha->reg->ctrl_status);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS) {
|
||||
DEBUG2(printk("scsi%ld: %s: Get firmware "
|
||||
|
|
|
@ -219,6 +219,13 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
|||
ha->mailbox_timeout_count++;
|
||||
mbx_sts[0] = (-1);
|
||||
set_bit(DPC_RESET_HA, &ha->dpc_flags);
|
||||
if (is_qla8022(ha)) {
|
||||
ql4_printk(KERN_INFO, ha,
|
||||
"disabling pause transmit on port 0 & 1.\n");
|
||||
qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
|
||||
CRB_NIU_XG_PAUSE_CTL_P0 |
|
||||
CRB_NIU_XG_PAUSE_CTL_P1);
|
||||
}
|
||||
goto mbox_exit;
|
||||
}
|
||||
|
||||
|
|
|
@ -1875,6 +1875,11 @@ exit:
|
|||
int qla4_8xxx_load_risc(struct scsi_qla_host *ha)
|
||||
{
|
||||
int retval;
|
||||
|
||||
/* clear the interrupt */
|
||||
writel(0, &ha->qla4_8xxx_reg->host_int);
|
||||
readl(&ha->qla4_8xxx_reg->host_int);
|
||||
|
||||
retval = qla4_8xxx_device_state_handler(ha);
|
||||
|
||||
if (retval == QLA_SUCCESS && !test_bit(AF_INIT_DONE, &ha->flags))
|
||||
|
|
|
@ -19,12 +19,28 @@
|
|||
#define PHAN_PEG_RCV_INITIALIZED 0xff01
|
||||
|
||||
/*CRB_RELATED*/
|
||||
#define QLA82XX_CRB_BASE QLA82XX_CAM_RAM(0x200)
|
||||
#define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X))
|
||||
|
||||
#define QLA82XX_CRB_BASE (QLA82XX_CAM_RAM(0x200))
|
||||
#define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X))
|
||||
#define CRB_CMDPEG_STATE QLA82XX_REG(0x50)
|
||||
#define CRB_RCVPEG_STATE QLA82XX_REG(0x13c)
|
||||
#define CRB_DMA_SHIFT QLA82XX_REG(0xcc)
|
||||
#define CRB_TEMP_STATE QLA82XX_REG(0x1b4)
|
||||
|
||||
#define qla82xx_get_temp_val(x) ((x) >> 16)
|
||||
#define qla82xx_get_temp_state(x) ((x) & 0xffff)
|
||||
#define qla82xx_encode_temp(val, state) (((val) << 16) | (state))
|
||||
|
||||
/*
|
||||
* Temperature control.
|
||||
*/
|
||||
enum {
|
||||
QLA82XX_TEMP_NORMAL = 0x1, /* Normal operating range */
|
||||
QLA82XX_TEMP_WARN, /* Sound alert, temperature getting high */
|
||||
QLA82XX_TEMP_PANIC /* Fatal error, hardware has shut down. */
|
||||
};
|
||||
|
||||
#define CRB_NIU_XG_PAUSE_CTL_P0 0x1
|
||||
#define CRB_NIU_XG_PAUSE_CTL_P1 0x8
|
||||
|
||||
#define QLA82XX_HW_H0_CH_HUB_ADR 0x05
|
||||
#define QLA82XX_HW_H1_CH_HUB_ADR 0x0E
|
||||
|
|
|
@ -35,43 +35,44 @@ static struct kmem_cache *srb_cachep;
|
|||
int ql4xdisablesysfsboot = 1;
|
||||
module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(ql4xdisablesysfsboot,
|
||||
"Set to disable exporting boot targets to sysfs\n"
|
||||
" 0 - Export boot targets\n"
|
||||
" 1 - Do not export boot targets (Default)");
|
||||
" Set to disable exporting boot targets to sysfs.\n"
|
||||
"\t\t 0 - Export boot targets\n"
|
||||
"\t\t 1 - Do not export boot targets (Default)");
|
||||
|
||||
int ql4xdontresethba = 0;
|
||||
module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(ql4xdontresethba,
|
||||
"Don't reset the HBA for driver recovery \n"
|
||||
" 0 - It will reset HBA (Default)\n"
|
||||
" 1 - It will NOT reset HBA");
|
||||
" Don't reset the HBA for driver recovery.\n"
|
||||
"\t\t 0 - It will reset HBA (Default)\n"
|
||||
"\t\t 1 - It will NOT reset HBA");
|
||||
|
||||
int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */
|
||||
int ql4xextended_error_logging;
|
||||
module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(ql4xextended_error_logging,
|
||||
"Option to enable extended error logging, "
|
||||
"Default is 0 - no logging, 1 - debug logging");
|
||||
" Option to enable extended error logging.\n"
|
||||
"\t\t 0 - no logging (Default)\n"
|
||||
"\t\t 2 - debug logging");
|
||||
|
||||
int ql4xenablemsix = 1;
|
||||
module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(ql4xenablemsix,
|
||||
"Set to enable MSI or MSI-X interrupt mechanism.\n"
|
||||
" 0 = enable INTx interrupt mechanism.\n"
|
||||
" 1 = enable MSI-X interrupt mechanism (Default).\n"
|
||||
" 2 = enable MSI interrupt mechanism.");
|
||||
" Set to enable MSI or MSI-X interrupt mechanism.\n"
|
||||
"\t\t 0 = enable INTx interrupt mechanism.\n"
|
||||
"\t\t 1 = enable MSI-X interrupt mechanism (Default).\n"
|
||||
"\t\t 2 = enable MSI interrupt mechanism.");
|
||||
|
||||
#define QL4_DEF_QDEPTH 32
|
||||
static int ql4xmaxqdepth = QL4_DEF_QDEPTH;
|
||||
module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(ql4xmaxqdepth,
|
||||
"Maximum queue depth to report for target devices.\n"
|
||||
" Default: 32.");
|
||||
" Maximum queue depth to report for target devices.\n"
|
||||
"\t\t Default: 32.");
|
||||
|
||||
static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
|
||||
module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(ql4xsess_recovery_tmo,
|
||||
"Target Session Recovery Timeout.\n"
|
||||
" Default: 120 sec.");
|
||||
"\t\t Default: 120 sec.");
|
||||
|
||||
static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
|
||||
/*
|
||||
|
@ -1630,7 +1631,9 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
|
|||
|
||||
/* Update timers after login */
|
||||
ddb_entry->default_relogin_timeout =
|
||||
le16_to_cpu(fw_ddb_entry->def_timeout);
|
||||
(le16_to_cpu(fw_ddb_entry->def_timeout) > LOGIN_TOV) &&
|
||||
(le16_to_cpu(fw_ddb_entry->def_timeout) < LOGIN_TOV * 10) ?
|
||||
le16_to_cpu(fw_ddb_entry->def_timeout) : LOGIN_TOV;
|
||||
ddb_entry->default_time2wait =
|
||||
le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
|
||||
|
||||
|
@ -1969,6 +1972,42 @@ mem_alloc_error_exit:
|
|||
return QLA_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4_8xxx_check_temp - Check the ISP82XX temperature.
|
||||
* @ha: adapter block pointer.
|
||||
*
|
||||
* Note: The caller should not hold the idc lock.
|
||||
**/
|
||||
static int qla4_8xxx_check_temp(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t temp, temp_state, temp_val;
|
||||
int status = QLA_SUCCESS;
|
||||
|
||||
temp = qla4_8xxx_rd_32(ha, CRB_TEMP_STATE);
|
||||
|
||||
temp_state = qla82xx_get_temp_state(temp);
|
||||
temp_val = qla82xx_get_temp_val(temp);
|
||||
|
||||
if (temp_state == QLA82XX_TEMP_PANIC) {
|
||||
ql4_printk(KERN_WARNING, ha, "Device temperature %d degrees C"
|
||||
" exceeds maximum allowed. Hardware has been shut"
|
||||
" down.\n", temp_val);
|
||||
status = QLA_ERROR;
|
||||
} else if (temp_state == QLA82XX_TEMP_WARN) {
|
||||
if (ha->temperature == QLA82XX_TEMP_NORMAL)
|
||||
ql4_printk(KERN_WARNING, ha, "Device temperature %d"
|
||||
" degrees C exceeds operating range."
|
||||
" Immediate action needed.\n", temp_val);
|
||||
} else {
|
||||
if (ha->temperature == QLA82XX_TEMP_WARN)
|
||||
ql4_printk(KERN_INFO, ha, "Device temperature is"
|
||||
" now %d degrees C in normal range.\n",
|
||||
temp_val);
|
||||
}
|
||||
ha->temperature = temp_state;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4_8xxx_check_fw_alive - Check firmware health
|
||||
* @ha: Pointer to host adapter structure.
|
||||
|
@ -2040,7 +2079,16 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
|
|||
test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
|
||||
test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) {
|
||||
dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
|
||||
if (dev_state == QLA82XX_DEV_NEED_RESET &&
|
||||
|
||||
if (qla4_8xxx_check_temp(ha)) {
|
||||
ql4_printk(KERN_INFO, ha, "disabling pause"
|
||||
" transmit on port 0 & 1.\n");
|
||||
qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
|
||||
CRB_NIU_XG_PAUSE_CTL_P0 |
|
||||
CRB_NIU_XG_PAUSE_CTL_P1);
|
||||
set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
|
||||
qla4xxx_wake_dpc(ha);
|
||||
} else if (dev_state == QLA82XX_DEV_NEED_RESET &&
|
||||
!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
|
||||
if (!ql4xdontresethba) {
|
||||
ql4_printk(KERN_INFO, ha, "%s: HW State: "
|
||||
|
@ -2057,9 +2105,21 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
|
|||
} else {
|
||||
/* Check firmware health */
|
||||
if (qla4_8xxx_check_fw_alive(ha)) {
|
||||
ql4_printk(KERN_INFO, ha, "disabling pause"
|
||||
" transmit on port 0 & 1.\n");
|
||||
qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
|
||||
CRB_NIU_XG_PAUSE_CTL_P0 |
|
||||
CRB_NIU_XG_PAUSE_CTL_P1);
|
||||
halt_status = qla4_8xxx_rd_32(ha,
|
||||
QLA82XX_PEG_HALT_STATUS1);
|
||||
|
||||
if (LSW(MSB(halt_status)) == 0x67)
|
||||
ql4_printk(KERN_ERR, ha, "%s:"
|
||||
" Firmware aborted with"
|
||||
" error code 0x00006700."
|
||||
" Device is being reset\n",
|
||||
__func__);
|
||||
|
||||
/* Since we cannot change dev_state in interrupt
|
||||
* context, set appropriate DPC flag then wakeup
|
||||
* DPC */
|
||||
|
@ -2078,7 +2138,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
|
|||
}
|
||||
}
|
||||
|
||||
void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
|
||||
static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
|
||||
{
|
||||
struct iscsi_session *sess;
|
||||
struct ddb_entry *ddb_entry;
|
||||
|
@ -3826,16 +3886,14 @@ exit_check:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void qla4xxx_free_nt_list(struct list_head *list_nt)
|
||||
static void qla4xxx_free_ddb_list(struct list_head *list_ddb)
|
||||
{
|
||||
struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;
|
||||
struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;
|
||||
|
||||
/* Free up the normaltargets list */
|
||||
list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
|
||||
list_del_init(&nt_ddb_idx->list);
|
||||
vfree(nt_ddb_idx);
|
||||
list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
|
||||
list_del_init(&ddb_idx->list);
|
||||
vfree(ddb_idx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
|
||||
|
@ -3884,6 +3942,8 @@ static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)
|
|||
static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
|
||||
struct ddb_entry *ddb_entry)
|
||||
{
|
||||
uint16_t def_timeout;
|
||||
|
||||
ddb_entry->ddb_type = FLASH_DDB;
|
||||
ddb_entry->fw_ddb_index = INVALID_ENTRY;
|
||||
ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
|
||||
|
@ -3894,9 +3954,10 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
|
|||
atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
|
||||
atomic_set(&ddb_entry->relogin_timer, 0);
|
||||
atomic_set(&ddb_entry->relogin_retry_count, 0);
|
||||
|
||||
def_timeout = le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
|
||||
ddb_entry->default_relogin_timeout =
|
||||
le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
|
||||
(def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ?
|
||||
def_timeout : LOGIN_TOV;
|
||||
ddb_entry->default_time2wait =
|
||||
le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);
|
||||
}
|
||||
|
@ -3934,7 +3995,6 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
|
|||
ip_state == IP_ADDRSTATE_DEPRICATED ||
|
||||
ip_state == IP_ADDRSTATE_DISABLING)
|
||||
ip_idx[idx] = -1;
|
||||
|
||||
}
|
||||
|
||||
/* Break if all IP states checked */
|
||||
|
@ -3947,58 +4007,37 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
|
|||
} while (time_after(wtime, jiffies));
|
||||
}
|
||||
|
||||
void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
|
||||
static void qla4xxx_build_st_list(struct scsi_qla_host *ha,
|
||||
struct list_head *list_st)
|
||||
{
|
||||
struct qla_ddb_index *st_ddb_idx;
|
||||
int max_ddbs;
|
||||
int fw_idx_size;
|
||||
struct dev_db_entry *fw_ddb_entry;
|
||||
dma_addr_t fw_ddb_dma;
|
||||
int ret;
|
||||
uint32_t idx = 0, next_idx = 0;
|
||||
uint32_t state = 0, conn_err = 0;
|
||||
uint16_t conn_id;
|
||||
struct dev_db_entry *fw_ddb_entry;
|
||||
struct ddb_entry *ddb_entry = NULL;
|
||||
dma_addr_t fw_ddb_dma;
|
||||
struct iscsi_cls_session *cls_sess;
|
||||
struct iscsi_session *sess;
|
||||
struct iscsi_cls_conn *cls_conn;
|
||||
struct iscsi_endpoint *ep;
|
||||
uint16_t cmds_max = 32, tmo = 0;
|
||||
uint32_t initial_cmdsn = 0;
|
||||
struct list_head list_st, list_nt; /* List of sendtargets */
|
||||
struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp;
|
||||
int fw_idx_size;
|
||||
unsigned long wtime;
|
||||
struct qla_ddb_index *nt_ddb_idx;
|
||||
|
||||
if (!test_bit(AF_LINK_UP, &ha->flags)) {
|
||||
set_bit(AF_BUILD_DDB_LIST, &ha->flags);
|
||||
ha->is_reset = is_reset;
|
||||
return;
|
||||
}
|
||||
max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
|
||||
MAX_DEV_DB_ENTRIES;
|
||||
uint16_t conn_id = 0;
|
||||
|
||||
fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
|
||||
&fw_ddb_dma);
|
||||
if (fw_ddb_entry == NULL) {
|
||||
DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
|
||||
goto exit_ddb_list;
|
||||
goto exit_st_list;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&list_st);
|
||||
INIT_LIST_HEAD(&list_nt);
|
||||
max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
|
||||
MAX_DEV_DB_ENTRIES;
|
||||
fw_idx_size = sizeof(struct qla_ddb_index);
|
||||
|
||||
for (idx = 0; idx < max_ddbs; idx = next_idx) {
|
||||
ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
|
||||
fw_ddb_dma, NULL,
|
||||
&next_idx, &state, &conn_err,
|
||||
NULL, &conn_id);
|
||||
ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
|
||||
NULL, &next_idx, &state,
|
||||
&conn_err, NULL, &conn_id);
|
||||
if (ret == QLA_ERROR)
|
||||
break;
|
||||
|
||||
if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
|
||||
goto continue_next_st;
|
||||
|
||||
/* Check if ST, add to the list_st */
|
||||
if (strlen((char *) fw_ddb_entry->iscsi_name) != 0)
|
||||
goto continue_next_st;
|
||||
|
@ -4009,12 +4048,235 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
|
|||
|
||||
st_ddb_idx->fw_ddb_idx = idx;
|
||||
|
||||
list_add_tail(&st_ddb_idx->list, &list_st);
|
||||
list_add_tail(&st_ddb_idx->list, list_st);
|
||||
continue_next_st:
|
||||
if (next_idx == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
exit_st_list:
|
||||
if (fw_ddb_entry)
|
||||
dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4xxx_remove_failed_ddb - Remove inactive or failed ddb from list
|
||||
* @ha: pointer to adapter structure
|
||||
* @list_ddb: List from which failed ddb to be removed
|
||||
*
|
||||
* Iterate over the list of DDBs and find and remove DDBs that are either in
|
||||
* no connection active state or failed state
|
||||
**/
|
||||
static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha,
|
||||
struct list_head *list_ddb)
|
||||
{
|
||||
struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;
|
||||
uint32_t next_idx = 0;
|
||||
uint32_t state = 0, conn_err = 0;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
|
||||
ret = qla4xxx_get_fwddb_entry(ha, ddb_idx->fw_ddb_idx,
|
||||
NULL, 0, NULL, &next_idx, &state,
|
||||
&conn_err, NULL, NULL);
|
||||
if (ret == QLA_ERROR)
|
||||
continue;
|
||||
|
||||
if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
|
||||
state == DDB_DS_SESSION_FAILED) {
|
||||
list_del_init(&ddb_idx->list);
|
||||
vfree(ddb_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
|
||||
struct dev_db_entry *fw_ddb_entry,
|
||||
int is_reset)
|
||||
{
|
||||
struct iscsi_cls_session *cls_sess;
|
||||
struct iscsi_session *sess;
|
||||
struct iscsi_cls_conn *cls_conn;
|
||||
struct iscsi_endpoint *ep;
|
||||
uint16_t cmds_max = 32;
|
||||
uint16_t conn_id = 0;
|
||||
uint32_t initial_cmdsn = 0;
|
||||
int ret = QLA_SUCCESS;
|
||||
|
||||
struct ddb_entry *ddb_entry = NULL;
|
||||
|
||||
/* Create session object, with INVALID_ENTRY,
|
||||
* the targer_id would get set when we issue the login
|
||||
*/
|
||||
cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host,
|
||||
cmds_max, sizeof(struct ddb_entry),
|
||||
sizeof(struct ql4_task_data),
|
||||
initial_cmdsn, INVALID_ENTRY);
|
||||
if (!cls_sess) {
|
||||
ret = QLA_ERROR;
|
||||
goto exit_setup;
|
||||
}
|
||||
|
||||
/*
|
||||
* so calling module_put function to decrement the
|
||||
* reference count.
|
||||
**/
|
||||
module_put(qla4xxx_iscsi_transport.owner);
|
||||
sess = cls_sess->dd_data;
|
||||
ddb_entry = sess->dd_data;
|
||||
ddb_entry->sess = cls_sess;
|
||||
|
||||
cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
|
||||
memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
|
||||
sizeof(struct dev_db_entry));
|
||||
|
||||
qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
|
||||
|
||||
cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id);
|
||||
|
||||
if (!cls_conn) {
|
||||
ret = QLA_ERROR;
|
||||
goto exit_setup;
|
||||
}
|
||||
|
||||
ddb_entry->conn = cls_conn;
|
||||
|
||||
/* Setup ep, for displaying attributes in sysfs */
|
||||
ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
|
||||
if (ep) {
|
||||
ep->conn = cls_conn;
|
||||
cls_conn->ep = ep;
|
||||
} else {
|
||||
DEBUG2(ql4_printk(KERN_ERR, ha, "Unable to get ep\n"));
|
||||
ret = QLA_ERROR;
|
||||
goto exit_setup;
|
||||
}
|
||||
|
||||
/* Update sess/conn params */
|
||||
qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);
|
||||
|
||||
if (is_reset == RESET_ADAPTER) {
|
||||
iscsi_block_session(cls_sess);
|
||||
/* Use the relogin path to discover new devices
|
||||
* by short-circuting the logic of setting
|
||||
* timer to relogin - instead set the flags
|
||||
* to initiate login right away.
|
||||
*/
|
||||
set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
|
||||
set_bit(DF_RELOGIN, &ddb_entry->flags);
|
||||
}
|
||||
|
||||
exit_setup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,
|
||||
struct list_head *list_nt, int is_reset)
|
||||
{
|
||||
struct dev_db_entry *fw_ddb_entry;
|
||||
dma_addr_t fw_ddb_dma;
|
||||
int max_ddbs;
|
||||
int fw_idx_size;
|
||||
int ret;
|
||||
uint32_t idx = 0, next_idx = 0;
|
||||
uint32_t state = 0, conn_err = 0;
|
||||
uint16_t conn_id = 0;
|
||||
struct qla_ddb_index *nt_ddb_idx;
|
||||
|
||||
fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
|
||||
&fw_ddb_dma);
|
||||
if (fw_ddb_entry == NULL) {
|
||||
DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
|
||||
goto exit_nt_list;
|
||||
}
|
||||
max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
|
||||
MAX_DEV_DB_ENTRIES;
|
||||
fw_idx_size = sizeof(struct qla_ddb_index);
|
||||
|
||||
for (idx = 0; idx < max_ddbs; idx = next_idx) {
|
||||
ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
|
||||
NULL, &next_idx, &state,
|
||||
&conn_err, NULL, &conn_id);
|
||||
if (ret == QLA_ERROR)
|
||||
break;
|
||||
|
||||
if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
|
||||
goto continue_next_nt;
|
||||
|
||||
/* Check if NT, then add to list it */
|
||||
if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
|
||||
goto continue_next_nt;
|
||||
|
||||
if (!(state == DDB_DS_NO_CONNECTION_ACTIVE ||
|
||||
state == DDB_DS_SESSION_FAILED))
|
||||
goto continue_next_nt;
|
||||
|
||||
DEBUG2(ql4_printk(KERN_INFO, ha,
|
||||
"Adding DDB to session = 0x%x\n", idx));
|
||||
if (is_reset == INIT_ADAPTER) {
|
||||
nt_ddb_idx = vmalloc(fw_idx_size);
|
||||
if (!nt_ddb_idx)
|
||||
break;
|
||||
|
||||
nt_ddb_idx->fw_ddb_idx = idx;
|
||||
|
||||
memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
|
||||
sizeof(struct dev_db_entry));
|
||||
|
||||
if (qla4xxx_is_flash_ddb_exists(ha, list_nt,
|
||||
fw_ddb_entry) == QLA_SUCCESS) {
|
||||
vfree(nt_ddb_idx);
|
||||
goto continue_next_nt;
|
||||
}
|
||||
list_add_tail(&nt_ddb_idx->list, list_nt);
|
||||
} else if (is_reset == RESET_ADAPTER) {
|
||||
if (qla4xxx_is_session_exists(ha, fw_ddb_entry) ==
|
||||
QLA_SUCCESS)
|
||||
goto continue_next_nt;
|
||||
}
|
||||
|
||||
ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset);
|
||||
if (ret == QLA_ERROR)
|
||||
goto exit_nt_list;
|
||||
|
||||
continue_next_nt:
|
||||
if (next_idx == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
exit_nt_list:
|
||||
if (fw_ddb_entry)
|
||||
dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4xxx_build_ddb_list - Build ddb list and setup sessions
|
||||
* @ha: pointer to adapter structure
|
||||
* @is_reset: Is this init path or reset path
|
||||
*
|
||||
* Create a list of sendtargets (st) from firmware DDBs, issue send targets
|
||||
* using connection open, then create the list of normal targets (nt)
|
||||
* from firmware DDBs. Based on the list of nt setup session and connection
|
||||
* objects.
|
||||
**/
|
||||
void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
|
||||
{
|
||||
uint16_t tmo = 0;
|
||||
struct list_head list_st, list_nt;
|
||||
struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp;
|
||||
unsigned long wtime;
|
||||
|
||||
if (!test_bit(AF_LINK_UP, &ha->flags)) {
|
||||
set_bit(AF_BUILD_DDB_LIST, &ha->flags);
|
||||
ha->is_reset = is_reset;
|
||||
return;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&list_st);
|
||||
INIT_LIST_HEAD(&list_nt);
|
||||
|
||||
qla4xxx_build_st_list(ha, &list_st);
|
||||
|
||||
/* Before issuing conn open mbox, ensure all IPs states are configured
|
||||
* Note, conn open fails if IPs are not configured
|
||||
*/
|
||||
|
@ -4026,153 +4288,32 @@ continue_next_st:
|
|||
}
|
||||
|
||||
/* Wait to ensure all sendtargets are done for min 12 sec wait */
|
||||
tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout);
|
||||
tmo = ((ha->def_timeout > LOGIN_TOV) &&
|
||||
(ha->def_timeout < LOGIN_TOV * 10) ?
|
||||
ha->def_timeout : LOGIN_TOV);
|
||||
|
||||
DEBUG2(ql4_printk(KERN_INFO, ha,
|
||||
"Default time to wait for build ddb %d\n", tmo));
|
||||
|
||||
wtime = jiffies + (HZ * tmo);
|
||||
do {
|
||||
list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st,
|
||||
list) {
|
||||
ret = qla4xxx_get_fwddb_entry(ha,
|
||||
st_ddb_idx->fw_ddb_idx,
|
||||
NULL, 0, NULL, &next_idx,
|
||||
&state, &conn_err, NULL,
|
||||
NULL);
|
||||
if (ret == QLA_ERROR)
|
||||
continue;
|
||||
if (list_empty(&list_st))
|
||||
break;
|
||||
|
||||
if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
|
||||
state == DDB_DS_SESSION_FAILED) {
|
||||
list_del_init(&st_ddb_idx->list);
|
||||
vfree(st_ddb_idx);
|
||||
}
|
||||
}
|
||||
qla4xxx_remove_failed_ddb(ha, &list_st);
|
||||
schedule_timeout_uninterruptible(HZ / 10);
|
||||
} while (time_after(wtime, jiffies));
|
||||
|
||||
/* Free up the sendtargets list */
|
||||
list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
|
||||
list_del_init(&st_ddb_idx->list);
|
||||
vfree(st_ddb_idx);
|
||||
}
|
||||
qla4xxx_free_ddb_list(&list_st);
|
||||
|
||||
for (idx = 0; idx < max_ddbs; idx = next_idx) {
|
||||
ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
|
||||
fw_ddb_dma, NULL,
|
||||
&next_idx, &state, &conn_err,
|
||||
NULL, &conn_id);
|
||||
if (ret == QLA_ERROR)
|
||||
break;
|
||||
qla4xxx_build_nt_list(ha, &list_nt, is_reset);
|
||||
|
||||
if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
|
||||
goto continue_next_nt;
|
||||
|
||||
/* Check if NT, then add to list it */
|
||||
if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
|
||||
goto continue_next_nt;
|
||||
|
||||
if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
|
||||
state == DDB_DS_SESSION_FAILED) {
|
||||
DEBUG2(ql4_printk(KERN_INFO, ha,
|
||||
"Adding DDB to session = 0x%x\n",
|
||||
idx));
|
||||
if (is_reset == INIT_ADAPTER) {
|
||||
nt_ddb_idx = vmalloc(fw_idx_size);
|
||||
if (!nt_ddb_idx)
|
||||
break;
|
||||
|
||||
nt_ddb_idx->fw_ddb_idx = idx;
|
||||
|
||||
memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
|
||||
sizeof(struct dev_db_entry));
|
||||
|
||||
if (qla4xxx_is_flash_ddb_exists(ha, &list_nt,
|
||||
fw_ddb_entry) == QLA_SUCCESS) {
|
||||
vfree(nt_ddb_idx);
|
||||
goto continue_next_nt;
|
||||
}
|
||||
list_add_tail(&nt_ddb_idx->list, &list_nt);
|
||||
} else if (is_reset == RESET_ADAPTER) {
|
||||
if (qla4xxx_is_session_exists(ha,
|
||||
fw_ddb_entry) == QLA_SUCCESS)
|
||||
goto continue_next_nt;
|
||||
}
|
||||
|
||||
/* Create session object, with INVALID_ENTRY,
|
||||
* the targer_id would get set when we issue the login
|
||||
*/
|
||||
cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport,
|
||||
ha->host, cmds_max,
|
||||
sizeof(struct ddb_entry),
|
||||
sizeof(struct ql4_task_data),
|
||||
initial_cmdsn, INVALID_ENTRY);
|
||||
if (!cls_sess)
|
||||
goto exit_ddb_list;
|
||||
|
||||
/*
|
||||
* iscsi_session_setup increments the driver reference
|
||||
* count which wouldn't let the driver to be unloaded.
|
||||
* so calling module_put function to decrement the
|
||||
* reference count.
|
||||
**/
|
||||
module_put(qla4xxx_iscsi_transport.owner);
|
||||
sess = cls_sess->dd_data;
|
||||
ddb_entry = sess->dd_data;
|
||||
ddb_entry->sess = cls_sess;
|
||||
|
||||
cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
|
||||
memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
|
||||
sizeof(struct dev_db_entry));
|
||||
|
||||
qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
|
||||
|
||||
cls_conn = iscsi_conn_setup(cls_sess,
|
||||
sizeof(struct qla_conn),
|
||||
conn_id);
|
||||
if (!cls_conn)
|
||||
goto exit_ddb_list;
|
||||
|
||||
ddb_entry->conn = cls_conn;
|
||||
|
||||
/* Setup ep, for displaying attributes in sysfs */
|
||||
ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
|
||||
if (ep) {
|
||||
ep->conn = cls_conn;
|
||||
cls_conn->ep = ep;
|
||||
} else {
|
||||
DEBUG2(ql4_printk(KERN_ERR, ha,
|
||||
"Unable to get ep\n"));
|
||||
}
|
||||
|
||||
/* Update sess/conn params */
|
||||
qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess,
|
||||
cls_conn);
|
||||
|
||||
if (is_reset == RESET_ADAPTER) {
|
||||
iscsi_block_session(cls_sess);
|
||||
/* Use the relogin path to discover new devices
|
||||
* by short-circuting the logic of setting
|
||||
* timer to relogin - instead set the flags
|
||||
* to initiate login right away.
|
||||
*/
|
||||
set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
|
||||
set_bit(DF_RELOGIN, &ddb_entry->flags);
|
||||
}
|
||||
}
|
||||
continue_next_nt:
|
||||
if (next_idx == 0)
|
||||
break;
|
||||
}
|
||||
exit_ddb_list:
|
||||
qla4xxx_free_nt_list(&list_nt);
|
||||
if (fw_ddb_entry)
|
||||
dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
|
||||
qla4xxx_free_ddb_list(&list_nt);
|
||||
|
||||
qla4xxx_free_ddb_index(ha);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* qla4xxx_probe_adapter - callback function to probe HBA
|
||||
* @pdev: pointer to pci_dev structure
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
* See LICENSE.qla4xxx for copyright and licensing details.
|
||||
*/
|
||||
|
||||
#define QLA4XXX_DRIVER_VERSION "5.02.00-k10"
|
||||
#define QLA4XXX_DRIVER_VERSION "5.02.00-k12"
|
||||
|
|
|
@ -1316,15 +1316,10 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
|
|||
}
|
||||
|
||||
if (scsi_target_is_busy(starget)) {
|
||||
if (list_empty(&sdev->starved_entry))
|
||||
list_add_tail(&sdev->starved_entry,
|
||||
&shost->starved_list);
|
||||
list_move_tail(&sdev->starved_entry, &shost->starved_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We're OK to process the command, so we can't be starved */
|
||||
if (!list_empty(&sdev->starved_entry))
|
||||
list_del_init(&sdev->starved_entry);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -3048,7 +3048,8 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
|
|||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
|
||||
FC_RPORT_DEVLOSS_PENDING);
|
||||
FC_RPORT_DEVLOSS_PENDING |
|
||||
FC_RPORT_DEVLOSS_CALLBK_DONE);
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
||||
/* ensure any stgt delete functions are done */
|
||||
|
|
|
@ -2368,16 +2368,15 @@ static ssize_t
|
|||
sg_proc_write_adio(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
int num;
|
||||
char buff[11];
|
||||
int err;
|
||||
unsigned long num;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
|
||||
return -EACCES;
|
||||
num = (count < 10) ? count : 10;
|
||||
if (copy_from_user(buff, buffer, num))
|
||||
return -EFAULT;
|
||||
buff[num] = '\0';
|
||||
sg_allow_dio = simple_strtoul(buff, NULL, 10) ? 1 : 0;
|
||||
err = kstrtoul_from_user(buffer, count, 0, &num);
|
||||
if (err)
|
||||
return err;
|
||||
sg_allow_dio = num ? 1 : 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -2390,17 +2389,15 @@ static ssize_t
|
|||
sg_proc_write_dressz(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
int num;
|
||||
int err;
|
||||
unsigned long k = ULONG_MAX;
|
||||
char buff[11];
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
|
||||
return -EACCES;
|
||||
num = (count < 10) ? count : 10;
|
||||
if (copy_from_user(buff, buffer, num))
|
||||
return -EFAULT;
|
||||
buff[num] = '\0';
|
||||
k = simple_strtoul(buff, NULL, 10);
|
||||
|
||||
err = kstrtoul_from_user(buffer, count, 0, &k);
|
||||
if (err)
|
||||
return err;
|
||||
if (k <= 1048576) { /* limit "big buff" to 1 MB */
|
||||
sg_big_buff = k;
|
||||
return count;
|
||||
|
|
|
@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev)
|
|||
struct sym_lcb *lp = sym_lp(tp, sdev->lun);
|
||||
unsigned long flags;
|
||||
|
||||
/* if slave_alloc returned before allocating a sym_lcb, return */
|
||||
if (!lp)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(np->s.host->host_lock, flags);
|
||||
|
||||
if (lp->busy_itlq || lp->busy_itl) {
|
||||
|
|
|
@ -82,7 +82,6 @@ fw-shipped-$(CONFIG_SERIAL_8250_CS) += cis/MT5634ZLX.cis cis/RS-COM-2P.cis \
|
|||
fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin
|
||||
fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \
|
||||
advansys/3550.bin advansys/38C0800.bin
|
||||
fw-shipped-$(CONFIG_SCSI_ISCI) += isci/isci_firmware.bin
|
||||
fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \
|
||||
qlogic/12160.bin
|
||||
fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
:10000000495343554F454D42E80018100002000087
|
||||
:1000100000000000000000000101000000000000DE
|
||||
:10002000FFFFCF5F0100000008DD0B0000FC0F00A8
|
||||
:10003000097C0B006EFC0A00FFFFCF5F010000008F
|
||||
:1000400008DD0B0000FC0F00097C0B006EFC0A00B1
|
||||
:10005000FFFFCF5F0100000008DD0B0000FC0F0078
|
||||
:10006000097C0B006EFC0A00FFFFCF5F010000005F
|
||||
:1000700008DD0B0000FC0F00097C0B006EFC0A0081
|
||||
:100080000101000000000000FFFFCF5F0200000040
|
||||
:1000900008DD0B0000FC0F00097C0B006EFC0A0061
|
||||
:1000A000FFFFCF5F0200000008DD0B0000FC0F0027
|
||||
:1000B000097C0B006EFC0A00FFFFCF5F020000000E
|
||||
:1000C00008DD0B0000FC0F00097C0B006EFC0A0031
|
||||
:1000D000FFFFCF5F0200000008DD0B0000FC0F00F7
|
||||
:0800E000097C0B006EFC0A0014
|
||||
:00000001FF
|
|
@ -857,7 +857,7 @@ struct fc_lport {
|
|||
enum fc_lport_state state;
|
||||
unsigned long boot_time;
|
||||
struct fc_host_statistics host_stats;
|
||||
struct fcoe_dev_stats *dev_stats;
|
||||
struct fcoe_dev_stats __percpu *dev_stats;
|
||||
u8 retry_count;
|
||||
|
||||
/* Fabric information */
|
||||
|
|
Загрузка…
Ссылка в новой задаче