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

Commit 85a46523 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by James Bottomley
Browse files

[SCSI] aic79xx: sane pci probing



remove ahd_tailq and do sane pci probing.  ported over from aic7xxx.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent d46b1d54
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -1247,9 +1247,6 @@ struct ahd_softc {
	uint16_t		  user_tagenable;/* Tagged Queuing allowed */
};

TAILQ_HEAD(ahd_softc_tailq, ahd_softc);
extern struct ahd_softc_tailq ahd_tailq;

/*************************** IO Cell Configuration ****************************/
#define	AHD_PRECOMP_SLEW_INDEX						\
    (AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0)
@@ -1374,8 +1371,6 @@ void ahd_enable_coalescing(struct ahd_softc *ahd,
void			 ahd_pause_and_flushwork(struct ahd_softc *ahd);
int			 ahd_suspend(struct ahd_softc *ahd); 
int			 ahd_resume(struct ahd_softc *ahd);
void			 ahd_softc_insert(struct ahd_softc *);
struct ahd_softc	*ahd_find_softc(struct ahd_softc *ahd);
void			 ahd_set_unit(struct ahd_softc *, int);
void			 ahd_set_name(struct ahd_softc *, char *);
struct scb		*ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
@@ -1524,7 +1519,6 @@ void ahd_print_scb(struct scb *scb);
void			ahd_print_devinfo(struct ahd_softc *ahd,
					  struct ahd_devinfo *devinfo);
void			ahd_dump_sglist(struct scb *scb);
void			ahd_dump_all_cards_state(void);
void			ahd_dump_card_state(struct ahd_softc *ahd);
int			ahd_print_register(ahd_reg_parse_entry_t *table,
					   u_int num_entries,
+2 −101
Original line number Diff line number Diff line
@@ -52,8 +52,6 @@
#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
#endif

/******************************** Globals *************************************/
struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);

/***************************** Lookup Tables **********************************/
char *ahd_chip_names[] =
@@ -5179,74 +5177,6 @@ ahd_softc_init(struct ahd_softc *ahd)
	return (0);
}

void
ahd_softc_insert(struct ahd_softc *ahd)
{
	struct ahd_softc *list_ahd;

#if AHD_PCI_CONFIG > 0
	/*
	 * Second Function PCI devices need to inherit some
	 * settings from function 0.
	 */
	if ((ahd->features & AHD_MULTI_FUNC) != 0) {
		TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
			ahd_dev_softc_t list_pci;
			ahd_dev_softc_t pci;

			list_pci = list_ahd->dev_softc;
			pci = ahd->dev_softc;
			if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci)
			 && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) {
				struct ahd_softc *master;
				struct ahd_softc *slave;

				if (ahd_get_pci_function(list_pci) == 0) {
					master = list_ahd;
					slave = ahd;
				} else {
					master = ahd;
					slave = list_ahd;
				}
				slave->flags &= ~AHD_BIOS_ENABLED; 
				slave->flags |=
				    master->flags & AHD_BIOS_ENABLED;
				break;
			}
		}
	}
#endif

	/*
	 * Insertion sort into our list of softcs.
	 */
	list_ahd = TAILQ_FIRST(&ahd_tailq);
	while (list_ahd != NULL
	    && ahd_softc_comp(ahd, list_ahd) <= 0)
		list_ahd = TAILQ_NEXT(list_ahd, links);
	if (list_ahd != NULL)
		TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
	else
		TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
	ahd->init_level++;
}

/*
 * Verify that the passed in softc pointer is for a
 * controller that is still configured.
 */
struct ahd_softc *
ahd_find_softc(struct ahd_softc *ahd)
{
	struct ahd_softc *list_ahd;

	TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
		if (list_ahd == ahd)
			return (ahd);
	}
	return (NULL);
}

void
ahd_set_unit(struct ahd_softc *ahd, int unit)
{
@@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
static void
ahd_reset_poll(void *arg)
{
	struct	ahd_softc *ahd;
	struct	ahd_softc *ahd = arg;
	u_int	scsiseq1;
	u_long	l;
	u_long	s;
	
	ahd_list_lock(&l);
	ahd = ahd_find_softc((struct ahd_softc *)arg);
	if (ahd == NULL) {
		printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
		ahd_list_unlock(&l);
		return;
	}
	ahd_lock(ahd, &s);
	ahd_pause(ahd);
	ahd_update_modes(ahd);
@@ -7924,7 +7846,6 @@ ahd_reset_poll(void *arg)
				ahd_reset_poll, ahd);
		ahd_unpause(ahd);
		ahd_unlock(ahd, &s);
		ahd_list_unlock(&l);
		return;
	}

@@ -7936,25 +7857,16 @@ ahd_reset_poll(void *arg)
	ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
	ahd_unlock(ahd, &s);
	ahd_release_simq(ahd);
	ahd_list_unlock(&l);
}

/**************************** Statistics Processing ***************************/
static void
ahd_stat_timer(void *arg)
{
	struct	ahd_softc *ahd;
	u_long	l;
	struct	ahd_softc *ahd = arg;
	u_long	s;
	int	enint_coal;
	
	ahd_list_lock(&l);
	ahd = ahd_find_softc((struct ahd_softc *)arg);
	if (ahd == NULL) {
		printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
		ahd_list_unlock(&l);
		return;
	}
	ahd_lock(ahd, &s);

	enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
@@ -7981,7 +7893,6 @@ ahd_stat_timer(void *arg)
	ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
			ahd_stat_timer, ahd);
	ahd_unlock(ahd, &s);
	ahd_list_unlock(&l);
}

/****************************** Status Processing *****************************/
@@ -8745,16 +8656,6 @@ sized:
	return (last_probe);
}

void
ahd_dump_all_cards_state(void)
{
	struct ahd_softc *list_ahd;

	TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
		ahd_dump_card_state(list_ahd);
	}
}

int
ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
		   const char *name, u_int address, u_int value,
+20 −88
Original line number Diff line number Diff line
@@ -59,11 +59,6 @@ static struct scsi_transport_template *ahd_linux_transport_template = NULL;
#include <linux/blkdev.h>		/* For block_size() */
#include <linux/delay.h>	/* For ssleep/msleep */

/*
 * Lock protecting manipulation of the ahd softc list.
 */
spinlock_t ahd_list_spinlock;

/*
 * Bucket size for counting good commands in between bad ones.
 */
@@ -302,13 +297,6 @@ static uint32_t aic79xx_pci_parity = ~0;
 */
uint32_t aic79xx_allow_memio = ~0;

/*
 * aic79xx_detect() has been run, so register all device arrivals
 * immediately with the system rather than deferring to the sorted
 * attachment performed by aic79xx_detect().
 */
int aic79xx_detect_complete;

/*
 * So that we can set how long each device is given as a selection timeout.
 * The table of values goes like this:
@@ -387,7 +375,9 @@ static void ahd_linux_setup_tag_info_global(char *p);
static aic_option_callback_t ahd_linux_setup_tag_info;
static aic_option_callback_t ahd_linux_setup_iocell_info;
static int  aic79xx_setup(char *c);
static int  ahd_linux_next_unit(void);

static int ahd_linux_unit;


/****************************** Inlines ***************************************/
static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
@@ -417,50 +407,6 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
#define BUILD_SCSIID(ahd, cmd)						\
	((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id)

/*
 * Try to detect an Adaptec 79XX controller.
 */
static int
ahd_linux_detect(struct scsi_host_template *template)
{
	struct	ahd_softc *ahd;
	int     found;
	int	error = 0;

	/*
	 * If we've been passed any parameters, process them now.
	 */
	if (aic79xx)
		aic79xx_setup(aic79xx);

	template->proc_name = "aic79xx";

	/*
	 * Initialize our softc list lock prior to
	 * probing for any adapters.
	 */
	ahd_list_lockinit();

#ifdef CONFIG_PCI
	error = ahd_linux_pci_init();
	if (error)
		return error;
#endif

	/*
	 * Register with the SCSI layer all
	 * controllers we've found.
	 */
	found = 0;
	TAILQ_FOREACH(ahd, &ahd_tailq, links) {

		if (ahd_linux_register_host(ahd, template) == 0)
			found++;
	}
	aic79xx_detect_complete++;
	return found;
}

/*
 * Return a string describing the driver.
 */
@@ -760,6 +706,7 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd)
struct scsi_host_template aic79xx_driver_template = {
	.module			= THIS_MODULE,
	.name			= "aic79xx",
	.proc_name		= "aic79xx",
	.proc_info		= ahd_linux_proc_info,
	.info			= ahd_linux_info,
	.queuecommand		= ahd_linux_queue,
@@ -1072,7 +1019,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
	host->max_lun = AHD_NUM_LUNS;
	host->max_channel = 0;
	host->sg_tablesize = AHD_NSEG;
	ahd_set_unit(ahd, ahd_linux_next_unit());
	ahd_set_unit(ahd, ahd_linux_unit++);
	sprintf(buf, "scsi%d", host->host_no);
	new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
	if (new_name != NULL) {
@@ -1100,29 +1047,6 @@ ahd_linux_get_memsize(void)
	return ((uint64_t)si.totalram << PAGE_SHIFT);
}

/*
 * Find the smallest available unit number to use
 * for a new device.  We don't just use a static
 * count to handle the "repeated hot-(un)plug"
 * scenario.
 */
static int
ahd_linux_next_unit(void)
{
	struct ahd_softc *ahd;
	int unit;

	unit = 0;
retry:
	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
		if (ahd->unit == unit) {
			unit++;
			goto retry;
		}
	}
	return (unit);
}

/*
 * Place the SCSI bus into a known state by either resetting it,
 * or forcing transfer negotiations on the next command to any
@@ -2755,23 +2679,31 @@ static struct spi_function_template ahd_linux_transport_functions = {
	.show_hold_mcs	= 1,
};



static int __init
ahd_linux_init(void)
{
	ahd_linux_transport_template = spi_attach_transport(&ahd_linux_transport_functions);
	int	error = 0;

	/*
	 * If we've been passed any parameters, process them now.
	 */
	if (aic79xx)
		aic79xx_setup(aic79xx);

	ahd_linux_transport_template =
		spi_attach_transport(&ahd_linux_transport_functions);
	if (!ahd_linux_transport_template)
		return -ENODEV;

	scsi_transport_reserve_target(ahd_linux_transport_template,
				      sizeof(struct ahd_linux_target));
	scsi_transport_reserve_device(ahd_linux_transport_template,
				      sizeof(struct ahd_linux_device));
	if (ahd_linux_detect(&aic79xx_driver_template) > 0)
		return 0;
	spi_release_transport(ahd_linux_transport_template);

	return -ENODEV;
	error = ahd_linux_pci_init();
	if (error)
		spi_release_transport(ahd_linux_transport_template);
	return error;
}

static void __exit
+0 −30
Original line number Diff line number Diff line
@@ -120,7 +120,6 @@ typedef struct scsi_cmnd *ahd_io_ctx_t;

/************************* Configuration Data *********************************/
extern uint32_t aic79xx_allow_memio;
extern int aic79xx_detect_complete;
extern struct scsi_host_template aic79xx_driver_template;

/***************************** Bus Space/DMA **********************************/
@@ -532,17 +531,6 @@ void ahd_format_transinfo(struct info_str *info,
			     struct ahd_transinfo *tinfo);

/******************************** Locking *************************************/
/* Lock protecting internal data structures */
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 held during ahd_list manipulation and ahd softc frees */
extern spinlock_t ahd_list_spinlock;
static __inline void ahd_list_lockinit(void);
static __inline void ahd_list_lock(unsigned long *flags);
static __inline void ahd_list_unlock(unsigned long *flags);

static __inline void
ahd_lockinit(struct ahd_softc *ahd)
{
@@ -561,24 +549,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
	spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
}

static __inline void
ahd_list_lockinit(void)
{
	spin_lock_init(&ahd_list_spinlock);
}

static __inline void
ahd_list_lock(unsigned long *flags)
{
	spin_lock_irqsave(&ahd_list_spinlock, *flags);
}

static __inline void
ahd_list_unlock(unsigned long *flags)
{
	spin_unlock_irqrestore(&ahd_list_spinlock, *flags);
}

/******************************* PCI Definitions ******************************/
/*
 * PCIM_xxx: mask to locate subfield in register
+34 −45
Original line number Diff line number Diff line
@@ -92,27 +92,31 @@ struct pci_driver aic79xx_pci_driver = {
static void
ahd_linux_pci_dev_remove(struct pci_dev *pdev)
{
	struct ahd_softc *ahd;
	u_long l;

	/*
	 * We should be able to just perform
	 * the free directly, but check our
	 * list for extra sanity.
	 */
	ahd_list_lock(&l);
	ahd = ahd_find_softc((struct ahd_softc *)pci_get_drvdata(pdev));
	if (ahd != NULL) {
	struct ahd_softc *ahd = pci_get_drvdata(pdev);
	u_long s;

		TAILQ_REMOVE(&ahd_tailq, ahd, links);
		ahd_list_unlock(&l);
	ahd_lock(ahd, &s);
	ahd_intr_enable(ahd, FALSE);
	ahd_unlock(ahd, &s);
	ahd_free(ahd);
}

static void
ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
{
	struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
	unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);

	master_pdev = pci_get_slot(pdev->bus, master_devfn);
	if (master_pdev) {
		struct ahd_softc *master = pci_get_drvdata(master_pdev);
		if (master) {
			ahd->flags &= ~AHD_BIOS_ENABLED;
			ahd->flags |= master->flags & AHD_BIOS_ENABLED;
		} else
		ahd_list_unlock(&l);
			printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
		pci_dev_put(master_pdev);
	}
}

static int
@@ -125,22 +129,6 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	char		*name;
	int		 error;

	/*
	 * Some BIOSen report the same device multiple times.
	 */
	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
		struct pci_dev *probed_pdev;

		probed_pdev = ahd->dev_softc;
		if (probed_pdev->bus->number == pdev->bus->number
		 && probed_pdev->devfn == pdev->devfn)
			break;
	}
	if (ahd != NULL) {
		/* Skip duplicate. */
		return (-ENODEV);
	}

	pci = pdev;
	entry = ahd_find_pci_device(pci);
	if (entry == NULL)
@@ -190,16 +178,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
		ahd_free(ahd);
		return (-error);
	}

	/*
	 * Second Function PCI devices need to inherit some
	 * * settings from function 0.
	 */
	if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
		ahd_linux_pci_inherit_flags(ahd);

	pci_set_drvdata(pdev, ahd);
	if (aic79xx_detect_complete) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)

	ahd_linux_register_host(ahd, &aic79xx_driver_template);
#else
		printf("aic79xx: ignoring PCI device found after "
		       "initialization\n");
		return (-ENODEV);
#endif
	}
	return (0);
}

Loading