Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73a25462 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by James Bottomley
Browse files

[SCSI] aic79xx: update to use scsi_transport_spi



This patch updates the aic79xx driver to take advantage of the
scsi_transport_spi infrastructure. Patch is quite a mess as some
procedures have been reshuffled to be closer to the aic7xxx driver.

Rejections fixed and
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 60a13213
Loading
Loading
Loading
Loading
+1675 −3578

File changed.

Preview size limit exceeded, changes collapsed.

+29 −168
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#ifndef _AIC79XX_LINUX_H_
#define _AIC79XX_LINUX_H_

#include <linux/config.h>
#include <linux/types.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
@@ -49,18 +50,23 @@
#include <linux/pci.h>
#include <linux/smp_lock.h>
#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <asm/byteorder.h>
#include <asm/io.h>

#include <linux/interrupt.h> /* For tasklet support. */
#include <linux/config.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>

/* Core SCSI definitions */
#define AIC_LIB_PREFIX ahd
#include "scsi.h"
#include <scsi/scsi_host.h>

/* Name space conflict with BSD queue macros */
#ifdef LIST_HEAD
@@ -95,7 +101,7 @@
/************************* Forward Declarations *******************************/
struct ahd_softc;
typedef struct pci_dev *ahd_dev_softc_t;
typedef Scsi_Cmnd      *ahd_io_ctx_t;
typedef struct scsi_cmnd      *ahd_io_ctx_t;

/******************************* Byte Order ***********************************/
#define ahd_htobe16(x)	cpu_to_be16(x)
@@ -115,7 +121,7 @@ typedef Scsi_Cmnd *ahd_io_ctx_t;
/************************* Configuration Data *********************************/
extern uint32_t aic79xx_allow_memio;
extern int aic79xx_detect_complete;
extern Scsi_Host_Template aic79xx_driver_template;
extern struct scsi_host_template aic79xx_driver_template;

/***************************** Bus Space/DMA **********************************/

@@ -145,11 +151,7 @@ struct ahd_linux_dma_tag
};
typedef struct ahd_linux_dma_tag* bus_dma_tag_t;

struct ahd_linux_dmamap
{
	dma_addr_t	bus_addr;
};
typedef struct ahd_linux_dmamap* bus_dmamap_t;
typedef dma_addr_t bus_dmamap_t;

typedef int bus_dma_filter_t(void*, dma_addr_t);
typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
@@ -226,12 +228,12 @@ typedef struct timer_list ahd_timer_t;
#define ahd_timer_init init_timer
#define ahd_timer_stop del_timer_sync
typedef void ahd_linux_callback_t (u_long);  
static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec,
static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
				     ahd_callback_t *func, void *arg);
static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);

static __inline void
ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg)
ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
{
	struct ahd_softc *ahd;

@@ -382,62 +384,12 @@ struct ahd_linux_device {
	 */
	u_int			commands_since_idle_or_otag;
#define AHD_OTAG_THRESH	500

	int			lun;
	Scsi_Device	       *scsi_device;
	struct			ahd_linux_target *target;
};

typedef enum {
	AHD_DV_REQUIRED		 = 0x01,
	AHD_INQ_VALID		 = 0x02,
	AHD_BASIC_DV		 = 0x04,
	AHD_ENHANCED_DV		 = 0x08
} ahd_linux_targ_flags;

/* DV States */
typedef enum {
	AHD_DV_STATE_EXIT = 0,
	AHD_DV_STATE_INQ_SHORT_ASYNC,
	AHD_DV_STATE_INQ_ASYNC,
	AHD_DV_STATE_INQ_ASYNC_VERIFY,
	AHD_DV_STATE_TUR,
	AHD_DV_STATE_REBD,
	AHD_DV_STATE_INQ_VERIFY,
	AHD_DV_STATE_WEB,
	AHD_DV_STATE_REB,
	AHD_DV_STATE_SU,
	AHD_DV_STATE_BUSY
} ahd_dv_state;

struct ahd_linux_target {
	struct ahd_linux_device	 *devices[AHD_NUM_LUNS];
	int			  channel;
	int			  target;
	int			  refcount;
	struct scsi_device	 *sdev[AHD_NUM_LUNS];
	struct ahd_transinfo	  last_tinfo;
	struct ahd_softc	 *ahd;
	ahd_linux_targ_flags	  flags;
	struct scsi_inquiry_data *inq_data;
	/*
	 * The next "fallback" period to use for narrow/wide transfers.
	 */
	uint8_t			  dv_next_narrow_period;
	uint8_t			  dv_next_wide_period;
	uint8_t			  dv_max_width;
	uint8_t			  dv_max_ppr_options;
	uint8_t			  dv_last_ppr_options;
	u_int			  dv_echo_size;
	ahd_dv_state		  dv_state;
	u_int			  dv_state_retry;
	uint8_t			 *dv_buffer;
	uint8_t			 *dv_buffer1;

	/*
	 * Cumulative counter of errors.
	 */
	u_long			errors_detected;
	u_long			cmds_since_error;
};

/********************* Definitions Required by the Core ***********************/
@@ -452,16 +404,11 @@ struct ahd_linux_target {
/*
 * Per-SCB OSM storage.
 */
typedef enum {
	AHD_SCB_UP_EH_SEM = 0x1
} ahd_linux_scb_flags;

struct scb_platform_data {
	struct ahd_linux_device	*dev;
	dma_addr_t		 buf_busaddr;
	uint32_t		 xfer_len;
	uint32_t		 sense_resid;	/* Auto-Sense residual */
	ahd_linux_scb_flags	 flags;
};

/*
@@ -470,42 +417,24 @@ struct scb_platform_data {
 * alignment restrictions of the various platforms supported by
 * this driver.
 */
typedef enum {
	AHD_DV_WAIT_SIMQ_EMPTY	 = 0x01,
	AHD_DV_WAIT_SIMQ_RELEASE = 0x02,
	AHD_DV_ACTIVE		 = 0x04,
	AHD_DV_SHUTDOWN		 = 0x08,
	AHD_RUN_CMPLT_Q_TIMER	 = 0x10
} ahd_linux_softc_flags;

TAILQ_HEAD(ahd_completeq, ahd_cmd);

struct ahd_platform_data {
	/*
	 * Fields accessed from interrupt context.
	 */
	struct ahd_linux_target *targets[AHD_NUM_TARGETS]; 
	struct ahd_completeq	 completeq;
	struct scsi_target *starget[AHD_NUM_TARGETS]; 

	spinlock_t		 spin_lock;
	u_int			 qfrozen;
	pid_t			 dv_pid;
	struct timer_list	 completeq_timer;
	struct timer_list	 reset_timer;
	struct timer_list	 stats_timer;
	struct semaphore	 eh_sem;
	struct semaphore	 dv_sem;
	struct semaphore	 dv_cmd_sem;	/* XXX This needs to be in
						 * the target struct
						 */
	struct scsi_device	*dv_scsi_dev;
	struct Scsi_Host        *host;		/* pointer to scsi host */
#define AHD_LINUX_NOIRQ	((uint32_t)~0)
	uint32_t		 irq;		/* IRQ for this adapter */
	uint32_t		 bios_address;
	uint32_t		 mem_busaddr;	/* Mem Base Addr */
	uint64_t		 hw_dma_mask;
	ahd_linux_softc_flags	 flags;
#define	AHD_SCB_UP_EH_SEM 0x1
	uint32_t		 flags;
};

/************************** OS Utility Wrappers *******************************/
@@ -622,7 +551,7 @@ ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)

/**************************** Initialization **********************************/
int		ahd_linux_register_host(struct ahd_softc *,
					Scsi_Host_Template *);
					struct scsi_host_template *);

uint64_t	ahd_linux_get_memsize(void);

@@ -643,17 +572,6 @@ static __inline void ahd_lockinit(struct ahd_softc *);
static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags);
static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags);

/* Lock acquisition and release of the above lock in midlayer entry points. */
static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *,
						  unsigned long *flags);
static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *,
						    unsigned long *flags);

/* Lock held during command compeletion to the upper layer */
static __inline void ahd_done_lockinit(struct ahd_softc *);
static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags);
static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags);

/* Lock held during ahd_list manipulation and ahd softc frees */
extern spinlock_t ahd_list_spinlock;
static __inline void ahd_list_lockinit(void);
@@ -678,57 +596,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
	spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
}

static __inline void
ahd_midlayer_entrypoint_lock(struct ahd_softc *ahd, unsigned long *flags)
{
	/*
	 * In 2.5.X and some 2.4.X versions, the midlayer takes our
	 * lock just before calling us, so we avoid locking again.
	 * For other kernel versions, the io_request_lock is taken
	 * just before our entry point is called.  In this case, we
	 * trade the io_request_lock for our per-softc lock.
	 */
#if AHD_SCSI_HAS_HOST_LOCK == 0
	spin_unlock(&io_request_lock);
	spin_lock(&ahd->platform_data->spin_lock);
#endif
}

static __inline void
ahd_midlayer_entrypoint_unlock(struct ahd_softc *ahd, unsigned long *flags)
{
#if AHD_SCSI_HAS_HOST_LOCK == 0
	spin_unlock(&ahd->platform_data->spin_lock);
	spin_lock(&io_request_lock);
#endif
}

static __inline void
ahd_done_lockinit(struct ahd_softc *ahd)
{
	/*
	 * In 2.5.X, our own lock is held during completions.
	 * In previous versions, the io_request_lock is used.
	 * In either case, we can't initialize this lock again.
	 */
}

static __inline void
ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags)
{
#if AHD_SCSI_HAS_HOST_LOCK == 0
	spin_lock(&io_request_lock);
#endif
}

static __inline void
ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags)
{
#if AHD_SCSI_HAS_HOST_LOCK == 0
	spin_unlock(&io_request_lock);
#endif
}

static __inline void
ahd_list_lockinit(void)
{
@@ -909,20 +776,14 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
int	ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
			    off_t, int, int);

/*************************** Domain Validation ********************************/
#define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete)
#define AHD_DV_SIMQ_FROZEN(ahd)					\
	((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0)	\
	 && (ahd)->platform_data->qfrozen == 1)

/*********************** Transaction Access Wrappers **************************/
static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t);
static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd);
static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahd_get_transaction_status(struct scb *);
static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd);
static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahd_get_scsi_status(struct scb *);
static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
static __inline u_long ahd_get_transfer_length(struct scb *);
@@ -941,7 +802,7 @@ static __inline void ahd_platform_scb_free(struct ahd_softc *ahd,
static __inline void ahd_freeze_scb(struct scb *scb);

static __inline
void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status)
void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
{
	cmd->result &= ~(CAM_STATUS_MASK << 16);
	cmd->result |= status << 16;
@@ -954,7 +815,7 @@ void ahd_set_transaction_status(struct scb *scb, uint32_t status)
}

static __inline
void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status)
void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
{
	cmd->result &= ~0xFFFF;
	cmd->result |= status;
@@ -967,7 +828,7 @@ void ahd_set_scsi_status(struct scb *scb, uint32_t status)
}

static __inline
uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd)
uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
{
	return ((cmd->result >> 16) & CAM_STATUS_MASK);
}
@@ -979,7 +840,7 @@ uint32_t ahd_get_transaction_status(struct scb *scb)
}

static __inline
uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd)
uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
{
	return (cmd->result & 0xFFFF);
}
+11 −7
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ static void ahd_dump_target_state(struct ahd_softc *ahd,
				      u_int our_id, char channel,
				      u_int target_id, u_int target_offset);
static void	ahd_dump_device_state(struct info_str *info,
				      struct ahd_linux_device *dev);
				      struct scsi_device *sdev);
static int	ahd_proc_write_seeprom(struct ahd_softc *ahd,
				       char *buffer, int length);

@@ -167,6 +167,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
		      u_int target_offset)
{
	struct	ahd_linux_target *targ;
	struct  scsi_target *starget;
	struct	ahd_initiator_tinfo *tinfo;
	struct	ahd_tmode_tstate *tstate;
	int	lun;
@@ -176,7 +177,8 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
	copy_info(info, "Target %d Negotiation Settings\n", target_id);
	copy_info(info, "\tUser: ");
	ahd_format_transinfo(info, &tinfo->user);
	targ = ahd->platform_data->targets[target_offset];
	starget = ahd->platform_data->starget[target_offset];
	targ = scsi_transport_target_data(starget);
	if (targ == NULL)
		return;

@@ -184,12 +186,11 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
	ahd_format_transinfo(info, &tinfo->goal);
	copy_info(info, "\tCurr: ");
	ahd_format_transinfo(info, &tinfo->curr);
	copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected);

	for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
		struct ahd_linux_device *dev;
		struct scsi_device *dev;

		dev = targ->devices[lun];
		dev = targ->sdev[lun];

		if (dev == NULL)
			continue;
@@ -199,10 +200,13 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
}

static void
ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev)
ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
{
	struct ahd_linux_device *dev = scsi_transport_device_data(sdev);

	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
		  dev->target->channel + 'A', dev->target->target, dev->lun);
		  sdev->sdev_target->channel + 'A',
		  sdev->sdev_target->id, sdev->lun);

	copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
	copy_info(info, "\t\tCommands Active %d\n", dev->active);