Advanced TCA SCSI / FC Disk Hotswap revision 0.92
Subsystems (2)
PATCH 1/1 Advanced TCA SCSI / FC Disk Hotswap revision 0.92
Attached is an update of the Advanced TCA disk hotswap driver to provide disk hotswap support for the Linux Kernel 2.5.44. Hotswap targets include both SCSI and FibreChannel. Note this support is generic in that it will work in a typical PC system with SCSI or FibreChannel disks.
The patch includes support for the QLA adaptor but this adaptor is not included in the standard linux kernel. If you havn't patched your kernel with this driver, just ignore the patch for the qla adaptor to still gain all functionality except for hotswap using that adaptor for WWN identifiers.
As always, the latest Advanced TCA hotswap patches (including scsi disk hotswap) can be found:
http://www.sourceforge.net/projects/atca-hotswap
Changes from kernel 2.5.44 0.90 to 0.91 release:
-----------------------------------------------------------------
* Dumped custom ramfs and integrated with driverfs under bus/scsi/hotswap_commads (suggested by several people)
* changed read_file to _show and write_file to _store while also changing symantics
* switched lun/id and lun/wwn ordering to id/lun and wwn/lun (pointed as an error by Michael Anderson)
* spinlocks changed to semaphores to fix lock held during sleep in function scsi_eh_bus_device_reset (pointed as an error by Patrick Mansfield)
Thanks for looking at the patch...
-steve
MAINTAINERS +6 -0
@@ -1418,6 +1418,12 @@ W: http://www.kernel.dk S: Maintained +SCSI HOTSWAP DRIVER +P: Steven Dake +M: [email protected] +L: [email protected] +S: Maintained + SCSI SG DRIVER P: Doug Gilbert M: [email protected]
drivers/scsi/Config.help +11 -0
@@ -34,6 +34,17 @@ is located on a SCSI disk. In this case, do not compile the driver for your SCSI host adapter (below) as a module either. +CONFIG_SCSIFCHOTSWAP + If you want to support the ability to include the hotswap FibreChannel + and SCSI driver, please say yes here. Hotswap can then be executed + through a ramfs interface which provides better error reporting. + + Further, this interface supports insertion and removal by WWN for + FibreChannel drivers which support this feature. + + The only FibreChannel driver that supports this feature is Qlogic V6 + with a specific support patch. + CONFIG_SD_EXTRA_DEVS This controls the amount of additional space allocated in tables for drivers that are loaded as modules after the kernel is booted. In
drivers/scsi/Config.in +1 -0
@@ -1,5 +1,6 @@ comment 'SCSI support type (disk, tape, CD-ROM)' +dep_tristate ' SCSI hotswap support' CONFIG_SCSIFCHOTSWAP $CONFIG_SCSI dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
drivers/scsi/Makefile +1 -0
@@ -117,6 +117,7 @@ obj-$(CONFIG_ARCH_ACORN) += ../acorn/scsi/ +obj-$(CONFIG_SCSIFCHOTSWAP) += hotswap.o obj-$(CONFIG_CHR_DEV_ST) += st.o obj-$(CONFIG_CHR_DEV_OSST) += osst.o obj-$(CONFIG_BLK_DEV_SD) += sd_mod.o
drivers/scsi/hosts.c +1 -0
@@ -371,6 +371,7 @@ scsi_hosts_registered++;spin_lock_init (&shost->default_lock); +sema_init (&shost->host_queue_sema,1 );scsi_assign_lock (shost, &shost->default_lock);atomic_set (&shost->host_active,0 );
drivers/scsi/hosts.h +7 -0
@@ -264,6 +264,12 @@*/ int (* bios_param)(Disk *,struct block_device *,int []); +/* +* Used to determine the id to send the inquiry command to during +* hot additions of FibreChannel targets +*/ +int (*get_scsi_info_from_wwn)(int mode,unsigned long long wwn,int *host,int *channel,int *lun,int *id); +/* * This determines if we will use a non-interrupt driven * or an interrupt driven scheme, It is set to the maximum number
@@ -374,6 +380,7 @@*/ struct list_head sh_list;Scsi_Device * host_queue; +struct semaphore host_queue_sema;struct list_head all_scsi_hosts;struct list_head my_devices;
drivers/scsi/hotswap.c +921 -0
921 lines not on this page · raw message
Binary files linux-2.5.44-qla/drivers/scsi/qla2xxx/.qla2x00.c.swp and linux-2.5.44-scsi-hotswap/drivers/scsi/qla2xxx/.qla2x00.c.swp differ Binary files linux-2.5.44-qla/drivers/scsi/qla2xxx/.qla2x00.h.swp and linux-2.5.44-scsi-hotswap/drivers/scsi/qla2xxx/.qla2x00.h.swp differ
drivers/scsi/qla2xxx/qla2x00.c +76 -0
94 lines not on this page · raw message
drivers/scsi/scsi.c +39 -0
@@ -413,6 +413,9 @@* allow us to more easily figure out whether we should * do anything here or not. */ + +down (&host->host_queue_sema); +for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
@@ -430,6 +433,9 @@break ; } } + +up (&host->host_queue_sema); +if (SDpnt) {/* * Some other device in this cluster is busy.
@@ -1694,6 +1700,8 @@ len += size; pos = begin + len;#endif +down (&HBA_ptr->host_queue_sema); +for (scd = HBA_ptr->host_queue; scd; scd = scd->next) {proc_print_scsidevice (scd, buffer, &size, len); len += size;
@@ -1706,6 +1714,8 @@if (pos > offset + length) goto stop_output; } + +up (&HBA_ptr->host_queue_sema); } stop_output:
@@ -1864,6 +1874,8 @@if (!HBA_ptr) goto out; +down (&HBA_ptr->host_queue_sema); +for (scd = HBA_ptr->host_queue; scd; scd = scd->next) { if ((scd->channel == channel && scd->id == id
@@ -1872,6 +1884,8 @@ } } +up (&HBA_ptr->host_queue_sema); + err = -ENOSYS ;if (scd) goto out;/* We do not yet support unplugging */
@@ -1910,6 +1924,8 @@if (!HBA_ptr) goto out; +down (&HBA_ptr->host_queue_sema); +for (scd = HBA_ptr->host_queue; scd; scd = scd->next) { if ((scd->channel == channel && scd->id == id
@@ -1918,6 +1934,8 @@ } } +up (&HBA_ptr->host_queue_sema); +if (scd ==NULL ) goto out;/* there is no such device attached */
@@ -1951,9 +1969,14 @@if (scd->prev !=NULL ) scd->prev->next = scd->next; +down (&HBA_ptr->host_queue_sema); +if (HBA_ptr->host_queue == scd) { HBA_ptr->host_queue = scd->next; } + +up (&HBA_ptr->host_queue_sema); +blk_cleanup_queue (&scd->request_queue);if (scd->inquiry)kfree (scd->inquiry);
@@ -1997,11 +2020,15 @@for (shpnt =scsi_host_get_next (NULL ); shpnt; shpnt =scsi_host_get_next (shpnt)) { +down (&shpnt->host_queue_sema); +for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {if (tpnt->detect) SDpnt->attached += (*tpnt->detect) (SDpnt); } + +up (&shpnt->host_queue_sema); }/*
@@ -2017,6 +2044,8 @@*/ for (shpnt =scsi_host_get_next (NULL ); shpnt; shpnt =scsi_host_get_next (shpnt)) { +down (&shpnt->host_queue_sema); +for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {if (tpnt->attach)
@@ -2032,6 +2061,8 @@ out_of_space =1 ; } } + +up (&shpnt->host_queue_sema); }/*
@@ -2068,6 +2099,8 @@for (shpnt =scsi_host_get_next (NULL ); shpnt; shpnt =scsi_host_get_next (shpnt)) { +spin_lock (&shpnt->host_queue_sema); +for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {if (tpnt->detach)
@@ -2084,6 +2117,8 @@scsi_release_commandblocks (SDpnt); } } + +up (&shpnt->host_queue_sema); }/* * Extract the template from the linked list.
@@ -2154,6 +2189,8 @@for (shpnt =scsi_host_get_next (NULL ); shpnt; shpnt =scsi_host_get_next (shpnt)) {printk (KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result\n" ); +down (&shpnt->host_queue_sema); +for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {/* (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result %d %x */
@@ -2185,6 +2222,8 @@ SCpnt->result); } } + +up (&shpnt->host_queue_sema); }#endif /* CONFIG_SCSI_LOGGING */ /* } */ }
drivers/scsi/scsi_error.c +21 -0
@@ -202,6 +202,8 @@int devices_failed =0 ; +down (&shost->host_queue_sema); +for (sdev = shost->host_queue; sdev; sdev = sdev->next) {for (scmd = sc_list; scmd; scmd = scmd->bh_next) {if (scmd->device == sdev) {
@@ -227,6 +229,8 @@ } } +up (&shost->host_queue_sema); +SCSI_LOG_ERROR_RECOVERY (2 ,printk ("Total of %d commands on %d" " devices require eh work\n" , total_failures, devices_failed));
@@ -247,6 +251,8 @@Scsi_Device *sdev;Scsi_Cmnd *scmd; +down (&shost->host_queue_sema); +for (found =0 , sdev = shost->host_queue; sdev; sdev = sdev->next) {for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {if (scsi_eh_eflags_chk (scmd,SCSI_EH_CMD_ERR )) {
@@ -283,6 +289,8 @@ } } +up (&shost->host_queue_sema); +SCSI_LOG_ERROR_RECOVERY (1 ,scsi_eh_prt_fail_stats (*sc_list, shost));if (shost->host_failed != found)
@@ -962,6 +970,8 @@SCSI_LOG_ERROR_RECOVERY (3 ,printk ("%s: Trying BDR\n" , __FUNCTION__)); +down (&shost->host_queue_sema); +for (sdev = shost->host_queue; sdev; sdev = sdev->next) {for (scmd = sc_todo; scmd; scmd = scmd->bh_next) if ((scmd->device == sdev) &&
@@ -985,6 +995,7 @@scsi_eh_finish_cmd (scmd, shost); } } +up (&shost->host_queue_sema);return shost->host_failed; }
@@ -1016,11 +1027,15 @@/* * Mark all affected devices to expect a unit attention. */ +down (&scmd->host->host_queue_sema); +for (sdev = scmd->host->host_queue; sdev; sdev = sdev->next)if (scmd->channel == sdev->channel) { sdev->was_reset =1 ; sdev->expecting_cc_ua =1 ; } + +up (&scmd->host->host_queue_sema); }return rtn; }
@@ -1052,11 +1067,13 @@/* * Mark all affected devices to expect a unit attention. */ +down (&scmd->host->host_queue_sema);for (sdev = scmd->host->host_queue; sdev; sdev = sdev->next)if (scmd->channel == sdev->channel) { sdev->was_reset =1 ; sdev->expecting_cc_ua =1 ; } +up (&scmd->host->host_queue_sema); }return rtn; }
@@ -1474,7 +1491,9 @@* now that error recovery is done, we will need to ensure that these * requests are started. */ +down (&shost->host_queue_sema);spin_lock_irqsave (shost->host_lock, flags); +for (sdev = shost->host_queue; sdev; sdev = sdev->next) {request_queue_t *q = &sdev->request_queue;
@@ -1487,7 +1506,9 @@ q->request_fn (q); } +spin_unlock_irqrestore (shost->host_lock, flags); +up (&shost->host_queue_sema); }/**
drivers/scsi/scsi_lib.c +16 -0
@@ -261,6 +261,8 @@if (SDpnt->single_lun &&blk_queue_empty (q) && SDpnt->device_busy ==0 ) {request_queue_t *q; +down (&SHpnt->host_queue_sema); +for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {if (((SHpnt->can_queue >0 ) && (SHpnt->host_busy >= SHpnt->can_queue))
@@ -273,6 +275,8 @@ q = &SDpnt->request_queue; q->request_fn (q); } + +up (&SHpnt->host_queue_sema); }/*
@@ -285,6 +289,7 @@*/ all_clear =1 ;if (SHpnt->some_device_starved) { +down (&SHpnt->host_queue_sema);for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {request_queue_t *q; if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue))
@@ -299,6 +304,7 @@ q->request_fn (q); all_clear =0 ; } +up (&SHpnt->host_queue_sema);if (SDpnt ==NULL && all_clear) { SHpnt->some_device_starved =0 ; }
@@ -1038,8 +1044,13 @@ SHpnt->host_self_blocked = FALSE;/* Now that we are unblocked, try to start the queues. */ + +down (&SHpnt->host_queue_sema); +for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next)scsi_queue_next_request (&SDloop->request_queue,NULL ); + +up (&SHpnt->host_queue_sema); }/*
@@ -1066,12 +1077,17 @@void scsi_report_bus_reset (struct Scsi_Host * SHpnt,int channel) {Scsi_Device *SDloop; + +down (&SHpnt->host_queue_sema); +for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next) {if (channel == SDloop->channel) { SDloop->was_reset =1 ; SDloop->expecting_cc_ua =1 ; } } + +up (&SHpnt->host_queue_sema); }/*
drivers/scsi/scsi_scan.c +9 -1
@@ -530,6 +530,8 @@/* * Add it to the end of the shost->host_queue list. */ +down (&shost->host_queue_sema); +if (shost->host_queue !=NULL ) { sdev->prev = shost->host_queue;while (sdev->prev->next !=NULL )
@@ -538,6 +540,8 @@ }else shost->host_queue = sdev; +up (&shost->host_queue_sema); + }return (sdev); }
@@ -554,8 +558,12 @@ {if (sdev->prev !=NULL ) sdev->prev->next = sdev->next; -else +else { +down (&sdev->host->host_queue_sema); sdev->host->host_queue = sdev->next; +up (&sdev->host->host_queue_sema); + } +if (sdev->next !=NULL ) sdev->next->prev = sdev->prev;
include/linux/scsi_hotswap.h +84 -0
84 lines not on this page · raw message