diff options
Diffstat (limited to 'drivers/scsi')
| -rw-r--r-- | drivers/scsi/hpsa_cmd.h | 78 | ||||
| -rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 8 | ||||
| -rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 14 | ||||
| -rw-r--r-- | drivers/scsi/scsi_transport_srp.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 31 | 
5 files changed, 77 insertions, 56 deletions
| diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index d126bb877250..ba6a3aa8d954 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -20,6 +20,11 @@  #ifndef HPSA_CMD_H  #define HPSA_CMD_H +#include <linux/compiler.h> + +#include <linux/build_bug.h> /* static_assert */ +#include <linux/stddef.h> /* offsetof */ +  /* general boundary defintions */  #define SENSEINFOBYTES          32 /* may vary between hbas */  #define SG_ENTRIES_IN_CMD	32 /* Max SG entries excluding chain blocks */ @@ -200,12 +205,10 @@ union u64bit {  	MAX_EXT_TARGETS + 1) /* + 1 is for the controller itself */  /* SCSI-3 Commands */ -#pragma pack(1) -  #define HPSA_INQUIRY 0x12  struct InquiryData {  	u8 data_byte[36]; -}; +} __packed;  #define HPSA_REPORT_LOG 0xc2    /* Report Logical LUNs */  #define HPSA_REPORT_PHYS 0xc3   /* Report Physical LUNs */ @@ -221,7 +224,7 @@ struct raid_map_disk_data {  	u8    xor_mult[2];            /**< XOR multipliers for this position,  					*  valid for data disks only */  	u8    reserved[2]; -}; +} __packed;  struct raid_map_data {  	__le32   structure_size;	/* Size of entire structure in bytes */ @@ -247,14 +250,14 @@ struct raid_map_data {  	__le16   dekindex;		/* Data encryption key index. */  	u8    reserved[16];  	struct raid_map_disk_data data[RAID_MAP_MAX_ENTRIES]; -}; +} __packed;  struct ReportLUNdata {  	u8 LUNListLength[4];  	u8 extended_response_flag;  	u8 reserved[3];  	u8 LUN[HPSA_MAX_LUN][8]; -}; +} __packed;  struct ext_report_lun_entry {  	u8 lunid[8]; @@ -269,20 +272,20 @@ struct ext_report_lun_entry {  	u8 lun_count; /* multi-lun device, how many luns */  	u8 redundant_paths;  	u32 ioaccel_handle; /* ioaccel1 only uses lower 16 bits */ -}; +} __packed;  struct ReportExtendedLUNdata {  	u8 LUNListLength[4];  	u8 extended_response_flag;  	u8 reserved[3];  	struct ext_report_lun_entry LUN[HPSA_MAX_PHYS_LUN]; -}; +} __packed;  struct SenseSubsystem_info {  	u8 reserved[36];  	u8 portname[8];  	u8 reserved1[1108]; -}; +} __packed;  /* BMIC commands */  #define BMIC_READ 0x26 @@ -317,7 +320,7 @@ union SCSI3Addr {  		u8 Targ:6;  		u8 Mode:2;        /* b10 */  	} LogUnit; -}; +} __packed;  struct PhysDevAddr {  	u32             TargetId:24; @@ -325,20 +328,20 @@ struct PhysDevAddr {  	u32             Mode:2;  	/* 2 level target device addr */  	union SCSI3Addr  Target[2]; -}; +} __packed;  struct LogDevAddr {  	u32            VolId:30;  	u32            Mode:2;  	u8             reserved[4]; -}; +} __packed;  union LUNAddr {  	u8               LunAddrBytes[8];  	union SCSI3Addr    SCSI3Lun[4];  	struct PhysDevAddr PhysDev;  	struct LogDevAddr  LogDev; -}; +} __packed;  struct CommandListHeader {  	u8              ReplyQueue; @@ -346,7 +349,7 @@ struct CommandListHeader {  	__le16          SGTotal;  	__le64		tag;  	union LUNAddr     LUN; -}; +} __packed;  struct RequestBlock {  	u8   CDBLen; @@ -365,18 +368,18 @@ struct RequestBlock {  #define GET_DIR(tad) (((tad) >> 6) & 0x03)  	u16  Timeout;  	u8   CDB[16]; -}; +} __packed;  struct ErrDescriptor {  	__le64 Addr;  	__le32 Len; -}; +} __packed;  struct SGDescriptor {  	__le64 Addr;  	__le32 Len;  	__le32 Ext; -}; +} __packed;  union MoreErrInfo {  	struct { @@ -390,7 +393,8 @@ union MoreErrInfo {  		u8  offense_num;  /* byte # of offense 0-base */  		u32 offense_value;  	} Invalid_Cmd; -}; +} __packed; +  struct ErrorInfo {  	u8               ScsiStatus;  	u8               SenseLen; @@ -398,7 +402,7 @@ struct ErrorInfo {  	u32              ResidualCnt;  	union MoreErrInfo  MoreErrInfo;  	u8               SenseInfo[SENSEINFOBYTES]; -}; +} __packed;  /* Command types */  #define CMD_IOCTL_PEND  0x01  #define CMD_SCSI	0x03 @@ -453,6 +457,15 @@ struct CommandList {  	atomic_t refcount; /* Must be last to avoid memset in hpsa_cmd_init() */  } __aligned(COMMANDLIST_ALIGNMENT); +/* + * Make sure our embedded atomic variable is aligned. Otherwise we break atomic + * operations on architectures that don't support unaligned atomics like IA64. + * + * The assert guards against reintroductin against unwanted __packed to + * the struct CommandList. + */ +static_assert(offsetof(struct CommandList, refcount) % __alignof__(atomic_t) == 0); +  /* Max S/G elements in I/O accelerator command */  #define IOACCEL1_MAXSGENTRIES           24  #define IOACCEL2_MAXSGENTRIES		28 @@ -489,7 +502,7 @@ struct io_accel1_cmd {  	__le64 host_addr;		/* 0x70 - 0x77 */  	u8  CISS_LUN[8];		/* 0x78 - 0x7F */  	struct SGDescriptor SG[IOACCEL1_MAXSGENTRIES]; -} __aligned(IOACCEL1_COMMANDLIST_ALIGNMENT); +} __packed __aligned(IOACCEL1_COMMANDLIST_ALIGNMENT);  #define IOACCEL1_FUNCTION_SCSIIO        0x00  #define IOACCEL1_SGLOFFSET              32 @@ -519,7 +532,7 @@ struct ioaccel2_sg_element {  	u8 chain_indicator;  #define IOACCEL2_CHAIN 0x80  #define IOACCEL2_LAST_SG 0x40 -}; +} __packed;  /*   * SCSI Response Format structure for IO Accelerator Mode 2 @@ -559,7 +572,7 @@ struct io_accel2_scsi_response {  	u8 sense_data_len;		/* sense/response data length */  	u8 resid_cnt[4];		/* residual count */  	u8 sense_data_buff[32];		/* sense/response data buffer */ -}; +} __packed;  /*   * Structure for I/O accelerator (mode 2 or m2) commands. @@ -592,7 +605,7 @@ struct io_accel2_cmd {  	__le32 tweak_upper;		/* Encryption tweak, upper 4 bytes */  	struct ioaccel2_sg_element sg[IOACCEL2_MAXSGENTRIES];  	struct io_accel2_scsi_response error_data; -} __aligned(IOACCEL2_COMMANDLIST_ALIGNMENT); +} __packed __aligned(IOACCEL2_COMMANDLIST_ALIGNMENT);  /*   * defines for Mode 2 command struct @@ -618,7 +631,7 @@ struct hpsa_tmf_struct {  	__le64 abort_tag;	/* cciss tag of SCSI cmd or TMF to abort */  	__le64 error_ptr;		/* Error Pointer */  	__le32 error_len;		/* Error Length */ -} __aligned(IOACCEL2_COMMANDLIST_ALIGNMENT); +} __packed __aligned(IOACCEL2_COMMANDLIST_ALIGNMENT);  /* Configuration Table Structure */  struct HostWrite { @@ -626,7 +639,7 @@ struct HostWrite {  	__le32		command_pool_addr_hi;  	__le32		CoalIntDelay;  	__le32		CoalIntCount; -}; +} __packed;  #define SIMPLE_MODE     0x02  #define PERFORMANT_MODE 0x04 @@ -675,7 +688,7 @@ struct CfgTable {  #define		HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_STATE_CHANGE (1 << 30)  #define		HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_CONFIG_CHANGE (1 << 31)  	__le32		clear_event_notify; -}; +} __packed;  #define NUM_BLOCKFETCH_ENTRIES 8  struct TransTable_struct { @@ -686,14 +699,14 @@ struct TransTable_struct {  	__le32		RepQCtrAddrHigh32;  #define MAX_REPLY_QUEUES 64  	struct vals32  RepQAddr[MAX_REPLY_QUEUES]; -}; +} __packed;  struct hpsa_pci_info {  	unsigned char	bus;  	unsigned char	dev_fn;  	unsigned short	domain;  	u32		board_id; -}; +} __packed;  struct bmic_identify_controller {  	u8	configured_logical_drive_count;	/* offset 0 */ @@ -702,7 +715,7 @@ struct bmic_identify_controller {  	u8	pad2[136];  	u8	controller_mode;	/* offset 292 */  	u8	pad3[32]; -}; +} __packed;  struct bmic_identify_physical_device { @@ -845,7 +858,7 @@ struct bmic_identify_physical_device {  	u8     max_link_rate[256];  	u8     neg_phys_link_rate[256];  	u8     box_conn_name[8]; -} __attribute((aligned(512))); +} __packed __attribute((aligned(512)));  struct bmic_sense_subsystem_info {  	u8	primary_slot_number; @@ -858,7 +871,7 @@ struct bmic_sense_subsystem_info {  	u8	secondary_array_serial_number[32];  	u8	secondary_cache_serial_number[32];  	u8	pad[332]; -}; +} __packed;  struct bmic_sense_storage_box_params {  	u8	reserved[36]; @@ -870,7 +883,6 @@ struct bmic_sense_storage_box_params {  	u8	reserver_3[84];  	u8	phys_connector[2];  	u8	reserved_4[296]; -}; +} __packed; -#pragma pack()  #endif /* HPSA_CMD_H */ diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 49bf2f70a470..31e5455d280c 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -223,7 +223,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)  		PM8001_EVENT_LOG_SIZE;  	pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option		= 0x01;  	pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt		= 0x01; -	for (i = 0; i < PM8001_MAX_INB_NUM; i++) { +	for (i = 0; i < pm8001_ha->max_q_num; i++) {  		pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt	=  			PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);  		pm8001_ha->inbnd_q_tbl[i].upper_base_addr	= @@ -249,7 +249,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)  		pm8001_ha->inbnd_q_tbl[i].producer_idx		= 0;  		pm8001_ha->inbnd_q_tbl[i].consumer_index	= 0;  	} -	for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) { +	for (i = 0; i < pm8001_ha->max_q_num; i++) {  		pm8001_ha->outbnd_q_tbl[i].element_size_cnt	=  			PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);  		pm8001_ha->outbnd_q_tbl[i].upper_base_addr	= @@ -671,9 +671,9 @@ static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)  	read_outbnd_queue_table(pm8001_ha);  	/* update main config table ,inbound table and outbound table */  	update_main_config_table(pm8001_ha); -	for (i = 0; i < PM8001_MAX_INB_NUM; i++) +	for (i = 0; i < pm8001_ha->max_q_num; i++)  		update_inbnd_queue_table(pm8001_ha, i); -	for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) +	for (i = 0; i < pm8001_ha->max_q_num; i++)  		update_outbnd_queue_table(pm8001_ha, i);  	/* 8081 controller donot require these operations */  	if (deviceid != 0x8081 && deviceid != 0x0042) { diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 91074fd97f64..f4bf62b007a0 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2475,6 +2475,7 @@ static void iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag)  	 */  	mutex_lock(&conn_mutex);  	conn->transport->stop_conn(conn, flag); +	conn->state = ISCSI_CONN_DOWN;  	mutex_unlock(&conn_mutex);  } @@ -2901,6 +2902,13 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)  	default:  		err = transport->set_param(conn, ev->u.set_param.param,  					   data, ev->u.set_param.len); +		if ((conn->state == ISCSI_CONN_BOUND) || +			(conn->state == ISCSI_CONN_UP)) { +			err = transport->set_param(conn, ev->u.set_param.param, +					data, ev->u.set_param.len); +		} else { +			return -ENOTCONN; +		}  	}  	return err; @@ -2960,6 +2968,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,  		mutex_lock(&conn->ep_mutex);  		conn->ep = NULL;  		mutex_unlock(&conn->ep_mutex); +		conn->state = ISCSI_CONN_DOWN;  	}  	transport->ep_disconnect(ep); @@ -3727,6 +3736,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)  		ev->r.retcode =	transport->bind_conn(session, conn,  						ev->u.b_conn.transport_eph,  						ev->u.b_conn.is_leading); +		if (!ev->r.retcode) +			conn->state = ISCSI_CONN_BOUND;  		mutex_unlock(&conn_mutex);  		if (ev->r.retcode || !transport->ep_connect) @@ -3966,7 +3977,8 @@ iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR);  static const char *const connection_state_names[] = {  	[ISCSI_CONN_UP] = "up",  	[ISCSI_CONN_DOWN] = "down", -	[ISCSI_CONN_FAILED] = "failed" +	[ISCSI_CONN_FAILED] = "failed", +	[ISCSI_CONN_BOUND] = "bound"  };  static ssize_t show_conn_state(struct device *dev, diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 1e939a2a387f..98a34ed10f1a 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -541,7 +541,7 @@ int srp_reconnect_rport(struct srp_rport *rport)  	res = mutex_lock_interruptible(&rport->mutex);  	if (res)  		goto out; -	if (rport->state != SRP_RPORT_FAIL_FAST) +	if (rport->state != SRP_RPORT_FAIL_FAST && rport->state != SRP_RPORT_LOST)  		/*  		 * sdev state must be SDEV_TRANSPORT_OFFLINE, transition  		 * to SDEV_BLOCK is illegal. Calling scsi_target_unblock() diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c86760788c72..d3d05e997c13 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6386,37 +6386,34 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,  	DECLARE_COMPLETION_ONSTACK(wait);  	struct request *req;  	unsigned long flags; -	int free_slot, task_tag, err; +	int task_tag, err;  	/* -	 * Get free slot, sleep if slots are unavailable. -	 * Even though we use wait_event() which sleeps indefinitely, -	 * the maximum wait time is bounded by %TM_CMD_TIMEOUT. +	 * blk_get_request() is used here only to get a free tag.  	 */  	req = blk_get_request(q, REQ_OP_DRV_OUT, 0);  	if (IS_ERR(req))  		return PTR_ERR(req);  	req->end_io_data = &wait; -	free_slot = req->tag; -	WARN_ON_ONCE(free_slot < 0 || free_slot >= hba->nutmrs);  	ufshcd_hold(hba, false);  	spin_lock_irqsave(host->host_lock, flags); -	task_tag = hba->nutrs + free_slot; +	blk_mq_start_request(req); +	task_tag = req->tag;  	treq->req_header.dword_0 |= cpu_to_be32(task_tag); -	memcpy(hba->utmrdl_base_addr + free_slot, treq, sizeof(*treq)); -	ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function); +	memcpy(hba->utmrdl_base_addr + task_tag, treq, sizeof(*treq)); +	ufshcd_vops_setup_task_mgmt(hba, task_tag, tm_function);  	/* send command to the controller */ -	__set_bit(free_slot, &hba->outstanding_tasks); +	__set_bit(task_tag, &hba->outstanding_tasks);  	/* Make sure descriptors are ready before ringing the task doorbell */  	wmb(); -	ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL); +	ufshcd_writel(hba, 1 << task_tag, REG_UTP_TASK_REQ_DOOR_BELL);  	/* Make sure that doorbell is committed immediately */  	wmb(); @@ -6436,24 +6433,24 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,  		ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_ERR);  		dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n",  				__func__, tm_function); -		if (ufshcd_clear_tm_cmd(hba, free_slot)) -			dev_WARN(hba->dev, "%s: unable clear tm cmd (slot %d) after timeout\n", -					__func__, free_slot); +		if (ufshcd_clear_tm_cmd(hba, task_tag)) +			dev_WARN(hba->dev, "%s: unable to clear tm cmd (slot %d) after timeout\n", +					__func__, task_tag);  		err = -ETIMEDOUT;  	} else {  		err = 0; -		memcpy(treq, hba->utmrdl_base_addr + free_slot, sizeof(*treq)); +		memcpy(treq, hba->utmrdl_base_addr + task_tag, sizeof(*treq));  		ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_COMP);  	}  	spin_lock_irqsave(hba->host->host_lock, flags); -	__clear_bit(free_slot, &hba->outstanding_tasks); +	__clear_bit(task_tag, &hba->outstanding_tasks);  	spin_unlock_irqrestore(hba->host->host_lock, flags); +	ufshcd_release(hba);  	blk_put_request(req); -	ufshcd_release(hba);  	return err;  } |