aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2005-08-15 07:28:46 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-08-15 10:18:55 -0400
commit85a46523ff68aa0e4d2477c51075ffd9fc7e7a14 (patch)
treec465c274ffe0e4118ed46ad4e0e09dca975aeb1f /drivers/scsi
parentd46b1d549e1414d673e0ec18219f4f5e30d5f3f5 (diff)
[SCSI] aic79xx: sane pci probing
remove ahd_tailq and do sane pci probing. ported over from aic7xxx. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h6
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c103
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c108
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h30
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c79
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c14
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_proc.c11
7 files changed, 60 insertions, 291 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index fd4b2f3eb0c2..653fb0b42aea 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1247,9 +1247,6 @@ struct ahd_softc {
1247 uint16_t user_tagenable;/* Tagged Queuing allowed */ 1247 uint16_t user_tagenable;/* Tagged Queuing allowed */
1248}; 1248};
1249 1249
1250TAILQ_HEAD(ahd_softc_tailq, ahd_softc);
1251extern struct ahd_softc_tailq ahd_tailq;
1252
1253/*************************** IO Cell Configuration ****************************/ 1250/*************************** IO Cell Configuration ****************************/
1254#define AHD_PRECOMP_SLEW_INDEX \ 1251#define AHD_PRECOMP_SLEW_INDEX \
1255 (AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0) 1252 (AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0)
@@ -1374,8 +1371,6 @@ void ahd_enable_coalescing(struct ahd_softc *ahd,
1374void ahd_pause_and_flushwork(struct ahd_softc *ahd); 1371void ahd_pause_and_flushwork(struct ahd_softc *ahd);
1375int ahd_suspend(struct ahd_softc *ahd); 1372int ahd_suspend(struct ahd_softc *ahd);
1376int ahd_resume(struct ahd_softc *ahd); 1373int ahd_resume(struct ahd_softc *ahd);
1377void ahd_softc_insert(struct ahd_softc *);
1378struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd);
1379void ahd_set_unit(struct ahd_softc *, int); 1374void ahd_set_unit(struct ahd_softc *, int);
1380void ahd_set_name(struct ahd_softc *, char *); 1375void ahd_set_name(struct ahd_softc *, char *);
1381struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); 1376struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
@@ -1524,7 +1519,6 @@ void ahd_print_scb(struct scb *scb);
1524void ahd_print_devinfo(struct ahd_softc *ahd, 1519void ahd_print_devinfo(struct ahd_softc *ahd,
1525 struct ahd_devinfo *devinfo); 1520 struct ahd_devinfo *devinfo);
1526void ahd_dump_sglist(struct scb *scb); 1521void ahd_dump_sglist(struct scb *scb);
1527void ahd_dump_all_cards_state(void);
1528void ahd_dump_card_state(struct ahd_softc *ahd); 1522void ahd_dump_card_state(struct ahd_softc *ahd);
1529int ahd_print_register(ahd_reg_parse_entry_t *table, 1523int ahd_print_register(ahd_reg_parse_entry_t *table,
1530 u_int num_entries, 1524 u_int num_entries,
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index d69bbffb34a0..4e8f00df978d 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -52,8 +52,6 @@
52#include <dev/aic7xxx/aicasm/aicasm_insformat.h> 52#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
53#endif 53#endif
54 54
55/******************************** Globals *************************************/
56struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);
57 55
58/***************************** Lookup Tables **********************************/ 56/***************************** Lookup Tables **********************************/
59char *ahd_chip_names[] = 57char *ahd_chip_names[] =
@@ -5180,74 +5178,6 @@ ahd_softc_init(struct ahd_softc *ahd)
5180} 5178}
5181 5179
5182void 5180void
5183ahd_softc_insert(struct ahd_softc *ahd)
5184{
5185 struct ahd_softc *list_ahd;
5186
5187#if AHD_PCI_CONFIG > 0
5188 /*
5189 * Second Function PCI devices need to inherit some
5190 * settings from function 0.
5191 */
5192 if ((ahd->features & AHD_MULTI_FUNC) != 0) {
5193 TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
5194 ahd_dev_softc_t list_pci;
5195 ahd_dev_softc_t pci;
5196
5197 list_pci = list_ahd->dev_softc;
5198 pci = ahd->dev_softc;
5199 if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci)
5200 && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) {
5201 struct ahd_softc *master;
5202 struct ahd_softc *slave;
5203
5204 if (ahd_get_pci_function(list_pci) == 0) {
5205 master = list_ahd;
5206 slave = ahd;
5207 } else {
5208 master = ahd;
5209 slave = list_ahd;
5210 }
5211 slave->flags &= ~AHD_BIOS_ENABLED;
5212 slave->flags |=
5213 master->flags & AHD_BIOS_ENABLED;
5214 break;
5215 }
5216 }
5217 }
5218#endif
5219
5220 /*
5221 * Insertion sort into our list of softcs.
5222 */
5223 list_ahd = TAILQ_FIRST(&ahd_tailq);
5224 while (list_ahd != NULL
5225 && ahd_softc_comp(ahd, list_ahd) <= 0)
5226 list_ahd = TAILQ_NEXT(list_ahd, links);
5227 if (list_ahd != NULL)
5228 TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
5229 else
5230 TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
5231 ahd->init_level++;
5232}
5233
5234/*
5235 * Verify that the passed in softc pointer is for a
5236 * controller that is still configured.
5237 */
5238struct ahd_softc *
5239ahd_find_softc(struct ahd_softc *ahd)
5240{
5241 struct ahd_softc *list_ahd;
5242
5243 TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
5244 if (list_ahd == ahd)
5245 return (ahd);
5246 }
5247 return (NULL);
5248}
5249
5250void
5251ahd_set_unit(struct ahd_softc *ahd, int unit) 5181ahd_set_unit(struct ahd_softc *ahd, int unit)
5252{ 5182{
5253 ahd->unit = unit; 5183 ahd->unit = unit;
@@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
7902static void 7832static void
7903ahd_reset_poll(void *arg) 7833ahd_reset_poll(void *arg)
7904{ 7834{
7905 struct ahd_softc *ahd; 7835 struct ahd_softc *ahd = arg;
7906 u_int scsiseq1; 7836 u_int scsiseq1;
7907 u_long l;
7908 u_long s; 7837 u_long s;
7909 7838
7910 ahd_list_lock(&l);
7911 ahd = ahd_find_softc((struct ahd_softc *)arg);
7912 if (ahd == NULL) {
7913 printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
7914 ahd_list_unlock(&l);
7915 return;
7916 }
7917 ahd_lock(ahd, &s); 7839 ahd_lock(ahd, &s);
7918 ahd_pause(ahd); 7840 ahd_pause(ahd);
7919 ahd_update_modes(ahd); 7841 ahd_update_modes(ahd);
@@ -7924,7 +7846,6 @@ ahd_reset_poll(void *arg)
7924 ahd_reset_poll, ahd); 7846 ahd_reset_poll, ahd);
7925 ahd_unpause(ahd); 7847 ahd_unpause(ahd);
7926 ahd_unlock(ahd, &s); 7848 ahd_unlock(ahd, &s);
7927 ahd_list_unlock(&l);
7928 return; 7849 return;
7929 } 7850 }
7930 7851
@@ -7936,25 +7857,16 @@ ahd_reset_poll(void *arg)
7936 ahd->flags &= ~AHD_RESET_POLL_ACTIVE; 7857 ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
7937 ahd_unlock(ahd, &s); 7858 ahd_unlock(ahd, &s);
7938 ahd_release_simq(ahd); 7859 ahd_release_simq(ahd);
7939 ahd_list_unlock(&l);
7940} 7860}
7941 7861
7942/**************************** Statistics Processing ***************************/ 7862/**************************** Statistics Processing ***************************/
7943static void 7863static void
7944ahd_stat_timer(void *arg) 7864ahd_stat_timer(void *arg)
7945{ 7865{
7946 struct ahd_softc *ahd; 7866 struct ahd_softc *ahd = arg;
7947 u_long l;
7948 u_long s; 7867 u_long s;
7949 int enint_coal; 7868 int enint_coal;
7950 7869
7951 ahd_list_lock(&l);
7952 ahd = ahd_find_softc((struct ahd_softc *)arg);
7953 if (ahd == NULL) {
7954 printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
7955 ahd_list_unlock(&l);
7956 return;
7957 }
7958 ahd_lock(ahd, &s); 7870 ahd_lock(ahd, &s);
7959 7871
7960 enint_coal = ahd->hs_mailbox & ENINT_COALESCE; 7872 enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
@@ -7981,7 +7893,6 @@ ahd_stat_timer(void *arg)
7981 ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, 7893 ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
7982 ahd_stat_timer, ahd); 7894 ahd_stat_timer, ahd);
7983 ahd_unlock(ahd, &s); 7895 ahd_unlock(ahd, &s);
7984 ahd_list_unlock(&l);
7985} 7896}
7986 7897
7987/****************************** Status Processing *****************************/ 7898/****************************** Status Processing *****************************/
@@ -8745,16 +8656,6 @@ sized:
8745 return (last_probe); 8656 return (last_probe);
8746} 8657}
8747 8658
8748void
8749ahd_dump_all_cards_state(void)
8750{
8751 struct ahd_softc *list_ahd;
8752
8753 TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
8754 ahd_dump_card_state(list_ahd);
8755 }
8756}
8757
8758int 8659int
8759ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, 8660ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
8760 const char *name, u_int address, u_int value, 8661 const char *name, u_int address, u_int value,
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 2f158624c5d2..3feb739cd554 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -60,11 +60,6 @@ static struct scsi_transport_template *ahd_linux_transport_template = NULL;
60#include <linux/delay.h> /* For ssleep/msleep */ 60#include <linux/delay.h> /* For ssleep/msleep */
61 61
62/* 62/*
63 * Lock protecting manipulation of the ahd softc list.
64 */
65spinlock_t ahd_list_spinlock;
66
67/*
68 * Bucket size for counting good commands in between bad ones. 63 * Bucket size for counting good commands in between bad ones.
69 */ 64 */
70#define AHD_LINUX_ERR_THRESH 1000 65#define AHD_LINUX_ERR_THRESH 1000
@@ -303,13 +298,6 @@ static uint32_t aic79xx_pci_parity = ~0;
303uint32_t aic79xx_allow_memio = ~0; 298uint32_t aic79xx_allow_memio = ~0;
304 299
305/* 300/*
306 * aic79xx_detect() has been run, so register all device arrivals
307 * immediately with the system rather than deferring to the sorted
308 * attachment performed by aic79xx_detect().
309 */
310int aic79xx_detect_complete;
311
312/*
313 * So that we can set how long each device is given as a selection timeout. 301 * So that we can set how long each device is given as a selection timeout.
314 * The table of values goes like this: 302 * The table of values goes like this:
315 * 0 - 256ms 303 * 0 - 256ms
@@ -387,7 +375,9 @@ static void ahd_linux_setup_tag_info_global(char *p);
387static aic_option_callback_t ahd_linux_setup_tag_info; 375static aic_option_callback_t ahd_linux_setup_tag_info;
388static aic_option_callback_t ahd_linux_setup_iocell_info; 376static aic_option_callback_t ahd_linux_setup_iocell_info;
389static int aic79xx_setup(char *c); 377static int aic79xx_setup(char *c);
390static int ahd_linux_next_unit(void); 378
379static int ahd_linux_unit;
380
391 381
392/****************************** Inlines ***************************************/ 382/****************************** Inlines ***************************************/
393static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); 383static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
@@ -418,50 +408,6 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
418 ((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id) 408 ((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id)
419 409
420/* 410/*
421 * Try to detect an Adaptec 79XX controller.
422 */
423static int
424ahd_linux_detect(struct scsi_host_template *template)
425{
426 struct ahd_softc *ahd;
427 int found;
428 int error = 0;
429
430 /*
431 * If we've been passed any parameters, process them now.
432 */
433 if (aic79xx)
434 aic79xx_setup(aic79xx);
435
436 template->proc_name = "aic79xx";
437
438 /*
439 * Initialize our softc list lock prior to
440 * probing for any adapters.
441 */
442 ahd_list_lockinit();
443
444#ifdef CONFIG_PCI
445 error = ahd_linux_pci_init();
446 if (error)
447 return error;
448#endif
449
450 /*
451 * Register with the SCSI layer all
452 * controllers we've found.
453 */
454 found = 0;
455 TAILQ_FOREACH(ahd, &ahd_tailq, links) {
456
457 if (ahd_linux_register_host(ahd, template) == 0)
458 found++;
459 }
460 aic79xx_detect_complete++;
461 return found;
462}
463
464/*
465 * Return a string describing the driver. 411 * Return a string describing the driver.
466 */ 412 */
467static const char * 413static const char *
@@ -760,6 +706,7 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd)
760struct scsi_host_template aic79xx_driver_template = { 706struct scsi_host_template aic79xx_driver_template = {
761 .module = THIS_MODULE, 707 .module = THIS_MODULE,
762 .name = "aic79xx", 708 .name = "aic79xx",
709 .proc_name = "aic79xx",
763 .proc_info = ahd_linux_proc_info, 710 .proc_info = ahd_linux_proc_info,
764 .info = ahd_linux_info, 711 .info = ahd_linux_info,
765 .queuecommand = ahd_linux_queue, 712 .queuecommand = ahd_linux_queue,
@@ -1072,7 +1019,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
1072 host->max_lun = AHD_NUM_LUNS; 1019 host->max_lun = AHD_NUM_LUNS;
1073 host->max_channel = 0; 1020 host->max_channel = 0;
1074 host->sg_tablesize = AHD_NSEG; 1021 host->sg_tablesize = AHD_NSEG;
1075 ahd_set_unit(ahd, ahd_linux_next_unit()); 1022 ahd_set_unit(ahd, ahd_linux_unit++);
1076 sprintf(buf, "scsi%d", host->host_no); 1023 sprintf(buf, "scsi%d", host->host_no);
1077 new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); 1024 new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
1078 if (new_name != NULL) { 1025 if (new_name != NULL) {
@@ -1101,29 +1048,6 @@ ahd_linux_get_memsize(void)
1101} 1048}
1102 1049
1103/* 1050/*
1104 * Find the smallest available unit number to use
1105 * for a new device. We don't just use a static
1106 * count to handle the "repeated hot-(un)plug"
1107 * scenario.
1108 */
1109static int
1110ahd_linux_next_unit(void)
1111{
1112 struct ahd_softc *ahd;
1113 int unit;
1114
1115 unit = 0;
1116retry:
1117 TAILQ_FOREACH(ahd, &ahd_tailq, links) {
1118 if (ahd->unit == unit) {
1119 unit++;
1120 goto retry;
1121 }
1122 }
1123 return (unit);
1124}
1125
1126/*
1127 * Place the SCSI bus into a known state by either resetting it, 1051 * Place the SCSI bus into a known state by either resetting it,
1128 * or forcing transfer negotiations on the next command to any 1052 * or forcing transfer negotiations on the next command to any
1129 * target. 1053 * target.
@@ -2755,23 +2679,31 @@ static struct spi_function_template ahd_linux_transport_functions = {
2755 .show_hold_mcs = 1, 2679 .show_hold_mcs = 1,
2756}; 2680};
2757 2681
2758
2759
2760static int __init 2682static int __init
2761ahd_linux_init(void) 2683ahd_linux_init(void)
2762{ 2684{
2763 ahd_linux_transport_template = spi_attach_transport(&ahd_linux_transport_functions); 2685 int error = 0;
2686
2687 /*
2688 * If we've been passed any parameters, process them now.
2689 */
2690 if (aic79xx)
2691 aic79xx_setup(aic79xx);
2692
2693 ahd_linux_transport_template =
2694 spi_attach_transport(&ahd_linux_transport_functions);
2764 if (!ahd_linux_transport_template) 2695 if (!ahd_linux_transport_template)
2765 return -ENODEV; 2696 return -ENODEV;
2697
2766 scsi_transport_reserve_target(ahd_linux_transport_template, 2698 scsi_transport_reserve_target(ahd_linux_transport_template,
2767 sizeof(struct ahd_linux_target)); 2699 sizeof(struct ahd_linux_target));
2768 scsi_transport_reserve_device(ahd_linux_transport_template, 2700 scsi_transport_reserve_device(ahd_linux_transport_template,
2769 sizeof(struct ahd_linux_device)); 2701 sizeof(struct ahd_linux_device));
2770 if (ahd_linux_detect(&aic79xx_driver_template) > 0)
2771 return 0;
2772 spi_release_transport(ahd_linux_transport_template);
2773 2702
2774 return -ENODEV; 2703 error = ahd_linux_pci_init();
2704 if (error)
2705 spi_release_transport(ahd_linux_transport_template);
2706 return error;
2775} 2707}
2776 2708
2777static void __exit 2709static void __exit
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 296d3a59efe9..052c6619accc 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -120,7 +120,6 @@ typedef struct scsi_cmnd *ahd_io_ctx_t;
120 120
121/************************* Configuration Data *********************************/ 121/************************* Configuration Data *********************************/
122extern uint32_t aic79xx_allow_memio; 122extern uint32_t aic79xx_allow_memio;
123extern int aic79xx_detect_complete;
124extern struct scsi_host_template aic79xx_driver_template; 123extern struct scsi_host_template aic79xx_driver_template;
125 124
126/***************************** Bus Space/DMA **********************************/ 125/***************************** Bus Space/DMA **********************************/
@@ -532,17 +531,6 @@ void ahd_format_transinfo(struct info_str *info,
532 struct ahd_transinfo *tinfo); 531 struct ahd_transinfo *tinfo);
533 532
534/******************************** Locking *************************************/ 533/******************************** Locking *************************************/
535/* Lock protecting internal data structures */
536static __inline void ahd_lockinit(struct ahd_softc *);
537static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags);
538static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags);
539
540/* Lock held during ahd_list manipulation and ahd softc frees */
541extern spinlock_t ahd_list_spinlock;
542static __inline void ahd_list_lockinit(void);
543static __inline void ahd_list_lock(unsigned long *flags);
544static __inline void ahd_list_unlock(unsigned long *flags);
545
546static __inline void 534static __inline void
547ahd_lockinit(struct ahd_softc *ahd) 535ahd_lockinit(struct ahd_softc *ahd)
548{ 536{
@@ -561,24 +549,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
561 spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags); 549 spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
562} 550}
563 551
564static __inline void
565ahd_list_lockinit(void)
566{
567 spin_lock_init(&ahd_list_spinlock);
568}
569
570static __inline void
571ahd_list_lock(unsigned long *flags)
572{
573 spin_lock_irqsave(&ahd_list_spinlock, *flags);
574}
575
576static __inline void
577ahd_list_unlock(unsigned long *flags)
578{
579 spin_unlock_irqrestore(&ahd_list_spinlock, *flags);
580}
581
582/******************************* PCI Definitions ******************************/ 552/******************************* PCI Definitions ******************************/
583/* 553/*
584 * PCIM_xxx: mask to locate subfield in register 554 * PCIM_xxx: mask to locate subfield in register
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 7cfb2eb2b868..390b53852d4b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -92,27 +92,31 @@ struct pci_driver aic79xx_pci_driver = {
92static void 92static void
93ahd_linux_pci_dev_remove(struct pci_dev *pdev) 93ahd_linux_pci_dev_remove(struct pci_dev *pdev)
94{ 94{
95 struct ahd_softc *ahd; 95 struct ahd_softc *ahd = pci_get_drvdata(pdev);
96 u_long l; 96 u_long s;
97 97
98 /* 98 ahd_lock(ahd, &s);
99 * We should be able to just perform 99 ahd_intr_enable(ahd, FALSE);
100 * the free directly, but check our 100 ahd_unlock(ahd, &s);
101 * list for extra sanity. 101 ahd_free(ahd);
102 */ 102}
103 ahd_list_lock(&l); 103
104 ahd = ahd_find_softc((struct ahd_softc *)pci_get_drvdata(pdev)); 104static void
105 if (ahd != NULL) { 105ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
106 u_long s; 106{
107 107 struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
108 TAILQ_REMOVE(&ahd_tailq, ahd, links); 108 unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
109 ahd_list_unlock(&l); 109
110 ahd_lock(ahd, &s); 110 master_pdev = pci_get_slot(pdev->bus, master_devfn);
111 ahd_intr_enable(ahd, FALSE); 111 if (master_pdev) {
112 ahd_unlock(ahd, &s); 112 struct ahd_softc *master = pci_get_drvdata(master_pdev);
113 ahd_free(ahd); 113 if (master) {
114 } else 114 ahd->flags &= ~AHD_BIOS_ENABLED;
115 ahd_list_unlock(&l); 115 ahd->flags |= master->flags & AHD_BIOS_ENABLED;
116 } else
117 printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
118 pci_dev_put(master_pdev);
119 }
116} 120}
117 121
118static int 122static int
@@ -125,22 +129,6 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
125 char *name; 129 char *name;
126 int error; 130 int error;
127 131
128 /*
129 * Some BIOSen report the same device multiple times.
130 */
131 TAILQ_FOREACH(ahd, &ahd_tailq, links) {
132 struct pci_dev *probed_pdev;
133
134 probed_pdev = ahd->dev_softc;
135 if (probed_pdev->bus->number == pdev->bus->number
136 && probed_pdev->devfn == pdev->devfn)
137 break;
138 }
139 if (ahd != NULL) {
140 /* Skip duplicate. */
141 return (-ENODEV);
142 }
143
144 pci = pdev; 132 pci = pdev;
145 entry = ahd_find_pci_device(pci); 133 entry = ahd_find_pci_device(pci);
146 if (entry == NULL) 134 if (entry == NULL)
@@ -190,16 +178,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
190 ahd_free(ahd); 178 ahd_free(ahd);
191 return (-error); 179 return (-error);
192 } 180 }
181
182 /*
183 * Second Function PCI devices need to inherit some
184 * * settings from function 0.
185 */
186 if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
187 ahd_linux_pci_inherit_flags(ahd);
188
193 pci_set_drvdata(pdev, ahd); 189 pci_set_drvdata(pdev, ahd);
194 if (aic79xx_detect_complete) { 190
195#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 191 ahd_linux_register_host(ahd, &aic79xx_driver_template);
196 ahd_linux_register_host(ahd, &aic79xx_driver_template);
197#else
198 printf("aic79xx: ignoring PCI device found after "
199 "initialization\n");
200 return (-ENODEV);
201#endif
202 }
203 return (0); 192 return (0);
204} 193}
205 194
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 703f6e44889d..2131db60018a 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -283,7 +283,6 @@ int
283ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) 283ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
284{ 284{
285 struct scb_data *shared_scb_data; 285 struct scb_data *shared_scb_data;
286 u_long l;
287 u_int command; 286 u_int command;
288 uint32_t devconfig; 287 uint32_t devconfig;
289 uint16_t subvendor; 288 uint16_t subvendor;
@@ -373,16 +372,9 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
373 * Allow interrupts now that we are completely setup. 372 * Allow interrupts now that we are completely setup.
374 */ 373 */
375 error = ahd_pci_map_int(ahd); 374 error = ahd_pci_map_int(ahd);
376 if (error != 0) 375 if (!error)
377 return (error); 376 ahd->init_level++;
378 377 return error;
379 ahd_list_lock(&l);
380 /*
381 * Link this softc in with all other ahd instances.
382 */
383 ahd_softc_insert(ahd);
384 ahd_list_unlock(&l);
385 return (0);
386} 378}
387 379
388/* 380/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
index cffdd104f9e4..32be1f55998c 100644
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -285,21 +285,13 @@ int
285ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, 285ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
286 off_t offset, int length, int inout) 286 off_t offset, int length, int inout)
287{ 287{
288 struct ahd_softc *ahd; 288 struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
289 struct info_str info; 289 struct info_str info;
290 char ahd_info[256]; 290 char ahd_info[256];
291 u_long l;
292 u_int max_targ; 291 u_int max_targ;
293 u_int i; 292 u_int i;
294 int retval; 293 int retval;
295 294
296 retval = -EINVAL;
297 ahd_list_lock(&l);
298 ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata);
299
300 if (ahd == NULL)
301 goto done;
302
303 /* Has data been written to the file? */ 295 /* Has data been written to the file? */
304 if (inout == TRUE) { 296 if (inout == TRUE) {
305 retval = ahd_proc_write_seeprom(ahd, buffer, length); 297 retval = ahd_proc_write_seeprom(ahd, buffer, length);
@@ -349,6 +341,5 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
349 } 341 }
350 retval = info.pos > info.offset ? info.pos - info.offset : 0; 342 retval = info.pos > info.offset ? info.pos - info.offset : 0;
351done: 343done:
352 ahd_list_unlock(&l);
353 return (retval); 344 return (retval);
354} 345}