diff options
Diffstat (limited to 'drivers/scsi/aacraid/commsup.c')
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 96 |
1 files changed, 75 insertions, 21 deletions
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 3a3017d8dc65..6d88f30296e1 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -775,20 +775,20 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
775 | { | 775 | { |
776 | struct hw_fib * hw_fib = fibptr->hw_fib_va; | 776 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
777 | struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; | 777 | struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; |
778 | u32 container; | 778 | u32 channel, id, lun, container; |
779 | struct scsi_device *device; | 779 | struct scsi_device *device; |
780 | enum { | 780 | enum { |
781 | NOTHING, | 781 | NOTHING, |
782 | DELETE, | 782 | DELETE, |
783 | ADD, | 783 | ADD, |
784 | CHANGE | 784 | CHANGE |
785 | } device_config_needed; | 785 | } device_config_needed = NOTHING; |
786 | 786 | ||
787 | /* Sniff for container changes */ | 787 | /* Sniff for container changes */ |
788 | 788 | ||
789 | if (!dev || !dev->fsa_dev) | 789 | if (!dev || !dev->fsa_dev) |
790 | return; | 790 | return; |
791 | container = (u32)-1; | 791 | container = channel = id = lun = (u32)-1; |
792 | 792 | ||
793 | /* | 793 | /* |
794 | * We have set this up to try and minimize the number of | 794 | * We have set this up to try and minimize the number of |
@@ -901,6 +901,36 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
901 | case AifEnConfigChange: | 901 | case AifEnConfigChange: |
902 | break; | 902 | break; |
903 | 903 | ||
904 | case AifEnEnclosureManagement: | ||
905 | switch (le32_to_cpu(((__le32 *)aifcmd->data)[3])) { | ||
906 | case EM_DRIVE_INSERTION: | ||
907 | case EM_DRIVE_REMOVAL: | ||
908 | container = le32_to_cpu( | ||
909 | ((__le32 *)aifcmd->data)[2]); | ||
910 | if ((container >> 28)) | ||
911 | break; | ||
912 | channel = (container >> 24) & 0xF; | ||
913 | if (channel >= dev->maximum_num_channels) | ||
914 | break; | ||
915 | id = container & 0xFFFF; | ||
916 | lun = (container >> 16) & 0xFF; | ||
917 | if (id >= dev->maximum_num_physicals) { | ||
918 | /* legacy dev_t ? */ | ||
919 | if ((0x2000 <= id) || lun || channel || | ||
920 | ((channel = (id >> 7) & 0x3F) >= | ||
921 | dev->maximum_num_channels)) | ||
922 | break; | ||
923 | lun = (id >> 4) & 7; | ||
924 | id &= 0xF; | ||
925 | } | ||
926 | channel = aac_phys_to_logical(channel); | ||
927 | device_config_needed = | ||
928 | (((__le32 *)aifcmd->data)[3] | ||
929 | == cpu_to_le32(EM_DRIVE_INSERTION)) ? | ||
930 | ADD : DELETE; | ||
931 | break; | ||
932 | } | ||
933 | break; | ||
904 | } | 934 | } |
905 | 935 | ||
906 | /* | 936 | /* |
@@ -969,7 +999,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
969 | break; | 999 | break; |
970 | } | 1000 | } |
971 | 1001 | ||
972 | device_config_needed = NOTHING; | 1002 | if (device_config_needed == NOTHING) |
973 | for (container = 0; container < dev->maximum_num_containers; | 1003 | for (container = 0; container < dev->maximum_num_containers; |
974 | ++container) { | 1004 | ++container) { |
975 | if ((dev->fsa_dev[container].config_waiting_on == 0) && | 1005 | if ((dev->fsa_dev[container].config_waiting_on == 0) && |
@@ -978,6 +1008,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
978 | device_config_needed = | 1008 | device_config_needed = |
979 | dev->fsa_dev[container].config_needed; | 1009 | dev->fsa_dev[container].config_needed; |
980 | dev->fsa_dev[container].config_needed = NOTHING; | 1010 | dev->fsa_dev[container].config_needed = NOTHING; |
1011 | channel = CONTAINER_TO_CHANNEL(container); | ||
1012 | id = CONTAINER_TO_ID(container); | ||
1013 | lun = CONTAINER_TO_LUN(container); | ||
981 | break; | 1014 | break; |
982 | } | 1015 | } |
983 | } | 1016 | } |
@@ -1001,34 +1034,56 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
1001 | /* | 1034 | /* |
1002 | * force reload of disk info via aac_probe_container | 1035 | * force reload of disk info via aac_probe_container |
1003 | */ | 1036 | */ |
1004 | if ((device_config_needed == CHANGE) | 1037 | if ((channel == CONTAINER_CHANNEL) && |
1005 | && (dev->fsa_dev[container].valid == 1)) | 1038 | (device_config_needed != NOTHING)) { |
1006 | dev->fsa_dev[container].valid = 2; | 1039 | if (dev->fsa_dev[container].valid == 1) |
1007 | if ((device_config_needed == CHANGE) || | 1040 | dev->fsa_dev[container].valid = 2; |
1008 | (device_config_needed == ADD)) | ||
1009 | aac_probe_container(dev, container); | 1041 | aac_probe_container(dev, container); |
1010 | device = scsi_device_lookup(dev->scsi_host_ptr, | 1042 | } |
1011 | CONTAINER_TO_CHANNEL(container), | 1043 | device = scsi_device_lookup(dev->scsi_host_ptr, channel, id, lun); |
1012 | CONTAINER_TO_ID(container), | ||
1013 | CONTAINER_TO_LUN(container)); | ||
1014 | if (device) { | 1044 | if (device) { |
1015 | switch (device_config_needed) { | 1045 | switch (device_config_needed) { |
1016 | case DELETE: | 1046 | case DELETE: |
1047 | if (scsi_device_online(device)) { | ||
1048 | scsi_device_set_state(device, SDEV_OFFLINE); | ||
1049 | sdev_printk(KERN_INFO, device, | ||
1050 | "Device offlined - %s\n", | ||
1051 | (channel == CONTAINER_CHANNEL) ? | ||
1052 | "array deleted" : | ||
1053 | "enclosure services event"); | ||
1054 | } | ||
1055 | break; | ||
1056 | case ADD: | ||
1057 | if (!scsi_device_online(device)) { | ||
1058 | sdev_printk(KERN_INFO, device, | ||
1059 | "Device online - %s\n", | ||
1060 | (channel == CONTAINER_CHANNEL) ? | ||
1061 | "array created" : | ||
1062 | "enclosure services event"); | ||
1063 | scsi_device_set_state(device, SDEV_RUNNING); | ||
1064 | } | ||
1065 | /* FALLTHRU */ | ||
1017 | case CHANGE: | 1066 | case CHANGE: |
1067 | if ((channel == CONTAINER_CHANNEL) | ||
1068 | && (!dev->fsa_dev[container].valid)) { | ||
1069 | if (!scsi_device_online(device)) | ||
1070 | break; | ||
1071 | scsi_device_set_state(device, SDEV_OFFLINE); | ||
1072 | sdev_printk(KERN_INFO, device, | ||
1073 | "Device offlined - %s\n", | ||
1074 | "array failed"); | ||
1075 | break; | ||
1076 | } | ||
1018 | scsi_rescan_device(&device->sdev_gendev); | 1077 | scsi_rescan_device(&device->sdev_gendev); |
1019 | 1078 | ||
1020 | default: | 1079 | default: |
1021 | break; | 1080 | break; |
1022 | } | 1081 | } |
1023 | scsi_device_put(device); | 1082 | scsi_device_put(device); |
1083 | device_config_needed = NOTHING; | ||
1024 | } | 1084 | } |
1025 | if (device_config_needed == ADD) { | 1085 | if (device_config_needed == ADD) |
1026 | scsi_add_device(dev->scsi_host_ptr, | 1086 | scsi_add_device(dev->scsi_host_ptr, channel, id, lun); |
1027 | CONTAINER_TO_CHANNEL(container), | ||
1028 | CONTAINER_TO_ID(container), | ||
1029 | CONTAINER_TO_LUN(container)); | ||
1030 | } | ||
1031 | |||
1032 | } | 1087 | } |
1033 | 1088 | ||
1034 | static int _aac_reset_adapter(struct aac_dev *aac, int forced) | 1089 | static int _aac_reset_adapter(struct aac_dev *aac, int forced) |
@@ -1469,7 +1524,6 @@ int aac_command_thread(void *data) | |||
1469 | *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); | 1524 | *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); |
1470 | aac_fib_adapter_complete(fib, (u16)sizeof(u32)); | 1525 | aac_fib_adapter_complete(fib, (u16)sizeof(u32)); |
1471 | } else { | 1526 | } else { |
1472 | struct list_head *entry; | ||
1473 | /* The u32 here is important and intended. We are using | 1527 | /* The u32 here is important and intended. We are using |
1474 | 32bit wrapping time to fit the adapter field */ | 1528 | 32bit wrapping time to fit the adapter field */ |
1475 | 1529 | ||