Commit 9588d24e authored by Bradley Grove's avatar Bradley Grove Committed by James Bottomley
Browse files

[SCSI] esas2r: Directly call kernel functions for atomic bit operations



Previously the code embedded the kernel's test_bit/clear_bit
functions in wrappers that accepted u32 parameters.  The
wrapper cast these parameters to longs before passing them
to the kernel's bit functions.   This did not work properly
on platforms with 64-bit longs.

Signed-off-by: default avatarBradley Grove <bgrove@attotech.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent a1f7177a
Loading
Loading
Loading
Loading
+59 −66
Original line number Diff line number Diff line
@@ -799,47 +799,47 @@ struct esas2r_adapter {
	struct esas2r_target *targetdb_end;
	unsigned char *regs;
	unsigned char *data_window;
	u32 volatile flags;
	#define AF_PORT_CHANGE      (u32)(0x00000001)
	#define AF_CHPRST_NEEDED    (u32)(0x00000004)
	#define AF_CHPRST_PENDING   (u32)(0x00000008)
	#define AF_CHPRST_DETECTED  (u32)(0x00000010)
	#define AF_BUSRST_NEEDED    (u32)(0x00000020)
	#define AF_BUSRST_PENDING   (u32)(0x00000040)
	#define AF_BUSRST_DETECTED  (u32)(0x00000080)
	#define AF_DISABLED         (u32)(0x00000100)
	#define AF_FLASH_LOCK       (u32)(0x00000200)
	#define AF_OS_RESET         (u32)(0x00002000)
	#define AF_FLASHING         (u32)(0x00004000)
	#define AF_POWER_MGT        (u32)(0x00008000)
	#define AF_NVR_VALID        (u32)(0x00010000)
	#define AF_DEGRADED_MODE    (u32)(0x00020000)
	#define AF_DISC_PENDING     (u32)(0x00040000)
	#define AF_TASKLET_SCHEDULED    (u32)(0x00080000)
	#define AF_HEARTBEAT        (u32)(0x00200000)
	#define AF_HEARTBEAT_ENB    (u32)(0x00400000)
	#define AF_NOT_PRESENT      (u32)(0x00800000)
	#define AF_CHPRST_STARTED   (u32)(0x01000000)
	#define AF_FIRST_INIT       (u32)(0x02000000)
	#define AF_POWER_DOWN       (u32)(0x04000000)
	#define AF_DISC_IN_PROG     (u32)(0x08000000)
	#define AF_COMM_LIST_TOGGLE (u32)(0x10000000)
	#define AF_LEGACY_SGE_MODE  (u32)(0x20000000)
	#define AF_DISC_POLLED      (u32)(0x40000000)
	u32 volatile flags2;
	#define AF2_SERIAL_FLASH    (u32)(0x00000001)
	#define AF2_DEV_SCAN        (u32)(0x00000002)
	#define AF2_DEV_CNT_OK      (u32)(0x00000004)
	#define AF2_COREDUMP_AVAIL  (u32)(0x00000008)
	#define AF2_COREDUMP_SAVED  (u32)(0x00000010)
	#define AF2_VDA_POWER_DOWN  (u32)(0x00000100)
	#define AF2_THUNDERLINK     (u32)(0x00000200)
	#define AF2_THUNDERBOLT     (u32)(0x00000400)
	#define AF2_INIT_DONE       (u32)(0x00000800)
	#define AF2_INT_PENDING     (u32)(0x00001000)
	#define AF2_TIMER_TICK      (u32)(0x00002000)
	#define AF2_IRQ_CLAIMED     (u32)(0x00004000)
	#define AF2_MSI_ENABLED     (u32)(0x00008000)
	long flags;
	#define AF_PORT_CHANGE      0
	#define AF_CHPRST_NEEDED    1
	#define AF_CHPRST_PENDING   2
	#define AF_CHPRST_DETECTED  3
	#define AF_BUSRST_NEEDED    4
	#define AF_BUSRST_PENDING   5
	#define AF_BUSRST_DETECTED  6
	#define AF_DISABLED         7
	#define AF_FLASH_LOCK       8
	#define AF_OS_RESET         9
	#define AF_FLASHING         10
	#define AF_POWER_MGT        11
	#define AF_NVR_VALID        12
	#define AF_DEGRADED_MODE    13
	#define AF_DISC_PENDING     14
	#define AF_TASKLET_SCHEDULED    15
	#define AF_HEARTBEAT        16
	#define AF_HEARTBEAT_ENB    17
	#define AF_NOT_PRESENT      18
	#define AF_CHPRST_STARTED   19
	#define AF_FIRST_INIT       20
	#define AF_POWER_DOWN       21
	#define AF_DISC_IN_PROG     22
	#define AF_COMM_LIST_TOGGLE 23
	#define AF_LEGACY_SGE_MODE  24
	#define AF_DISC_POLLED      25
	long flags2;
	#define AF2_SERIAL_FLASH    0
	#define AF2_DEV_SCAN        1
	#define AF2_DEV_CNT_OK      2
	#define AF2_COREDUMP_AVAIL  3
	#define AF2_COREDUMP_SAVED  4
	#define AF2_VDA_POWER_DOWN  5
	#define AF2_THUNDERLINK     6
	#define AF2_THUNDERBOLT     7
	#define AF2_INIT_DONE       8
	#define AF2_INT_PENDING     9
	#define AF2_TIMER_TICK      10
	#define AF2_IRQ_CLAIMED     11
	#define AF2_MSI_ENABLED     12
	atomic_t disable_cnt;
	atomic_t dis_ints_cnt;
	u32 int_stat;
@@ -1150,16 +1150,6 @@ void esas2r_queue_fw_event(struct esas2r_adapter *a,
			   int data_sz);

/* Inline functions */
static inline u32 esas2r_lock_set_flags(volatile u32 *flags, u32 bits)
{
	return test_and_set_bit(ilog2(bits), (volatile unsigned long *)flags);
}

static inline u32 esas2r_lock_clear_flags(volatile u32 *flags, u32 bits)
{
	return test_and_clear_bit(ilog2(bits),
				  (volatile unsigned long *)flags);
}

/* Allocate a chip scatter/gather list entry */
static inline struct esas2r_mem_desc *esas2r_alloc_sgl(struct esas2r_adapter *a)
@@ -1303,10 +1293,13 @@ static inline void esas2r_rq_destroy_request(struct esas2r_request *rq,

static inline bool esas2r_is_tasklet_pending(struct esas2r_adapter *a)
{
	return (a->flags & (AF_BUSRST_NEEDED | AF_BUSRST_DETECTED
			    | AF_CHPRST_NEEDED | AF_CHPRST_DETECTED
			    | AF_PORT_CHANGE))
	       ? true : false;

	return test_bit(AF_BUSRST_NEEDED, &a->flags) ||
	       test_bit(AF_BUSRST_DETECTED, &a->flags) ||
	       test_bit(AF_CHPRST_NEEDED, &a->flags) ||
	       test_bit(AF_CHPRST_DETECTED, &a->flags) ||
	       test_bit(AF_PORT_CHANGE, &a->flags);

}

/*
@@ -1345,24 +1338,24 @@ static inline void esas2r_enable_chip_interrupts(struct esas2r_adapter *a)
static inline void esas2r_schedule_tasklet(struct esas2r_adapter *a)
{
	/* make sure we don't schedule twice */
	if (!(esas2r_lock_set_flags(&a->flags, AF_TASKLET_SCHEDULED) &
	      ilog2(AF_TASKLET_SCHEDULED)))
	if (!test_and_set_bit(AF_TASKLET_SCHEDULED, &a->flags))
		tasklet_hi_schedule(&a->tasklet);
}

static inline void esas2r_enable_heartbeat(struct esas2r_adapter *a)
{
	if (!(a->flags & (AF_DEGRADED_MODE | AF_CHPRST_PENDING))
	    && (a->nvram->options2 & SASNVR2_HEARTBEAT))
		esas2r_lock_set_flags(&a->flags, AF_HEARTBEAT_ENB);
	if (!test_bit(AF_DEGRADED_MODE, &a->flags) &&
	    !test_bit(AF_CHPRST_PENDING, &a->flags) &&
	    (a->nvram->options2 & SASNVR2_HEARTBEAT))
		set_bit(AF_HEARTBEAT_ENB, &a->flags);
	else
		esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT_ENB);
		clear_bit(AF_HEARTBEAT_ENB, &a->flags);
}

static inline void esas2r_disable_heartbeat(struct esas2r_adapter *a)
{
	esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT_ENB);
	esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT);
	clear_bit(AF_HEARTBEAT_ENB, &a->flags);
	clear_bit(AF_HEARTBEAT, &a->flags);
}

/* Set the initial state for resetting the adapter on the next pass through
@@ -1372,9 +1365,9 @@ static inline void esas2r_local_reset_adapter(struct esas2r_adapter *a)
{
	esas2r_disable_heartbeat(a);

	esas2r_lock_set_flags(&a->flags, AF_CHPRST_NEEDED);
	esas2r_lock_set_flags(&a->flags, AF_CHPRST_PENDING);
	esas2r_lock_set_flags(&a->flags, AF_DISC_PENDING);
	set_bit(AF_CHPRST_NEEDED, &a->flags);
	set_bit(AF_CHPRST_PENDING, &a->flags);
	set_bit(AF_DISC_PENDING, &a->flags);
}

/* See if an interrupt is pending on the adapter. */
+25 −30
Original line number Diff line number Diff line
@@ -86,9 +86,9 @@ void esas2r_disc_initialize(struct esas2r_adapter *a)

	esas2r_trace_enter();

	esas2r_lock_clear_flags(&a->flags, AF_DISC_IN_PROG);
	esas2r_lock_clear_flags(&a->flags2, AF2_DEV_SCAN);
	esas2r_lock_clear_flags(&a->flags2, AF2_DEV_CNT_OK);
	clear_bit(AF_DISC_IN_PROG, &a->flags);
	clear_bit(AF2_DEV_SCAN, &a->flags2);
	clear_bit(AF2_DEV_CNT_OK, &a->flags2);

	a->disc_start_time = jiffies_to_msecs(jiffies);
	a->disc_wait_time = nvr->dev_wait_time * 1000;
@@ -107,7 +107,8 @@ void esas2r_disc_initialize(struct esas2r_adapter *a)

	a->general_req.interrupt_cx = NULL;

	if (a->flags & (AF_CHPRST_DETECTED | AF_POWER_MGT)) {
	if (test_bit(AF_CHPRST_DETECTED, &a->flags) ||
	    test_bit(AF_POWER_MGT, &a->flags)) {
		if (a->prev_dev_cnt == 0) {
			/* Don't bother waiting if there is nothing to wait
			 * for.
@@ -212,9 +213,7 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
			|| a->disc_wait_cnt == 0)) {
			/* After three seconds of waiting, schedule a scan. */
			if (time >= 3000
			    && !(esas2r_lock_set_flags(&a->flags2,
						       AF2_DEV_SCAN) &
				 ilog2(AF2_DEV_SCAN))) {
			    && !test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) {
				spin_lock_irqsave(&a->mem_lock, flags);
				esas2r_disc_queue_event(a, DCDE_DEV_SCAN);
				spin_unlock_irqrestore(&a->mem_lock, flags);
@@ -228,18 +227,14 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
		 * We are done waiting...we think.  Adjust the wait time to
		 * consume events after the count is met.
		 */
		if (!(esas2r_lock_set_flags(&a->flags2, AF2_DEV_CNT_OK)
		      & ilog2(AF2_DEV_CNT_OK)))
		if (!test_and_set_bit(AF2_DEV_CNT_OK, &a->flags2))
			a->disc_wait_time = time + 3000;

		/* If we haven't done a full scan yet, do it now. */
		if (!(esas2r_lock_set_flags(&a->flags2,
					    AF2_DEV_SCAN) &
		      ilog2(AF2_DEV_SCAN))) {
		if (!test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) {
			spin_lock_irqsave(&a->mem_lock, flags);
			esas2r_disc_queue_event(a, DCDE_DEV_SCAN);
			spin_unlock_irqrestore(&a->mem_lock, flags);

			esas2r_trace_exit();
			return;
		}
@@ -253,9 +248,7 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
			return;
		}
	} else {
		if (!(esas2r_lock_set_flags(&a->flags2,
					    AF2_DEV_SCAN) &
		      ilog2(AF2_DEV_SCAN))) {
		if (!test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) {
			spin_lock_irqsave(&a->mem_lock, flags);
			esas2r_disc_queue_event(a, DCDE_DEV_SCAN);
			spin_unlock_irqrestore(&a->mem_lock, flags);
@@ -265,8 +258,8 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
	/* We want to stop waiting for devices. */
	a->disc_wait_time = 0;

	if ((a->flags & AF_DISC_POLLED)
	    && (a->flags & AF_DISC_IN_PROG)) {
	if (test_bit(AF_DISC_POLLED, &a->flags) &&
	    test_bit(AF_DISC_IN_PROG, &a->flags)) {
		/*
		 * Polled discovery is still pending so continue the active
		 * discovery until it is done.  At that point, we will stop
@@ -280,14 +273,14 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
		 * driven; i.e. There is no transition.
		 */
		esas2r_disc_fix_curr_requests(a);
		esas2r_lock_clear_flags(&a->flags, AF_DISC_PENDING);
		clear_bit(AF_DISC_PENDING, &a->flags);

		/*
		 * We have deferred target state changes until now because we
		 * don't want to report any removals (due to the first arrival)
		 * until the device wait time expires.
		 */
		esas2r_lock_set_flags(&a->flags, AF_PORT_CHANGE);
		set_bit(AF_PORT_CHANGE, &a->flags);
	}

	esas2r_trace_exit();
@@ -308,7 +301,8 @@ void esas2r_disc_queue_event(struct esas2r_adapter *a, u8 disc_evt)
	 * Don't start discovery before or during polled discovery.  if we did,
	 * we would have a deadlock if we are in the ISR already.
	 */
	if (!(a->flags & (AF_CHPRST_PENDING | AF_DISC_POLLED)))
	if (!test_bit(AF_CHPRST_PENDING, &a->flags) &&
	    !test_bit(AF_DISC_POLLED, &a->flags))
		esas2r_disc_start_port(a);

	esas2r_trace_exit();
@@ -322,7 +316,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)

	esas2r_trace_enter();

	if (a->flags & AF_DISC_IN_PROG) {
	if (test_bit(AF_DISC_IN_PROG, &a->flags)) {
		esas2r_trace_exit();

		return false;
@@ -330,7 +324,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)

	/* If there is a discovery waiting, process it. */
	if (dc->disc_evt) {
		if ((a->flags & AF_DISC_POLLED)
		if (test_bit(AF_DISC_POLLED, &a->flags)
		    && a->disc_wait_time == 0) {
			/*
			 * We are doing polled discovery, but we no longer want
@@ -347,7 +341,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)

		esas2r_hdebug("disc done");

		esas2r_lock_set_flags(&a->flags, AF_PORT_CHANGE);
		set_bit(AF_PORT_CHANGE, &a->flags);

		esas2r_trace_exit();

@@ -356,10 +350,10 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)

	/* Handle the discovery context */
	esas2r_trace("disc_evt: %d", dc->disc_evt);
	esas2r_lock_set_flags(&a->flags, AF_DISC_IN_PROG);
	set_bit(AF_DISC_IN_PROG, &a->flags);
	dc->flags = 0;

	if (a->flags & AF_DISC_POLLED)
	if (test_bit(AF_DISC_POLLED, &a->flags))
		dc->flags |= DCF_POLLED;

	rq->interrupt_cx = dc;
@@ -379,7 +373,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)
	}

	/* Continue interrupt driven discovery */
	if (!(a->flags & AF_DISC_POLLED))
	if (!test_bit(AF_DISC_POLLED, &a->flags))
		ret = esas2r_disc_continue(a, rq);
	else
		ret = true;
@@ -453,10 +447,10 @@ static bool esas2r_disc_continue(struct esas2r_adapter *a,
	/* Discovery is done...for now. */
	rq->interrupt_cx = NULL;

	if (!(a->flags & AF_DISC_PENDING))
	if (!test_bit(AF_DISC_PENDING, &a->flags))
		esas2r_disc_fix_curr_requests(a);

	esas2r_lock_clear_flags(&a->flags, AF_DISC_IN_PROG);
	clear_bit(AF_DISC_IN_PROG, &a->flags);

	/* Start the next discovery. */
	return esas2r_disc_start_port(a);
@@ -480,7 +474,8 @@ static bool esas2r_disc_start_request(struct esas2r_adapter *a,

	spin_lock_irqsave(&a->queue_lock, flags);

	if (!(a->flags & (AF_CHPRST_PENDING | AF_FLASHING)))
	if (!test_bit(AF_CHPRST_PENDING, &a->flags) &&
	    !test_bit(AF_FLASHING, &a->flags))
		esas2r_disc_local_start_request(a, rq);
	else
		list_add_tail(&rq->req_list, &a->defer_list);
+19 −15
Original line number Diff line number Diff line
@@ -231,7 +231,7 @@ static bool load_image(struct esas2r_adapter *a, struct esas2r_request *rq)
	 * RS_PENDING, FM API tasks will continue.
	 */
	rq->req_stat = RS_PENDING;
	if (a->flags & AF_DEGRADED_MODE)
	if (test_bit(AF_DEGRADED_MODE, &a->flags))
		/* not suppported for now */;
	else
		build_flash_msg(a, rq);
@@ -315,7 +315,7 @@ static bool complete_fmapi_req(struct esas2r_adapter *a,
		memset(fc->scratch, 0, FM_BUF_SZ);

	esas2r_enable_heartbeat(a);
	esas2r_lock_clear_flags(&a->flags, AF_FLASH_LOCK);
	clear_bit(AF_FLASH_LOCK, &a->flags);
	return false;
}

@@ -526,7 +526,7 @@ no_cfg:
			 * The download is complete.  If in degraded mode,
			 * attempt a chip reset.
			 */
			if (a->flags & AF_DEGRADED_MODE)
			if (test_bit(AF_DEGRADED_MODE, &a->flags))
				esas2r_local_reset_adapter(a);

			a->flash_ver = fi->cmp_hdr[CH_IT_BIOS].version;
@@ -890,7 +890,7 @@ bool esas2r_process_fs_ioctl(struct esas2r_adapter *a,
		}
	}

	if (a->flags & AF_DEGRADED_MODE) {
	if (test_bit(AF_DEGRADED_MODE, &a->flags)) {
		fs->status = ATTO_STS_DEGRADED;
		return false;
	}
@@ -945,8 +945,12 @@ static bool esas2r_flash_access(struct esas2r_adapter *a, u32 function)

	/* Now wait for the firmware to process it */
	starttime = jiffies_to_msecs(jiffies);
	timeout = a->flags &
		  (AF_CHPRST_PENDING | AF_DISC_PENDING) ? 40000 : 5000;

	if (test_bit(AF_CHPRST_PENDING, &a->flags) ||
	    test_bit(AF_DISC_PENDING, &a->flags))
		timeout = 40000;
	else
		timeout = 5000;

	while (true) {
		intstat = esas2r_read_register_dword(a, MU_INT_STATUS_OUT);
@@ -1008,7 +1012,7 @@ bool esas2r_read_flash_block(struct esas2r_adapter *a,
		u32 offset;
		u32 iatvr;

		if (a->flags2 & AF2_SERIAL_FLASH)
		if (test_bit(AF2_SERIAL_FLASH, &a->flags2))
			iatvr = MW_DATA_ADDR_SER_FLASH + (from & -WINDOW_SIZE);
		else
			iatvr = MW_DATA_ADDR_PAR_FLASH + (from & -WINDOW_SIZE);
@@ -1236,9 +1240,9 @@ static void esas2r_nvram_callback(struct esas2r_adapter *a,
	if (rq->req_stat != RS_PENDING) {
		/* update the NVRAM state */
		if (rq->req_stat == RS_SUCCESS)
			esas2r_lock_set_flags(&a->flags, AF_NVR_VALID);
			set_bit(AF_NVR_VALID, &a->flags);
		else
			esas2r_lock_clear_flags(&a->flags, AF_NVR_VALID);
			clear_bit(AF_NVR_VALID, &a->flags);

		esas2r_enable_heartbeat(a);

@@ -1258,7 +1262,7 @@ bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq,
	u32 *sas_address_dwords = (u32 *)&sas_address_bytes[0];
	struct atto_vda_flash_req *vrq = &rq->vrq->flash;

	if (a->flags & AF_DEGRADED_MODE)
	if (test_bit(AF_DEGRADED_MODE, &a->flags))
		return false;

	if (down_interruptible(&a->nvram_semaphore))
@@ -1302,7 +1306,7 @@ bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq,
			       FLS_OFFSET_NVR,
			       sizeof(struct esas2r_sas_nvram));

	if (a->flags & AF_LEGACY_SGE_MODE) {
	if (test_bit(AF_LEGACY_SGE_MODE, &a->flags)) {

		vrq->data.sge[0].length =
			cpu_to_le32(SGE_LAST |
@@ -1337,7 +1341,7 @@ bool esas2r_nvram_validate(struct esas2r_adapter *a)
	} else if (n->version > SASNVR_VERSION) {
		esas2r_hdebug("invalid NVRAM version");
	} else {
		esas2r_lock_set_flags(&a->flags, AF_NVR_VALID);
		set_bit(AF_NVR_VALID, &a->flags);
		rslt = true;
	}

@@ -1359,7 +1363,7 @@ void esas2r_nvram_set_defaults(struct esas2r_adapter *a)
	struct esas2r_sas_nvram *n = a->nvram;
	u32 time = jiffies_to_msecs(jiffies);

	esas2r_lock_clear_flags(&a->flags, AF_NVR_VALID);
	clear_bit(AF_NVR_VALID, &a->flags);
	*n = default_sas_nvram;
	n->sas_addr[3] |= 0x0F;
	n->sas_addr[4] = HIBYTE(LOWORD(time));
@@ -1389,7 +1393,7 @@ bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi,
	u8 j;
	struct esas2r_component_header *ch;

	if (esas2r_lock_set_flags(&a->flags, AF_FLASH_LOCK) & AF_FLASH_LOCK) {
	if (test_and_set_bit(AF_FLASH_LOCK, &a->flags)) {
		/* flag was already set */
		fi->status = FI_STAT_BUSY;
		return false;
@@ -1413,7 +1417,7 @@ bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi,
		return complete_fmapi_req(a, rq, FI_STAT_IMG_VER);
	}

	if (a->flags & AF_DEGRADED_MODE)
	if (test_bit(AF_DEGRADED_MODE, &a->flags))
		return complete_fmapi_req(a, rq, FI_STAT_DEGRADED);

	switch (fi->action) {
+69 −74

File changed.

Preview size limit exceeded, changes collapsed.

+49 −48
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ irqreturn_t esas2r_interrupt(int irq, void *dev_id)
	if (!esas2r_adapter_interrupt_pending(a))
		return IRQ_NONE;

	esas2r_lock_set_flags(&a->flags2, AF2_INT_PENDING);
	set_bit(AF2_INT_PENDING, &a->flags2);
	esas2r_schedule_tasklet(a);

	return IRQ_HANDLED;
@@ -317,9 +317,10 @@ void esas2r_do_deferred_processes(struct esas2r_adapter *a)
	 *  = 2 - can start any request
	 */

	if (a->flags & (AF_CHPRST_PENDING | AF_FLASHING))
	if (test_bit(AF_CHPRST_PENDING, &a->flags) ||
	    test_bit(AF_FLASHING, &a->flags))
		startreqs = 0;
	else if (a->flags & AF_DISC_PENDING)
	else if (test_bit(AF_DISC_PENDING, &a->flags))
		startreqs = 1;

	atomic_inc(&a->disable_cnt);
@@ -367,7 +368,7 @@ void esas2r_do_deferred_processes(struct esas2r_adapter *a)
				 * Flashing could have been set by last local
				 * start
				 */
				if (a->flags & AF_FLASHING)
				if (test_bit(AF_FLASHING, &a->flags))
					break;
			}
		}
@@ -404,7 +405,7 @@ void esas2r_process_adapter_reset(struct esas2r_adapter *a)

		dc->disc_evt = 0;

		esas2r_lock_clear_flags(&a->flags, AF_DISC_IN_PROG);
		clear_bit(AF_DISC_IN_PROG, &a->flags);
	}

	/*
@@ -425,7 +426,7 @@ void esas2r_process_adapter_reset(struct esas2r_adapter *a)
		a->last_write =
			a->last_read = a->list_size - 1;

	esas2r_lock_set_flags(&a->flags, AF_COMM_LIST_TOGGLE);
	set_bit(AF_COMM_LIST_TOGGLE, &a->flags);

	/* Kill all the requests on the active list */
	list_for_each(element, &a->defer_list) {
@@ -470,7 +471,7 @@ static void esas2r_process_bus_reset(struct esas2r_adapter *a)
	if (atomic_read(&a->disable_cnt) == 0)
		esas2r_do_deferred_processes(a);

	esas2r_lock_clear_flags(&a->flags, AF_OS_RESET);
	clear_bit(AF_OS_RESET, &a->flags);

	esas2r_trace_exit();
}
@@ -478,10 +479,10 @@ static void esas2r_process_bus_reset(struct esas2r_adapter *a)
static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)
{

	esas2r_lock_clear_flags(&a->flags, AF_CHPRST_NEEDED);
	esas2r_lock_clear_flags(&a->flags, AF_BUSRST_NEEDED);
	esas2r_lock_clear_flags(&a->flags, AF_BUSRST_DETECTED);
	esas2r_lock_clear_flags(&a->flags, AF_BUSRST_PENDING);
	clear_bit(AF_CHPRST_NEEDED, &a->flags);
	clear_bit(AF_BUSRST_NEEDED, &a->flags);
	clear_bit(AF_BUSRST_DETECTED, &a->flags);
	clear_bit(AF_BUSRST_PENDING, &a->flags);
	/*
	 * Make sure we don't get attempt more than 3 resets
	 * when the uptime between resets does not exceed one
@@ -507,10 +508,10 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)
		 * prevent the heartbeat from trying to recover.
		 */

		esas2r_lock_set_flags(&a->flags, AF_DEGRADED_MODE);
		esas2r_lock_set_flags(&a->flags, AF_DISABLED);
		esas2r_lock_clear_flags(&a->flags, AF_CHPRST_PENDING);
		esas2r_lock_clear_flags(&a->flags, AF_DISC_PENDING);
		set_bit(AF_DEGRADED_MODE, &a->flags);
		set_bit(AF_DISABLED, &a->flags);
		clear_bit(AF_CHPRST_PENDING, &a->flags);
		clear_bit(AF_DISC_PENDING, &a->flags);

		esas2r_disable_chip_interrupts(a);
		a->int_mask = 0;
@@ -519,18 +520,17 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)
		esas2r_log(ESAS2R_LOG_CRIT,
			   "Adapter disabled because of hardware failure");
	} else {
		u32 flags =
			esas2r_lock_set_flags(&a->flags, AF_CHPRST_STARTED);
		bool alrdyrst = test_and_set_bit(AF_CHPRST_STARTED, &a->flags);

		if (!(flags & AF_CHPRST_STARTED))
		if (!alrdyrst)
			/*
			 * Only disable interrupts if this is
			 * the first reset attempt.
			 */
			esas2r_disable_chip_interrupts(a);

		if ((a->flags & AF_POWER_MGT) && !(a->flags & AF_FIRST_INIT) &&
		    !(flags & AF_CHPRST_STARTED)) {
		if ((test_bit(AF_POWER_MGT, &a->flags)) &&
		    !test_bit(AF_FIRST_INIT, &a->flags) && !alrdyrst) {
			/*
			 * Don't reset the chip on the first
			 * deferred power up attempt.
@@ -543,10 +543,10 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)
		/* Kick off the reinitialization */
		a->chip_uptime += ESAS2R_CHP_UPTIME_CNT;
		a->chip_init_time = jiffies_to_msecs(jiffies);
		if (!(a->flags & AF_POWER_MGT)) {
		if (!test_bit(AF_POWER_MGT, &a->flags)) {
			esas2r_process_adapter_reset(a);

			if (!(flags & AF_CHPRST_STARTED)) {
			if (!alrdyrst) {
				/* Remove devices now that I/O is cleaned up. */
				a->prev_dev_cnt =
					esas2r_targ_db_get_tgt_cnt(a);
@@ -560,38 +560,37 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)

static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a)
{
	while (a->flags & AF_CHPRST_DETECTED) {
	while (test_bit(AF_CHPRST_DETECTED, &a->flags)) {
		/*
		 * Balance the enable in esas2r_initadapter_hw.
		 * Esas2r_power_down already took care of it for power
		 * management.
		 */
		if (!(a->flags & AF_DEGRADED_MODE) && !(a->flags &
							AF_POWER_MGT))
		if (!test_bit(AF_DEGRADED_MODE, &a->flags) &&
		    !test_bit(AF_POWER_MGT, &a->flags))
			esas2r_disable_chip_interrupts(a);

		/* Reinitialize the chip. */
		esas2r_check_adapter(a);
		esas2r_init_adapter_hw(a, 0);

		if (a->flags & AF_CHPRST_NEEDED)
		if (test_bit(AF_CHPRST_NEEDED, &a->flags))
			break;

		if (a->flags & AF_POWER_MGT) {
		if (test_bit(AF_POWER_MGT, &a->flags)) {
			/* Recovery from power management. */
			if (a->flags & AF_FIRST_INIT) {
			if (test_bit(AF_FIRST_INIT, &a->flags)) {
				/* Chip reset during normal power up */
				esas2r_log(ESAS2R_LOG_CRIT,
					   "The firmware was reset during a normal power-up sequence");
			} else {
				/* Deferred power up complete. */
				esas2r_lock_clear_flags(&a->flags,
							AF_POWER_MGT);
				clear_bit(AF_POWER_MGT, &a->flags);
				esas2r_send_reset_ae(a, true);
			}
		} else {
			/* Recovery from online chip reset. */
			if (a->flags & AF_FIRST_INIT) {
			if (test_bit(AF_FIRST_INIT, &a->flags)) {
				/* Chip reset during driver load */
			} else {
				/* Chip reset after driver load */
@@ -602,14 +601,14 @@ static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a)
				   "Recovering from a chip reset while the chip was online");
		}

		esas2r_lock_clear_flags(&a->flags, AF_CHPRST_STARTED);
		clear_bit(AF_CHPRST_STARTED, &a->flags);
		esas2r_enable_chip_interrupts(a);

		/*
		 * Clear this flag last!  this indicates that the chip has been
		 * reset already during initialization.
		 */
		esas2r_lock_clear_flags(&a->flags, AF_CHPRST_DETECTED);
		clear_bit(AF_CHPRST_DETECTED, &a->flags);
	}
}

@@ -617,26 +616,28 @@ static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a)
/* Perform deferred tasks when chip interrupts are disabled */
void esas2r_do_tasklet_tasks(struct esas2r_adapter *a)
{
	if (a->flags & (AF_CHPRST_NEEDED | AF_CHPRST_DETECTED)) {
		if (a->flags & AF_CHPRST_NEEDED)

	if (test_bit(AF_CHPRST_NEEDED, &a->flags) ||
	    test_bit(AF_CHPRST_DETECTED, &a->flags)) {
		if (test_bit(AF_CHPRST_NEEDED, &a->flags))
			esas2r_chip_rst_needed_during_tasklet(a);

		esas2r_handle_chip_rst_during_tasklet(a);
	}

	if (a->flags & AF_BUSRST_NEEDED) {
	if (test_bit(AF_BUSRST_NEEDED, &a->flags)) {
		esas2r_hdebug("hard resetting bus");

		esas2r_lock_clear_flags(&a->flags, AF_BUSRST_NEEDED);
		clear_bit(AF_BUSRST_NEEDED, &a->flags);

		if (a->flags & AF_FLASHING)
			esas2r_lock_set_flags(&a->flags, AF_BUSRST_DETECTED);
		if (test_bit(AF_FLASHING, &a->flags))
			set_bit(AF_BUSRST_DETECTED, &a->flags);
		else
			esas2r_write_register_dword(a, MU_DOORBELL_IN,
						    DRBL_RESET_BUS);
	}

	if (a->flags & AF_BUSRST_DETECTED) {
	if (test_bit(AF_BUSRST_DETECTED, &a->flags)) {
		esas2r_process_bus_reset(a);

		esas2r_log_dev(ESAS2R_LOG_WARN,
@@ -645,14 +646,14 @@ void esas2r_do_tasklet_tasks(struct esas2r_adapter *a)

		scsi_report_bus_reset(a->host, 0);

		esas2r_lock_clear_flags(&a->flags, AF_BUSRST_DETECTED);
		esas2r_lock_clear_flags(&a->flags, AF_BUSRST_PENDING);
		clear_bit(AF_BUSRST_DETECTED, &a->flags);
		clear_bit(AF_BUSRST_PENDING, &a->flags);

		esas2r_log(ESAS2R_LOG_WARN, "Bus reset complete");
	}

	if (a->flags & AF_PORT_CHANGE) {
		esas2r_lock_clear_flags(&a->flags, AF_PORT_CHANGE);
	if (test_bit(AF_PORT_CHANGE, &a->flags)) {
		clear_bit(AF_PORT_CHANGE, &a->flags);

		esas2r_targ_db_report_changes(a);
	}
@@ -672,10 +673,10 @@ static void esas2r_doorbell_interrupt(struct esas2r_adapter *a, u32 doorbell)
	esas2r_write_register_dword(a, MU_DOORBELL_OUT, doorbell);

	if (doorbell & DRBL_RESET_BUS)
		esas2r_lock_set_flags(&a->flags, AF_BUSRST_DETECTED);
		set_bit(AF_BUSRST_DETECTED, &a->flags);

	if (doorbell & DRBL_FORCE_INT)
		esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT);
		clear_bit(AF_HEARTBEAT, &a->flags);

	if (doorbell & DRBL_PANIC_REASON_MASK) {
		esas2r_hdebug("*** Firmware Panic ***");
@@ -683,7 +684,7 @@ static void esas2r_doorbell_interrupt(struct esas2r_adapter *a, u32 doorbell)
	}

	if (doorbell & DRBL_FW_RESET) {
		esas2r_lock_set_flags(&a->flags2, AF2_COREDUMP_AVAIL);
		set_bit(AF2_COREDUMP_AVAIL, &a->flags2);
		esas2r_local_reset_adapter(a);
	}

@@ -918,7 +919,7 @@ void esas2r_complete_request(struct esas2r_adapter *a,
{
	if (rq->vrq->scsi.function == VDA_FUNC_FLASH
	    && rq->vrq->flash.sub_func == VDA_FLASH_COMMIT)
		esas2r_lock_clear_flags(&a->flags, AF_FLASHING);
		clear_bit(AF_FLASHING, &a->flags);

	/* See if we setup a callback to do special processing */

Loading