Commit da4f58ff authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI misc update from James Bottomley:
 "The patch contains the usual assortment of driver updates (be2iscsi,
  bfa, bnx2i, fcoe, hpsa, isci, lpfc, megaraid, mpt2sas, pm8001, sg)
  plus an assortment of other changes and fixes.  Also new is the fact
  that the isci update is delivered as a git merge (with signed tag)."

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (158 commits)
  isci: End the RNC resumption wait when the RNC is destroyed.
  isci: Fixed RNC bug that lost the suspension or resumption during destroy
  isci: Fix RNC AWAIT_SUSPENSION->INVALIDATING transition.
  isci: Manage the IREQ_NO_AUTO_FREE_TAG under scic_lock.
  isci: Remove obviated host callback list.
  isci: Check IDEV_GONE before performing abort path operations.
  isci: Restore the ATAPI device RNC management code.
  isci: Don't wait for an RNC suspend if it's being destroyed.
  isci: Change the phy control and link reset interface for HW reasons.
  isci: Added timeouts to RNC suspensions in the abort path.
  isci: Add protocol indicator for TMF requests.
  isci: Directly control IREQ_ABORT_PATH_ACTIVE when completing TMFs.
  isci: Wait for RNC resumption before leaving the abort path.
  isci: Fix RNC suspend call for SCI_RESUMING state.
  isci: Manage tag releases differently when aborting tasks.
  isci: Callbacks to libsas occur under scic_lock and are synchronized.
  isci: When in the abort path, defeat other resume calls until done.
  isci: Implement waiting for suspend in the abort path.
  isci: Make sure all TCs are terminated and cleaned in LUN reset.
  isci: Manage the LLHANG timer enable/disable per-device.
  ...
parents ba01a87e e3469333
Release Date : Mon. Mar 19, 2012 17:00:00 PST 2012 -
(emaild-id:megaraidlinux@lsi.com)
Adam Radford
Current Version : 00.00.06.15-rc1
Old Version : 00.00.06.14-rc1
1. Optimize HostMSIxVectors setting.
2. Add fpRead/WriteCapable, fpRead/WriteAcrossStripe checks.
-------------------------------------------------------------------------------
Release Date : Fri. Jan 6, 2012 17:00:00 PST 2010 -
(emaild-id:megaraidlinux@lsi.com)
Adam Radford
......
......@@ -1599,6 +1599,7 @@ F: include/linux/bcma/
BROCADE BFA FC SCSI DRIVER
M: Jing Huang <huangj@brocade.com>
M: Krishna C Gudipati <kgudipat@brocade.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/bfa/
......@@ -6882,6 +6883,14 @@ F: Documentation/cdrom/
F: drivers/cdrom/cdrom.c
F: include/linux/cdrom.h
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
M: Vinayak Holikatti <vinholikatti@gmail.com>
M: Santosh Y <santoshsy@gmail.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: Documentation/scsi/ufs.txt
F: drivers/scsi/ufs/
UNSORTED BLOCK IMAGES (UBI)
M: Artem Bityutskiy <dedekind1@gmail.com>
W: http://www.linux-mtd.infradead.org/
......
......@@ -408,6 +408,7 @@ config BLK_DEV_3W_XXXX_RAID
config SCSI_HPSA
tristate "HP Smart Array SCSI driver"
depends on PCI && SCSI
select CHECK_SIGNATURE
help
This driver supports HP Smart Array Controllers (circa 2009).
It is a SCSI alternative to the cciss driver, which is a block
......
......@@ -424,6 +424,8 @@ static int aac_src_deliver_message(struct fib *fib)
static int aac_src_ioremap(struct aac_dev *dev, u32 size)
{
if (!size) {
iounmap(dev->regs.src.bar1);
dev->regs.src.bar1 = NULL;
iounmap(dev->regs.src.bar0);
dev->base = dev->regs.src.bar0 = NULL;
return 0;
......
......@@ -132,10 +132,6 @@ struct be_ctrl_info {
((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \
(size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K))
/* Byte offset into the page corresponding to given address */
#define OFFSET_IN_PAGE(addr) \
((size_t)(addr) & (PAGE_SIZE_4K-1))
/* Returns bit offset within a DWORD of a bitfield */
#define AMAP_BIT_OFFSET(_struct, field) \
(((size_t)&(((_struct *)0)->field))%32)
......
......@@ -15,6 +15,8 @@
* Costa Mesa, CA 92626
*/
#include <scsi/iscsi_proto.h>
#include "be.h"
#include "be_mgmt.h"
#include "be_main.h"
......
......@@ -23,7 +23,7 @@
* firmware in the BE. These requests are communicated to the processor
* using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one
* WRB inside a MAILBOX.
* The commands are serviced by the ARM processor in the BladeEngine's MPU.
* The commands are serviced by the ARM processor in the OneConnect's MPU.
*/
struct be_sge {
u32 pa_lo;
......@@ -163,7 +163,8 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3
#define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7
#define OPCODE_COMMON_ISCSI_NTWK_SET_VLAN 14
#define OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR 17
#define OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR 17
#define OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR 18
#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR 21
#define OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY 22
#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY 23
......@@ -274,11 +275,11 @@ struct mgmt_conn_login_options {
struct mgmt_auth_method_format auth_data;
} __packed;
struct ip_address_format {
struct ip_addr_format {
u16 size_of_structure;
u8 reserved;
u8 ip_type;
u8 ip_address[16];
u8 addr[16];
u32 rsvd0;
} __packed;
......@@ -290,9 +291,9 @@ struct mgmt_conn_info {
u16 dest_port_redirected;
u16 cid;
u32 estimated_throughput;
struct ip_address_format src_ipaddr;
struct ip_address_format dest_ipaddr;
struct ip_address_format dest_ipaddr_redirected;
struct ip_addr_format src_ipaddr;
struct ip_addr_format dest_ipaddr;
struct ip_addr_format dest_ipaddr_redirected;
struct mgmt_conn_login_options negotiated_login_options;
} __packed;
......@@ -322,43 +323,115 @@ struct mgmt_session_info {
struct mgmt_conn_info conn_list[1];
} __packed;
struct be_cmd_req_get_session {
struct be_cmd_get_session_req {
struct be_cmd_req_hdr hdr;
u32 session_handle;
} __packed;
struct be_cmd_resp_get_session {
struct be_cmd_get_session_resp {
struct be_cmd_resp_hdr hdr;
struct mgmt_session_info session_info;
} __packed;
struct mac_addr {
u16 size_of_struct;
u16 size_of_structure;
u8 addr[ETH_ALEN];
} __packed;
struct be_cmd_req_get_boot_target {
struct be_cmd_get_boot_target_req {
struct be_cmd_req_hdr hdr;
} __packed;
struct be_cmd_resp_get_boot_target {
struct be_cmd_get_boot_target_resp {
struct be_cmd_resp_hdr hdr;
u32 boot_session_count;
int boot_session_handle;
};
struct be_cmd_req_mac_query {
struct be_cmd_mac_query_req {
struct be_cmd_req_hdr hdr;
u8 type;
u8 permanent;
u16 if_id;
} __packed;
struct be_cmd_resp_mac_query {
struct be_cmd_get_mac_resp {
struct be_cmd_resp_hdr hdr;
struct mac_addr mac;
};
struct be_ip_addr_subnet_format {
u16 size_of_structure;
u8 ip_type;
u8 ipv6_prefix_length;
u8 addr[16];
u8 subnet_mask[16];
u32 rsvd0;
} __packed;
struct be_cmd_get_if_info_req {
struct be_cmd_req_hdr hdr;
u32 interface_hndl;
u32 ip_type;
} __packed;
struct be_cmd_get_if_info_resp {
struct be_cmd_req_hdr hdr;
u32 interface_hndl;
u32 vlan_priority;
u32 ip_addr_count;
u32 dhcp_state;
struct be_ip_addr_subnet_format ip_addr;
} __packed;
struct be_ip_addr_record {
u32 action;
u32 interface_hndl;
struct be_ip_addr_subnet_format ip_addr;
u32 status;
} __packed;
struct be_ip_addr_record_params {
u32 record_entry_count;
struct be_ip_addr_record ip_record;
} __packed;
struct be_cmd_set_ip_addr_req {
struct be_cmd_req_hdr hdr;
struct be_ip_addr_record_params ip_params;
} __packed;
struct be_cmd_set_dhcp_req {
struct be_cmd_req_hdr hdr;
u32 interface_hndl;
u32 ip_type;
u32 flags;
u32 retry_count;
} __packed;
struct be_cmd_rel_dhcp_req {
struct be_cmd_req_hdr hdr;
u32 interface_hndl;
u32 ip_type;
} __packed;
struct be_cmd_set_def_gateway_req {
struct be_cmd_req_hdr hdr;
u32 action;
struct ip_addr_format ip_addr;
} __packed;
struct be_cmd_get_def_gateway_req {
struct be_cmd_req_hdr hdr;
u32 ip_type;
} __packed;
struct be_cmd_get_def_gateway_resp {
struct be_cmd_req_hdr hdr;
struct ip_addr_format ip_addr;
} __packed;
/******************** Create CQ ***************************/
/**
* Pseudo amap definition in which each bit of the actual structure is defined
......@@ -489,7 +562,7 @@ struct be_cmd_req_modify_eq_delay {
#define ETH_ALEN 6
struct be_cmd_req_get_mac_addr {
struct be_cmd_get_nic_conf_req {
struct be_cmd_req_hdr hdr;
u32 nic_port_count;
u32 speed;
......@@ -501,7 +574,7 @@ struct be_cmd_req_get_mac_addr {
u32 rsvd[23];
};
struct be_cmd_resp_get_mac_addr {
struct be_cmd_get_nic_conf_resp {
struct be_cmd_resp_hdr hdr;
u32 nic_port_count;
u32 speed;
......@@ -513,6 +586,39 @@ struct be_cmd_resp_get_mac_addr {
u32 rsvd[23];
};
#define BEISCSI_ALIAS_LEN 32
struct be_cmd_hba_name {
struct be_cmd_req_hdr hdr;
u16 flags;
u16 rsvd0;
u8 initiator_name[ISCSI_NAME_LEN];
u8 initiator_alias[BEISCSI_ALIAS_LEN];
} __packed;
struct be_cmd_ntwk_link_status_req {
struct be_cmd_req_hdr hdr;
u32 rsvd0;
} __packed;
/*** Port Speed Values ***/
#define BE2ISCSI_LINK_SPEED_ZERO 0x00
#define BE2ISCSI_LINK_SPEED_10MBPS 0x01
#define BE2ISCSI_LINK_SPEED_100MBPS 0x02
#define BE2ISCSI_LINK_SPEED_1GBPS 0x03
#define BE2ISCSI_LINK_SPEED_10GBPS 0x04
struct be_cmd_ntwk_link_status_resp {
struct be_cmd_resp_hdr hdr;
u8 phys_port;
u8 mac_duplex;
u8 mac_speed;
u8 mac_fault;
u8 mgmt_mac_duplex;
u8 mgmt_mac_speed;
u16 qos_link_speed;
u32 logical_link_speed;
} __packed;
int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
struct be_queue_info *eq, int eq_delay);
......@@ -530,11 +636,8 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
int be_poll_mcc(struct be_ctrl_info *ctrl);
int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba);
unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba);
unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba);
unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba,
u32 boot_session_handle,
struct be_dma_mem *nonemb_cmd);
unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba);
void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
/*ISCSI Functuions */
......@@ -715,7 +818,7 @@ struct be_eq_delay_params_in {
struct tcp_connect_and_offload_in {
struct be_cmd_req_hdr hdr;
struct ip_address_format ip_address;
struct ip_addr_format ip_address;
u16 tcp_port;
u16 cid;
u16 cq_id;
......@@ -792,13 +895,14 @@ struct be_fw_cfg {
u32 function_caps;
} __packed;
struct be_all_if_id {
struct be_cmd_get_all_if_id_req {
struct be_cmd_req_hdr hdr;
u32 if_count;
u32 if_hndl_list[1];
} __packed;
#define ISCSI_OPCODE_SCSI_DATA_OUT 5
#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5
#define OPCODE_COMMON_MODIFY_EQ_DELAY 41
#define OPCODE_COMMON_ISCSI_CLEANUP 59
#define OPCODE_COMMON_TCP_UPLOAD 56
......@@ -810,6 +914,8 @@ struct be_all_if_id {
#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
#define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
#define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52
#define OPCODE_COMMON_WRITE_FLASH 96
#define OPCODE_COMMON_READ_FLASH 97
/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
#define CMD_ISCSI_COMMAND_INVALIDATE 1
......
This diff is collapsed.
......@@ -25,6 +25,21 @@
#define BE2_IPV4 0x1
#define BE2_IPV6 0x10
#define BE2_DHCP_V4 0x05
#define NON_BLOCKING 0x0
#define BLOCKING 0x1
void beiscsi_create_def_ifaces(struct beiscsi_hba *phba);
void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba);
int be2iscsi_iface_get_param(struct iscsi_iface *iface,
enum iscsi_param_type param_type,
int param, char *buf);
int be2iscsi_iface_set_param(struct Scsi_Host *shost,
void *data, uint32_t count);
umode_t be2iscsi_attr_is_visible(int param_type, int param);
......
This diff is collapsed.
......@@ -34,9 +34,9 @@
#include "be.h"
#define DRV_NAME "be2iscsi"
#define BUILD_STR "4.1.239.0"
#define BE_NAME "ServerEngines BladeEngine2" \
"Linux iSCSI Driver version" BUILD_STR
#define BUILD_STR "4.2.162.0"
#define BE_NAME "Emulex OneConnect" \
"Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
#define BE_VENDOR_ID 0x19A2
......@@ -316,6 +316,8 @@ struct beiscsi_hba {
struct iscsi_endpoint **ep_array;
struct iscsi_boot_kset *boot_kset;
struct Scsi_Host *shost;
struct iscsi_iface *ipv4_iface;
struct iscsi_iface *ipv6_iface;
struct {
/**
* group together since they are used most frequently
......@@ -345,7 +347,7 @@ struct beiscsi_hba {
struct work_struct work_cqs; /* The work being queued */
struct be_ctrl_info ctrl;
unsigned int generation;
unsigned int read_mac_address;
unsigned int interface_handle;
struct mgmt_session_info boot_sess;
struct invalidate_command_table inv_tbl[128];
......@@ -525,8 +527,6 @@ struct hwi_async_pdu_context {
unsigned int free_entries;
unsigned int busy_entries;
unsigned int buffer_size;
unsigned int num_entries;
struct list_head free_list;
} async_header;
......@@ -543,11 +543,12 @@ struct hwi_async_pdu_context {
unsigned int free_entries;
unsigned int busy_entries;
unsigned int buffer_size;
struct list_head free_list;
unsigned int num_entries;
} async_data;
unsigned int buffer_size;
unsigned int num_entries;
/**
* This is a varying size list! Do not add anything
* after this entry!!
......
This diff is collapsed.
......@@ -20,11 +20,16 @@
#ifndef _BEISCSI_MGMT_
#define _BEISCSI_MGMT_
#include <linux/types.h>
#include <linux/list.h>
#include <scsi/scsi_bsg_iscsi.h>
#include "be_iscsi.h"
#include "be_main.h"
#define IP_ACTION_ADD 0x01
#define IP_ACTION_DEL 0x02
#define IP_V6_LEN 16
#define IP_V4_LEN 4
/**
* Pseudo amap definition in which each bit of the actual structure is defined
* as a byte: used to calculate offset/shift/mask of each field
......@@ -98,6 +103,10 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invalidate_command_table *inv_tbl,
unsigned int num_invalidate, unsigned int cid,
struct be_dma_mem *nonemb_cmd);
unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba,
struct bsg_job *job,
struct be_dma_mem *nonemb_cmd);
struct iscsi_invalidate_connection_params_in {
struct be_cmd_req_hdr hdr;
......@@ -204,6 +213,13 @@ struct be_mgmt_controller_attributes_resp {
struct mgmt_controller_attributes params;
} __packed;
struct be_bsg_vendor_cmd {
struct be_cmd_req_hdr hdr;
unsigned short region;
unsigned short offset;
unsigned short sector;
} __packed;
/* configuration management */
#define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws)
......@@ -225,6 +241,9 @@ struct be_mgmt_controller_attributes_resp {
bus_address.u.a32.address_hi; \
}
#define BEISCSI_WRITE_FLASH 0
#define BEISCSI_READ_FLASH 1
struct beiscsi_endpoint {
struct beiscsi_hba *phba;
struct beiscsi_sess *sess;
......@@ -248,4 +267,27 @@ unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
unsigned short issue_reset,
unsigned short savecfg_flag);
int mgmt_set_ip(struct beiscsi_hba *phba,
struct iscsi_iface_param_info *ip_param,
struct iscsi_iface_param_info *subnet_param,
uint32_t boot_proto);
unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba);
unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
u32 boot_session_handle,
struct be_dma_mem *nonemb_cmd);
int mgmt_get_nic_conf(struct beiscsi_hba *phba,
struct be_cmd_get_nic_conf_resp *mac);
int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
struct be_cmd_get_if_info_resp *if_info);
int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
struct be_cmd_get_def_gateway_resp *gateway);
int mgmt_set_gateway(struct beiscsi_hba *phba,
struct iscsi_iface_param_info *gateway_param);
#endif
......@@ -799,9 +799,6 @@ struct bfad_port_s *bfa_fcb_lport_new(struct bfad_s *bfad,
enum bfa_lport_role roles,
struct bfad_vf_s *vf_drv,
struct bfad_vport_s *vp_drv);
void bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
struct bfad_vf_s *vf_drv,
struct bfad_vport_s *vp_drv);
/*
* vport callbacks
......
......@@ -616,7 +616,7 @@ bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
__port_action[port->fabric->fab_type].online(port);
wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
BFA_LOG(KERN_INFO, bfad, bfa_log_level,
BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
"Logical port online: WWN = %s Role = %s\n",
lpwwn_buf, "Initiator");
bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_ONLINE);
......@@ -639,12 +639,12 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
if (bfa_sm_cmp_state(port->fabric,
bfa_fcs_fabric_sm_online) == BFA_TRUE) {
BFA_LOG(KERN_ERR, bfad, bfa_log_level,
BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
"Logical port lost fabric connectivity: WWN = %s Role = %s\n",
lpwwn_buf, "Initiator");
bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
} else {
BFA_LOG(KERN_INFO, bfad, bfa_log_level,
BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
"Logical port taken offline: WWN = %s Role = %s\n",
lpwwn_buf, "Initiator");
bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_OFFLINE);
......@@ -709,14 +709,10 @@ bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DELETE);
/* Base port will be deleted by the OS driver */
if (port->vport) {
bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
port->fabric->vf_drv,
port->vport ? port->vport->vport_drv : NULL);
if (port->vport)
bfa_fcs_vport_delete_comp(port->vport);
} else {
else
bfa_wc_down(&port->fabric->wc);
}
}
......@@ -5714,17 +5710,23 @@ bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
(struct bfad_vport_s *)vport->vport_drv;
bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
bfa_lps_delete(vport->lps);
if (vport_drv->comp_del)
if (vport_drv->comp_del) {
complete(vport_drv->comp_del);
else
kfree(vport_drv);
return;
}
bfa_lps_delete(vport->lps);
/*
* We queue the vport delete work to the IM work_q from here.
* The memory for the bfad_vport_s is freed from the FC function
* template vport_delete entry point.
*/
if (vport_drv)
bfad_im_port_delete(vport_drv->drv_port.bfad,
&vport_drv->drv_port);
}
/*
* fcs_vport_public FCS virtual port public interfaces
*/
......
......@@ -456,23 +456,6 @@ bfa_fcb_lport_new(struct bfad_s *bfad, struct bfa_fcs_lport_s *port,
return port_drv;
}
void
bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
{
struct bfad_port_s *port_drv;
/* this will be only called from rmmod context */
if (vp_drv && !vp_drv->comp_del) {
port_drv = (vp_drv) ? (&(vp_drv)->drv_port) :
((vf_drv) ? (&(vf_drv)->base_port) :
(&(bfad)->pport));
bfa_trc(bfad, roles);
if (roles & BFA_LPORT_ROLE_FCP_IM)
bfad_im_port_delete(bfad, port_drv);
}
}
/*
* FCS RPORT alloc callback, after successful PLOGI by FCS
*/
......
......@@ -497,6 +497,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport)
if (im_port->flags & BFAD_PORT_DELETE) {
bfad_scsi_host_free(bfad, im_port);
list_del(&vport->list_entry);
kfree(vport);
return 0;
}
......@@ -758,25 +759,10 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
else if (!strcmp(model, "Brocade-804"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 8Gbps FC HBA for HP Bladesystem C-class");
else if (!strcmp(model, "Brocade-902") ||
!strcmp(model, "Brocade-1741"))
else if (!strcmp(model, "Brocade-1741"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 10Gbps CNA for Dell M-Series Blade Servers");
else if (strstr(model, "Brocade-1560")) {
if (nports == 1)
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 16Gbps PCIe single port FC HBA");
else
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 16Gbps PCIe dual port FC HBA");
} else if (strstr(model, "Brocade-1710")) {
if (nports == 1)
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 10Gbps single port CNA");
else
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 10Gbps dual port CNA");
} else if (strstr(model, "Brocade-1860")) {
else if (strstr(model, "Brocade-1860")) {
if (nports == 1 && bfa_ioc_is_cna(&bfad->bfa.ioc))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 10Gbps single port CNA");
......
/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
*
* Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2006 - 2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......
/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
*
* Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2006 - 2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......
/* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
*
* Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2006 - 2012 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
......
/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
*
* Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2006 - 2012 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
......
/* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
*
* Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2006 - 2012 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
......@@ -18,8 +18,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
static u32 adapter_count;
#define DRV_MODULE_NAME "bnx2i"
#define DRV_MODULE_VERSION "2.7.0.3"
#define DRV_MODULE_RELDATE "Jun 15, 2011"
#define DRV_MODULE_VERSION "2.7.2.2"
#define DRV_MODULE_RELDATE "Apr 25, 2012"
static char version[] __devinitdata =
"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
......
/*
* bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
*
* Copyright (c) 2006 - 2011 Broadcom Corporation
* Copyright (c) 2006 - 2012 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
......@@ -2244,6 +2244,7 @@ static struct scsi_host_template bnx2i_host_template = {
.eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target,
.change_queue_depth = iscsi_change_queue_depth,
.target_alloc = iscsi_target_alloc,
.can_queue = 2048,
.max_sectors = 127,
.cmd_per_lun = 128,
......
/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
*
* Copyright (c) 2004 - 2011 Broadcom Corporation
* Copyright (c) 2004 - 2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......
......@@ -55,11 +55,16 @@
#define ALUA_FAILOVER_TIMEOUT (60 * HZ)
#define ALUA_FAILOVER_RETRIES 5
/* flags passed from user level */
#define ALUA_OPTIMIZE_STPG 1
struct alua_dh_data {
int group_id;
int rel_port;
int tpgs;
int state;
int pref;
unsigned flags; /* used for optimizing STPG */
unsigned char inq[ALUA_INQUIRY_SIZE];
unsigned char *buff;
int bufflen;
......@@ -554,14 +559,16 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
for (k = 4, ucp = h->buff + 4; k < len; k += off, ucp += off) {
if (h->group_id == (ucp[2] << 8) + ucp[3]) {
h->state = ucp[0] & 0x0f;
h->pref = ucp[0] >> 7;
valid_states = ucp[1];
}
off = 8 + (ucp[7] * 4);
}
sdev_printk(KERN_INFO, sdev,
"%s: port group %02x state %c supports %c%c%c%c%c%c%c\n",
"%s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n",
ALUA_DH_NAME, h->group_id, print_alua_state(h->state),
h->pref ? "preferred" : "non-preferred",
valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
......@@ -621,6 +628,37 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
out:
return err;
}
/*
* alua_set_params - set/unset the optimize flag
* @sdev: device on the path to be activated
* params - parameters in the following format
* "no_of_params\0param1\0param2\0param3\0...\0"
* For example, to set the flag pass the following parameters
* from multipath.conf
* hardware_handler "2 alua 1"
*/
static int alua_set_params(struct scsi_device *sdev, const char *params)
{
struct alua_dh_data *h = get_alua_data(sdev);
unsigned int optimize = 0, argc;
const char *p = params;
int result = SCSI_DH_OK;
if ((sscanf(params, "%u", &argc) != 1) || (argc != 1))
return -EINVAL;
while (*p++)
;
if ((sscanf(p, "%u", &optimize) != 1) || (optimize > 1))
return -EINVAL;
if (optimize)
h->flags |= ALUA_OPTIMIZE_STPG;
else
h->flags &= ~ALUA_OPTIMIZE_STPG;
return result;
}
/*
* alua_activate - activate a path
......@@ -637,14 +675,37 @@ static int alua_activate(struct scsi_device *sdev,
{
struct alua_dh_data *h = get_alua_data(sdev);
int err = SCSI_DH_OK;
int stpg = 0;
err = alua_rtpg(sdev, h);
if (err != SCSI_DH_OK)
goto out;
if (h->tpgs & TPGS_MODE_EXPLICIT &&
h->state != TPGS_STATE_OPTIMIZED &&
h->state != TPGS_STATE_LBA_DEPENDENT) {
if (h->tpgs & TPGS_MODE_EXPLICIT) {
switch (h->state) {
case TPGS_STATE_NONOPTIMIZED:
stpg = 1;
if ((h->flags & ALUA_OPTIMIZE_STPG) &&
(!h->pref) &&
(h->tpgs & TPGS_MODE_IMPLICIT))
stpg = 0;
break;
case TPGS_STATE_STANDBY:
stpg = 1;
break;
case TPGS_STATE_UNAVAILABLE:
case TPGS_STATE_OFFLINE:
err = SCSI_DH_IO;
break;
case TPGS_STATE_TRANSITIONING:
err = SCSI_DH_RETRY;
break;
default:
break;
}
}
if (stpg) {
h->callback_fn = fn;
h->callback_data = data;
err = submit_stpg(h);
......@@ -698,6 +759,7 @@ static struct scsi_device_handler alua_dh = {
.prep_fn = alua_prep_fn,
.check_sense = alua_check_sense,
.activate = alua_activate,
.set_params = alua_set_params,
.match = alua_match,
};
......
......@@ -411,20 +411,18 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
}
/**
* fcoe_interface_cleanup() - Clean up a FCoE interface
* fcoe_interface_remove() - remove FCoE interface from netdev
* @fcoe: The FCoE interface to be cleaned up
*
* Caller must be holding the RTNL mutex
*/
static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
static void fcoe_interface_remove(struct fcoe_interface *fcoe)
{
struct net_device *netdev = fcoe->netdev;
struct fcoe_ctlr *fip = &fcoe->ctlr;
u8 flogi_maddr[ETH_ALEN];
const struct net_device_ops *ops;
rtnl_lock();
/*
* Don't listen for Ethernet packets anymore.
* synchronize_net() ensures that the packet handlers are not running
......@@ -453,12 +451,28 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE"
" specific feature for LLD.\n");
}
fcoe->removed = 1;
}
/**
* fcoe_interface_cleanup() - Clean up a FCoE interface
* @fcoe: The FCoE interface to be cleaned up
*/
static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
{
struct net_device *netdev = fcoe->netdev;
struct fcoe_ctlr *fip = &fcoe->ctlr;
rtnl_lock();
if (!fcoe->removed)
fcoe_interface_remove(fcoe);
rtnl_unlock();
/* Release the self-reference taken during fcoe_interface_create() */
/* tear-down the FCoE controller */
fcoe_ctlr_destroy(fip);
scsi_host_put(fcoe->ctlr.lp->host);
kfree(fcoe);
dev_put(netdev);
module_put(THIS_MODULE);
......@@ -522,13 +536,11 @@ static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr)
struct fcoe_port *port = lport_priv(lport);
struct fcoe_interface *fcoe = port->priv;
rtnl_lock();
if (!is_zero_ether_addr(port->data_src_addr))
dev_uc_del(fcoe->netdev, port->data_src_addr);
if (!is_zero_ether_addr(addr))
dev_uc_add(fcoe->netdev, addr);
memcpy(port->data_src_addr, addr, ETH_ALEN);
rtnl_unlock();
}
/**
......@@ -941,6 +953,10 @@ static void fcoe_if_destroy(struct fc_lport *lport)
rtnl_lock();
if (!is_zero_ether_addr(port->data_src_addr))
dev_uc_del(netdev, port->data_src_addr);
if (lport->vport)
synchronize_net();
else
fcoe_interface_remove(fcoe);
rtnl_unlock();
/* Free queued packets for the per-CPU receive threads */
......@@ -959,7 +975,11 @@ static void fcoe_if_destroy(struct fc_lport *lport)
/* Free memory used by statistical counters */
fc_lport_free_stats(lport);
/* Release the Scsi_Host */
/*
* Release the Scsi_Host for vport but hold on to
* master lport until it fcoe interface fully cleaned-up.
*/
if (lport->vport)
scsi_host_put(lport->host);
}
......@@ -2274,10 +2294,9 @@ static void fcoe_percpu_clean(struct fc_lport *lport)
continue;
skb = dev_alloc_skb(0);
if (!skb) {
spin_unlock_bh(&pp->fcoe_rx_list.lock);
if (!skb)
continue;
}
skb->destructor = fcoe_percpu_flush_done;
spin_lock_bh(&pp->fcoe_rx_list.lock);
......
......@@ -71,7 +71,8 @@ do { \
* @ctlr: The FCoE controller (for FIP)
* @oem: The offload exchange manager for all local port
* instances associated with this port
* This structure is 1:1 with a net devive.
* @removed: Indicates fcoe interface removed from net device
* This structure is 1:1 with a net device.
*/
struct fcoe_interface {
struct list_head list;
......@@ -81,6 +82,7 @@ struct fcoe_interface {
struct packet_type fip_packet_type;
struct fcoe_ctlr ctlr;
struct fc_exch_mgr *oem;
u8 removed;
};
#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr)
......
......@@ -1883,7 +1883,13 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
frame = (struct fip_frame *)skb->data;
memset(frame, 0, len);
memcpy(frame->eth.h_dest, dest, ETH_ALEN);
if (sub == FIP_SC_VN_BEACON) {
hton24(frame->eth.h_source, FIP_VN_FC_MAP);
hton24(frame->eth.h_source + 3, fip->port_id);
} else {
memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
}
frame->eth.h_proto = htons(ETH_P_FIP);
frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
......
This diff is collapsed.
......@@ -34,7 +34,7 @@ struct access_method {
void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
unsigned long (*fifo_full)(struct ctlr_info *h);
bool (*intr_pending)(struct ctlr_info *h);
unsigned long (*command_completed)(struct ctlr_info *h);
unsigned long (*command_completed)(struct ctlr_info *h, u8 q);
};
struct hpsa_scsi_dev_t {
......@@ -48,6 +48,13 @@ struct hpsa_scsi_dev_t {
unsigned char raid_level; /* from inquiry page 0xC1 */
};
struct reply_pool {
u64 *head;
size_t size;
u8 wraparound;
u32 current_entry;
};
struct ctlr_info {
int ctlr;
char devname[8];
......@@ -68,7 +75,7 @@ struct ctlr_info {
# define DOORBELL_INT 1
# define SIMPLE_MODE_INT 2
# define MEMQ_MODE_INT 3
unsigned int intr[4];
unsigned int intr[MAX_REPLY_QUEUES];
unsigned int msix_vector;
unsigned int msi_vector;
int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
......@@ -78,7 +85,6 @@ struct ctlr_info {
struct list_head reqQ;
struct list_head cmpQ;
unsigned int Qdepth;
unsigned int maxQsinceinit;
unsigned int maxSG;
spinlock_t lock;
int maxsgentries;
......@@ -111,20 +117,45 @@ struct ctlr_info {
unsigned long transMethod;
/*
* Performant mode completion buffer
* Performant mode completion buffers
*/
u64 *reply_pool;
dma_addr_t reply_pool_dhandle;
u64 *reply_pool_head;
size_t reply_pool_size;
unsigned char reply_pool_wraparound;
struct reply_pool reply_queue[MAX_REPLY_QUEUES];
u8 nreply_queues;
dma_addr_t reply_pool_dhandle;
u32 *blockFetchTable;
unsigned char *hba_inquiry_data;
u64 last_intr_timestamp;
u32 last_heartbeat;
u64 last_heartbeat_timestamp;
u32 heartbeat_sample_interval;
atomic_t firmware_flash_in_progress;
u32 lockup_detected;
struct list_head lockup_list;
/* Address of h->q[x] is passed to intr handler to know which queue */
u8 q[MAX_REPLY_QUEUES];
u32 TMFSupportFlags; /* cache what task mgmt funcs are supported. */
#define HPSATMF_BITS_SUPPORTED (1 << 0)
#define HPSATMF_PHYS_LUN_RESET (1 << 1)
#define HPSATMF_PHYS_NEX_RESET (1 << 2)
#define HPSATMF_PHYS_TASK_ABORT (1 << 3)
#define HPSATMF_PHYS_TSET_ABORT (1 << 4)
#define HPSATMF_PHYS_CLEAR_ACA (1 << 5)
#define HPSATMF_PHYS_CLEAR_TSET (1 << 6)
#define HPSATMF_PHYS_QRY_TASK (1 << 7)
#define HPSATMF_PHYS_QRY_TSET (1 << 8)
#define HPSATMF_PHYS_QRY_ASYNC (1 << 9)
#define HPSATMF_MASK_SUPPORTED (1 << 16)
#define HPSATMF_LOG_LUN_RESET (1 << 17)
#define HPSATMF_LOG_NEX_RESET (1 << 18)
#define HPSATMF_LOG_TASK_ABORT (1 << 19)
#define HPSATMF_LOG_TSET_ABORT (1 << 20)
#define HPSATMF_LOG_CLEAR_ACA (1 << 21)
#define HPSATMF_LOG_CLEAR_TSET (1 << 22)
#define HPSATMF_LOG_QRY_TASK (1 << 23)
#define HPSATMF_LOG_QRY_TSET (1 << 24)
#define HPSATMF_LOG_QRY_ASYNC (1 << 25)
};
#define HPSA_ABORT_MSG 0
#define HPSA_DEVICE_RESET_MSG 1
......@@ -216,9 +247,6 @@ static void SA5_submit_command(struct ctlr_info *h,
c->Header.Tag.lower);
writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
(void) readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
h->commands_outstanding++;
if (h->commands_outstanding > h->max_outstanding)
h->max_outstanding = h->commands_outstanding;
}
/*
......@@ -254,16 +282,17 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
}
}
static unsigned long SA5_performant_completed(struct ctlr_info *h)
static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
{
unsigned long register_value = FIFO_EMPTY;
struct reply_pool *rq = &h->reply_queue[q];
unsigned long flags, register_value = FIFO_EMPTY;
/* msi auto clears the interrupt pending bit. */
if (!(h->msi_vector || h->msix_vector)) {
/* flush the controller write of the reply queue by reading
* outbound doorbell status register.
*/
register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
/* msi auto clears the interrupt pending bit. */
if (!(h->msi_vector || h->msix_vector)) {
writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR);
/* Do a read in order to flush the write to the controller
* (as per spec.)
......@@ -271,19 +300,20 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h)
register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
}
if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
register_value = *(h->reply_pool_head);
(h->reply_pool_head)++;
if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
register_value = rq->head[rq->current_entry];
rq->current_entry++;
spin_lock_irqsave(&h->lock, flags);
h->commands_outstanding--;
spin_unlock_irqrestore(&h->lock, flags);
} else {
register_value = FIFO_EMPTY;
}
/* Check for wraparound */
if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
h->reply_pool_head = h->reply_pool;
h->reply_pool_wraparound ^= 1;
if (rq->current_entry == h->max_commands) {
rq->current_entry = 0;
rq->wraparound ^= 1;
}
return register_value;
}
......@@ -303,13 +333,18 @@ static unsigned long SA5_fifo_full(struct ctlr_info *h)
* returns value read from hardware.
* returns FIFO_EMPTY if there is nothing to read
*/
static unsigned long SA5_completed(struct ctlr_info *h)
static unsigned long SA5_completed(struct ctlr_info *h,
__attribute__((unused)) u8 q)
{
unsigned long register_value
= readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
unsigned long flags;
if (register_value != FIFO_EMPTY)
if (register_value != FIFO_EMPTY) {
spin_lock_irqsave(&h->lock, flags);
h->commands_outstanding--;
spin_unlock_irqrestore(&h->lock, flags);
}
#ifdef HPSA_DEBUG
if (register_value != FIFO_EMPTY)
......
......@@ -82,6 +82,29 @@
#define TYPE_CMD 0x00
#define TYPE_MSG 0x01
/* Message Types */
#define HPSA_TASK_MANAGEMENT 0x00
#define HPSA_RESET 0x01
#define HPSA_SCAN 0x02
#define HPSA_NOOP 0x03
#define HPSA_CTLR_RESET_TYPE 0x00
#define HPSA_BUS_RESET_TYPE 0x01
#define HPSA_TARGET_RESET_TYPE 0x03
#define HPSA_LUN_RESET_TYPE 0x04
#define HPSA_NEXUS_RESET_TYPE 0x05
/* Task Management Functions */
#define HPSA_TMF_ABORT_TASK 0x00
#define HPSA_TMF_ABORT_TASK_SET 0x01
#define HPSA_TMF_CLEAR_ACA 0x02
#define HPSA_TMF_CLEAR_TASK_SET 0x03
#define HPSA_TMF_QUERY_TASK 0x04
#define HPSA_TMF_QUERY_TASK_SET 0x05
#define HPSA_TMF_QUERY_ASYNCEVENT 0x06
/* config space register offsets */
#define CFG_VENDORID 0x00
#define CFG_DEVICEID 0x02
......@@ -106,6 +129,7 @@
#define CFGTBL_Trans_Simple 0x00000002l
#define CFGTBL_Trans_Performant 0x00000004l
#define CFGTBL_Trans_use_short_tags 0x20000000l
#define CFGTBL_Trans_enable_directed_msix (1 << 30)
#define CFGTBL_BusType_Ultra2 0x00000001l
#define CFGTBL_BusType_Ultra3 0x00000002l
......@@ -162,6 +186,7 @@ struct SenseSubsystem_info {
#define BMIC_WRITE 0x27
#define BMIC_CACHE_FLUSH 0xc2
#define HPSA_CACHE_FLUSH 0x01 /* C2 was already being used by HPSA */
#define BMIC_FLASH_FIRMWARE 0xF7
/* Command List Structure */
union SCSI3Addr {
......@@ -337,11 +362,17 @@ struct CfgTable {
u32 MaxPhysicalDevices;
u32 MaxPhysicalDrivesPerLogicalUnit;
u32 MaxPerformantModeCommands;
u8 reserved[0x78 - 0x58];
u32 MaxBlockFetch;
u32 PowerConservationSupport;
u32 PowerConservationEnable;
u32 TMFSupportFlags;
u8 TMFTagMask[8];
u8 reserved[0x78 - 0x70];
u32 misc_fw_support; /* offset 0x78 */
#define MISC_FW_DOORBELL_RESET (0x02)
#define MISC_FW_DOORBELL_RESET2 (0x010)
u8 driver_version[32];
};
#define NUM_BLOCKFETCH_ENTRIES 8
......@@ -351,8 +382,8 @@ struct TransTable_struct {
u32 RepQCount;
u32 RepQCtrAddrLow32;
u32 RepQCtrAddrHigh32;
u32 RepQAddr0Low32;
u32 RepQAddr0High32;
#define MAX_REPLY_QUEUES 8
struct vals32 RepQAddr[MAX_REPLY_QUEUES];
};
struct hpsa_pci_info {
......
This diff is collapsed.
......@@ -55,6 +55,7 @@
#ifndef _SCI_HOST_H_
#define _SCI_HOST_H_
#include <scsi/sas_ata.h>
#include "remote_device.h"
#include "phy.h"
#include "isci.h"
......@@ -108,6 +109,8 @@ struct sci_port_configuration_agent;
typedef void (*port_config_fn)(struct isci_host *,
struct sci_port_configuration_agent *,
struct isci_port *, struct isci_phy *);
bool is_port_config_apc(struct isci_host *ihost);
bool is_controller_start_complete(struct isci_host *ihost);
struct sci_port_configuration_agent {
u16 phy_configured_mask;
......@@ -157,13 +160,17 @@ struct isci_host {
struct sci_power_control power_control;
u8 io_request_sequence[SCI_MAX_IO_REQUESTS];
struct scu_task_context *task_context_table;
dma_addr_t task_context_dma;
dma_addr_t tc_dma;
union scu_remote_node_context *remote_node_context_table;
dma_addr_t rnc_dma;
u32 *completion_queue;
dma_addr_t cq_dma;
u32 completion_queue_get;
u32 logical_port_entries;
u32 remote_node_entries;
u32 task_context_entries;
void *ufi_buf;
dma_addr_t ufi_dma;
struct sci_unsolicited_frame_control uf_control;
/* phy startup */
......@@ -190,17 +197,13 @@ struct isci_host {
struct asd_sas_port sas_ports[SCI_MAX_PORTS];
struct sas_ha_struct sas_ha;
spinlock_t state_lock;
struct pci_dev *pdev;
enum isci_status status;
#define IHOST_START_PENDING 0
#define IHOST_STOP_PENDING 1
#define IHOST_IRQ_ENABLED 2
unsigned long flags;
wait_queue_head_t eventq;
struct Scsi_Host *shost;
struct tasklet_struct completion_tasklet;
struct list_head requests_to_complete;
struct list_head requests_to_errorback;
spinlock_t scic_lock;
struct isci_request *reqs[SCI_MAX_IO_REQUESTS];
struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES];
......@@ -273,13 +276,6 @@ enum sci_controller_states {
*/
SCIC_STOPPING,
/**
* This state indicates that the controller has successfully been stopped.
* In this state no new IO operations are permitted.
* This state is entered from the STOPPING state.
*/
SCIC_STOPPED,
/**
* This state indicates that the controller could not successfully be
* initialized. In this state no new IO operations are permitted.
......@@ -309,32 +305,16 @@ static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
return pci_get_drvdata(pdev);
}
static inline struct Scsi_Host *to_shost(struct isci_host *ihost)
{
return ihost->sas_ha.core.shost;
}
#define for_each_isci_host(id, ihost, pdev) \
for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
ihost = to_pci_info(pdev)->hosts[++id])
static inline enum isci_status isci_host_get_state(struct isci_host *isci_host)
{
return isci_host->status;
}
static inline void isci_host_change_state(struct isci_host *isci_host,
enum isci_status status)
{
unsigned long flags;
dev_dbg(&isci_host->pdev->dev,
"%s: isci_host = %p, state = 0x%x",
__func__,
isci_host,
status);
spin_lock_irqsave(&isci_host->state_lock, flags);
isci_host->status = status;
spin_unlock_irqrestore(&isci_host->state_lock, flags);
}
static inline void wait_for_start(struct isci_host *ihost)
{
wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags));
......@@ -360,6 +340,11 @@ static inline struct isci_host *dev_to_ihost(struct domain_device *dev)
return dev->port->ha->lldd_ha;
}
static inline struct isci_host *idev_to_ihost(struct isci_remote_device *idev)
{
return dev_to_ihost(idev->domain_dev);
}
/* we always use protocol engine group zero */
#define ISCI_PEG 0
......@@ -378,8 +363,7 @@ static inline int sci_remote_device_node_count(struct isci_remote_device *idev)
{
struct domain_device *dev = idev->domain_dev;
if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) &&
!idev->is_direct_attached)
if (dev_is_sata(dev) && dev->parent)
return SCU_STP_REMOTE_NODE_COUNT;
return SCU_SSP_REMOTE_NODE_COUNT;
}
......@@ -475,66 +459,32 @@ void sci_controller_free_remote_node_context(
struct isci_remote_device *idev,
u16 node_id);
struct isci_request *sci_request_by_tag(struct isci_host *ihost,
u16 io_tag);
void sci_controller_power_control_queue_insert(
struct isci_host *ihost,
struct isci_request *sci_request_by_tag(struct isci_host *ihost, u16 io_tag);
void sci_controller_power_control_queue_insert(struct isci_host *ihost,
struct isci_phy *iphy);
void sci_controller_power_control_queue_remove(
struct isci_host *ihost,
void sci_controller_power_control_queue_remove(struct isci_host *ihost,
struct isci_phy *iphy);
void sci_controller_link_up(
struct isci_host *ihost,
struct isci_port *iport,
void sci_controller_link_up(struct isci_host *ihost, struct isci_port *iport,
struct isci_phy *iphy);
void sci_controller_link_down(
struct isci_host *ihost,
struct isci_port *iport,
void sci_controller_link_down(struct isci_host *ihost, struct isci_port *iport,
struct isci_phy *iphy);
void sci_controller_remote_device_stopped(
struct isci_host *ihost,
void sci_controller_remote_device_stopped(struct isci_host *ihost,
struct isci_remote_device *idev);
void sci_controller_copy_task_context(
struct isci_host *ihost,
struct isci_request *ireq);
void sci_controller_register_setup(struct isci_host *ihost);
enum sci_status sci_controller_continue_io(struct isci_request *ireq);
int isci_host_scan_finished(struct Scsi_Host *, unsigned long);
void isci_host_scan_start(struct Scsi_Host *);
u16 isci_alloc_tag(struct isci_host *ihost);
enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag);
void isci_tci_free(struct isci_host *ihost, u16 tci);
void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_task *task);
int isci_host_init(struct isci_host *);
void isci_host_init_controller_names(
struct isci_host *isci_host,
unsigned int controller_idx);
void isci_host_deinit(
struct isci_host *);
void isci_host_port_link_up(
struct isci_host *,
struct isci_port *,
struct isci_phy *);
int isci_host_dev_found(struct domain_device *);
void isci_host_remote_device_start_complete(
struct isci_host *,
struct isci_remote_device *,
enum sci_status);
void sci_controller_disable_interrupts(
struct isci_host *ihost);
void isci_host_completion_routine(unsigned long data);
void isci_host_deinit(struct isci_host *);
void sci_controller_disable_interrupts(struct isci_host *ihost);
bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost);
void sci_controller_transition_to_ready(struct isci_host *ihost, enum sci_status status);
enum sci_status sci_controller_start_io(
struct isci_host *ihost,
......
......@@ -271,13 +271,12 @@ static void isci_unregister(struct isci_host *isci_host)
if (!isci_host)
return;
shost = isci_host->shost;
sas_unregister_ha(&isci_host->sas_ha);
sas_remove_host(isci_host->shost);
scsi_remove_host(isci_host->shost);
scsi_host_put(isci_host->shost);
shost = to_shost(isci_host);
sas_remove_host(shost);
scsi_remove_host(shost);
scsi_host_put(shost);
}
static int __devinit isci_pci_init(struct pci_dev *pdev)
......@@ -397,38 +396,199 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
return err;
}
static void isci_user_parameters_get(struct sci_user_parameters *u)
{
int i;
for (i = 0; i < SCI_MAX_PHYS; i++) {
struct sci_phy_user_params *u_phy = &u->phys[i];
u_phy->max_speed_generation = phy_gen;
/* we are not exporting these for now */
u_phy->align_insertion_frequency = 0x7f;
u_phy->in_connection_align_insertion_frequency = 0xff;
u_phy->notify_enable_spin_up_insertion_frequency = 0x33;
}
u->stp_inactivity_timeout = stp_inactive_to;
u->ssp_inactivity_timeout = ssp_inactive_to;
u->stp_max_occupancy_timeout = stp_max_occ_to;
u->ssp_max_occupancy_timeout = ssp_max_occ_to;
u->no_outbound_task_timeout = no_outbound_task_to;
u->max_concurr_spinup = max_concurr_spinup;
}
static enum sci_status sci_user_parameters_set(struct isci_host *ihost,
struct sci_user_parameters *sci_parms)
{
u16 index;
/*
* Validate the user parameters. If they are not legal, then
* return a failure.
*/
for (index = 0; index < SCI_MAX_PHYS; index++) {
struct sci_phy_user_params *u;
u = &sci_parms->phys[index];
if (!((u->max_speed_generation <= SCIC_SDS_PARM_MAX_SPEED) &&
(u->max_speed_generation > SCIC_SDS_PARM_NO_SPEED)))
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
if (u->in_connection_align_insertion_frequency < 3)
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
if ((u->in_connection_align_insertion_frequency < 3) ||
(u->align_insertion_frequency == 0) ||
(u->notify_enable_spin_up_insertion_frequency == 0))
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
}
if ((sci_parms->stp_inactivity_timeout == 0) ||
(sci_parms->ssp_inactivity_timeout == 0) ||
(sci_parms->stp_max_occupancy_timeout == 0) ||
(sci_parms->ssp_max_occupancy_timeout == 0) ||
(sci_parms->no_outbound_task_timeout == 0))
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
memcpy(&ihost->user_parameters, sci_parms, sizeof(*sci_parms));
return SCI_SUCCESS;
}
static void sci_oem_defaults(struct isci_host *ihost)
{
/* these defaults are overridden by the platform / firmware */
struct sci_user_parameters *user = &ihost->user_parameters;
struct sci_oem_params *oem = &ihost->oem_parameters;
int i;
/* Default to APC mode. */
oem->controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
/* Default to APC mode. */
oem->controller.max_concurr_spin_up = 1;
/* Default to no SSC operation. */
oem->controller.do_enable_ssc = false;
/* Default to short cables on all phys. */
oem->controller.cable_selection_mask = 0;
/* Initialize all of the port parameter information to narrow ports. */
for (i = 0; i < SCI_MAX_PORTS; i++)
oem->ports[i].phy_mask = 0;
/* Initialize all of the phy parameter information. */
for (i = 0; i < SCI_MAX_PHYS; i++) {
/* Default to 3G (i.e. Gen 2). */
user->phys[i].max_speed_generation = SCIC_SDS_PARM_GEN2_SPEED;
/* the frequencies cannot be 0 */
user->phys[i].align_insertion_frequency = 0x7f;
user->phys[i].in_connection_align_insertion_frequency = 0xff;
user->phys[i].notify_enable_spin_up_insertion_frequency = 0x33;
/* Previous Vitesse based expanders had a arbitration issue that
* is worked around by having the upper 32-bits of SAS address
* with a value greater then the Vitesse company identifier.
* Hence, usage of 0x5FCFFFFF.
*/
oem->phys[i].sas_address.low = 0x1 + ihost->id;
oem->phys[i].sas_address.high = 0x5FCFFFFF;
}
user->stp_inactivity_timeout = 5;
user->ssp_inactivity_timeout = 5;
user->stp_max_occupancy_timeout = 5;
user->ssp_max_occupancy_timeout = 20;
user->no_outbound_task_timeout = 2;
}
static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
{
struct isci_host *isci_host;
struct isci_orom *orom = to_pci_info(pdev)->orom;
struct sci_user_parameters sci_user_params;
u8 oem_version = ISCI_ROM_VER_1_0;
struct isci_host *ihost;
struct Scsi_Host *shost;
int err;
int err, i;
isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL);
if (!isci_host)
ihost = devm_kzalloc(&pdev->dev, sizeof(*ihost), GFP_KERNEL);
if (!ihost)
return NULL;
isci_host->pdev = pdev;
isci_host->id = id;
ihost->pdev = pdev;
ihost->id = id;
spin_lock_init(&ihost->scic_lock);
init_waitqueue_head(&ihost->eventq);
ihost->sas_ha.dev = &ihost->pdev->dev;
ihost->sas_ha.lldd_ha = ihost;
tasklet_init(&ihost->completion_tasklet,
isci_host_completion_routine, (unsigned long)ihost);
/* validate module parameters */
/* TODO: kill struct sci_user_parameters and reference directly */
sci_oem_defaults(ihost);
isci_user_parameters_get(&sci_user_params);
if (sci_user_parameters_set(ihost, &sci_user_params)) {
dev_warn(&pdev->dev,
"%s: sci_user_parameters_set failed\n", __func__);
return NULL;
}
/* sanity check platform (or 'firmware') oem parameters */
if (orom) {
if (id < 0 || id >= SCI_MAX_CONTROLLERS || id > orom->hdr.num_elements) {
dev_warn(&pdev->dev, "parsing firmware oem parameters failed\n");
return NULL;
}
ihost->oem_parameters = orom->ctrl[id];
oem_version = orom->hdr.version;
}
/* validate oem parameters (platform, firmware, or built-in defaults) */
if (sci_oem_parameters_validate(&ihost->oem_parameters, oem_version)) {
dev_warn(&pdev->dev, "oem parameter validation failed\n");
return NULL;
}
for (i = 0; i < SCI_MAX_PORTS; i++) {
struct isci_port *iport = &ihost->ports[i];
INIT_LIST_HEAD(&iport->remote_dev_list);
iport->isci_host = ihost;
}
for (i = 0; i < SCI_MAX_PHYS; i++)
isci_phy_init(&ihost->phys[i], ihost, i);
for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
struct isci_remote_device *idev = &ihost->devices[i];
INIT_LIST_HEAD(&idev->node);
}
shost = scsi_host_alloc(&isci_sht, sizeof(void *));
if (!shost)
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)));
(is_cable_select_overridden() ? "* " : ""), ihost->id,
lookup_cable_names(decode_cable_selection(ihost, 3)),
lookup_cable_names(decode_cable_selection(ihost, 2)),
lookup_cable_names(decode_cable_selection(ihost, 1)),
lookup_cable_names(decode_cable_selection(ihost, 0)));
err = isci_host_init(isci_host);
err = isci_host_init(ihost);
if (err)
goto err_shost;
SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha;
isci_host->sas_ha.core.shost = shost;
SHOST_TO_SAS_HA(shost) = &ihost->sas_ha;
ihost->sas_ha.core.shost = shost;
shost->transportt = isci_transport_template;
shost->max_id = ~0;
......@@ -439,11 +599,11 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
if (err)
goto err_shost;
err = isci_register_sas_ha(isci_host);
err = isci_register_sas_ha(ihost);
if (err)
goto err_shost_remove;
return isci_host;
return ihost;
err_shost_remove:
scsi_remove_host(shost);
......@@ -476,7 +636,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
if (!orom)
orom = isci_request_oprom(pdev);
for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
for (i = 0; orom && i < num_controllers(pdev); i++) {
if (sci_oem_parameters_validate(&orom->ctrl[i],
orom->hdr.version)) {
dev_warn(&pdev->dev,
......@@ -525,11 +685,11 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
pci_info->hosts[i] = h;
/* turn on DIF support */
scsi_host_set_prot(h->shost,
scsi_host_set_prot(to_shost(h),
SHOST_DIF_TYPE1_PROTECTION |
SHOST_DIF_TYPE2_PROTECTION |
SHOST_DIF_TYPE3_PROTECTION);
scsi_host_set_guard(h->shost, SHOST_DIX_GUARD_CRC);
scsi_host_set_guard(to_shost(h), SHOST_DIX_GUARD_CRC);
}
err = isci_setup_interrupts(pdev);
......@@ -537,7 +697,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
goto err_host_alloc;
for_each_isci_host(i, isci_host, pdev)
scsi_scan_host(isci_host->shost);
scsi_scan_host(to_shost(isci_host));
return 0;
......
......@@ -580,7 +580,7 @@ static void sci_phy_start_sas_link_training(struct isci_phy *iphy)
sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SAS_SPEED_EN);
iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS;
iphy->protocol = SAS_PROTOCOL_SSP;
}
static void sci_phy_start_sata_link_training(struct isci_phy *iphy)
......@@ -591,7 +591,7 @@ static void sci_phy_start_sata_link_training(struct isci_phy *iphy)
*/
sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_POWER);
iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
iphy->protocol = SAS_PROTOCOL_SATA;
}
/**
......@@ -668,6 +668,19 @@ static const char *phy_event_name(u32 event_code)
phy_to_host(iphy)->id, iphy->phy_index, \
phy_state_name(state), phy_event_name(code), code)
void scu_link_layer_set_txcomsas_timeout(struct isci_phy *iphy, u32 timeout)
{
u32 val;
/* Extend timeout */
val = readl(&iphy->link_layer_registers->transmit_comsas_signal);
val &= ~SCU_SAS_LLTXCOMSAS_GEN_VAL(NEGTIME, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_MASK);
val |= SCU_SAS_LLTXCOMSAS_GEN_VAL(NEGTIME, timeout);
writel(val, &iphy->link_layer_registers->transmit_comsas_signal);
}
enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
{
enum sci_phy_states state = iphy->sm.current_state_id;
......@@ -683,6 +696,13 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
sci_phy_start_sata_link_training(iphy);
iphy->is_in_link_training = true;
break;
case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
/* Extend timeout value */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED);
/* Start the oob/sn state machine over again */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
default:
phy_event_dbg(iphy, state, event_code);
return SCI_FAILURE;
......@@ -717,9 +737,19 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
sci_phy_start_sata_link_training(iphy);
break;
case SCU_EVENT_LINK_FAILURE:
/* Change the timeout value to default */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
/* Extend the timeout value */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED);
/* Start the oob/sn state machine over again */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
default:
phy_event_warn(iphy, state, event_code);
return SCI_FAILURE;
......@@ -740,7 +770,14 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
sci_phy_start_sata_link_training(iphy);
break;
case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
/* Extend the timeout value */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED);
/* Start the oob/sn state machine over again */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
case SCU_EVENT_LINK_FAILURE:
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
case SCU_EVENT_HARD_RESET_RECEIVED:
/* Start the oob/sn state machine over again */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
......@@ -753,6 +790,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
case SCI_PHY_SUB_AWAIT_SAS_POWER:
switch (scu_get_event_code(event_code)) {
case SCU_EVENT_LINK_FAILURE:
/* Change the timeout value to default */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
......@@ -764,6 +804,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
case SCI_PHY_SUB_AWAIT_SATA_POWER:
switch (scu_get_event_code(event_code)) {
case SCU_EVENT_LINK_FAILURE:
/* Change the timeout value to default */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
......@@ -788,6 +831,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
case SCI_PHY_SUB_AWAIT_SATA_PHY_EN:
switch (scu_get_event_code(event_code)) {
case SCU_EVENT_LINK_FAILURE:
/* Change the timeout value to default */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
......@@ -797,7 +843,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
*/
break;
case SCU_EVENT_SATA_PHY_DETECTED:
iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
iphy->protocol = SAS_PROTOCOL_SATA;
/* We have received the SATA PHY notification change state */
sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN);
......@@ -836,6 +882,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
SCI_PHY_SUB_AWAIT_SIG_FIS_UF);
break;
case SCU_EVENT_LINK_FAILURE:
/* Change the timeout value to default */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
......@@ -859,6 +908,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
break;
case SCU_EVENT_LINK_FAILURE:
/* Change the timeout value to default */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
......@@ -871,16 +923,26 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
case SCI_PHY_READY:
switch (scu_get_event_code(event_code)) {
case SCU_EVENT_LINK_FAILURE:
/* Set default timeout */
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
case SCU_EVENT_BROADCAST_CHANGE:
case SCU_EVENT_BROADCAST_SES:
case SCU_EVENT_BROADCAST_RESERVED0:
case SCU_EVENT_BROADCAST_RESERVED1:
case SCU_EVENT_BROADCAST_EXPANDER:
case SCU_EVENT_BROADCAST_AEN:
/* Broadcast change received. Notify the port. */
if (phy_get_non_dummy_port(iphy) != NULL)
sci_port_broadcast_change_received(iphy->owning_port, iphy);
else
iphy->bcn_received_while_port_unassigned = true;
break;
case SCU_EVENT_BROADCAST_RESERVED3:
case SCU_EVENT_BROADCAST_RESERVED4:
default:
phy_event_warn(iphy, state, event_code);
return SCI_FAILURE_INVALID_STATE;
......@@ -1215,7 +1277,7 @@ static void sci_phy_starting_state_enter(struct sci_base_state_machine *sm)
scu_link_layer_start_oob(iphy);
/* We don't know what kind of phy we are going to be just yet */
iphy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
iphy->protocol = SAS_PROTOCOL_NONE;
iphy->bcn_received_while_port_unassigned = false;
if (iphy->sm.previous_state_id == SCI_PHY_READY)
......@@ -1250,7 +1312,7 @@ static void sci_phy_resetting_state_enter(struct sci_base_state_machine *sm)
*/
sci_port_deactivate_phy(iphy->owning_port, iphy, false);
if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
if (iphy->protocol == SAS_PROTOCOL_SSP) {
scu_link_layer_tx_hard_reset(iphy);
} else {
/* The SCU does not need to have a discrete reset state so
......@@ -1316,7 +1378,7 @@ void sci_phy_construct(struct isci_phy *iphy,
iphy->owning_port = iport;
iphy->phy_index = phy_index;
iphy->bcn_received_while_port_unassigned = false;
iphy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
iphy->protocol = SAS_PROTOCOL_NONE;
iphy->link_layer_registers = NULL;
iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
......@@ -1380,12 +1442,14 @@ int isci_phy_control(struct asd_sas_phy *sas_phy,
switch (func) {
case PHY_FUNC_DISABLE:
spin_lock_irqsave(&ihost->scic_lock, flags);
scu_link_layer_start_oob(iphy);
sci_phy_stop(iphy);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
break;
case PHY_FUNC_LINK_RESET:
spin_lock_irqsave(&ihost->scic_lock, flags);
scu_link_layer_start_oob(iphy);
sci_phy_stop(iphy);
sci_phy_start(iphy);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
......
......@@ -76,13 +76,6 @@
*/
#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250
enum sci_phy_protocol {
SCIC_SDS_PHY_PROTOCOL_UNKNOWN,
SCIC_SDS_PHY_PROTOCOL_SAS,
SCIC_SDS_PHY_PROTOCOL_SATA,
SCIC_SDS_MAX_PHY_PROTOCOLS
};
/**
* isci_phy - hba local phy infrastructure
* @sm:
......@@ -95,7 +88,7 @@ struct isci_phy {
struct sci_base_state_machine sm;
struct isci_port *owning_port;
enum sas_linkrate max_negotiated_speed;
enum sci_phy_protocol protocol;
enum sas_protocol protocol;
u8 phy_index;
bool bcn_received_while_port_unassigned;
bool is_in_link_training;
......
This diff is collapsed.
......@@ -97,7 +97,6 @@ enum isci_status {
struct isci_port {
struct isci_host *isci_host;
struct list_head remote_dev_list;
struct list_head domain_dev_list;
#define IPORT_RESET_PENDING 0
unsigned long state;
enum sci_status hard_reset_status;
......@@ -112,6 +111,7 @@ struct isci_port {
u16 reserved_tag;
u32 started_request_count;
u32 assigned_device_count;
u32 hang_detect_users;
u32 not_ready_reason;
struct isci_phy *phy_table[SCI_MAX_PHYS];
struct isci_host *owning_controller;
......@@ -270,14 +270,13 @@ void sci_port_get_attached_sas_address(
struct isci_port *iport,
struct sci_sas_address *sas_address);
void sci_port_set_hang_detection_timeout(
struct isci_port *isci_port,
u32 timeout);
void isci_port_formed(struct asd_sas_phy *);
void isci_port_deformed(struct asd_sas_phy *);
void isci_port_init(
struct isci_port *port,
struct isci_host *host,
int index);
int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport,
struct isci_phy *iphy);
int isci_ata_check_ready(struct domain_device *dev);
......
......@@ -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 (250)
#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (1000)
enum SCIC_SDS_APC_ACTIVITY {
SCIC_SDS_APC_SKIP_PHY,
......@@ -472,13 +472,9 @@ sci_apc_agent_validate_phy_configuration(struct isci_host *ihost,
* 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,
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);
}
......@@ -697,6 +693,9 @@ static void apc_agent_timeout(unsigned long data)
&ihost->phys[index], false);
}
if (is_controller_start_complete(ihost))
sci_controller_transition_to_ready(ihost, SCI_SUCCESS);
done:
spin_unlock_irqrestore(&ihost->scic_lock, flags);
}
......@@ -732,6 +731,11 @@ void sci_port_configuration_agent_construct(
}
}
bool is_port_config_apc(struct isci_host *ihost)
{
return ihost->port_agent.link_up_handler == sci_apc_agent_link_up;
}
enum sci_status sci_port_configuration_agent_initialize(
struct isci_host *ihost,
struct sci_port_configuration_agent *port_agent)
......
......@@ -112,18 +112,6 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
return rom;
}
enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem,
struct isci_orom *orom, int scu_index)
{
/* check for valid inputs */
if (scu_index < 0 || scu_index >= SCI_MAX_CONTROLLERS ||
scu_index > orom->hdr.num_elements || !oem)
return -EINVAL;
*oem = orom->ctrl[scu_index];
return 0;
}
struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw)
{
struct isci_orom *orom = NULL, *data;
......
......@@ -156,8 +156,6 @@ 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);
enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem,
struct isci_orom *orom, int scu_index);
struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw);
struct isci_orom *isci_get_efi_var(struct pci_dev *pdev);
......
......@@ -1239,6 +1239,14 @@ struct scu_transport_layer_registers {
#define SCU_SAS_LLCTL_GEN_BIT(name) \
SCU_GEN_BIT(SCU_SAS_LINK_LAYER_CONTROL_ ## name)
#define SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT (0xF0)
#define SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED (0x1FF)
#define SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_SHIFT (0)
#define SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_MASK (0x3FF)
#define SCU_SAS_LLTXCOMSAS_GEN_VAL(name, value) \
SCU_GEN_VALUE(SCU_SAS_LINK_LAYER_TXCOMSAS_ ## name, value)
/* #define SCU_FRXHECR_DCNT_OFFSET 0x00B0 */
#define SCU_PSZGCR_OFFSET 0x00E4
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment