diff options
Diffstat (limited to 'drivers/scsi/dpt_i2o.c')
-rw-r--r-- | drivers/scsi/dpt_i2o.c | 132 |
1 files changed, 71 insertions, 61 deletions
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 2e2362d787ca..502732ac270d 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c | |||
@@ -173,20 +173,20 @@ static struct pci_device_id dptids[] = { | |||
173 | }; | 173 | }; |
174 | MODULE_DEVICE_TABLE(pci,dptids); | 174 | MODULE_DEVICE_TABLE(pci,dptids); |
175 | 175 | ||
176 | static int adpt_detect(struct scsi_host_template* sht) | 176 | static void adpt_exit(void); |
177 | |||
178 | static int adpt_detect(void) | ||
177 | { | 179 | { |
178 | struct pci_dev *pDev = NULL; | 180 | struct pci_dev *pDev = NULL; |
179 | adpt_hba* pHba; | 181 | adpt_hba* pHba; |
180 | 182 | ||
181 | adpt_init(); | ||
182 | |||
183 | PINFO("Detecting Adaptec I2O RAID controllers...\n"); | 183 | PINFO("Detecting Adaptec I2O RAID controllers...\n"); |
184 | 184 | ||
185 | /* search for all Adatpec I2O RAID cards */ | 185 | /* search for all Adatpec I2O RAID cards */ |
186 | while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) { | 186 | while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) { |
187 | if(pDev->device == PCI_DPT_DEVICE_ID || | 187 | if(pDev->device == PCI_DPT_DEVICE_ID || |
188 | pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){ | 188 | pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){ |
189 | if(adpt_install_hba(sht, pDev) ){ | 189 | if(adpt_install_hba(pDev) ){ |
190 | PERROR("Could not Init an I2O RAID device\n"); | 190 | PERROR("Could not Init an I2O RAID device\n"); |
191 | PERROR("Will not try to detect others.\n"); | 191 | PERROR("Will not try to detect others.\n"); |
192 | return hba_count-1; | 192 | return hba_count-1; |
@@ -248,34 +248,33 @@ rebuild_sys_tab: | |||
248 | } | 248 | } |
249 | 249 | ||
250 | for (pHba = hba_chain; pHba; pHba = pHba->next) { | 250 | for (pHba = hba_chain; pHba; pHba = pHba->next) { |
251 | if( adpt_scsi_register(pHba,sht) < 0){ | 251 | if (adpt_scsi_register(pHba) < 0) { |
252 | adpt_i2o_delete_hba(pHba); | 252 | adpt_i2o_delete_hba(pHba); |
253 | continue; | 253 | continue; |
254 | } | 254 | } |
255 | pHba->initialized = TRUE; | 255 | pHba->initialized = TRUE; |
256 | pHba->state &= ~DPTI_STATE_RESET; | 256 | pHba->state &= ~DPTI_STATE_RESET; |
257 | scsi_scan_host(pHba->host); | ||
257 | } | 258 | } |
258 | 259 | ||
259 | // Register our control device node | 260 | // Register our control device node |
260 | // nodes will need to be created in /dev to access this | 261 | // nodes will need to be created in /dev to access this |
261 | // the nodes can not be created from within the driver | 262 | // the nodes can not be created from within the driver |
262 | if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) { | 263 | if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) { |
263 | adpt_i2o_sys_shutdown(); | 264 | adpt_exit(); |
264 | return 0; | 265 | return 0; |
265 | } | 266 | } |
266 | return hba_count; | 267 | return hba_count; |
267 | } | 268 | } |
268 | 269 | ||
269 | 270 | ||
270 | /* | 271 | static int adpt_release(adpt_hba *pHba) |
271 | * scsi_unregister will be called AFTER we return. | ||
272 | */ | ||
273 | static int adpt_release(struct Scsi_Host *host) | ||
274 | { | 272 | { |
275 | adpt_hba* pHba = (adpt_hba*) host->hostdata[0]; | 273 | struct Scsi_Host *shost = pHba->host; |
274 | scsi_remove_host(shost); | ||
276 | // adpt_i2o_quiesce_hba(pHba); | 275 | // adpt_i2o_quiesce_hba(pHba); |
277 | adpt_i2o_delete_hba(pHba); | 276 | adpt_i2o_delete_hba(pHba); |
278 | scsi_unregister(host); | 277 | scsi_host_put(shost); |
279 | return 0; | 278 | return 0; |
280 | } | 279 | } |
281 | 280 | ||
@@ -882,7 +881,7 @@ static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p) | |||
882 | #endif | 881 | #endif |
883 | 882 | ||
884 | 883 | ||
885 | static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) | 884 | static int adpt_install_hba(struct pci_dev* pDev) |
886 | { | 885 | { |
887 | 886 | ||
888 | adpt_hba* pHba = NULL; | 887 | adpt_hba* pHba = NULL; |
@@ -1031,8 +1030,6 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) | |||
1031 | 1030 | ||
1032 | 1031 | ||
1033 | mutex_lock(&adpt_configuration_lock); | 1032 | mutex_lock(&adpt_configuration_lock); |
1034 | // scsi_unregister calls our adpt_release which | ||
1035 | // does a quiese | ||
1036 | if(pHba->host){ | 1033 | if(pHba->host){ |
1037 | free_irq(pHba->host->irq, pHba); | 1034 | free_irq(pHba->host->irq, pHba); |
1038 | } | 1035 | } |
@@ -1084,17 +1081,6 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) | |||
1084 | } | 1081 | } |
1085 | 1082 | ||
1086 | 1083 | ||
1087 | static int adpt_init(void) | ||
1088 | { | ||
1089 | printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); | ||
1090 | #ifdef REBOOT_NOTIFIER | ||
1091 | register_reboot_notifier(&adpt_reboot_notifier); | ||
1092 | #endif | ||
1093 | |||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | |||
1098 | static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun) | 1084 | static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun) |
1099 | { | 1085 | { |
1100 | struct adpt_device* d; | 1086 | struct adpt_device* d; |
@@ -2180,37 +2166,6 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d | |||
2180 | } | 2166 | } |
2181 | 2167 | ||
2182 | 2168 | ||
2183 | static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht) | ||
2184 | { | ||
2185 | struct Scsi_Host *host = NULL; | ||
2186 | |||
2187 | host = scsi_register(sht, sizeof(adpt_hba*)); | ||
2188 | if (host == NULL) { | ||
2189 | printk ("%s: scsi_register returned NULL\n",pHba->name); | ||
2190 | return -1; | ||
2191 | } | ||
2192 | host->hostdata[0] = (unsigned long)pHba; | ||
2193 | pHba->host = host; | ||
2194 | |||
2195 | host->irq = pHba->pDev->irq; | ||
2196 | /* no IO ports, so don't have to set host->io_port and | ||
2197 | * host->n_io_port | ||
2198 | */ | ||
2199 | host->io_port = 0; | ||
2200 | host->n_io_port = 0; | ||
2201 | /* see comments in scsi_host.h */ | ||
2202 | host->max_id = 16; | ||
2203 | host->max_lun = 256; | ||
2204 | host->max_channel = pHba->top_scsi_channel + 1; | ||
2205 | host->cmd_per_lun = 1; | ||
2206 | host->unique_id = (uint) pHba; | ||
2207 | host->sg_tablesize = pHba->sg_tablesize; | ||
2208 | host->can_queue = pHba->post_fifo_size; | ||
2209 | |||
2210 | return 0; | ||
2211 | } | ||
2212 | |||
2213 | |||
2214 | static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) | 2169 | static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) |
2215 | { | 2170 | { |
2216 | adpt_hba* pHba; | 2171 | adpt_hba* pHba; |
@@ -3329,12 +3284,10 @@ static static void adpt_delay(int millisec) | |||
3329 | 3284 | ||
3330 | #endif | 3285 | #endif |
3331 | 3286 | ||
3332 | static struct scsi_host_template driver_template = { | 3287 | static struct scsi_host_template adpt_template = { |
3333 | .name = "dpt_i2o", | 3288 | .name = "dpt_i2o", |
3334 | .proc_name = "dpt_i2o", | 3289 | .proc_name = "dpt_i2o", |
3335 | .proc_info = adpt_proc_info, | 3290 | .proc_info = adpt_proc_info, |
3336 | .detect = adpt_detect, | ||
3337 | .release = adpt_release, | ||
3338 | .info = adpt_info, | 3291 | .info = adpt_info, |
3339 | .queuecommand = adpt_queue, | 3292 | .queuecommand = adpt_queue, |
3340 | .eh_abort_handler = adpt_abort, | 3293 | .eh_abort_handler = adpt_abort, |
@@ -3348,5 +3301,62 @@ static struct scsi_host_template driver_template = { | |||
3348 | .cmd_per_lun = 1, | 3301 | .cmd_per_lun = 1, |
3349 | .use_clustering = ENABLE_CLUSTERING, | 3302 | .use_clustering = ENABLE_CLUSTERING, |
3350 | }; | 3303 | }; |
3351 | #include "scsi_module.c" | 3304 | |
3305 | static s32 adpt_scsi_register(adpt_hba* pHba) | ||
3306 | { | ||
3307 | struct Scsi_Host *host; | ||
3308 | |||
3309 | host = scsi_host_alloc(&adpt_template, sizeof(adpt_hba*)); | ||
3310 | if (host == NULL) { | ||
3311 | printk ("%s: scsi_host_alloc returned NULL\n",pHba->name); | ||
3312 | return -1; | ||
3313 | } | ||
3314 | host->hostdata[0] = (unsigned long)pHba; | ||
3315 | pHba->host = host; | ||
3316 | |||
3317 | host->irq = pHba->pDev->irq; | ||
3318 | /* no IO ports, so don't have to set host->io_port and | ||
3319 | * host->n_io_port | ||
3320 | */ | ||
3321 | host->io_port = 0; | ||
3322 | host->n_io_port = 0; | ||
3323 | /* see comments in scsi_host.h */ | ||
3324 | host->max_id = 16; | ||
3325 | host->max_lun = 256; | ||
3326 | host->max_channel = pHba->top_scsi_channel + 1; | ||
3327 | host->cmd_per_lun = 1; | ||
3328 | host->unique_id = (uint) pHba; | ||
3329 | host->sg_tablesize = pHba->sg_tablesize; | ||
3330 | host->can_queue = pHba->post_fifo_size; | ||
3331 | |||
3332 | if (scsi_add_host(host, &pHba->pDev->dev)) { | ||
3333 | scsi_host_put(host); | ||
3334 | return -1; | ||
3335 | } | ||
3336 | |||
3337 | return 0; | ||
3338 | } | ||
3339 | |||
3340 | static int __init adpt_init(void) | ||
3341 | { | ||
3342 | int count; | ||
3343 | |||
3344 | printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); | ||
3345 | #ifdef REBOOT_NOTIFIER | ||
3346 | register_reboot_notifier(&adpt_reboot_notifier); | ||
3347 | #endif | ||
3348 | |||
3349 | count = adpt_detect(); | ||
3350 | |||
3351 | return count > 0 ? 0 : -ENODEV; | ||
3352 | } | ||
3353 | |||
3354 | static void __exit adpt_exit(void) | ||
3355 | { | ||
3356 | while (hba_chain) | ||
3357 | adpt_release(hba_chain); | ||
3358 | } | ||
3359 | |||
3360 | module_init(adpt_init); | ||
3361 | module_exit(adpt_exit); | ||
3352 | MODULE_LICENSE("GPL"); | 3362 | MODULE_LICENSE("GPL"); |