aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMark Haverkamp <markh@osdl.org>2005-09-26 16:04:56 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-09-26 18:42:50 -0400
commit131256cf203d0df62014dda8453a70cb6af0d0bb (patch)
tree6e7ba27ba4d4181a312a7b1bec385cf68b501dcd /drivers/scsi
parent2f130980d14cb938226011875ca5224cd46dc1f9 (diff)
[SCSI] aacraid: handle AIF hotplug events (update)
Received from Mark Salyzyn from Adaptec. Hotplug sniffs the AIFs (events) from the adapter and if a container change resulting in the device going offline (container zero), online (container zero completed) or changing capacity (morph) it will take actions by calling the appropriate API. Signed-off-by: Mark Haverkamp <markh@osdl.org> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/aacraid/aachba.c4
-rw-r--r--drivers/scsi/aacraid/aacraid.h4
-rw-r--r--drivers/scsi/aacraid/commsup.c274
3 files changed, 280 insertions, 2 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 0a209b2cd695..85d133c40bd3 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -479,7 +479,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
479 * is updated in the struct fsa_dev_info structure rather than returned. 479 * is updated in the struct fsa_dev_info structure rather than returned.
480 */ 480 */
481 481
482static int probe_container(struct aac_dev *dev, int cid) 482int probe_container(struct aac_dev *dev, int cid)
483{ 483{
484 struct fsa_dev_info *fsa_dev_ptr; 484 struct fsa_dev_info *fsa_dev_ptr;
485 int status; 485 int status;
@@ -1471,6 +1471,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
1471 case TEST_UNIT_READY: 1471 case TEST_UNIT_READY:
1472 spin_unlock_irq(host->host_lock); 1472 spin_unlock_irq(host->host_lock);
1473 probe_container(dev, cid); 1473 probe_container(dev, cid);
1474 if ((fsa_dev_ptr[cid].valid & 1) == 0)
1475 fsa_dev_ptr[cid].valid = 0;
1474 spin_lock_irq(host->host_lock); 1476 spin_lock_irq(host->host_lock);
1475 if (fsa_dev_ptr[cid].valid == 0) { 1477 if (fsa_dev_ptr[cid].valid == 0) {
1476 scsicmd->result = DID_NO_CONNECT << 16; 1478 scsicmd->result = DID_NO_CONNECT << 16;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 6fd5074efa5c..0880f4807fc9 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -780,7 +780,9 @@ struct fsa_dev_info {
780 u64 last; 780 u64 last;
781 u64 size; 781 u64 size;
782 u32 type; 782 u32 type;
783 u32 config_waiting_on;
783 u16 queue_depth; 784 u16 queue_depth;
785 u8 config_needed;
784 u8 valid; 786 u8 valid;
785 u8 ro; 787 u8 ro;
786 u8 locked; 788 u8 locked;
@@ -1715,6 +1717,7 @@ extern struct aac_common aac_config;
1715#define AifCmdJobProgress 2 /* Progress report */ 1717#define AifCmdJobProgress 2 /* Progress report */
1716#define AifJobCtrZero 101 /* Array Zero progress */ 1718#define AifJobCtrZero 101 /* Array Zero progress */
1717#define AifJobStsSuccess 1 /* Job completes */ 1719#define AifJobStsSuccess 1 /* Job completes */
1720#define AifJobStsRunning 102 /* Job running */
1718#define AifCmdAPIReport 3 /* Report from other user of API */ 1721#define AifCmdAPIReport 3 /* Report from other user of API */
1719#define AifCmdDriverNotify 4 /* Notify host driver of event */ 1722#define AifCmdDriverNotify 4 /* Notify host driver of event */
1720#define AifDenMorphComplete 200 /* A morph operation completed */ 1723#define AifDenMorphComplete 200 /* A morph operation completed */
@@ -1785,6 +1788,7 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size);
1785struct aac_driver_ident* aac_get_driver_ident(int devtype); 1788struct aac_driver_ident* aac_get_driver_ident(int devtype);
1786int aac_get_adapter_info(struct aac_dev* dev); 1789int aac_get_adapter_info(struct aac_dev* dev);
1787int aac_send_shutdown(struct aac_dev *dev); 1790int aac_send_shutdown(struct aac_dev *dev);
1791int probe_container(struct aac_dev *dev, int cid);
1788extern int numacb; 1792extern int numacb;
1789extern int acbsize; 1793extern int acbsize;
1790extern char aac_driver_version[]; 1794extern char aac_driver_version[];
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 3741be2f4bfa..69985b08a270 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -39,6 +39,7 @@
39#include <linux/completion.h> 39#include <linux/completion.h>
40#include <linux/blkdev.h> 40#include <linux/blkdev.h>
41#include <scsi/scsi_host.h> 41#include <scsi/scsi_host.h>
42#include <scsi/scsi_device.h>
42#include <asm/semaphore.h> 43#include <asm/semaphore.h>
43 44
44#include "aacraid.h" 45#include "aacraid.h"
@@ -791,6 +792,268 @@ void aac_printf(struct aac_dev *dev, u32 val)
791 memset(cp, 0, 256); 792 memset(cp, 0, 256);
792} 793}
793 794
795
796/**
797 * aac_handle_aif - Handle a message from the firmware
798 * @dev: Which adapter this fib is from
799 * @fibptr: Pointer to fibptr from adapter
800 *
801 * This routine handles a driver notify fib from the adapter and
802 * dispatches it to the appropriate routine for handling.
803 */
804
805static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
806{
807 struct hw_fib * hw_fib = fibptr->hw_fib;
808 struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;
809 int busy;
810 u32 container;
811 struct scsi_device *device;
812 enum {
813 NOTHING,
814 DELETE,
815 ADD,
816 CHANGE
817 } device_config_needed;
818
819 /* Sniff for container changes */
820
821 if (!dev)
822 return;
823 container = (u32)-1;
824
825 /*
826 * We have set this up to try and minimize the number of
827 * re-configures that take place. As a result of this when
828 * certain AIF's come in we will set a flag waiting for another
829 * type of AIF before setting the re-config flag.
830 */
831 switch (le32_to_cpu(aifcmd->command)) {
832 case AifCmdDriverNotify:
833 switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) {
834 /*
835 * Morph or Expand complete
836 */
837 case AifDenMorphComplete:
838 case AifDenVolumeExtendComplete:
839 container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
840 if (container >= dev->maximum_num_containers)
841 break;
842
843 /*
844 * Find the Scsi_Device associated with the SCSI
845 * address. Make sure we have the right array, and if
846 * so set the flag to initiate a new re-config once we
847 * see an AifEnConfigChange AIF come through.
848 */
849
850 if ((dev != NULL) && (dev->scsi_host_ptr != NULL)) {
851 device = scsi_device_lookup(dev->scsi_host_ptr,
852 CONTAINER_TO_CHANNEL(container),
853 CONTAINER_TO_ID(container),
854 CONTAINER_TO_LUN(container));
855 if (device) {
856 dev->fsa_dev[container].config_needed = CHANGE;
857 dev->fsa_dev[container].config_waiting_on = AifEnConfigChange;
858 scsi_device_put(device);
859 }
860 }
861 }
862
863 /*
864 * If we are waiting on something and this happens to be
865 * that thing then set the re-configure flag.
866 */
867 if (container != (u32)-1) {
868 if (container >= dev->maximum_num_containers)
869 break;
870 if (dev->fsa_dev[container].config_waiting_on ==
871 le32_to_cpu(*(u32 *)aifcmd->data))
872 dev->fsa_dev[container].config_waiting_on = 0;
873 } else for (container = 0;
874 container < dev->maximum_num_containers; ++container) {
875 if (dev->fsa_dev[container].config_waiting_on ==
876 le32_to_cpu(*(u32 *)aifcmd->data))
877 dev->fsa_dev[container].config_waiting_on = 0;
878 }
879 break;
880
881 case AifCmdEventNotify:
882 switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) {
883 /*
884 * Add an Array.
885 */
886 case AifEnAddContainer:
887 container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
888 if (container >= dev->maximum_num_containers)
889 break;
890 dev->fsa_dev[container].config_needed = ADD;
891 dev->fsa_dev[container].config_waiting_on =
892 AifEnConfigChange;
893 break;
894
895 /*
896 * Delete an Array.
897 */
898 case AifEnDeleteContainer:
899 container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
900 if (container >= dev->maximum_num_containers)
901 break;
902 dev->fsa_dev[container].config_needed = DELETE;
903 dev->fsa_dev[container].config_waiting_on =
904 AifEnConfigChange;
905 break;
906
907 /*
908 * Container change detected. If we currently are not
909 * waiting on something else, setup to wait on a Config Change.
910 */
911 case AifEnContainerChange:
912 container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
913 if (container >= dev->maximum_num_containers)
914 break;
915 if (dev->fsa_dev[container].config_waiting_on)
916 break;
917 dev->fsa_dev[container].config_needed = CHANGE;
918 dev->fsa_dev[container].config_waiting_on =
919 AifEnConfigChange;
920 break;
921
922 case AifEnConfigChange:
923 break;
924
925 }
926
927 /*
928 * If we are waiting on something and this happens to be
929 * that thing then set the re-configure flag.
930 */
931 if (container != (u32)-1) {
932 if (container >= dev->maximum_num_containers)
933 break;
934 if (dev->fsa_dev[container].config_waiting_on ==
935 le32_to_cpu(*(u32 *)aifcmd->data))
936 dev->fsa_dev[container].config_waiting_on = 0;
937 } else for (container = 0;
938 container < dev->maximum_num_containers; ++container) {
939 if (dev->fsa_dev[container].config_waiting_on ==
940 le32_to_cpu(*(u32 *)aifcmd->data))
941 dev->fsa_dev[container].config_waiting_on = 0;
942 }
943 break;
944
945 case AifCmdJobProgress:
946 /*
947 * These are job progress AIF's. When a Clear is being
948 * done on a container it is initially created then hidden from
949 * the OS. When the clear completes we don't get a config
950 * change so we monitor the job status complete on a clear then
951 * wait for a container change.
952 */
953
954 if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero))
955 && ((((u32 *)aifcmd->data)[6] == ((u32 *)aifcmd->data)[5])
956 || (((u32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsSuccess)))) {
957 for (container = 0;
958 container < dev->maximum_num_containers;
959 ++container) {
960 /*
961 * Stomp on all config sequencing for all
962 * containers?
963 */
964 dev->fsa_dev[container].config_waiting_on =
965 AifEnContainerChange;
966 dev->fsa_dev[container].config_needed = ADD;
967 }
968 }
969 if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero))
970 && (((u32 *)aifcmd->data)[6] == 0)
971 && (((u32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsRunning))) {
972 for (container = 0;
973 container < dev->maximum_num_containers;
974 ++container) {
975 /*
976 * Stomp on all config sequencing for all
977 * containers?
978 */
979 dev->fsa_dev[container].config_waiting_on =
980 AifEnContainerChange;
981 dev->fsa_dev[container].config_needed = DELETE;
982 }
983 }
984 break;
985 }
986
987 device_config_needed = NOTHING;
988 for (container = 0; container < dev->maximum_num_containers;
989 ++container) {
990 if ((dev->fsa_dev[container].config_waiting_on == 0)
991 && (dev->fsa_dev[container].config_needed != NOTHING)) {
992 device_config_needed =
993 dev->fsa_dev[container].config_needed;
994 dev->fsa_dev[container].config_needed = NOTHING;
995 break;
996 }
997 }
998 if (device_config_needed == NOTHING)
999 return;
1000
1001 /*
1002 * If we decided that a re-configuration needs to be done,
1003 * schedule it here on the way out the door, please close the door
1004 * behind you.
1005 */
1006
1007 busy = 0;
1008
1009
1010 /*
1011 * Find the Scsi_Device associated with the SCSI address,
1012 * and mark it as changed, invalidating the cache. This deals
1013 * with changes to existing device IDs.
1014 */
1015
1016 if (!dev || !dev->scsi_host_ptr)
1017 return;
1018 /*
1019 * force reload of disk info via probe_container
1020 */
1021 if ((device_config_needed == CHANGE)
1022 && (dev->fsa_dev[container].valid == 1))
1023 dev->fsa_dev[container].valid = 2;
1024 if ((device_config_needed == CHANGE) ||
1025 (device_config_needed == ADD))
1026 probe_container(dev, container);
1027 device = scsi_device_lookup(dev->scsi_host_ptr,
1028 CONTAINER_TO_CHANNEL(container),
1029 CONTAINER_TO_ID(container),
1030 CONTAINER_TO_LUN(container));
1031 if (device) {
1032 switch (device_config_needed) {
1033 case DELETE:
1034 scsi_remove_device(device);
1035 break;
1036 case CHANGE:
1037 if (!dev->fsa_dev[container].valid) {
1038 scsi_remove_device(device);
1039 break;
1040 }
1041 scsi_rescan_device(&device->sdev_gendev);
1042
1043 default:
1044 break;
1045 }
1046 scsi_device_put(device);
1047 }
1048 if (device_config_needed == ADD) {
1049 scsi_add_device(dev->scsi_host_ptr,
1050 CONTAINER_TO_CHANNEL(container),
1051 CONTAINER_TO_ID(container),
1052 CONTAINER_TO_LUN(container));
1053 }
1054
1055}
1056
794/** 1057/**
795 * aac_command_thread - command processing thread 1058 * aac_command_thread - command processing thread
796 * @dev: Adapter to monitor 1059 * @dev: Adapter to monitor
@@ -860,6 +1123,7 @@ int aac_command_thread(struct aac_dev * dev)
860 aifcmd = (struct aac_aifcmd *) hw_fib->data; 1123 aifcmd = (struct aac_aifcmd *) hw_fib->data;
861 if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { 1124 if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
862 /* Handle Driver Notify Events */ 1125 /* Handle Driver Notify Events */
1126 aac_handle_aif(dev, fib);
863 *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); 1127 *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
864 fib_adapter_complete(fib, (u16)sizeof(u32)); 1128 fib_adapter_complete(fib, (u16)sizeof(u32));
865 } else { 1129 } else {
@@ -872,7 +1136,15 @@ int aac_command_thread(struct aac_dev * dev)
872 unsigned num; 1136 unsigned num;
873 struct hw_fib ** hw_fib_pool, ** hw_fib_p; 1137 struct hw_fib ** hw_fib_pool, ** hw_fib_p;
874 struct fib ** fib_pool, ** fib_p; 1138 struct fib ** fib_pool, ** fib_p;
875 1139
1140 /* Sniff events */
1141 if ((aifcmd->command ==
1142 cpu_to_le32(AifCmdEventNotify)) ||
1143 (aifcmd->command ==
1144 cpu_to_le32(AifCmdJobProgress))) {
1145 aac_handle_aif(dev, fib);
1146 }
1147
876 time_now = jiffies/HZ; 1148 time_now = jiffies/HZ;
877 1149
878 /* 1150 /*