diff options
Diffstat (limited to 'drivers/scsi')
32 files changed, 1690 insertions, 426 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 12c208fb18c5..b3ae796eb624 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -1,5 +1,11 @@ | |||
1 | menu "SCSI device support" | 1 | menu "SCSI device support" |
2 | 2 | ||
3 | config RAID_ATTRS | ||
4 | tristate "RAID Transport Class" | ||
5 | default n | ||
6 | ---help--- | ||
7 | Provides RAID | ||
8 | |||
3 | config SCSI | 9 | config SCSI |
4 | tristate "SCSI device support" | 10 | tristate "SCSI device support" |
5 | ---help--- | 11 | ---help--- |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 3746fb9fa2f5..85f9e6bb34b9 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -22,6 +22,8 @@ subdir-$(CONFIG_PCMCIA) += pcmcia | |||
22 | 22 | ||
23 | obj-$(CONFIG_SCSI) += scsi_mod.o | 23 | obj-$(CONFIG_SCSI) += scsi_mod.o |
24 | 24 | ||
25 | obj-$(CONFIG_RAID_ATTRS) += raid_class.o | ||
26 | |||
25 | # --- NOTE ORDERING HERE --- | 27 | # --- NOTE ORDERING HERE --- |
26 | # For kernel non-modular link, transport attributes need to | 28 | # For kernel non-modular link, transport attributes need to |
27 | # be initialised before drivers | 29 | # be initialised before drivers |
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 83bfab73ff65..a8e3dfcd0dc7 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -972,7 +972,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
972 | fibsize = sizeof(struct aac_read64) + | 972 | fibsize = sizeof(struct aac_read64) + |
973 | ((le32_to_cpu(readcmd->sg.count) - 1) * | 973 | ((le32_to_cpu(readcmd->sg.count) - 1) * |
974 | sizeof (struct sgentry64)); | 974 | sizeof (struct sgentry64)); |
975 | BUG_ON (fibsize > (sizeof(struct hw_fib) - | 975 | BUG_ON (fibsize > (dev->max_fib_size - |
976 | sizeof(struct aac_fibhdr))); | 976 | sizeof(struct aac_fibhdr))); |
977 | /* | 977 | /* |
978 | * Now send the Fib to the adapter | 978 | * Now send the Fib to the adapter |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 3feb739cd554..6b6d4e287793 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -48,12 +48,6 @@ | |||
48 | 48 | ||
49 | static struct scsi_transport_template *ahd_linux_transport_template = NULL; | 49 | static struct scsi_transport_template *ahd_linux_transport_template = NULL; |
50 | 50 | ||
51 | /* | ||
52 | * Include aiclib.c as part of our | ||
53 | * "module dependencies are hard" work around. | ||
54 | */ | ||
55 | #include "aiclib.c" | ||
56 | |||
57 | #include <linux/init.h> /* __setup */ | 51 | #include <linux/init.h> /* __setup */ |
58 | #include <linux/mm.h> /* For fetching system memory size */ | 52 | #include <linux/mm.h> /* For fetching system memory size */ |
59 | #include <linux/blkdev.h> /* For block_size() */ | 53 | #include <linux/blkdev.h> /* For block_size() */ |
@@ -372,8 +366,6 @@ static int ahd_linux_run_command(struct ahd_softc*, | |||
372 | struct ahd_linux_device *, | 366 | struct ahd_linux_device *, |
373 | struct scsi_cmnd *); | 367 | struct scsi_cmnd *); |
374 | static void ahd_linux_setup_tag_info_global(char *p); | 368 | static void ahd_linux_setup_tag_info_global(char *p); |
375 | static aic_option_callback_t ahd_linux_setup_tag_info; | ||
376 | static aic_option_callback_t ahd_linux_setup_iocell_info; | ||
377 | static int aic79xx_setup(char *c); | 369 | static int aic79xx_setup(char *c); |
378 | 370 | ||
379 | static int ahd_linux_unit; | 371 | static int ahd_linux_unit; |
@@ -907,6 +899,86 @@ ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) | |||
907 | } | 899 | } |
908 | } | 900 | } |
909 | 901 | ||
902 | static char * | ||
903 | ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, | ||
904 | void (*callback)(u_long, int, int, int32_t), | ||
905 | u_long callback_arg) | ||
906 | { | ||
907 | char *tok_end; | ||
908 | char *tok_end2; | ||
909 | int i; | ||
910 | int instance; | ||
911 | int targ; | ||
912 | int done; | ||
913 | char tok_list[] = {'.', ',', '{', '}', '\0'}; | ||
914 | |||
915 | /* All options use a ':' name/arg separator */ | ||
916 | if (*opt_arg != ':') | ||
917 | return (opt_arg); | ||
918 | opt_arg++; | ||
919 | instance = -1; | ||
920 | targ = -1; | ||
921 | done = FALSE; | ||
922 | /* | ||
923 | * Restore separator that may be in | ||
924 | * the middle of our option argument. | ||
925 | */ | ||
926 | tok_end = strchr(opt_arg, '\0'); | ||
927 | if (tok_end < end) | ||
928 | *tok_end = ','; | ||
929 | while (!done) { | ||
930 | switch (*opt_arg) { | ||
931 | case '{': | ||
932 | if (instance == -1) { | ||
933 | instance = 0; | ||
934 | } else { | ||
935 | if (depth > 1) { | ||
936 | if (targ == -1) | ||
937 | targ = 0; | ||
938 | } else { | ||
939 | printf("Malformed Option %s\n", | ||
940 | opt_name); | ||
941 | done = TRUE; | ||
942 | } | ||
943 | } | ||
944 | opt_arg++; | ||
945 | break; | ||
946 | case '}': | ||
947 | if (targ != -1) | ||
948 | targ = -1; | ||
949 | else if (instance != -1) | ||
950 | instance = -1; | ||
951 | opt_arg++; | ||
952 | break; | ||
953 | case ',': | ||
954 | case '.': | ||
955 | if (instance == -1) | ||
956 | done = TRUE; | ||
957 | else if (targ >= 0) | ||
958 | targ++; | ||
959 | else if (instance >= 0) | ||
960 | instance++; | ||
961 | opt_arg++; | ||
962 | break; | ||
963 | case '\0': | ||
964 | done = TRUE; | ||
965 | break; | ||
966 | default: | ||
967 | tok_end = end; | ||
968 | for (i = 0; tok_list[i]; i++) { | ||
969 | tok_end2 = strchr(opt_arg, tok_list[i]); | ||
970 | if ((tok_end2) && (tok_end2 < tok_end)) | ||
971 | tok_end = tok_end2; | ||
972 | } | ||
973 | callback(callback_arg, instance, targ, | ||
974 | simple_strtol(opt_arg, NULL, 0)); | ||
975 | opt_arg = tok_end; | ||
976 | break; | ||
977 | } | ||
978 | } | ||
979 | return (opt_arg); | ||
980 | } | ||
981 | |||
910 | /* | 982 | /* |
911 | * Handle Linux boot parameters. This routine allows for assigning a value | 983 | * Handle Linux boot parameters. This routine allows for assigning a value |
912 | * to a parameter with a ':' between the parameter and the value. | 984 | * to a parameter with a ':' between the parameter and the value. |
@@ -964,18 +1036,18 @@ aic79xx_setup(char *s) | |||
964 | if (strncmp(p, "global_tag_depth", n) == 0) { | 1036 | if (strncmp(p, "global_tag_depth", n) == 0) { |
965 | ahd_linux_setup_tag_info_global(p + n); | 1037 | ahd_linux_setup_tag_info_global(p + n); |
966 | } else if (strncmp(p, "tag_info", n) == 0) { | 1038 | } else if (strncmp(p, "tag_info", n) == 0) { |
967 | s = aic_parse_brace_option("tag_info", p + n, end, | 1039 | s = ahd_parse_brace_option("tag_info", p + n, end, |
968 | 2, ahd_linux_setup_tag_info, 0); | 1040 | 2, ahd_linux_setup_tag_info, 0); |
969 | } else if (strncmp(p, "slewrate", n) == 0) { | 1041 | } else if (strncmp(p, "slewrate", n) == 0) { |
970 | s = aic_parse_brace_option("slewrate", | 1042 | s = ahd_parse_brace_option("slewrate", |
971 | p + n, end, 1, ahd_linux_setup_iocell_info, | 1043 | p + n, end, 1, ahd_linux_setup_iocell_info, |
972 | AIC79XX_SLEWRATE_INDEX); | 1044 | AIC79XX_SLEWRATE_INDEX); |
973 | } else if (strncmp(p, "precomp", n) == 0) { | 1045 | } else if (strncmp(p, "precomp", n) == 0) { |
974 | s = aic_parse_brace_option("precomp", | 1046 | s = ahd_parse_brace_option("precomp", |
975 | p + n, end, 1, ahd_linux_setup_iocell_info, | 1047 | p + n, end, 1, ahd_linux_setup_iocell_info, |
976 | AIC79XX_PRECOMP_INDEX); | 1048 | AIC79XX_PRECOMP_INDEX); |
977 | } else if (strncmp(p, "amplitude", n) == 0) { | 1049 | } else if (strncmp(p, "amplitude", n) == 0) { |
978 | s = aic_parse_brace_option("amplitude", | 1050 | s = ahd_parse_brace_option("amplitude", |
979 | p + n, end, 1, ahd_linux_setup_iocell_info, | 1051 | p + n, end, 1, ahd_linux_setup_iocell_info, |
980 | AIC79XX_AMPLITUDE_INDEX); | 1052 | AIC79XX_AMPLITUDE_INDEX); |
981 | } else if (p[n] == ':') { | 1053 | } else if (p[n] == ':') { |
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index 32be1f55998c..39a27840fce6 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c | |||
@@ -53,6 +53,49 @@ static void ahd_dump_device_state(struct info_str *info, | |||
53 | static int ahd_proc_write_seeprom(struct ahd_softc *ahd, | 53 | static int ahd_proc_write_seeprom(struct ahd_softc *ahd, |
54 | char *buffer, int length); | 54 | char *buffer, int length); |
55 | 55 | ||
56 | /* | ||
57 | * Table of syncrates that don't follow the "divisible by 4" | ||
58 | * rule. This table will be expanded in future SCSI specs. | ||
59 | */ | ||
60 | static struct { | ||
61 | u_int period_factor; | ||
62 | u_int period; /* in 100ths of ns */ | ||
63 | } scsi_syncrates[] = { | ||
64 | { 0x08, 625 }, /* FAST-160 */ | ||
65 | { 0x09, 1250 }, /* FAST-80 */ | ||
66 | { 0x0a, 2500 }, /* FAST-40 40MHz */ | ||
67 | { 0x0b, 3030 }, /* FAST-40 33MHz */ | ||
68 | { 0x0c, 5000 } /* FAST-20 */ | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * Return the frequency in kHz corresponding to the given | ||
73 | * sync period factor. | ||
74 | */ | ||
75 | static u_int | ||
76 | ahd_calc_syncsrate(u_int period_factor) | ||
77 | { | ||
78 | int i; | ||
79 | int num_syncrates; | ||
80 | |||
81 | num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); | ||
82 | /* See if the period is in the "exception" table */ | ||
83 | for (i = 0; i < num_syncrates; i++) { | ||
84 | |||
85 | if (period_factor == scsi_syncrates[i].period_factor) { | ||
86 | /* Period in kHz */ | ||
87 | return (100000000 / scsi_syncrates[i].period); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * Wasn't in the table, so use the standard | ||
93 | * 4 times conversion. | ||
94 | */ | ||
95 | return (10000000 / (period_factor * 4 * 10)); | ||
96 | } | ||
97 | |||
98 | |||
56 | static void | 99 | static void |
57 | copy_mem_info(struct info_str *info, char *data, int len) | 100 | copy_mem_info(struct info_str *info, char *data, int len) |
58 | { | 101 | { |
@@ -109,7 +152,7 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) | |||
109 | speed = 3300; | 152 | speed = 3300; |
110 | freq = 0; | 153 | freq = 0; |
111 | if (tinfo->offset != 0) { | 154 | if (tinfo->offset != 0) { |
112 | freq = aic_calc_syncsrate(tinfo->period); | 155 | freq = ahd_calc_syncsrate(tinfo->period); |
113 | speed = freq; | 156 | speed = freq; |
114 | } | 157 | } |
115 | speed *= (0x01 << tinfo->width); | 158 | speed *= (0x01 << tinfo->width); |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 54173887e160..c932b3b94490 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -125,12 +125,6 @@ | |||
125 | 125 | ||
126 | static struct scsi_transport_template *ahc_linux_transport_template = NULL; | 126 | static struct scsi_transport_template *ahc_linux_transport_template = NULL; |
127 | 127 | ||
128 | /* | ||
129 | * Include aiclib.c as part of our | ||
130 | * "module dependencies are hard" work around. | ||
131 | */ | ||
132 | #include "aiclib.c" | ||
133 | |||
134 | #include <linux/init.h> /* __setup */ | 128 | #include <linux/init.h> /* __setup */ |
135 | #include <linux/mm.h> /* For fetching system memory size */ | 129 | #include <linux/mm.h> /* For fetching system memory size */ |
136 | #include <linux/blkdev.h> /* For block_size() */ | 130 | #include <linux/blkdev.h> /* For block_size() */ |
@@ -391,7 +385,6 @@ static int ahc_linux_run_command(struct ahc_softc*, | |||
391 | struct ahc_linux_device *, | 385 | struct ahc_linux_device *, |
392 | struct scsi_cmnd *); | 386 | struct scsi_cmnd *); |
393 | static void ahc_linux_setup_tag_info_global(char *p); | 387 | static void ahc_linux_setup_tag_info_global(char *p); |
394 | static aic_option_callback_t ahc_linux_setup_tag_info; | ||
395 | static int aic7xxx_setup(char *s); | 388 | static int aic7xxx_setup(char *s); |
396 | 389 | ||
397 | static int ahc_linux_unit; | 390 | static int ahc_linux_unit; |
@@ -920,6 +913,86 @@ ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) | |||
920 | } | 913 | } |
921 | } | 914 | } |
922 | 915 | ||
916 | static char * | ||
917 | ahc_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, | ||
918 | void (*callback)(u_long, int, int, int32_t), | ||
919 | u_long callback_arg) | ||
920 | { | ||
921 | char *tok_end; | ||
922 | char *tok_end2; | ||
923 | int i; | ||
924 | int instance; | ||
925 | int targ; | ||
926 | int done; | ||
927 | char tok_list[] = {'.', ',', '{', '}', '\0'}; | ||
928 | |||
929 | /* All options use a ':' name/arg separator */ | ||
930 | if (*opt_arg != ':') | ||
931 | return (opt_arg); | ||
932 | opt_arg++; | ||
933 | instance = -1; | ||
934 | targ = -1; | ||
935 | done = FALSE; | ||
936 | /* | ||
937 | * Restore separator that may be in | ||
938 | * the middle of our option argument. | ||
939 | */ | ||
940 | tok_end = strchr(opt_arg, '\0'); | ||
941 | if (tok_end < end) | ||
942 | *tok_end = ','; | ||
943 | while (!done) { | ||
944 | switch (*opt_arg) { | ||
945 | case '{': | ||
946 | if (instance == -1) { | ||
947 | instance = 0; | ||
948 | } else { | ||
949 | if (depth > 1) { | ||
950 | if (targ == -1) | ||
951 | targ = 0; | ||
952 | } else { | ||
953 | printf("Malformed Option %s\n", | ||
954 | opt_name); | ||
955 | done = TRUE; | ||
956 | } | ||
957 | } | ||
958 | opt_arg++; | ||
959 | break; | ||
960 | case '}': | ||
961 | if (targ != -1) | ||
962 | targ = -1; | ||
963 | else if (instance != -1) | ||
964 | instance = -1; | ||
965 | opt_arg++; | ||
966 | break; | ||
967 | case ',': | ||
968 | case '.': | ||
969 | if (instance == -1) | ||
970 | done = TRUE; | ||
971 | else if (targ >= 0) | ||
972 | targ++; | ||
973 | else if (instance >= 0) | ||
974 | instance++; | ||
975 | opt_arg++; | ||
976 | break; | ||
977 | case '\0': | ||
978 | done = TRUE; | ||
979 | break; | ||
980 | default: | ||
981 | tok_end = end; | ||
982 | for (i = 0; tok_list[i]; i++) { | ||
983 | tok_end2 = strchr(opt_arg, tok_list[i]); | ||
984 | if ((tok_end2) && (tok_end2 < tok_end)) | ||
985 | tok_end = tok_end2; | ||
986 | } | ||
987 | callback(callback_arg, instance, targ, | ||
988 | simple_strtol(opt_arg, NULL, 0)); | ||
989 | opt_arg = tok_end; | ||
990 | break; | ||
991 | } | ||
992 | } | ||
993 | return (opt_arg); | ||
994 | } | ||
995 | |||
923 | /* | 996 | /* |
924 | * Handle Linux boot parameters. This routine allows for assigning a value | 997 | * Handle Linux boot parameters. This routine allows for assigning a value |
925 | * to a parameter with a ':' between the parameter and the value. | 998 | * to a parameter with a ':' between the parameter and the value. |
@@ -974,7 +1047,7 @@ aic7xxx_setup(char *s) | |||
974 | if (strncmp(p, "global_tag_depth", n) == 0) { | 1047 | if (strncmp(p, "global_tag_depth", n) == 0) { |
975 | ahc_linux_setup_tag_info_global(p + n); | 1048 | ahc_linux_setup_tag_info_global(p + n); |
976 | } else if (strncmp(p, "tag_info", n) == 0) { | 1049 | } else if (strncmp(p, "tag_info", n) == 0) { |
977 | s = aic_parse_brace_option("tag_info", p + n, end, | 1050 | s = ahc_parse_brace_option("tag_info", p + n, end, |
978 | 2, ahc_linux_setup_tag_info, 0); | 1051 | 2, ahc_linux_setup_tag_info, 0); |
979 | } else if (p[n] == ':') { | 1052 | } else if (p[n] == ':') { |
980 | *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); | 1053 | *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index 3802c91f0b07..04a3506cf340 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c | |||
@@ -54,6 +54,49 @@ static void ahc_dump_device_state(struct info_str *info, | |||
54 | static int ahc_proc_write_seeprom(struct ahc_softc *ahc, | 54 | static int ahc_proc_write_seeprom(struct ahc_softc *ahc, |
55 | char *buffer, int length); | 55 | char *buffer, int length); |
56 | 56 | ||
57 | /* | ||
58 | * Table of syncrates that don't follow the "divisible by 4" | ||
59 | * rule. This table will be expanded in future SCSI specs. | ||
60 | */ | ||
61 | static struct { | ||
62 | u_int period_factor; | ||
63 | u_int period; /* in 100ths of ns */ | ||
64 | } scsi_syncrates[] = { | ||
65 | { 0x08, 625 }, /* FAST-160 */ | ||
66 | { 0x09, 1250 }, /* FAST-80 */ | ||
67 | { 0x0a, 2500 }, /* FAST-40 40MHz */ | ||
68 | { 0x0b, 3030 }, /* FAST-40 33MHz */ | ||
69 | { 0x0c, 5000 } /* FAST-20 */ | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * Return the frequency in kHz corresponding to the given | ||
74 | * sync period factor. | ||
75 | */ | ||
76 | static u_int | ||
77 | ahc_calc_syncsrate(u_int period_factor) | ||
78 | { | ||
79 | int i; | ||
80 | int num_syncrates; | ||
81 | |||
82 | num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); | ||
83 | /* See if the period is in the "exception" table */ | ||
84 | for (i = 0; i < num_syncrates; i++) { | ||
85 | |||
86 | if (period_factor == scsi_syncrates[i].period_factor) { | ||
87 | /* Period in kHz */ | ||
88 | return (100000000 / scsi_syncrates[i].period); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Wasn't in the table, so use the standard | ||
94 | * 4 times conversion. | ||
95 | */ | ||
96 | return (10000000 / (period_factor * 4 * 10)); | ||
97 | } | ||
98 | |||
99 | |||
57 | static void | 100 | static void |
58 | copy_mem_info(struct info_str *info, char *data, int len) | 101 | copy_mem_info(struct info_str *info, char *data, int len) |
59 | { | 102 | { |
@@ -106,7 +149,7 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo) | |||
106 | speed = 3300; | 149 | speed = 3300; |
107 | freq = 0; | 150 | freq = 0; |
108 | if (tinfo->offset != 0) { | 151 | if (tinfo->offset != 0) { |
109 | freq = aic_calc_syncsrate(tinfo->period); | 152 | freq = ahc_calc_syncsrate(tinfo->period); |
110 | speed = freq; | 153 | speed = freq; |
111 | } | 154 | } |
112 | speed *= (0x01 << tinfo->width); | 155 | speed *= (0x01 << tinfo->width); |
diff --git a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c index 4d44a9211185..828ae3d9a510 100644 --- a/drivers/scsi/aic7xxx/aiclib.c +++ b/drivers/scsi/aic7xxx/aiclib.c | |||
@@ -32,124 +32,3 @@ | |||
32 | 32 | ||
33 | #include "aiclib.h" | 33 | #include "aiclib.h" |
34 | 34 | ||
35 | |||
36 | /* | ||
37 | * Table of syncrates that don't follow the "divisible by 4" | ||
38 | * rule. This table will be expanded in future SCSI specs. | ||
39 | */ | ||
40 | static struct { | ||
41 | u_int period_factor; | ||
42 | u_int period; /* in 100ths of ns */ | ||
43 | } scsi_syncrates[] = { | ||
44 | { 0x08, 625 }, /* FAST-160 */ | ||
45 | { 0x09, 1250 }, /* FAST-80 */ | ||
46 | { 0x0a, 2500 }, /* FAST-40 40MHz */ | ||
47 | { 0x0b, 3030 }, /* FAST-40 33MHz */ | ||
48 | { 0x0c, 5000 } /* FAST-20 */ | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * Return the frequency in kHz corresponding to the given | ||
53 | * sync period factor. | ||
54 | */ | ||
55 | u_int | ||
56 | aic_calc_syncsrate(u_int period_factor) | ||
57 | { | ||
58 | int i; | ||
59 | int num_syncrates; | ||
60 | |||
61 | num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); | ||
62 | /* See if the period is in the "exception" table */ | ||
63 | for (i = 0; i < num_syncrates; i++) { | ||
64 | |||
65 | if (period_factor == scsi_syncrates[i].period_factor) { | ||
66 | /* Period in kHz */ | ||
67 | return (100000000 / scsi_syncrates[i].period); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * Wasn't in the table, so use the standard | ||
73 | * 4 times conversion. | ||
74 | */ | ||
75 | return (10000000 / (period_factor * 4 * 10)); | ||
76 | } | ||
77 | |||
78 | char * | ||
79 | aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, | ||
80 | aic_option_callback_t *callback, u_long callback_arg) | ||
81 | { | ||
82 | char *tok_end; | ||
83 | char *tok_end2; | ||
84 | int i; | ||
85 | int instance; | ||
86 | int targ; | ||
87 | int done; | ||
88 | char tok_list[] = {'.', ',', '{', '}', '\0'}; | ||
89 | |||
90 | /* All options use a ':' name/arg separator */ | ||
91 | if (*opt_arg != ':') | ||
92 | return (opt_arg); | ||
93 | opt_arg++; | ||
94 | instance = -1; | ||
95 | targ = -1; | ||
96 | done = FALSE; | ||
97 | /* | ||
98 | * Restore separator that may be in | ||
99 | * the middle of our option argument. | ||
100 | */ | ||
101 | tok_end = strchr(opt_arg, '\0'); | ||
102 | if (tok_end < end) | ||
103 | *tok_end = ','; | ||
104 | while (!done) { | ||
105 | switch (*opt_arg) { | ||
106 | case '{': | ||
107 | if (instance == -1) { | ||
108 | instance = 0; | ||
109 | } else { | ||
110 | if (depth > 1) { | ||
111 | if (targ == -1) | ||
112 | targ = 0; | ||
113 | } else { | ||
114 | printf("Malformed Option %s\n", | ||
115 | opt_name); | ||
116 | done = TRUE; | ||
117 | } | ||
118 | } | ||
119 | opt_arg++; | ||
120 | break; | ||
121 | case '}': | ||
122 | if (targ != -1) | ||
123 | targ = -1; | ||
124 | else if (instance != -1) | ||
125 | instance = -1; | ||
126 | opt_arg++; | ||
127 | break; | ||
128 | case ',': | ||
129 | case '.': | ||
130 | if (instance == -1) | ||
131 | done = TRUE; | ||
132 | else if (targ >= 0) | ||
133 | targ++; | ||
134 | else if (instance >= 0) | ||
135 | instance++; | ||
136 | opt_arg++; | ||
137 | break; | ||
138 | case '\0': | ||
139 | done = TRUE; | ||
140 | break; | ||
141 | default: | ||
142 | tok_end = end; | ||
143 | for (i = 0; tok_list[i]; i++) { | ||
144 | tok_end2 = strchr(opt_arg, tok_list[i]); | ||
145 | if ((tok_end2) && (tok_end2 < tok_end)) | ||
146 | tok_end = tok_end2; | ||
147 | } | ||
148 | callback(callback_arg, instance, targ, | ||
149 | simple_strtol(opt_arg, NULL, 0)); | ||
150 | opt_arg = tok_end; | ||
151 | break; | ||
152 | } | ||
153 | } | ||
154 | return (opt_arg); | ||
155 | } | ||
diff --git a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h index e7d94cbaf2a8..3bfbf0fe1ec2 100644 --- a/drivers/scsi/aic7xxx/aiclib.h +++ b/drivers/scsi/aic7xxx/aiclib.h | |||
@@ -141,28 +141,6 @@ aic_sector_div(sector_t capacity, int heads, int sectors) | |||
141 | return (int)capacity; | 141 | return (int)capacity; |
142 | } | 142 | } |
143 | 143 | ||
144 | /**************************** Module Library Hack *****************************/ | ||
145 | /* | ||
146 | * What we'd like to do is have a single "scsi library" module that both the | ||
147 | * aic7xxx and aic79xx drivers could load and depend on. A cursory examination | ||
148 | * of implementing module dependencies in Linux (handling the install and | ||
149 | * initrd cases) does not look promissing. For now, we just duplicate this | ||
150 | * code in both drivers using a simple symbol renaming scheme that hides this | ||
151 | * hack from the drivers. | ||
152 | */ | ||
153 | #define AIC_LIB_ENTRY_CONCAT(x, prefix) prefix ## x | ||
154 | #define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix) | ||
155 | #define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX) | ||
156 | |||
157 | #define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate) | ||
158 | |||
159 | u_int aic_calc_syncsrate(u_int /*period_factor*/); | ||
160 | |||
161 | typedef void aic_option_callback_t(u_long, int, int, int32_t); | ||
162 | char * aic_parse_brace_option(char *opt_name, char *opt_arg, | ||
163 | char *end, int depth, | ||
164 | aic_option_callback_t *, u_long); | ||
165 | |||
166 | static __inline uint32_t | 144 | static __inline uint32_t |
167 | scsi_4btoul(uint8_t *bytes) | 145 | scsi_4btoul(uint8_t *bytes) |
168 | { | 146 | { |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 8640ad1c17e2..85503fad789a 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/blkdev.h> | 25 | #include <linux/blkdev.h> |
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/kthread.h> | ||
27 | #include <linux/string.h> | 28 | #include <linux/string.h> |
28 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
29 | #include <linux/init.h> | 30 | #include <linux/init.h> |
@@ -225,15 +226,8 @@ static void scsi_host_dev_release(struct device *dev) | |||
225 | struct Scsi_Host *shost = dev_to_shost(dev); | 226 | struct Scsi_Host *shost = dev_to_shost(dev); |
226 | struct device *parent = dev->parent; | 227 | struct device *parent = dev->parent; |
227 | 228 | ||
228 | if (shost->ehandler) { | 229 | if (shost->ehandler) |
229 | DECLARE_COMPLETION(sem); | 230 | kthread_stop(shost->ehandler); |
230 | shost->eh_notify = &sem; | ||
231 | shost->eh_kill = 1; | ||
232 | up(shost->eh_wait); | ||
233 | wait_for_completion(&sem); | ||
234 | shost->eh_notify = NULL; | ||
235 | } | ||
236 | |||
237 | if (shost->work_q) | 231 | if (shost->work_q) |
238 | destroy_workqueue(shost->work_q); | 232 | destroy_workqueue(shost->work_q); |
239 | 233 | ||
@@ -263,7 +257,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
263 | { | 257 | { |
264 | struct Scsi_Host *shost; | 258 | struct Scsi_Host *shost; |
265 | int gfp_mask = GFP_KERNEL, rval; | 259 | int gfp_mask = GFP_KERNEL, rval; |
266 | DECLARE_COMPLETION(complete); | ||
267 | 260 | ||
268 | if (sht->unchecked_isa_dma && privsize) | 261 | if (sht->unchecked_isa_dma && privsize) |
269 | gfp_mask |= __GFP_DMA; | 262 | gfp_mask |= __GFP_DMA; |
@@ -369,12 +362,12 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
369 | snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d", | 362 | snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d", |
370 | shost->host_no); | 363 | shost->host_no); |
371 | 364 | ||
372 | shost->eh_notify = &complete; | 365 | shost->ehandler = kthread_run(scsi_error_handler, shost, |
373 | rval = kernel_thread(scsi_error_handler, shost, 0); | 366 | "scsi_eh_%d", shost->host_no); |
374 | if (rval < 0) | 367 | if (IS_ERR(shost->ehandler)) { |
368 | rval = PTR_ERR(shost->ehandler); | ||
375 | goto fail_destroy_freelist; | 369 | goto fail_destroy_freelist; |
376 | wait_for_completion(&complete); | 370 | } |
377 | shost->eh_notify = NULL; | ||
378 | 371 | ||
379 | scsi_proc_hostdir_add(shost->hostt); | 372 | scsi_proc_hostdir_add(shost->hostt); |
380 | return shost; | 373 | return shost; |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index e3e6752c4104..1b911dadf64b 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -87,7 +87,7 @@ static int max_channel = 3; | |||
87 | static int init_timeout = 5; | 87 | static int init_timeout = 5; |
88 | static int max_requests = 50; | 88 | static int max_requests = 50; |
89 | 89 | ||
90 | #define IBMVSCSI_VERSION "1.5.6" | 90 | #define IBMVSCSI_VERSION "1.5.7" |
91 | 91 | ||
92 | MODULE_DESCRIPTION("IBM Virtual SCSI"); | 92 | MODULE_DESCRIPTION("IBM Virtual SCSI"); |
93 | MODULE_AUTHOR("Dave Boutcher"); | 93 | MODULE_AUTHOR("Dave Boutcher"); |
@@ -145,6 +145,8 @@ static int initialize_event_pool(struct event_pool *pool, | |||
145 | sizeof(*evt->xfer_iu) * i; | 145 | sizeof(*evt->xfer_iu) * i; |
146 | evt->xfer_iu = pool->iu_storage + i; | 146 | evt->xfer_iu = pool->iu_storage + i; |
147 | evt->hostdata = hostdata; | 147 | evt->hostdata = hostdata; |
148 | evt->ext_list = NULL; | ||
149 | evt->ext_list_token = 0; | ||
148 | } | 150 | } |
149 | 151 | ||
150 | return 0; | 152 | return 0; |
@@ -161,9 +163,16 @@ static void release_event_pool(struct event_pool *pool, | |||
161 | struct ibmvscsi_host_data *hostdata) | 163 | struct ibmvscsi_host_data *hostdata) |
162 | { | 164 | { |
163 | int i, in_use = 0; | 165 | int i, in_use = 0; |
164 | for (i = 0; i < pool->size; ++i) | 166 | for (i = 0; i < pool->size; ++i) { |
165 | if (atomic_read(&pool->events[i].free) != 1) | 167 | if (atomic_read(&pool->events[i].free) != 1) |
166 | ++in_use; | 168 | ++in_use; |
169 | if (pool->events[i].ext_list) { | ||
170 | dma_free_coherent(hostdata->dev, | ||
171 | SG_ALL * sizeof(struct memory_descriptor), | ||
172 | pool->events[i].ext_list, | ||
173 | pool->events[i].ext_list_token); | ||
174 | } | ||
175 | } | ||
167 | if (in_use) | 176 | if (in_use) |
168 | printk(KERN_WARNING | 177 | printk(KERN_WARNING |
169 | "ibmvscsi: releasing event pool with %d " | 178 | "ibmvscsi: releasing event pool with %d " |
@@ -286,24 +295,41 @@ static void set_srp_direction(struct scsi_cmnd *cmd, | |||
286 | } else { | 295 | } else { |
287 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | 296 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { |
288 | srp_cmd->data_out_format = SRP_INDIRECT_BUFFER; | 297 | srp_cmd->data_out_format = SRP_INDIRECT_BUFFER; |
289 | srp_cmd->data_out_count = numbuf; | 298 | srp_cmd->data_out_count = |
299 | numbuf < MAX_INDIRECT_BUFS ? | ||
300 | numbuf: MAX_INDIRECT_BUFS; | ||
290 | } else { | 301 | } else { |
291 | srp_cmd->data_in_format = SRP_INDIRECT_BUFFER; | 302 | srp_cmd->data_in_format = SRP_INDIRECT_BUFFER; |
292 | srp_cmd->data_in_count = numbuf; | 303 | srp_cmd->data_in_count = |
304 | numbuf < MAX_INDIRECT_BUFS ? | ||
305 | numbuf: MAX_INDIRECT_BUFS; | ||
293 | } | 306 | } |
294 | } | 307 | } |
295 | } | 308 | } |
296 | 309 | ||
310 | static void unmap_sg_list(int num_entries, | ||
311 | struct device *dev, | ||
312 | struct memory_descriptor *md) | ||
313 | { | ||
314 | int i; | ||
315 | |||
316 | for (i = 0; i < num_entries; ++i) { | ||
317 | dma_unmap_single(dev, | ||
318 | md[i].virtual_address, | ||
319 | md[i].length, DMA_BIDIRECTIONAL); | ||
320 | } | ||
321 | } | ||
322 | |||
297 | /** | 323 | /** |
298 | * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format | 324 | * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format |
299 | * @cmd: srp_cmd whose additional_data member will be unmapped | 325 | * @cmd: srp_cmd whose additional_data member will be unmapped |
300 | * @dev: device for which the memory is mapped | 326 | * @dev: device for which the memory is mapped |
301 | * | 327 | * |
302 | */ | 328 | */ |
303 | static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev) | 329 | static void unmap_cmd_data(struct srp_cmd *cmd, |
330 | struct srp_event_struct *evt_struct, | ||
331 | struct device *dev) | ||
304 | { | 332 | { |
305 | int i; | ||
306 | |||
307 | if ((cmd->data_out_format == SRP_NO_BUFFER) && | 333 | if ((cmd->data_out_format == SRP_NO_BUFFER) && |
308 | (cmd->data_in_format == SRP_NO_BUFFER)) | 334 | (cmd->data_in_format == SRP_NO_BUFFER)) |
309 | return; | 335 | return; |
@@ -318,15 +344,34 @@ static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev) | |||
318 | (struct indirect_descriptor *)cmd->additional_data; | 344 | (struct indirect_descriptor *)cmd->additional_data; |
319 | int num_mapped = indirect->head.length / | 345 | int num_mapped = indirect->head.length / |
320 | sizeof(indirect->list[0]); | 346 | sizeof(indirect->list[0]); |
321 | for (i = 0; i < num_mapped; ++i) { | 347 | |
322 | struct memory_descriptor *data = &indirect->list[i]; | 348 | if (num_mapped <= MAX_INDIRECT_BUFS) { |
323 | dma_unmap_single(dev, | 349 | unmap_sg_list(num_mapped, dev, &indirect->list[0]); |
324 | data->virtual_address, | 350 | return; |
325 | data->length, DMA_BIDIRECTIONAL); | ||
326 | } | 351 | } |
352 | |||
353 | unmap_sg_list(num_mapped, dev, evt_struct->ext_list); | ||
327 | } | 354 | } |
328 | } | 355 | } |
329 | 356 | ||
357 | static int map_sg_list(int num_entries, | ||
358 | struct scatterlist *sg, | ||
359 | struct memory_descriptor *md) | ||
360 | { | ||
361 | int i; | ||
362 | u64 total_length = 0; | ||
363 | |||
364 | for (i = 0; i < num_entries; ++i) { | ||
365 | struct memory_descriptor *descr = md + i; | ||
366 | struct scatterlist *sg_entry = &sg[i]; | ||
367 | descr->virtual_address = sg_dma_address(sg_entry); | ||
368 | descr->length = sg_dma_len(sg_entry); | ||
369 | descr->memory_handle = 0; | ||
370 | total_length += sg_dma_len(sg_entry); | ||
371 | } | ||
372 | return total_length; | ||
373 | } | ||
374 | |||
330 | /** | 375 | /** |
331 | * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields | 376 | * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields |
332 | * @cmd: Scsi_Cmnd with the scatterlist | 377 | * @cmd: Scsi_Cmnd with the scatterlist |
@@ -337,10 +382,11 @@ static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev) | |||
337 | * Returns 1 on success. | 382 | * Returns 1 on success. |
338 | */ | 383 | */ |
339 | static int map_sg_data(struct scsi_cmnd *cmd, | 384 | static int map_sg_data(struct scsi_cmnd *cmd, |
385 | struct srp_event_struct *evt_struct, | ||
340 | struct srp_cmd *srp_cmd, struct device *dev) | 386 | struct srp_cmd *srp_cmd, struct device *dev) |
341 | { | 387 | { |
342 | 388 | ||
343 | int i, sg_mapped; | 389 | int sg_mapped; |
344 | u64 total_length = 0; | 390 | u64 total_length = 0; |
345 | struct scatterlist *sg = cmd->request_buffer; | 391 | struct scatterlist *sg = cmd->request_buffer; |
346 | struct memory_descriptor *data = | 392 | struct memory_descriptor *data = |
@@ -363,27 +409,46 @@ static int map_sg_data(struct scsi_cmnd *cmd, | |||
363 | return 1; | 409 | return 1; |
364 | } | 410 | } |
365 | 411 | ||
366 | if (sg_mapped > MAX_INDIRECT_BUFS) { | 412 | if (sg_mapped > SG_ALL) { |
367 | printk(KERN_ERR | 413 | printk(KERN_ERR |
368 | "ibmvscsi: More than %d mapped sg entries, got %d\n", | 414 | "ibmvscsi: More than %d mapped sg entries, got %d\n", |
369 | MAX_INDIRECT_BUFS, sg_mapped); | 415 | SG_ALL, sg_mapped); |
370 | return 0; | 416 | return 0; |
371 | } | 417 | } |
372 | 418 | ||
373 | indirect->head.virtual_address = 0; | 419 | indirect->head.virtual_address = 0; |
374 | indirect->head.length = sg_mapped * sizeof(indirect->list[0]); | 420 | indirect->head.length = sg_mapped * sizeof(indirect->list[0]); |
375 | indirect->head.memory_handle = 0; | 421 | indirect->head.memory_handle = 0; |
376 | for (i = 0; i < sg_mapped; ++i) { | 422 | |
377 | struct memory_descriptor *descr = &indirect->list[i]; | 423 | if (sg_mapped <= MAX_INDIRECT_BUFS) { |
378 | struct scatterlist *sg_entry = &sg[i]; | 424 | total_length = map_sg_list(sg_mapped, sg, &indirect->list[0]); |
379 | descr->virtual_address = sg_dma_address(sg_entry); | 425 | indirect->total_length = total_length; |
380 | descr->length = sg_dma_len(sg_entry); | 426 | return 1; |
381 | descr->memory_handle = 0; | ||
382 | total_length += sg_dma_len(sg_entry); | ||
383 | } | 427 | } |
384 | indirect->total_length = total_length; | ||
385 | 428 | ||
386 | return 1; | 429 | /* get indirect table */ |
430 | if (!evt_struct->ext_list) { | ||
431 | evt_struct->ext_list =(struct memory_descriptor*) | ||
432 | dma_alloc_coherent(dev, | ||
433 | SG_ALL * sizeof(struct memory_descriptor), | ||
434 | &evt_struct->ext_list_token, 0); | ||
435 | if (!evt_struct->ext_list) { | ||
436 | printk(KERN_ERR | ||
437 | "ibmvscsi: Can't allocate memory for indirect table\n"); | ||
438 | return 0; | ||
439 | |||
440 | } | ||
441 | } | ||
442 | |||
443 | total_length = map_sg_list(sg_mapped, sg, evt_struct->ext_list); | ||
444 | |||
445 | indirect->total_length = total_length; | ||
446 | indirect->head.virtual_address = evt_struct->ext_list_token; | ||
447 | indirect->head.length = sg_mapped * sizeof(indirect->list[0]); | ||
448 | memcpy(indirect->list, evt_struct->ext_list, | ||
449 | MAX_INDIRECT_BUFS * sizeof(struct memory_descriptor)); | ||
450 | |||
451 | return 1; | ||
387 | } | 452 | } |
388 | 453 | ||
389 | /** | 454 | /** |
@@ -428,6 +493,7 @@ static int map_single_data(struct scsi_cmnd *cmd, | |||
428 | * Returns 1 on success. | 493 | * Returns 1 on success. |
429 | */ | 494 | */ |
430 | static int map_data_for_srp_cmd(struct scsi_cmnd *cmd, | 495 | static int map_data_for_srp_cmd(struct scsi_cmnd *cmd, |
496 | struct srp_event_struct *evt_struct, | ||
431 | struct srp_cmd *srp_cmd, struct device *dev) | 497 | struct srp_cmd *srp_cmd, struct device *dev) |
432 | { | 498 | { |
433 | switch (cmd->sc_data_direction) { | 499 | switch (cmd->sc_data_direction) { |
@@ -450,7 +516,7 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd, | |||
450 | if (!cmd->request_buffer) | 516 | if (!cmd->request_buffer) |
451 | return 1; | 517 | return 1; |
452 | if (cmd->use_sg) | 518 | if (cmd->use_sg) |
453 | return map_sg_data(cmd, srp_cmd, dev); | 519 | return map_sg_data(cmd, evt_struct, srp_cmd, dev); |
454 | return map_single_data(cmd, srp_cmd, dev); | 520 | return map_single_data(cmd, srp_cmd, dev); |
455 | } | 521 | } |
456 | 522 | ||
@@ -486,6 +552,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, | |||
486 | printk(KERN_WARNING | 552 | printk(KERN_WARNING |
487 | "ibmvscsi: Warning, request_limit exceeded\n"); | 553 | "ibmvscsi: Warning, request_limit exceeded\n"); |
488 | unmap_cmd_data(&evt_struct->iu.srp.cmd, | 554 | unmap_cmd_data(&evt_struct->iu.srp.cmd, |
555 | evt_struct, | ||
489 | hostdata->dev); | 556 | hostdata->dev); |
490 | free_event_struct(&hostdata->pool, evt_struct); | 557 | free_event_struct(&hostdata->pool, evt_struct); |
491 | return SCSI_MLQUEUE_HOST_BUSY; | 558 | return SCSI_MLQUEUE_HOST_BUSY; |
@@ -513,7 +580,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, | |||
513 | return 0; | 580 | return 0; |
514 | 581 | ||
515 | send_error: | 582 | send_error: |
516 | unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev); | 583 | unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); |
517 | 584 | ||
518 | if ((cmnd = evt_struct->cmnd) != NULL) { | 585 | if ((cmnd = evt_struct->cmnd) != NULL) { |
519 | cmnd->result = DID_ERROR << 16; | 586 | cmnd->result = DID_ERROR << 16; |
@@ -551,6 +618,7 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct) | |||
551 | rsp->sense_and_response_data, | 618 | rsp->sense_and_response_data, |
552 | rsp->sense_data_list_length); | 619 | rsp->sense_data_list_length); |
553 | unmap_cmd_data(&evt_struct->iu.srp.cmd, | 620 | unmap_cmd_data(&evt_struct->iu.srp.cmd, |
621 | evt_struct, | ||
554 | evt_struct->hostdata->dev); | 622 | evt_struct->hostdata->dev); |
555 | 623 | ||
556 | if (rsp->doover) | 624 | if (rsp->doover) |
@@ -583,6 +651,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
583 | { | 651 | { |
584 | struct srp_cmd *srp_cmd; | 652 | struct srp_cmd *srp_cmd; |
585 | struct srp_event_struct *evt_struct; | 653 | struct srp_event_struct *evt_struct; |
654 | struct indirect_descriptor *indirect; | ||
586 | struct ibmvscsi_host_data *hostdata = | 655 | struct ibmvscsi_host_data *hostdata = |
587 | (struct ibmvscsi_host_data *)&cmnd->device->host->hostdata; | 656 | (struct ibmvscsi_host_data *)&cmnd->device->host->hostdata; |
588 | u16 lun = lun_from_dev(cmnd->device); | 657 | u16 lun = lun_from_dev(cmnd->device); |
@@ -591,14 +660,6 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
591 | if (!evt_struct) | 660 | if (!evt_struct) |
592 | return SCSI_MLQUEUE_HOST_BUSY; | 661 | return SCSI_MLQUEUE_HOST_BUSY; |
593 | 662 | ||
594 | init_event_struct(evt_struct, | ||
595 | handle_cmd_rsp, | ||
596 | VIOSRP_SRP_FORMAT, | ||
597 | cmnd->timeout_per_command/HZ); | ||
598 | |||
599 | evt_struct->cmnd = cmnd; | ||
600 | evt_struct->cmnd_done = done; | ||
601 | |||
602 | /* Set up the actual SRP IU */ | 663 | /* Set up the actual SRP IU */ |
603 | srp_cmd = &evt_struct->iu.srp.cmd; | 664 | srp_cmd = &evt_struct->iu.srp.cmd; |
604 | memset(srp_cmd, 0x00, sizeof(*srp_cmd)); | 665 | memset(srp_cmd, 0x00, sizeof(*srp_cmd)); |
@@ -606,17 +667,25 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
606 | memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd)); | 667 | memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd)); |
607 | srp_cmd->lun = ((u64) lun) << 48; | 668 | srp_cmd->lun = ((u64) lun) << 48; |
608 | 669 | ||
609 | if (!map_data_for_srp_cmd(cmnd, srp_cmd, hostdata->dev)) { | 670 | if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { |
610 | printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n"); | 671 | printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n"); |
611 | free_event_struct(&hostdata->pool, evt_struct); | 672 | free_event_struct(&hostdata->pool, evt_struct); |
612 | return SCSI_MLQUEUE_HOST_BUSY; | 673 | return SCSI_MLQUEUE_HOST_BUSY; |
613 | } | 674 | } |
614 | 675 | ||
676 | init_event_struct(evt_struct, | ||
677 | handle_cmd_rsp, | ||
678 | VIOSRP_SRP_FORMAT, | ||
679 | cmnd->timeout_per_command/HZ); | ||
680 | |||
681 | evt_struct->cmnd = cmnd; | ||
682 | evt_struct->cmnd_done = done; | ||
683 | |||
615 | /* Fix up dma address of the buffer itself */ | 684 | /* Fix up dma address of the buffer itself */ |
616 | if ((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) || | 685 | indirect = (struct indirect_descriptor *)srp_cmd->additional_data; |
617 | (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) { | 686 | if (((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) || |
618 | struct indirect_descriptor *indirect = | 687 | (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) && |
619 | (struct indirect_descriptor *)srp_cmd->additional_data; | 688 | (indirect->head.virtual_address == 0)) { |
620 | indirect->head.virtual_address = evt_struct->crq.IU_data_ptr + | 689 | indirect->head.virtual_address = evt_struct->crq.IU_data_ptr + |
621 | offsetof(struct srp_cmd, additional_data) + | 690 | offsetof(struct srp_cmd, additional_data) + |
622 | offsetof(struct indirect_descriptor, list); | 691 | offsetof(struct indirect_descriptor, list); |
@@ -931,7 +1000,8 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
931 | 1000 | ||
932 | cmd->result = (DID_ABORT << 16); | 1001 | cmd->result = (DID_ABORT << 16); |
933 | list_del(&found_evt->list); | 1002 | list_del(&found_evt->list); |
934 | unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev); | 1003 | unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt, |
1004 | found_evt->hostdata->dev); | ||
935 | free_event_struct(&found_evt->hostdata->pool, found_evt); | 1005 | free_event_struct(&found_evt->hostdata->pool, found_evt); |
936 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | 1006 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); |
937 | atomic_inc(&hostdata->request_limit); | 1007 | atomic_inc(&hostdata->request_limit); |
@@ -1023,7 +1093,8 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
1023 | if (tmp_evt->cmnd) | 1093 | if (tmp_evt->cmnd) |
1024 | tmp_evt->cmnd->result = (DID_RESET << 16); | 1094 | tmp_evt->cmnd->result = (DID_RESET << 16); |
1025 | list_del(&tmp_evt->list); | 1095 | list_del(&tmp_evt->list); |
1026 | unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt->hostdata->dev); | 1096 | unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt, |
1097 | tmp_evt->hostdata->dev); | ||
1027 | free_event_struct(&tmp_evt->hostdata->pool, | 1098 | free_event_struct(&tmp_evt->hostdata->pool, |
1028 | tmp_evt); | 1099 | tmp_evt); |
1029 | atomic_inc(&hostdata->request_limit); | 1100 | atomic_inc(&hostdata->request_limit); |
@@ -1052,6 +1123,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata) | |||
1052 | if (tmp_evt->cmnd) { | 1123 | if (tmp_evt->cmnd) { |
1053 | tmp_evt->cmnd->result = (DID_ERROR << 16); | 1124 | tmp_evt->cmnd->result = (DID_ERROR << 16); |
1054 | unmap_cmd_data(&tmp_evt->iu.srp.cmd, | 1125 | unmap_cmd_data(&tmp_evt->iu.srp.cmd, |
1126 | tmp_evt, | ||
1055 | tmp_evt->hostdata->dev); | 1127 | tmp_evt->hostdata->dev); |
1056 | if (tmp_evt->cmnd_done) | 1128 | if (tmp_evt->cmnd_done) |
1057 | tmp_evt->cmnd_done(tmp_evt->cmnd); | 1129 | tmp_evt->cmnd_done(tmp_evt->cmnd); |
@@ -1356,7 +1428,7 @@ static struct scsi_host_template driver_template = { | |||
1356 | .cmd_per_lun = 16, | 1428 | .cmd_per_lun = 16, |
1357 | .can_queue = 1, /* Updated after SRP_LOGIN */ | 1429 | .can_queue = 1, /* Updated after SRP_LOGIN */ |
1358 | .this_id = -1, | 1430 | .this_id = -1, |
1359 | .sg_tablesize = MAX_INDIRECT_BUFS, | 1431 | .sg_tablesize = SG_ALL, |
1360 | .use_clustering = ENABLE_CLUSTERING, | 1432 | .use_clustering = ENABLE_CLUSTERING, |
1361 | .shost_attrs = ibmvscsi_attrs, | 1433 | .shost_attrs = ibmvscsi_attrs, |
1362 | }; | 1434 | }; |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index 1030b703c30e..8bec0438dc8a 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h | |||
@@ -68,6 +68,8 @@ struct srp_event_struct { | |||
68 | void (*cmnd_done) (struct scsi_cmnd *); | 68 | void (*cmnd_done) (struct scsi_cmnd *); |
69 | struct completion comp; | 69 | struct completion comp; |
70 | union viosrp_iu *sync_srp; | 70 | union viosrp_iu *sync_srp; |
71 | struct memory_descriptor *ext_list; | ||
72 | dma_addr_t ext_list_token; | ||
71 | }; | 73 | }; |
72 | 74 | ||
73 | /* a pool of event structs for use */ | 75 | /* a pool of event structs for use */ |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 659a5d63467d..fe0fce71adc7 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -211,6 +211,138 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) | |||
211 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); | 211 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); |
212 | } | 212 | } |
213 | 213 | ||
214 | /* Scsi_Host attributes. */ | ||
215 | |||
216 | static ssize_t | ||
217 | qla2x00_drvr_version_show(struct class_device *cdev, char *buf) | ||
218 | { | ||
219 | return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str); | ||
220 | } | ||
221 | |||
222 | static ssize_t | ||
223 | qla2x00_fw_version_show(struct class_device *cdev, char *buf) | ||
224 | { | ||
225 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
226 | char fw_str[30]; | ||
227 | |||
228 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
229 | ha->isp_ops.fw_version_str(ha, fw_str)); | ||
230 | } | ||
231 | |||
232 | static ssize_t | ||
233 | qla2x00_serial_num_show(struct class_device *cdev, char *buf) | ||
234 | { | ||
235 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
236 | uint32_t sn; | ||
237 | |||
238 | sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; | ||
239 | return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000, | ||
240 | sn % 100000); | ||
241 | } | ||
242 | |||
243 | static ssize_t | ||
244 | qla2x00_isp_name_show(struct class_device *cdev, char *buf) | ||
245 | { | ||
246 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
247 | return snprintf(buf, PAGE_SIZE, "%s\n", ha->brd_info->isp_name); | ||
248 | } | ||
249 | |||
250 | static ssize_t | ||
251 | qla2x00_isp_id_show(struct class_device *cdev, char *buf) | ||
252 | { | ||
253 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
254 | return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", | ||
255 | ha->product_id[0], ha->product_id[1], ha->product_id[2], | ||
256 | ha->product_id[3]); | ||
257 | } | ||
258 | |||
259 | static ssize_t | ||
260 | qla2x00_model_name_show(struct class_device *cdev, char *buf) | ||
261 | { | ||
262 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
263 | return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number); | ||
264 | } | ||
265 | |||
266 | static ssize_t | ||
267 | qla2x00_model_desc_show(struct class_device *cdev, char *buf) | ||
268 | { | ||
269 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
270 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
271 | ha->model_desc ? ha->model_desc: ""); | ||
272 | } | ||
273 | |||
274 | static ssize_t | ||
275 | qla2x00_pci_info_show(struct class_device *cdev, char *buf) | ||
276 | { | ||
277 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
278 | char pci_info[30]; | ||
279 | |||
280 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
281 | ha->isp_ops.pci_info_str(ha, pci_info)); | ||
282 | } | ||
283 | |||
284 | static ssize_t | ||
285 | qla2x00_state_show(struct class_device *cdev, char *buf) | ||
286 | { | ||
287 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
288 | int len = 0; | ||
289 | |||
290 | if (atomic_read(&ha->loop_state) == LOOP_DOWN || | ||
291 | atomic_read(&ha->loop_state) == LOOP_DEAD) | ||
292 | len = snprintf(buf, PAGE_SIZE, "Link Down\n"); | ||
293 | else if (atomic_read(&ha->loop_state) != LOOP_READY || | ||
294 | test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || | ||
295 | test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) | ||
296 | len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n"); | ||
297 | else { | ||
298 | len = snprintf(buf, PAGE_SIZE, "Link Up - "); | ||
299 | |||
300 | switch (ha->current_topology) { | ||
301 | case ISP_CFG_NL: | ||
302 | len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n"); | ||
303 | break; | ||
304 | case ISP_CFG_FL: | ||
305 | len += snprintf(buf + len, PAGE_SIZE-len, "FL_Port\n"); | ||
306 | break; | ||
307 | case ISP_CFG_N: | ||
308 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
309 | "N_Port to N_Port\n"); | ||
310 | break; | ||
311 | case ISP_CFG_F: | ||
312 | len += snprintf(buf + len, PAGE_SIZE-len, "F_Port\n"); | ||
313 | break; | ||
314 | default: | ||
315 | len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n"); | ||
316 | break; | ||
317 | } | ||
318 | } | ||
319 | return len; | ||
320 | } | ||
321 | |||
322 | static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, | ||
323 | NULL); | ||
324 | static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); | ||
325 | static CLASS_DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); | ||
326 | static CLASS_DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL); | ||
327 | static CLASS_DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL); | ||
328 | static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL); | ||
329 | static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL); | ||
330 | static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL); | ||
331 | static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL); | ||
332 | |||
333 | struct class_device_attribute *qla2x00_host_attrs[] = { | ||
334 | &class_device_attr_driver_version, | ||
335 | &class_device_attr_fw_version, | ||
336 | &class_device_attr_serial_num, | ||
337 | &class_device_attr_isp_name, | ||
338 | &class_device_attr_isp_id, | ||
339 | &class_device_attr_model_name, | ||
340 | &class_device_attr_model_desc, | ||
341 | &class_device_attr_pci_info, | ||
342 | &class_device_attr_state, | ||
343 | NULL, | ||
344 | }; | ||
345 | |||
214 | /* Host attributes. */ | 346 | /* Host attributes. */ |
215 | 347 | ||
216 | static void | 348 | static void |
@@ -304,10 +436,13 @@ struct fc_function_template qla2xxx_transport_functions = { | |||
304 | 436 | ||
305 | .show_host_node_name = 1, | 437 | .show_host_node_name = 1, |
306 | .show_host_port_name = 1, | 438 | .show_host_port_name = 1, |
439 | .show_host_supported_classes = 1, | ||
440 | |||
307 | .get_host_port_id = qla2x00_get_host_port_id, | 441 | .get_host_port_id = qla2x00_get_host_port_id, |
308 | .show_host_port_id = 1, | 442 | .show_host_port_id = 1, |
309 | 443 | ||
310 | .dd_fcrport_size = sizeof(struct fc_port *), | 444 | .dd_fcrport_size = sizeof(struct fc_port *), |
445 | .show_rport_supported_classes = 1, | ||
311 | 446 | ||
312 | .get_starget_node_name = qla2x00_get_starget_node_name, | 447 | .get_starget_node_name = qla2x00_get_starget_node_name, |
313 | .show_starget_node_name = 1, | 448 | .show_starget_node_name = 1, |
@@ -329,4 +464,5 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha) | |||
329 | be64_to_cpu(*(uint64_t *)ha->init_cb->node_name); | 464 | be64_to_cpu(*(uint64_t *)ha->init_cb->node_name); |
330 | fc_host_port_name(ha->host) = | 465 | fc_host_port_name(ha->host) = |
331 | be64_to_cpu(*(uint64_t *)ha->init_cb->port_name); | 466 | be64_to_cpu(*(uint64_t *)ha->init_cb->port_name); |
467 | fc_host_supported_classes(ha->host) = FC_COS_CLASS3; | ||
332 | } | 468 | } |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index b8d90e97e017..9684e7a91fa9 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
@@ -81,6 +81,7 @@ | |||
81 | #define DEBUG2_3_11(x) do {x;} while (0); | 81 | #define DEBUG2_3_11(x) do {x;} while (0); |
82 | #define DEBUG2_9_10(x) do {x;} while (0); | 82 | #define DEBUG2_9_10(x) do {x;} while (0); |
83 | #define DEBUG2_11(x) do {x;} while (0); | 83 | #define DEBUG2_11(x) do {x;} while (0); |
84 | #define DEBUG2_13(x) do {x;} while (0); | ||
84 | #else | 85 | #else |
85 | #define DEBUG2(x) do {} while (0); | 86 | #define DEBUG2(x) do {} while (0); |
86 | #endif | 87 | #endif |
@@ -169,8 +170,14 @@ | |||
169 | 170 | ||
170 | #if defined(QL_DEBUG_LEVEL_13) | 171 | #if defined(QL_DEBUG_LEVEL_13) |
171 | #define DEBUG13(x) do {x;} while (0) | 172 | #define DEBUG13(x) do {x;} while (0) |
173 | #if !defined(DEBUG2_13) | ||
174 | #define DEBUG2_13(x) do {x;} while(0) | ||
175 | #endif | ||
172 | #else | 176 | #else |
173 | #define DEBUG13(x) do {} while (0) | 177 | #define DEBUG13(x) do {} while (0) |
178 | #if !defined(QL_DEBUG_LEVEL_2) | ||
179 | #define DEBUG2_13(x) do {} while(0) | ||
180 | #endif | ||
174 | #endif | 181 | #endif |
175 | 182 | ||
176 | #if defined(QL_DEBUG_LEVEL_14) | 183 | #if defined(QL_DEBUG_LEVEL_14) |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 1c6d366f4fad..b455c31405e4 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -214,6 +214,7 @@ | |||
214 | * valid range of an N-PORT id is 0 through 0x7ef. | 214 | * valid range of an N-PORT id is 0 through 0x7ef. |
215 | */ | 215 | */ |
216 | #define NPH_LAST_HANDLE 0x7ef | 216 | #define NPH_LAST_HANDLE 0x7ef |
217 | #define NPH_MGMT_SERVER 0x7fa /* FFFFFA */ | ||
217 | #define NPH_SNS 0x7fc /* FFFFFC */ | 218 | #define NPH_SNS 0x7fc /* FFFFFC */ |
218 | #define NPH_FABRIC_CONTROLLER 0x7fd /* FFFFFD */ | 219 | #define NPH_FABRIC_CONTROLLER 0x7fd /* FFFFFD */ |
219 | #define NPH_F_PORT 0x7fe /* FFFFFE */ | 220 | #define NPH_F_PORT 0x7fe /* FFFFFE */ |
@@ -630,6 +631,7 @@ typedef struct { | |||
630 | #define MBC_WRITE_RAM_WORD_EXTENDED 0xd /* Write RAM word extended */ | 631 | #define MBC_WRITE_RAM_WORD_EXTENDED 0xd /* Write RAM word extended */ |
631 | #define MBC_READ_RAM_EXTENDED 0xf /* Read RAM extended. */ | 632 | #define MBC_READ_RAM_EXTENDED 0xf /* Read RAM extended. */ |
632 | #define MBC_IOCB_COMMAND 0x12 /* Execute IOCB command. */ | 633 | #define MBC_IOCB_COMMAND 0x12 /* Execute IOCB command. */ |
634 | #define MBC_STOP_FIRMWARE 0x14 /* Stop firmware. */ | ||
633 | #define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */ | 635 | #define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */ |
634 | #define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */ | 636 | #define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */ |
635 | #define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */ | 637 | #define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */ |
@@ -913,7 +915,7 @@ typedef struct { | |||
913 | * MSB BIT 1 = | 915 | * MSB BIT 1 = |
914 | * MSB BIT 2 = | 916 | * MSB BIT 2 = |
915 | * MSB BIT 3 = | 917 | * MSB BIT 3 = |
916 | * MSB BIT 4 = | 918 | * MSB BIT 4 = LED mode |
917 | * MSB BIT 5 = enable 50 ohm termination | 919 | * MSB BIT 5 = enable 50 ohm termination |
918 | * MSB BIT 6 = Data Rate (2300 only) | 920 | * MSB BIT 6 = Data Rate (2300 only) |
919 | * MSB BIT 7 = Data Rate (2300 only) | 921 | * MSB BIT 7 = Data Rate (2300 only) |
@@ -1035,7 +1037,7 @@ typedef struct { | |||
1035 | * MSB BIT 1 = | 1037 | * MSB BIT 1 = |
1036 | * MSB BIT 2 = | 1038 | * MSB BIT 2 = |
1037 | * MSB BIT 3 = | 1039 | * MSB BIT 3 = |
1038 | * MSB BIT 4 = | 1040 | * MSB BIT 4 = LED mode |
1039 | * MSB BIT 5 = enable 50 ohm termination | 1041 | * MSB BIT 5 = enable 50 ohm termination |
1040 | * MSB BIT 6 = Data Rate (2300 only) | 1042 | * MSB BIT 6 = Data Rate (2300 only) |
1041 | * MSB BIT 7 = Data Rate (2300 only) | 1043 | * MSB BIT 7 = Data Rate (2300 only) |
@@ -1131,10 +1133,7 @@ typedef struct { | |||
1131 | 1133 | ||
1132 | uint8_t link_down_timeout; | 1134 | uint8_t link_down_timeout; |
1133 | 1135 | ||
1134 | uint8_t adapter_id_0[4]; | 1136 | uint8_t adapter_id[16]; |
1135 | uint8_t adapter_id_1[4]; | ||
1136 | uint8_t adapter_id_2[4]; | ||
1137 | uint8_t adapter_id_3[4]; | ||
1138 | 1137 | ||
1139 | uint8_t alt1_boot_node_name[WWN_SIZE]; | 1138 | uint8_t alt1_boot_node_name[WWN_SIZE]; |
1140 | uint16_t alt1_boot_lun_number; | 1139 | uint16_t alt1_boot_lun_number; |
@@ -1673,6 +1672,7 @@ typedef struct fc_port { | |||
1673 | uint8_t cur_path; /* current path id */ | 1672 | uint8_t cur_path; /* current path id */ |
1674 | 1673 | ||
1675 | struct fc_rport *rport; | 1674 | struct fc_rport *rport; |
1675 | u32 supported_classes; | ||
1676 | } fc_port_t; | 1676 | } fc_port_t; |
1677 | 1677 | ||
1678 | /* | 1678 | /* |
@@ -1727,6 +1727,8 @@ typedef struct fc_port { | |||
1727 | 1727 | ||
1728 | #define CT_REJECT_RESPONSE 0x8001 | 1728 | #define CT_REJECT_RESPONSE 0x8001 |
1729 | #define CT_ACCEPT_RESPONSE 0x8002 | 1729 | #define CT_ACCEPT_RESPONSE 0x8002 |
1730 | #define CT_REASON_CANNOT_PERFORM 0x09 | ||
1731 | #define CT_EXPL_ALREADY_REGISTERED 0x10 | ||
1730 | 1732 | ||
1731 | #define NS_N_PORT_TYPE 0x01 | 1733 | #define NS_N_PORT_TYPE 0x01 |
1732 | #define NS_NL_PORT_TYPE 0x02 | 1734 | #define NS_NL_PORT_TYPE 0x02 |
@@ -1768,6 +1770,100 @@ typedef struct fc_port { | |||
1768 | #define RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255) | 1770 | #define RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255) |
1769 | #define RSNN_NN_RSP_SIZE 16 | 1771 | #define RSNN_NN_RSP_SIZE 16 |
1770 | 1772 | ||
1773 | /* | ||
1774 | * HBA attribute types. | ||
1775 | */ | ||
1776 | #define FDMI_HBA_ATTR_COUNT 9 | ||
1777 | #define FDMI_HBA_NODE_NAME 1 | ||
1778 | #define FDMI_HBA_MANUFACTURER 2 | ||
1779 | #define FDMI_HBA_SERIAL_NUMBER 3 | ||
1780 | #define FDMI_HBA_MODEL 4 | ||
1781 | #define FDMI_HBA_MODEL_DESCRIPTION 5 | ||
1782 | #define FDMI_HBA_HARDWARE_VERSION 6 | ||
1783 | #define FDMI_HBA_DRIVER_VERSION 7 | ||
1784 | #define FDMI_HBA_OPTION_ROM_VERSION 8 | ||
1785 | #define FDMI_HBA_FIRMWARE_VERSION 9 | ||
1786 | #define FDMI_HBA_OS_NAME_AND_VERSION 0xa | ||
1787 | #define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH 0xb | ||
1788 | |||
1789 | struct ct_fdmi_hba_attr { | ||
1790 | uint16_t type; | ||
1791 | uint16_t len; | ||
1792 | union { | ||
1793 | uint8_t node_name[WWN_SIZE]; | ||
1794 | uint8_t manufacturer[32]; | ||
1795 | uint8_t serial_num[8]; | ||
1796 | uint8_t model[16]; | ||
1797 | uint8_t model_desc[80]; | ||
1798 | uint8_t hw_version[16]; | ||
1799 | uint8_t driver_version[32]; | ||
1800 | uint8_t orom_version[16]; | ||
1801 | uint8_t fw_version[16]; | ||
1802 | uint8_t os_version[128]; | ||
1803 | uint8_t max_ct_len[4]; | ||
1804 | } a; | ||
1805 | }; | ||
1806 | |||
1807 | struct ct_fdmi_hba_attributes { | ||
1808 | uint32_t count; | ||
1809 | struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT]; | ||
1810 | }; | ||
1811 | |||
1812 | /* | ||
1813 | * Port attribute types. | ||
1814 | */ | ||
1815 | #define FDMI_PORT_ATTR_COUNT 5 | ||
1816 | #define FDMI_PORT_FC4_TYPES 1 | ||
1817 | #define FDMI_PORT_SUPPORT_SPEED 2 | ||
1818 | #define FDMI_PORT_CURRENT_SPEED 3 | ||
1819 | #define FDMI_PORT_MAX_FRAME_SIZE 4 | ||
1820 | #define FDMI_PORT_OS_DEVICE_NAME 5 | ||
1821 | #define FDMI_PORT_HOST_NAME 6 | ||
1822 | |||
1823 | struct ct_fdmi_port_attr { | ||
1824 | uint16_t type; | ||
1825 | uint16_t len; | ||
1826 | union { | ||
1827 | uint8_t fc4_types[32]; | ||
1828 | uint32_t sup_speed; | ||
1829 | uint32_t cur_speed; | ||
1830 | uint32_t max_frame_size; | ||
1831 | uint8_t os_dev_name[32]; | ||
1832 | uint8_t host_name[32]; | ||
1833 | } a; | ||
1834 | }; | ||
1835 | |||
1836 | /* | ||
1837 | * Port Attribute Block. | ||
1838 | */ | ||
1839 | struct ct_fdmi_port_attributes { | ||
1840 | uint32_t count; | ||
1841 | struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT]; | ||
1842 | }; | ||
1843 | |||
1844 | /* FDMI definitions. */ | ||
1845 | #define GRHL_CMD 0x100 | ||
1846 | #define GHAT_CMD 0x101 | ||
1847 | #define GRPL_CMD 0x102 | ||
1848 | #define GPAT_CMD 0x110 | ||
1849 | |||
1850 | #define RHBA_CMD 0x200 | ||
1851 | #define RHBA_RSP_SIZE 16 | ||
1852 | |||
1853 | #define RHAT_CMD 0x201 | ||
1854 | #define RPRT_CMD 0x210 | ||
1855 | |||
1856 | #define RPA_CMD 0x211 | ||
1857 | #define RPA_RSP_SIZE 16 | ||
1858 | |||
1859 | #define DHBA_CMD 0x300 | ||
1860 | #define DHBA_REQ_SIZE (16 + 8) | ||
1861 | #define DHBA_RSP_SIZE 16 | ||
1862 | |||
1863 | #define DHAT_CMD 0x301 | ||
1864 | #define DPRT_CMD 0x310 | ||
1865 | #define DPA_CMD 0x311 | ||
1866 | |||
1771 | /* CT command header -- request/response common fields */ | 1867 | /* CT command header -- request/response common fields */ |
1772 | struct ct_cmd_hdr { | 1868 | struct ct_cmd_hdr { |
1773 | uint8_t revision; | 1869 | uint8_t revision; |
@@ -1825,6 +1921,43 @@ struct ct_sns_req { | |||
1825 | uint8_t name_len; | 1921 | uint8_t name_len; |
1826 | uint8_t sym_node_name[255]; | 1922 | uint8_t sym_node_name[255]; |
1827 | } rsnn_nn; | 1923 | } rsnn_nn; |
1924 | |||
1925 | struct { | ||
1926 | uint8_t hba_indentifier[8]; | ||
1927 | } ghat; | ||
1928 | |||
1929 | struct { | ||
1930 | uint8_t hba_identifier[8]; | ||
1931 | uint32_t entry_count; | ||
1932 | uint8_t port_name[8]; | ||
1933 | struct ct_fdmi_hba_attributes attrs; | ||
1934 | } rhba; | ||
1935 | |||
1936 | struct { | ||
1937 | uint8_t hba_identifier[8]; | ||
1938 | struct ct_fdmi_hba_attributes attrs; | ||
1939 | } rhat; | ||
1940 | |||
1941 | struct { | ||
1942 | uint8_t port_name[8]; | ||
1943 | struct ct_fdmi_port_attributes attrs; | ||
1944 | } rpa; | ||
1945 | |||
1946 | struct { | ||
1947 | uint8_t port_name[8]; | ||
1948 | } dhba; | ||
1949 | |||
1950 | struct { | ||
1951 | uint8_t port_name[8]; | ||
1952 | } dhat; | ||
1953 | |||
1954 | struct { | ||
1955 | uint8_t port_name[8]; | ||
1956 | } dprt; | ||
1957 | |||
1958 | struct { | ||
1959 | uint8_t port_name[8]; | ||
1960 | } dpa; | ||
1828 | } req; | 1961 | } req; |
1829 | }; | 1962 | }; |
1830 | 1963 | ||
@@ -1882,6 +2015,12 @@ struct ct_sns_rsp { | |||
1882 | struct { | 2015 | struct { |
1883 | uint8_t fc4_types[32]; | 2016 | uint8_t fc4_types[32]; |
1884 | } gft_id; | 2017 | } gft_id; |
2018 | |||
2019 | struct { | ||
2020 | uint32_t entry_count; | ||
2021 | uint8_t port_name[8]; | ||
2022 | struct ct_fdmi_hba_attributes attrs; | ||
2023 | } ghat; | ||
1885 | } rsp; | 2024 | } rsp; |
1886 | }; | 2025 | }; |
1887 | 2026 | ||
@@ -2032,6 +2171,8 @@ struct isp_operations { | |||
2032 | uint16_t (*calc_req_entries) (uint16_t); | 2171 | uint16_t (*calc_req_entries) (uint16_t); |
2033 | void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t); | 2172 | void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t); |
2034 | void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t); | 2173 | void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t); |
2174 | void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t, | ||
2175 | uint32_t); | ||
2035 | 2176 | ||
2036 | uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *, | 2177 | uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *, |
2037 | uint32_t, uint32_t); | 2178 | uint32_t, uint32_t); |
@@ -2111,6 +2252,7 @@ typedef struct scsi_qla_host { | |||
2111 | #define IOCTL_ERROR_RECOVERY 23 | 2252 | #define IOCTL_ERROR_RECOVERY 23 |
2112 | #define LOOP_RESET_NEEDED 24 | 2253 | #define LOOP_RESET_NEEDED 24 |
2113 | #define BEACON_BLINK_NEEDED 25 | 2254 | #define BEACON_BLINK_NEEDED 25 |
2255 | #define REGISTER_FDMI_NEEDED 26 | ||
2114 | 2256 | ||
2115 | uint32_t device_flags; | 2257 | uint32_t device_flags; |
2116 | #define DFLG_LOCAL_DEVICES BIT_0 | 2258 | #define DFLG_LOCAL_DEVICES BIT_0 |
@@ -2204,6 +2346,7 @@ typedef struct scsi_qla_host { | |||
2204 | int port_down_retry_count; | 2346 | int port_down_retry_count; |
2205 | uint8_t mbx_count; | 2347 | uint8_t mbx_count; |
2206 | uint16_t last_loop_id; | 2348 | uint16_t last_loop_id; |
2349 | uint16_t mgmt_svr_loop_id; | ||
2207 | 2350 | ||
2208 | uint32_t login_retry_count; | 2351 | uint32_t login_retry_count; |
2209 | 2352 | ||
@@ -2318,6 +2461,7 @@ typedef struct scsi_qla_host { | |||
2318 | uint8_t model_number[16+1]; | 2461 | uint8_t model_number[16+1]; |
2319 | #define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 2462 | #define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
2320 | char *model_desc; | 2463 | char *model_desc; |
2464 | uint8_t adapter_id[16+1]; | ||
2321 | 2465 | ||
2322 | uint8_t *node_name; | 2466 | uint8_t *node_name; |
2323 | uint8_t *port_name; | 2467 | uint8_t *port_name; |
@@ -2377,6 +2521,7 @@ typedef struct scsi_qla_host { | |||
2377 | #define QLA_SUSPENDED 0x106 | 2521 | #define QLA_SUSPENDED 0x106 |
2378 | #define QLA_BUSY 0x107 | 2522 | #define QLA_BUSY 0x107 |
2379 | #define QLA_RSCNS_HANDLED 0x108 | 2523 | #define QLA_RSCNS_HANDLED 0x108 |
2524 | #define QLA_ALREADY_REGISTERED 0x109 | ||
2380 | 2525 | ||
2381 | /* | 2526 | /* |
2382 | * Stat info for all adpaters | 2527 | * Stat info for all adpaters |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 665c203e0675..1ed32e7b5472 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -79,6 +79,7 @@ extern int ql2xplogiabsentdevice; | |||
79 | extern int ql2xenablezio; | 79 | extern int ql2xenablezio; |
80 | extern int ql2xintrdelaytimer; | 80 | extern int ql2xintrdelaytimer; |
81 | extern int ql2xloginretrycount; | 81 | extern int ql2xloginretrycount; |
82 | extern int ql2xfdmienable; | ||
82 | 83 | ||
83 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); | 84 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); |
84 | 85 | ||
@@ -147,9 +148,6 @@ qla2x00_abort_target(fc_port_t *); | |||
147 | #endif | 148 | #endif |
148 | 149 | ||
149 | extern int | 150 | extern int |
150 | qla2x00_target_reset(scsi_qla_host_t *, struct fc_port *); | ||
151 | |||
152 | extern int | ||
153 | qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, | 151 | qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, |
154 | uint8_t *, uint16_t *); | 152 | uint8_t *, uint16_t *); |
155 | 153 | ||
@@ -215,6 +213,9 @@ qla2x00_get_serdes_params(scsi_qla_host_t *, uint16_t *, uint16_t *, | |||
215 | extern int | 213 | extern int |
216 | qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); | 214 | qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); |
217 | 215 | ||
216 | extern int | ||
217 | qla2x00_stop_firmware(scsi_qla_host_t *); | ||
218 | |||
218 | /* | 219 | /* |
219 | * Global Function Prototypes in qla_isr.c source file. | 220 | * Global Function Prototypes in qla_isr.c source file. |
220 | */ | 221 | */ |
@@ -269,6 +270,9 @@ extern int qla2x00_rft_id(scsi_qla_host_t *); | |||
269 | extern int qla2x00_rff_id(scsi_qla_host_t *); | 270 | extern int qla2x00_rff_id(scsi_qla_host_t *); |
270 | extern int qla2x00_rnn_id(scsi_qla_host_t *); | 271 | extern int qla2x00_rnn_id(scsi_qla_host_t *); |
271 | extern int qla2x00_rsnn_nn(scsi_qla_host_t *); | 272 | extern int qla2x00_rsnn_nn(scsi_qla_host_t *); |
273 | extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); | ||
274 | extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); | ||
275 | extern int qla2x00_fdmi_register(scsi_qla_host_t *); | ||
272 | 276 | ||
273 | /* | 277 | /* |
274 | * Global Function Prototypes in qla_rscn.c source file. | 278 | * Global Function Prototypes in qla_rscn.c source file. |
@@ -289,6 +293,8 @@ extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *); | |||
289 | /* | 293 | /* |
290 | * Global Function Prototypes in qla_attr.c source file. | 294 | * Global Function Prototypes in qla_attr.c source file. |
291 | */ | 295 | */ |
296 | struct class_device_attribute; | ||
297 | extern struct class_device_attribute *qla2x00_host_attrs[]; | ||
292 | struct fc_function_template; | 298 | struct fc_function_template; |
293 | extern struct fc_function_template qla2xxx_transport_functions; | 299 | extern struct fc_function_template qla2xxx_transport_functions; |
294 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); | 300 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); |
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 31ce4f62da13..e7b138c2e339 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c | |||
@@ -1099,3 +1099,567 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *ha) | |||
1099 | 1099 | ||
1100 | return (rval); | 1100 | return (rval); |
1101 | } | 1101 | } |
1102 | |||
1103 | /** | ||
1104 | * qla2x00_mgmt_svr_login() - Login to fabric Managment Service. | ||
1105 | * @ha: HA context | ||
1106 | * | ||
1107 | * Returns 0 on success. | ||
1108 | */ | ||
1109 | static int | ||
1110 | qla2x00_mgmt_svr_login(scsi_qla_host_t *ha) | ||
1111 | { | ||
1112 | int ret; | ||
1113 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | ||
1114 | |||
1115 | ret = QLA_SUCCESS; | ||
1116 | if (ha->flags.management_server_logged_in) | ||
1117 | return ret; | ||
1118 | |||
1119 | ha->isp_ops.fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa, | ||
1120 | mb, BIT_1); | ||
1121 | if (mb[0] != MBS_COMMAND_COMPLETE) { | ||
1122 | DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: " | ||
1123 | "loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x\n", | ||
1124 | __func__, ha->host_no, ha->mgmt_svr_loop_id, mb[0], mb[1], | ||
1125 | mb[2], mb[6], mb[7])); | ||
1126 | ret = QLA_FUNCTION_FAILED; | ||
1127 | } else | ||
1128 | ha->flags.management_server_logged_in = 1; | ||
1129 | |||
1130 | return ret; | ||
1131 | } | ||
1132 | |||
1133 | /** | ||
1134 | * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query. | ||
1135 | * @ha: HA context | ||
1136 | * @req_size: request size in bytes | ||
1137 | * @rsp_size: response size in bytes | ||
1138 | * | ||
1139 | * Returns a pointer to the @ha's ms_iocb. | ||
1140 | */ | ||
1141 | void * | ||
1142 | qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size, | ||
1143 | uint32_t rsp_size) | ||
1144 | { | ||
1145 | ms_iocb_entry_t *ms_pkt; | ||
1146 | |||
1147 | ms_pkt = ha->ms_iocb; | ||
1148 | memset(ms_pkt, 0, sizeof(ms_iocb_entry_t)); | ||
1149 | |||
1150 | ms_pkt->entry_type = MS_IOCB_TYPE; | ||
1151 | ms_pkt->entry_count = 1; | ||
1152 | SET_TARGET_ID(ha, ms_pkt->loop_id, ha->mgmt_svr_loop_id); | ||
1153 | ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); | ||
1154 | ms_pkt->timeout = __constant_cpu_to_le16(59); | ||
1155 | ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); | ||
1156 | ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); | ||
1157 | ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); | ||
1158 | ms_pkt->req_bytecount = cpu_to_le32(req_size); | ||
1159 | |||
1160 | ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | ||
1161 | ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | ||
1162 | ms_pkt->dseg_req_length = ms_pkt->req_bytecount; | ||
1163 | |||
1164 | ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | ||
1165 | ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | ||
1166 | ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount; | ||
1167 | |||
1168 | return ms_pkt; | ||
1169 | } | ||
1170 | |||
1171 | /** | ||
1172 | * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query. | ||
1173 | * @ha: HA context | ||
1174 | * @req_size: request size in bytes | ||
1175 | * @rsp_size: response size in bytes | ||
1176 | * | ||
1177 | * Returns a pointer to the @ha's ms_iocb. | ||
1178 | */ | ||
1179 | void * | ||
1180 | qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size, | ||
1181 | uint32_t rsp_size) | ||
1182 | { | ||
1183 | struct ct_entry_24xx *ct_pkt; | ||
1184 | |||
1185 | ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; | ||
1186 | memset(ct_pkt, 0, sizeof(struct ct_entry_24xx)); | ||
1187 | |||
1188 | ct_pkt->entry_type = CT_IOCB_TYPE; | ||
1189 | ct_pkt->entry_count = 1; | ||
1190 | ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id); | ||
1191 | ct_pkt->timeout = __constant_cpu_to_le16(59); | ||
1192 | ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); | ||
1193 | ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); | ||
1194 | ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); | ||
1195 | ct_pkt->cmd_byte_count = cpu_to_le32(req_size); | ||
1196 | |||
1197 | ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | ||
1198 | ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | ||
1199 | ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; | ||
1200 | |||
1201 | ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | ||
1202 | ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | ||
1203 | ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; | ||
1204 | |||
1205 | return ct_pkt; | ||
1206 | } | ||
1207 | |||
1208 | static inline ms_iocb_entry_t * | ||
1209 | qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size) | ||
1210 | { | ||
1211 | ms_iocb_entry_t *ms_pkt = ha->ms_iocb; | ||
1212 | struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; | ||
1213 | |||
1214 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { | ||
1215 | ct_pkt->cmd_byte_count = cpu_to_le32(req_size); | ||
1216 | ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; | ||
1217 | } else { | ||
1218 | ms_pkt->req_bytecount = cpu_to_le32(req_size); | ||
1219 | ms_pkt->dseg_req_length = ms_pkt->req_bytecount; | ||
1220 | } | ||
1221 | |||
1222 | return ms_pkt; | ||
1223 | } | ||
1224 | |||
1225 | /** | ||
1226 | * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query. | ||
1227 | * @ct_req: CT request buffer | ||
1228 | * @cmd: GS command | ||
1229 | * @rsp_size: response size in bytes | ||
1230 | * | ||
1231 | * Returns a pointer to the intitialized @ct_req. | ||
1232 | */ | ||
1233 | static inline struct ct_sns_req * | ||
1234 | qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd, | ||
1235 | uint16_t rsp_size) | ||
1236 | { | ||
1237 | memset(ct_req, 0, sizeof(struct ct_sns_pkt)); | ||
1238 | |||
1239 | ct_req->header.revision = 0x01; | ||
1240 | ct_req->header.gs_type = 0xFA; | ||
1241 | ct_req->header.gs_subtype = 0x10; | ||
1242 | ct_req->command = cpu_to_be16(cmd); | ||
1243 | ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); | ||
1244 | |||
1245 | return ct_req; | ||
1246 | } | ||
1247 | |||
1248 | /** | ||
1249 | * qla2x00_fdmi_rhba() - | ||
1250 | * @ha: HA context | ||
1251 | * | ||
1252 | * Returns 0 on success. | ||
1253 | */ | ||
1254 | static int | ||
1255 | qla2x00_fdmi_rhba(scsi_qla_host_t *ha) | ||
1256 | { | ||
1257 | int rval, alen; | ||
1258 | uint32_t size, sn; | ||
1259 | |||
1260 | ms_iocb_entry_t *ms_pkt; | ||
1261 | struct ct_sns_req *ct_req; | ||
1262 | struct ct_sns_rsp *ct_rsp; | ||
1263 | uint8_t *entries; | ||
1264 | struct ct_fdmi_hba_attr *eiter; | ||
1265 | |||
1266 | /* Issue RHBA */ | ||
1267 | /* Prepare common MS IOCB */ | ||
1268 | /* Request size adjusted after CT preparation */ | ||
1269 | ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE); | ||
1270 | |||
1271 | /* Prepare CT request */ | ||
1272 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD, | ||
1273 | RHBA_RSP_SIZE); | ||
1274 | ct_rsp = &ha->ct_sns->p.rsp; | ||
1275 | |||
1276 | /* Prepare FDMI command arguments -- attribute block, attributes. */ | ||
1277 | memcpy(ct_req->req.rhba.hba_identifier, ha->port_name, WWN_SIZE); | ||
1278 | ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1); | ||
1279 | memcpy(ct_req->req.rhba.port_name, ha->port_name, WWN_SIZE); | ||
1280 | size = 2 * WWN_SIZE + 4 + 4; | ||
1281 | |||
1282 | /* Attributes */ | ||
1283 | ct_req->req.rhba.attrs.count = | ||
1284 | __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT); | ||
1285 | entries = ct_req->req.rhba.hba_identifier; | ||
1286 | |||
1287 | /* Nodename. */ | ||
1288 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1289 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME); | ||
1290 | eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE); | ||
1291 | memcpy(eiter->a.node_name, ha->node_name, WWN_SIZE); | ||
1292 | size += 4 + WWN_SIZE; | ||
1293 | |||
1294 | DEBUG13(printk("%s(%ld): NODENAME=%02x%02x%02x%02x%02x%02x%02x%02x.\n", | ||
1295 | __func__, ha->host_no, | ||
1296 | eiter->a.node_name[0], eiter->a.node_name[1], eiter->a.node_name[2], | ||
1297 | eiter->a.node_name[3], eiter->a.node_name[4], eiter->a.node_name[5], | ||
1298 | eiter->a.node_name[6], eiter->a.node_name[7])); | ||
1299 | |||
1300 | /* Manufacturer. */ | ||
1301 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1302 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER); | ||
1303 | strcpy(eiter->a.manufacturer, "QLogic Corporation"); | ||
1304 | alen = strlen(eiter->a.manufacturer); | ||
1305 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1306 | eiter->len = cpu_to_be16(4 + alen); | ||
1307 | size += 4 + alen; | ||
1308 | |||
1309 | DEBUG13(printk("%s(%ld): MANUFACTURER=%s.\n", __func__, ha->host_no, | ||
1310 | eiter->a.manufacturer)); | ||
1311 | |||
1312 | /* Serial number. */ | ||
1313 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1314 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); | ||
1315 | sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; | ||
1316 | sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000); | ||
1317 | alen = strlen(eiter->a.serial_num); | ||
1318 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1319 | eiter->len = cpu_to_be16(4 + alen); | ||
1320 | size += 4 + alen; | ||
1321 | |||
1322 | DEBUG13(printk("%s(%ld): SERIALNO=%s.\n", __func__, ha->host_no, | ||
1323 | eiter->a.serial_num)); | ||
1324 | |||
1325 | /* Model name. */ | ||
1326 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1327 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL); | ||
1328 | strcpy(eiter->a.model, ha->model_number); | ||
1329 | alen = strlen(eiter->a.model); | ||
1330 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1331 | eiter->len = cpu_to_be16(4 + alen); | ||
1332 | size += 4 + alen; | ||
1333 | |||
1334 | DEBUG13(printk("%s(%ld): MODEL_NAME=%s.\n", __func__, ha->host_no, | ||
1335 | eiter->a.model)); | ||
1336 | |||
1337 | /* Model description. */ | ||
1338 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1339 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); | ||
1340 | if (ha->model_desc) | ||
1341 | strncpy(eiter->a.model_desc, ha->model_desc, 80); | ||
1342 | alen = strlen(eiter->a.model_desc); | ||
1343 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1344 | eiter->len = cpu_to_be16(4 + alen); | ||
1345 | size += 4 + alen; | ||
1346 | |||
1347 | DEBUG13(printk("%s(%ld): MODEL_DESC=%s.\n", __func__, ha->host_no, | ||
1348 | eiter->a.model_desc)); | ||
1349 | |||
1350 | /* Hardware version. */ | ||
1351 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1352 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); | ||
1353 | strcpy(eiter->a.hw_version, ha->adapter_id); | ||
1354 | alen = strlen(eiter->a.hw_version); | ||
1355 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1356 | eiter->len = cpu_to_be16(4 + alen); | ||
1357 | size += 4 + alen; | ||
1358 | |||
1359 | DEBUG13(printk("%s(%ld): HARDWAREVER=%s.\n", __func__, ha->host_no, | ||
1360 | eiter->a.hw_version)); | ||
1361 | |||
1362 | /* Driver version. */ | ||
1363 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1364 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION); | ||
1365 | strcpy(eiter->a.driver_version, qla2x00_version_str); | ||
1366 | alen = strlen(eiter->a.driver_version); | ||
1367 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1368 | eiter->len = cpu_to_be16(4 + alen); | ||
1369 | size += 4 + alen; | ||
1370 | |||
1371 | DEBUG13(printk("%s(%ld): DRIVERVER=%s.\n", __func__, ha->host_no, | ||
1372 | eiter->a.driver_version)); | ||
1373 | |||
1374 | /* Option ROM version. */ | ||
1375 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1376 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); | ||
1377 | strcpy(eiter->a.orom_version, "0.00"); | ||
1378 | alen = strlen(eiter->a.orom_version); | ||
1379 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1380 | eiter->len = cpu_to_be16(4 + alen); | ||
1381 | size += 4 + alen; | ||
1382 | |||
1383 | DEBUG13(printk("%s(%ld): OPTROMVER=%s.\n", __func__, ha->host_no, | ||
1384 | eiter->a.orom_version)); | ||
1385 | |||
1386 | /* Firmware version */ | ||
1387 | eiter = (struct ct_fdmi_hba_attr *) (entries + size); | ||
1388 | eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); | ||
1389 | ha->isp_ops.fw_version_str(ha, eiter->a.fw_version); | ||
1390 | alen = strlen(eiter->a.fw_version); | ||
1391 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1392 | eiter->len = cpu_to_be16(4 + alen); | ||
1393 | size += 4 + alen; | ||
1394 | |||
1395 | DEBUG13(printk("%s(%ld): FIRMWAREVER=%s.\n", __func__, ha->host_no, | ||
1396 | eiter->a.fw_version)); | ||
1397 | |||
1398 | /* Update MS request size. */ | ||
1399 | qla2x00_update_ms_fdmi_iocb(ha, size + 16); | ||
1400 | |||
1401 | DEBUG13(printk("%s(%ld): RHBA identifier=" | ||
1402 | "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__, | ||
1403 | ha->host_no, ct_req->req.rhba.hba_identifier[0], | ||
1404 | ct_req->req.rhba.hba_identifier[1], | ||
1405 | ct_req->req.rhba.hba_identifier[2], | ||
1406 | ct_req->req.rhba.hba_identifier[3], | ||
1407 | ct_req->req.rhba.hba_identifier[4], | ||
1408 | ct_req->req.rhba.hba_identifier[5], | ||
1409 | ct_req->req.rhba.hba_identifier[6], | ||
1410 | ct_req->req.rhba.hba_identifier[7], size)); | ||
1411 | DEBUG13(qla2x00_dump_buffer(entries, size)); | ||
1412 | |||
1413 | /* Execute MS IOCB */ | ||
1414 | rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, | ||
1415 | sizeof(ms_iocb_entry_t)); | ||
1416 | if (rval != QLA_SUCCESS) { | ||
1417 | /*EMPTY*/ | ||
1418 | DEBUG2_3(printk("scsi(%ld): RHBA issue IOCB failed (%d).\n", | ||
1419 | ha->host_no, rval)); | ||
1420 | } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RHBA") != | ||
1421 | QLA_SUCCESS) { | ||
1422 | rval = QLA_FUNCTION_FAILED; | ||
1423 | if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && | ||
1424 | ct_rsp->header.explanation_code == | ||
1425 | CT_EXPL_ALREADY_REGISTERED) { | ||
1426 | DEBUG2_13(printk("%s(%ld): HBA already registered.\n", | ||
1427 | __func__, ha->host_no)); | ||
1428 | rval = QLA_ALREADY_REGISTERED; | ||
1429 | } | ||
1430 | } else { | ||
1431 | DEBUG2(printk("scsi(%ld): RHBA exiting normally.\n", | ||
1432 | ha->host_no)); | ||
1433 | } | ||
1434 | |||
1435 | return rval; | ||
1436 | } | ||
1437 | |||
1438 | /** | ||
1439 | * qla2x00_fdmi_dhba() - | ||
1440 | * @ha: HA context | ||
1441 | * | ||
1442 | * Returns 0 on success. | ||
1443 | */ | ||
1444 | static int | ||
1445 | qla2x00_fdmi_dhba(scsi_qla_host_t *ha) | ||
1446 | { | ||
1447 | int rval; | ||
1448 | |||
1449 | ms_iocb_entry_t *ms_pkt; | ||
1450 | struct ct_sns_req *ct_req; | ||
1451 | struct ct_sns_rsp *ct_rsp; | ||
1452 | |||
1453 | /* Issue RPA */ | ||
1454 | /* Prepare common MS IOCB */ | ||
1455 | ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE, | ||
1456 | DHBA_RSP_SIZE); | ||
1457 | |||
1458 | /* Prepare CT request */ | ||
1459 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD, | ||
1460 | DHBA_RSP_SIZE); | ||
1461 | ct_rsp = &ha->ct_sns->p.rsp; | ||
1462 | |||
1463 | /* Prepare FDMI command arguments -- portname. */ | ||
1464 | memcpy(ct_req->req.dhba.port_name, ha->port_name, WWN_SIZE); | ||
1465 | |||
1466 | DEBUG13(printk("%s(%ld): DHBA portname=" | ||
1467 | "%02x%02x%02x%02x%02x%02x%02x%02x.\n", __func__, ha->host_no, | ||
1468 | ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1], | ||
1469 | ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3], | ||
1470 | ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5], | ||
1471 | ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7])); | ||
1472 | |||
1473 | /* Execute MS IOCB */ | ||
1474 | rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, | ||
1475 | sizeof(ms_iocb_entry_t)); | ||
1476 | if (rval != QLA_SUCCESS) { | ||
1477 | /*EMPTY*/ | ||
1478 | DEBUG2_3(printk("scsi(%ld): DHBA issue IOCB failed (%d).\n", | ||
1479 | ha->host_no, rval)); | ||
1480 | } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "DHBA") != | ||
1481 | QLA_SUCCESS) { | ||
1482 | rval = QLA_FUNCTION_FAILED; | ||
1483 | } else { | ||
1484 | DEBUG2(printk("scsi(%ld): DHBA exiting normally.\n", | ||
1485 | ha->host_no)); | ||
1486 | } | ||
1487 | |||
1488 | return rval; | ||
1489 | } | ||
1490 | |||
1491 | /** | ||
1492 | * qla2x00_fdmi_rpa() - | ||
1493 | * @ha: HA context | ||
1494 | * | ||
1495 | * Returns 0 on success. | ||
1496 | */ | ||
1497 | static int | ||
1498 | qla2x00_fdmi_rpa(scsi_qla_host_t *ha) | ||
1499 | { | ||
1500 | int rval, alen; | ||
1501 | uint32_t size, max_frame_size; | ||
1502 | |||
1503 | ms_iocb_entry_t *ms_pkt; | ||
1504 | struct ct_sns_req *ct_req; | ||
1505 | struct ct_sns_rsp *ct_rsp; | ||
1506 | uint8_t *entries; | ||
1507 | struct ct_fdmi_port_attr *eiter; | ||
1508 | struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; | ||
1509 | |||
1510 | /* Issue RPA */ | ||
1511 | /* Prepare common MS IOCB */ | ||
1512 | /* Request size adjusted after CT preparation */ | ||
1513 | ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE); | ||
1514 | |||
1515 | /* Prepare CT request */ | ||
1516 | ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD, | ||
1517 | RPA_RSP_SIZE); | ||
1518 | ct_rsp = &ha->ct_sns->p.rsp; | ||
1519 | |||
1520 | /* Prepare FDMI command arguments -- attribute block, attributes. */ | ||
1521 | memcpy(ct_req->req.rpa.port_name, ha->port_name, WWN_SIZE); | ||
1522 | size = WWN_SIZE + 4; | ||
1523 | |||
1524 | /* Attributes */ | ||
1525 | ct_req->req.rpa.attrs.count = | ||
1526 | __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT); | ||
1527 | entries = ct_req->req.rpa.port_name; | ||
1528 | |||
1529 | /* FC4 types. */ | ||
1530 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1531 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES); | ||
1532 | eiter->len = __constant_cpu_to_be16(4 + 32); | ||
1533 | eiter->a.fc4_types[2] = 0x01; | ||
1534 | size += 4 + 32; | ||
1535 | |||
1536 | DEBUG13(printk("%s(%ld): FC4_TYPES=%02x %02x.\n", __func__, ha->host_no, | ||
1537 | eiter->a.fc4_types[2], eiter->a.fc4_types[1])); | ||
1538 | |||
1539 | /* Supported speed. */ | ||
1540 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1541 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); | ||
1542 | eiter->len = __constant_cpu_to_be16(4 + 4); | ||
1543 | if (IS_QLA25XX(ha)) | ||
1544 | eiter->a.sup_speed = __constant_cpu_to_be32(4); | ||
1545 | else if (IS_QLA24XX(ha)) | ||
1546 | eiter->a.sup_speed = __constant_cpu_to_be32(8); | ||
1547 | else if (IS_QLA23XX(ha)) | ||
1548 | eiter->a.sup_speed = __constant_cpu_to_be32(2); | ||
1549 | else | ||
1550 | eiter->a.sup_speed = __constant_cpu_to_be32(1); | ||
1551 | size += 4 + 4; | ||
1552 | |||
1553 | DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no, | ||
1554 | eiter->a.sup_speed)); | ||
1555 | |||
1556 | /* Current speed. */ | ||
1557 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1558 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED); | ||
1559 | eiter->len = __constant_cpu_to_be16(4 + 4); | ||
1560 | switch (ha->link_data_rate) { | ||
1561 | case 0: | ||
1562 | eiter->a.cur_speed = __constant_cpu_to_be32(1); | ||
1563 | break; | ||
1564 | case 1: | ||
1565 | eiter->a.cur_speed = __constant_cpu_to_be32(2); | ||
1566 | break; | ||
1567 | case 3: | ||
1568 | eiter->a.cur_speed = __constant_cpu_to_be32(8); | ||
1569 | break; | ||
1570 | case 4: | ||
1571 | eiter->a.cur_speed = __constant_cpu_to_be32(4); | ||
1572 | break; | ||
1573 | } | ||
1574 | size += 4 + 4; | ||
1575 | |||
1576 | DEBUG13(printk("%s(%ld): CURRENT_SPEED=%x.\n", __func__, ha->host_no, | ||
1577 | eiter->a.cur_speed)); | ||
1578 | |||
1579 | /* Max frame size. */ | ||
1580 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1581 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); | ||
1582 | eiter->len = __constant_cpu_to_be16(4 + 4); | ||
1583 | max_frame_size = IS_QLA24XX(ha) || IS_QLA25XX(ha) ? | ||
1584 | (uint32_t) icb24->frame_payload_size: | ||
1585 | (uint32_t) ha->init_cb->frame_payload_size; | ||
1586 | eiter->a.max_frame_size = cpu_to_be32(max_frame_size); | ||
1587 | size += 4 + 4; | ||
1588 | |||
1589 | DEBUG13(printk("%s(%ld): MAX_FRAME_SIZE=%x.\n", __func__, ha->host_no, | ||
1590 | eiter->a.max_frame_size)); | ||
1591 | |||
1592 | /* OS device name. */ | ||
1593 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | ||
1594 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); | ||
1595 | sprintf(eiter->a.os_dev_name, "/proc/scsi/qla2xxx/%ld", ha->host_no); | ||
1596 | alen = strlen(eiter->a.os_dev_name); | ||
1597 | alen += (alen & 3) ? (4 - (alen & 3)) : 4; | ||
1598 | eiter->len = cpu_to_be16(4 + alen); | ||
1599 | size += 4 + alen; | ||
1600 | |||
1601 | DEBUG13(printk("%s(%ld): OS_DEVICE_NAME=%s.\n", __func__, ha->host_no, | ||
1602 | eiter->a.os_dev_name)); | ||
1603 | |||
1604 | /* Update MS request size. */ | ||
1605 | qla2x00_update_ms_fdmi_iocb(ha, size + 16); | ||
1606 | |||
1607 | DEBUG13(printk("%s(%ld): RPA portname=" | ||
1608 | "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__, | ||
1609 | ha->host_no, ct_req->req.rpa.port_name[0], | ||
1610 | ct_req->req.rpa.port_name[1], ct_req->req.rpa.port_name[2], | ||
1611 | ct_req->req.rpa.port_name[3], ct_req->req.rpa.port_name[4], | ||
1612 | ct_req->req.rpa.port_name[5], ct_req->req.rpa.port_name[6], | ||
1613 | ct_req->req.rpa.port_name[7], size)); | ||
1614 | DEBUG13(qla2x00_dump_buffer(entries, size)); | ||
1615 | |||
1616 | /* Execute MS IOCB */ | ||
1617 | rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, | ||
1618 | sizeof(ms_iocb_entry_t)); | ||
1619 | if (rval != QLA_SUCCESS) { | ||
1620 | /*EMPTY*/ | ||
1621 | DEBUG2_3(printk("scsi(%ld): RPA issue IOCB failed (%d).\n", | ||
1622 | ha->host_no, rval)); | ||
1623 | } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RPA") != | ||
1624 | QLA_SUCCESS) { | ||
1625 | rval = QLA_FUNCTION_FAILED; | ||
1626 | } else { | ||
1627 | DEBUG2(printk("scsi(%ld): RPA exiting normally.\n", | ||
1628 | ha->host_no)); | ||
1629 | } | ||
1630 | |||
1631 | return rval; | ||
1632 | } | ||
1633 | |||
1634 | /** | ||
1635 | * qla2x00_fdmi_register() - | ||
1636 | * @ha: HA context | ||
1637 | * | ||
1638 | * Returns 0 on success. | ||
1639 | */ | ||
1640 | int | ||
1641 | qla2x00_fdmi_register(scsi_qla_host_t *ha) | ||
1642 | { | ||
1643 | int rval; | ||
1644 | |||
1645 | rval = qla2x00_mgmt_svr_login(ha); | ||
1646 | if (rval) | ||
1647 | return rval; | ||
1648 | |||
1649 | rval = qla2x00_fdmi_rhba(ha); | ||
1650 | if (rval) { | ||
1651 | if (rval != QLA_ALREADY_REGISTERED) | ||
1652 | return rval; | ||
1653 | |||
1654 | rval = qla2x00_fdmi_dhba(ha); | ||
1655 | if (rval) | ||
1656 | return rval; | ||
1657 | |||
1658 | rval = qla2x00_fdmi_rhba(ha); | ||
1659 | if (rval) | ||
1660 | return rval; | ||
1661 | } | ||
1662 | rval = qla2x00_fdmi_rpa(ha); | ||
1663 | |||
1664 | return rval; | ||
1665 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a6d2559217cd..c619583e646b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -88,6 +88,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
88 | ha->mbx_flags = 0; | 88 | ha->mbx_flags = 0; |
89 | ha->isp_abort_cnt = 0; | 89 | ha->isp_abort_cnt = 0; |
90 | ha->beacon_blink_led = 0; | 90 | ha->beacon_blink_led = 0; |
91 | set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); | ||
91 | 92 | ||
92 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); | 93 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); |
93 | rval = ha->isp_ops.pci_config(ha); | 94 | rval = ha->isp_ops.pci_config(ha); |
@@ -1563,7 +1564,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1563 | ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0); | 1564 | ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0); |
1564 | ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0); | 1565 | ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0); |
1565 | ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0); | 1566 | ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0); |
1566 | ha->flags.enable_led_scheme = ((nv->efi_parameters & BIT_3) ? 1 : 0); | 1567 | ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0; |
1567 | 1568 | ||
1568 | ha->operating_mode = | 1569 | ha->operating_mode = |
1569 | (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4; | 1570 | (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4; |
@@ -1697,6 +1698,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags) | |||
1697 | fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; | 1698 | fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; |
1698 | atomic_set(&fcport->state, FCS_UNCONFIGURED); | 1699 | atomic_set(&fcport->state, FCS_UNCONFIGURED); |
1699 | fcport->flags = FCF_RLC_SUPPORT; | 1700 | fcport->flags = FCF_RLC_SUPPORT; |
1701 | fcport->supported_classes = FC_COS_UNSPECIFIED; | ||
1700 | 1702 | ||
1701 | return (fcport); | 1703 | return (fcport); |
1702 | } | 1704 | } |
@@ -1898,7 +1900,8 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) | |||
1898 | continue; | 1900 | continue; |
1899 | 1901 | ||
1900 | /* Bypass if not same domain and area of adapter. */ | 1902 | /* Bypass if not same domain and area of adapter. */ |
1901 | if (area != ha->d_id.b.area || domain != ha->d_id.b.domain) | 1903 | if (area && domain && |
1904 | (area != ha->d_id.b.area || domain != ha->d_id.b.domain)) | ||
1902 | continue; | 1905 | continue; |
1903 | 1906 | ||
1904 | /* Bypass invalid local loop ID. */ | 1907 | /* Bypass invalid local loop ID. */ |
@@ -2075,6 +2078,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) | |||
2075 | return; | 2078 | return; |
2076 | } | 2079 | } |
2077 | rport->dd_data = fcport; | 2080 | rport->dd_data = fcport; |
2081 | rport->supported_classes = fcport->supported_classes; | ||
2078 | 2082 | ||
2079 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; | 2083 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; |
2080 | if (fcport->port_type == FCT_INITIATOR) | 2084 | if (fcport->port_type == FCT_INITIATOR) |
@@ -2130,6 +2134,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
2130 | return (QLA_SUCCESS); | 2134 | return (QLA_SUCCESS); |
2131 | } | 2135 | } |
2132 | do { | 2136 | do { |
2137 | /* FDMI support. */ | ||
2138 | if (ql2xfdmienable && | ||
2139 | test_and_clear_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags)) | ||
2140 | qla2x00_fdmi_register(ha); | ||
2141 | |||
2133 | /* Ensure we are logged into the SNS. */ | 2142 | /* Ensure we are logged into the SNS. */ |
2134 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) | 2143 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) |
2135 | loop_id = NPH_SNS; | 2144 | loop_id = NPH_SNS; |
@@ -2392,6 +2401,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2392 | if (new_fcport->d_id.b24 == ha->d_id.b24) | 2401 | if (new_fcport->d_id.b24 == ha->d_id.b24) |
2393 | continue; | 2402 | continue; |
2394 | 2403 | ||
2404 | /* Bypass if same domain and area of adapter. */ | ||
2405 | if (((new_fcport->d_id.b24 & 0xffff00) == | ||
2406 | (ha->d_id.b24 & 0xffff00)) && ha->current_topology == | ||
2407 | ISP_CFG_FL) | ||
2408 | continue; | ||
2409 | |||
2395 | /* Bypass reserved domain fields. */ | 2410 | /* Bypass reserved domain fields. */ |
2396 | if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0) | 2411 | if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0) |
2397 | continue; | 2412 | continue; |
@@ -2794,6 +2809,11 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
2794 | } | 2809 | } |
2795 | } | 2810 | } |
2796 | 2811 | ||
2812 | if (mb[10] & BIT_0) | ||
2813 | fcport->supported_classes |= FC_COS_CLASS2; | ||
2814 | if (mb[10] & BIT_1) | ||
2815 | fcport->supported_classes |= FC_COS_CLASS3; | ||
2816 | |||
2797 | rval = QLA_SUCCESS; | 2817 | rval = QLA_SUCCESS; |
2798 | break; | 2818 | break; |
2799 | } else if (mb[0] == MBS_LOOP_ID_USED) { | 2819 | } else if (mb[0] == MBS_LOOP_ID_USED) { |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index ebdc3c54d155..37f82e2cd7fb 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -810,12 +810,8 @@ qla24xx_start_scsi(srb_t *sp) | |||
810 | ha->req_q_cnt = ha->request_q_length - | 810 | ha->req_q_cnt = ha->request_q_length - |
811 | (ha->req_ring_index - cnt); | 811 | (ha->req_ring_index - cnt); |
812 | } | 812 | } |
813 | if (ha->req_q_cnt < (req_cnt + 2)) { | 813 | if (ha->req_q_cnt < (req_cnt + 2)) |
814 | if (cmd->use_sg) | ||
815 | pci_unmap_sg(ha->pdev, sg, cmd->use_sg, | ||
816 | cmd->sc_data_direction); | ||
817 | goto queuing_error; | 814 | goto queuing_error; |
818 | } | ||
819 | 815 | ||
820 | /* Build command packet. */ | 816 | /* Build command packet. */ |
821 | ha->current_outstanding_cmd = handle; | 817 | ha->current_outstanding_cmd = handle; |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index f910de6dd437..c255bb0268a9 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -451,6 +451,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
451 | 451 | ||
452 | ha->flags.management_server_logged_in = 0; | 452 | ha->flags.management_server_logged_in = 0; |
453 | ha->link_data_rate = 0; | 453 | ha->link_data_rate = 0; |
454 | if (ql2xfdmienable) | ||
455 | set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); | ||
454 | 456 | ||
455 | /* Update AEN queue. */ | 457 | /* Update AEN queue. */ |
456 | qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL); | 458 | qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL); |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 409ea0ac4032..13e1c9047079 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include "qla_def.h" | 19 | #include "qla_def.h" |
20 | 20 | ||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <scsi/scsi_transport_fc.h> | ||
22 | 23 | ||
23 | static void | 24 | static void |
24 | qla2x00_mbx_sem_timeout(unsigned long data) | 25 | qla2x00_mbx_sem_timeout(unsigned long data) |
@@ -251,7 +252,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
251 | mb0 = RD_REG_WORD(®->isp24.mailbox0); | 252 | mb0 = RD_REG_WORD(®->isp24.mailbox0); |
252 | ictrl = RD_REG_DWORD(®->isp24.ictrl); | 253 | ictrl = RD_REG_DWORD(®->isp24.ictrl); |
253 | } else { | 254 | } else { |
254 | mb0 = RD_MAILBOX_REG(ha, reg->isp, 0); | 255 | mb0 = RD_MAILBOX_REG(ha, ®->isp, 0); |
255 | ictrl = RD_REG_WORD(®->isp.ictrl); | 256 | ictrl = RD_REG_WORD(®->isp.ictrl); |
256 | } | 257 | } |
257 | printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n", | 258 | printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n", |
@@ -983,58 +984,6 @@ qla2x00_abort_target(fc_port_t *fcport) | |||
983 | #endif | 984 | #endif |
984 | 985 | ||
985 | /* | 986 | /* |
986 | * qla2x00_target_reset | ||
987 | * Issue target reset mailbox command. | ||
988 | * | ||
989 | * Input: | ||
990 | * ha = adapter block pointer. | ||
991 | * TARGET_QUEUE_LOCK must be released. | ||
992 | * ADAPTER_STATE_LOCK must be released. | ||
993 | * | ||
994 | * Returns: | ||
995 | * qla2x00 local function return status code. | ||
996 | * | ||
997 | * Context: | ||
998 | * Kernel context. | ||
999 | */ | ||
1000 | int | ||
1001 | qla2x00_target_reset(scsi_qla_host_t *ha, struct fc_port *fcport) | ||
1002 | { | ||
1003 | int rval; | ||
1004 | mbx_cmd_t mc; | ||
1005 | mbx_cmd_t *mcp = &mc; | ||
1006 | |||
1007 | DEBUG11(printk("qla2x00_target_reset(%ld): entered.\n", ha->host_no);) | ||
1008 | |||
1009 | if (atomic_read(&fcport->state) != FCS_ONLINE) | ||
1010 | return 0; | ||
1011 | |||
1012 | mcp->mb[0] = MBC_TARGET_RESET; | ||
1013 | if (HAS_EXTENDED_IDS(ha)) | ||
1014 | mcp->mb[1] = fcport->loop_id; | ||
1015 | else | ||
1016 | mcp->mb[1] = fcport->loop_id << 8; | ||
1017 | mcp->mb[2] = ha->loop_reset_delay; | ||
1018 | mcp->out_mb = MBX_2|MBX_1|MBX_0; | ||
1019 | mcp->in_mb = MBX_0; | ||
1020 | mcp->tov = 30; | ||
1021 | mcp->flags = 0; | ||
1022 | rval = qla2x00_mailbox_command(ha, mcp); | ||
1023 | |||
1024 | if (rval != QLA_SUCCESS) { | ||
1025 | /*EMPTY*/ | ||
1026 | DEBUG2_3_11(printk("qla2x00_target_reset(%ld): failed=%x.\n", | ||
1027 | ha->host_no, rval);) | ||
1028 | } else { | ||
1029 | /*EMPTY*/ | ||
1030 | DEBUG11(printk("qla2x00_target_reset(%ld): done.\n", | ||
1031 | ha->host_no);) | ||
1032 | } | ||
1033 | |||
1034 | return rval; | ||
1035 | } | ||
1036 | |||
1037 | /* | ||
1038 | * qla2x00_get_adapter_id | 987 | * qla2x00_get_adapter_id |
1039 | * Get adapter ID and topology. | 988 | * Get adapter ID and topology. |
1040 | * | 989 | * |
@@ -1326,6 +1275,10 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) | |||
1326 | fcport->port_type = FCT_INITIATOR; | 1275 | fcport->port_type = FCT_INITIATOR; |
1327 | else | 1276 | else |
1328 | fcport->port_type = FCT_TARGET; | 1277 | fcport->port_type = FCT_TARGET; |
1278 | |||
1279 | /* Passback COS information. */ | ||
1280 | fcport->supported_classes = (pd->options & BIT_4) ? | ||
1281 | FC_COS_CLASS2: FC_COS_CLASS3; | ||
1329 | } | 1282 | } |
1330 | 1283 | ||
1331 | gpd_error_out: | 1284 | gpd_error_out: |
@@ -1661,6 +1614,13 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | |||
1661 | mb[1] |= BIT_1; | 1614 | mb[1] |= BIT_1; |
1662 | } else | 1615 | } else |
1663 | mb[1] = BIT_0; | 1616 | mb[1] = BIT_0; |
1617 | |||
1618 | /* Passback COS information. */ | ||
1619 | mb[10] = 0; | ||
1620 | if (lg->io_parameter[7] || lg->io_parameter[8]) | ||
1621 | mb[10] |= BIT_0; /* Class 2. */ | ||
1622 | if (lg->io_parameter[9] || lg->io_parameter[10]) | ||
1623 | mb[10] |= BIT_1; /* Class 3. */ | ||
1664 | } | 1624 | } |
1665 | 1625 | ||
1666 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); | 1626 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); |
@@ -1723,6 +1683,8 @@ qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | |||
1723 | mb[2] = mcp->mb[2]; | 1683 | mb[2] = mcp->mb[2]; |
1724 | mb[6] = mcp->mb[6]; | 1684 | mb[6] = mcp->mb[6]; |
1725 | mb[7] = mcp->mb[7]; | 1685 | mb[7] = mcp->mb[7]; |
1686 | /* COS retrieved from Get-Port-Database mailbox command. */ | ||
1687 | mb[10] = 0; | ||
1726 | } | 1688 | } |
1727 | 1689 | ||
1728 | if (rval != QLA_SUCCESS) { | 1690 | if (rval != QLA_SUCCESS) { |
@@ -2465,3 +2427,32 @@ qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g, | |||
2465 | 2427 | ||
2466 | return rval; | 2428 | return rval; |
2467 | } | 2429 | } |
2430 | |||
2431 | int | ||
2432 | qla2x00_stop_firmware(scsi_qla_host_t *ha) | ||
2433 | { | ||
2434 | int rval; | ||
2435 | mbx_cmd_t mc; | ||
2436 | mbx_cmd_t *mcp = &mc; | ||
2437 | |||
2438 | if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) | ||
2439 | return QLA_FUNCTION_FAILED; | ||
2440 | |||
2441 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2442 | |||
2443 | mcp->mb[0] = MBC_STOP_FIRMWARE; | ||
2444 | mcp->out_mb = MBX_0; | ||
2445 | mcp->in_mb = MBX_0; | ||
2446 | mcp->tov = 5; | ||
2447 | mcp->flags = 0; | ||
2448 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2449 | |||
2450 | if (rval != QLA_SUCCESS) { | ||
2451 | DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, | ||
2452 | ha->host_no, rval)); | ||
2453 | } else { | ||
2454 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); | ||
2455 | } | ||
2456 | |||
2457 | return rval; | ||
2458 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 9000659bfbcf..8982978c42fd 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -79,7 +79,7 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR); | |||
79 | MODULE_PARM_DESC(ql2xloginretrycount, | 79 | MODULE_PARM_DESC(ql2xloginretrycount, |
80 | "Specify an alternate value for the NVRAM login retry count."); | 80 | "Specify an alternate value for the NVRAM login retry count."); |
81 | 81 | ||
82 | int ql2xfwloadbin; | 82 | int ql2xfwloadbin=1; |
83 | module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR); | 83 | module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR); |
84 | MODULE_PARM_DESC(ql2xfwloadbin, | 84 | MODULE_PARM_DESC(ql2xfwloadbin, |
85 | "Load ISP2xxx firmware image via hotplug."); | 85 | "Load ISP2xxx firmware image via hotplug."); |
@@ -88,6 +88,12 @@ static void qla2x00_free_device(scsi_qla_host_t *); | |||
88 | 88 | ||
89 | static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); | 89 | static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); |
90 | 90 | ||
91 | int ql2xfdmienable; | ||
92 | module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR); | ||
93 | MODULE_PARM_DESC(ql2xfdmienable, | ||
94 | "Enables FDMI registratons " | ||
95 | "Default is 0 - no FDMI. 1 - perfom FDMI."); | ||
96 | |||
91 | /* | 97 | /* |
92 | * SCSI host template entry points | 98 | * SCSI host template entry points |
93 | */ | 99 | */ |
@@ -105,6 +111,9 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *); | |||
105 | static int qla2x00_loop_reset(scsi_qla_host_t *ha); | 111 | static int qla2x00_loop_reset(scsi_qla_host_t *ha); |
106 | static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); | 112 | static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); |
107 | 113 | ||
114 | static int qla2x00_change_queue_depth(struct scsi_device *, int); | ||
115 | static int qla2x00_change_queue_type(struct scsi_device *, int); | ||
116 | |||
108 | static struct scsi_host_template qla2x00_driver_template = { | 117 | static struct scsi_host_template qla2x00_driver_template = { |
109 | .module = THIS_MODULE, | 118 | .module = THIS_MODULE, |
110 | .name = "qla2xxx", | 119 | .name = "qla2xxx", |
@@ -119,6 +128,8 @@ static struct scsi_host_template qla2x00_driver_template = { | |||
119 | 128 | ||
120 | .slave_alloc = qla2xxx_slave_alloc, | 129 | .slave_alloc = qla2xxx_slave_alloc, |
121 | .slave_destroy = qla2xxx_slave_destroy, | 130 | .slave_destroy = qla2xxx_slave_destroy, |
131 | .change_queue_depth = qla2x00_change_queue_depth, | ||
132 | .change_queue_type = qla2x00_change_queue_type, | ||
122 | .this_id = -1, | 133 | .this_id = -1, |
123 | .cmd_per_lun = 3, | 134 | .cmd_per_lun = 3, |
124 | .use_clustering = ENABLE_CLUSTERING, | 135 | .use_clustering = ENABLE_CLUSTERING, |
@@ -129,6 +140,7 @@ static struct scsi_host_template qla2x00_driver_template = { | |||
129 | * which equates to 0x800000 sectors. | 140 | * which equates to 0x800000 sectors. |
130 | */ | 141 | */ |
131 | .max_sectors = 0xFFFF, | 142 | .max_sectors = 0xFFFF, |
143 | .shost_attrs = qla2x00_host_attrs, | ||
132 | }; | 144 | }; |
133 | 145 | ||
134 | static struct scsi_host_template qla24xx_driver_template = { | 146 | static struct scsi_host_template qla24xx_driver_template = { |
@@ -145,12 +157,15 @@ static struct scsi_host_template qla24xx_driver_template = { | |||
145 | 157 | ||
146 | .slave_alloc = qla2xxx_slave_alloc, | 158 | .slave_alloc = qla2xxx_slave_alloc, |
147 | .slave_destroy = qla2xxx_slave_destroy, | 159 | .slave_destroy = qla2xxx_slave_destroy, |
160 | .change_queue_depth = qla2x00_change_queue_depth, | ||
161 | .change_queue_type = qla2x00_change_queue_type, | ||
148 | .this_id = -1, | 162 | .this_id = -1, |
149 | .cmd_per_lun = 3, | 163 | .cmd_per_lun = 3, |
150 | .use_clustering = ENABLE_CLUSTERING, | 164 | .use_clustering = ENABLE_CLUSTERING, |
151 | .sg_tablesize = SG_ALL, | 165 | .sg_tablesize = SG_ALL, |
152 | 166 | ||
153 | .max_sectors = 0xFFFF, | 167 | .max_sectors = 0xFFFF, |
168 | .shost_attrs = qla2x00_host_attrs, | ||
154 | }; | 169 | }; |
155 | 170 | ||
156 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; | 171 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; |
@@ -487,14 +502,13 @@ qc24_fail_command: | |||
487 | static int | 502 | static int |
488 | qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd) | 503 | qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd) |
489 | { | 504 | { |
490 | #define ABORT_POLLING_PERIOD HZ | 505 | #define ABORT_POLLING_PERIOD 1000 |
491 | #define ABORT_WAIT_ITER ((10 * HZ) / (ABORT_POLLING_PERIOD)) | 506 | #define ABORT_WAIT_ITER ((10 * 1000) / (ABORT_POLLING_PERIOD)) |
492 | unsigned long wait_iter = ABORT_WAIT_ITER; | 507 | unsigned long wait_iter = ABORT_WAIT_ITER; |
493 | int ret = QLA_SUCCESS; | 508 | int ret = QLA_SUCCESS; |
494 | 509 | ||
495 | while (CMD_SP(cmd)) { | 510 | while (CMD_SP(cmd)) { |
496 | set_current_state(TASK_UNINTERRUPTIBLE); | 511 | msleep(ABORT_POLLING_PERIOD); |
497 | schedule_timeout(ABORT_POLLING_PERIOD); | ||
498 | 512 | ||
499 | if (--wait_iter) | 513 | if (--wait_iter) |
500 | break; | 514 | break; |
@@ -1016,7 +1030,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha) | |||
1016 | if (fcport->port_type != FCT_TARGET) | 1030 | if (fcport->port_type != FCT_TARGET) |
1017 | continue; | 1031 | continue; |
1018 | 1032 | ||
1019 | status = qla2x00_target_reset(ha, fcport); | 1033 | status = qla2x00_device_reset(ha, fcport); |
1020 | if (status != QLA_SUCCESS) | 1034 | if (status != QLA_SUCCESS) |
1021 | break; | 1035 | break; |
1022 | } | 1036 | } |
@@ -1103,6 +1117,28 @@ qla2xxx_slave_destroy(struct scsi_device *sdev) | |||
1103 | sdev->hostdata = NULL; | 1117 | sdev->hostdata = NULL; |
1104 | } | 1118 | } |
1105 | 1119 | ||
1120 | static int | ||
1121 | qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth) | ||
1122 | { | ||
1123 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); | ||
1124 | return sdev->queue_depth; | ||
1125 | } | ||
1126 | |||
1127 | static int | ||
1128 | qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type) | ||
1129 | { | ||
1130 | if (sdev->tagged_supported) { | ||
1131 | scsi_set_tag_type(sdev, tag_type); | ||
1132 | if (tag_type) | ||
1133 | scsi_activate_tcq(sdev, sdev->queue_depth); | ||
1134 | else | ||
1135 | scsi_deactivate_tcq(sdev, sdev->queue_depth); | ||
1136 | } else | ||
1137 | tag_type = 0; | ||
1138 | |||
1139 | return tag_type; | ||
1140 | } | ||
1141 | |||
1106 | /** | 1142 | /** |
1107 | * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. | 1143 | * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. |
1108 | * @ha: HA context | 1144 | * @ha: HA context |
@@ -1113,36 +1149,23 @@ qla2xxx_slave_destroy(struct scsi_device *sdev) | |||
1113 | static void | 1149 | static void |
1114 | qla2x00_config_dma_addressing(scsi_qla_host_t *ha) | 1150 | qla2x00_config_dma_addressing(scsi_qla_host_t *ha) |
1115 | { | 1151 | { |
1116 | /* Assume 32bit DMA address */ | 1152 | /* Assume a 32bit DMA mask. */ |
1117 | ha->flags.enable_64bit_addressing = 0; | 1153 | ha->flags.enable_64bit_addressing = 0; |
1118 | 1154 | ||
1119 | /* | 1155 | if (!dma_set_mask(&ha->pdev->dev, DMA_64BIT_MASK)) { |
1120 | * Given the two variants pci_set_dma_mask(), allow the compiler to | 1156 | /* Any upper-dword bits set? */ |
1121 | * assist in setting the proper dma mask. | 1157 | if (MSD(dma_get_required_mask(&ha->pdev->dev)) && |
1122 | */ | 1158 | !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) { |
1123 | if (sizeof(dma_addr_t) > 4) { | 1159 | /* Ok, a 64bit DMA mask is applicable. */ |
1124 | if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) { | ||
1125 | ha->flags.enable_64bit_addressing = 1; | 1160 | ha->flags.enable_64bit_addressing = 1; |
1126 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64; | 1161 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64; |
1127 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64; | 1162 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64; |
1128 | 1163 | return; | |
1129 | if (pci_set_consistent_dma_mask(ha->pdev, | ||
1130 | DMA_64BIT_MASK)) { | ||
1131 | qla_printk(KERN_DEBUG, ha, | ||
1132 | "Failed to set 64 bit PCI consistent mask; " | ||
1133 | "using 32 bit.\n"); | ||
1134 | pci_set_consistent_dma_mask(ha->pdev, | ||
1135 | DMA_32BIT_MASK); | ||
1136 | } | ||
1137 | } else { | ||
1138 | qla_printk(KERN_DEBUG, ha, | ||
1139 | "Failed to set 64 bit PCI DMA mask, falling back " | ||
1140 | "to 32 bit MASK.\n"); | ||
1141 | pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK); | ||
1142 | } | 1164 | } |
1143 | } else { | ||
1144 | pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK); | ||
1145 | } | 1165 | } |
1166 | |||
1167 | dma_set_mask(&ha->pdev->dev, DMA_32BIT_MASK); | ||
1168 | pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK); | ||
1146 | } | 1169 | } |
1147 | 1170 | ||
1148 | static int | 1171 | static int |
@@ -1316,6 +1339,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1316 | ha->prev_topology = 0; | 1339 | ha->prev_topology = 0; |
1317 | ha->ports = MAX_BUSES; | 1340 | ha->ports = MAX_BUSES; |
1318 | ha->init_cb_size = sizeof(init_cb_t); | 1341 | ha->init_cb_size = sizeof(init_cb_t); |
1342 | ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; | ||
1319 | 1343 | ||
1320 | /* Assign ISP specific operations. */ | 1344 | /* Assign ISP specific operations. */ |
1321 | ha->isp_ops.pci_config = qla2100_pci_config; | 1345 | ha->isp_ops.pci_config = qla2100_pci_config; |
@@ -1338,6 +1362,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1338 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32; | 1362 | ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32; |
1339 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32; | 1363 | ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32; |
1340 | ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb; | 1364 | ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb; |
1365 | ha->isp_ops.prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb; | ||
1341 | ha->isp_ops.read_nvram = qla2x00_read_nvram_data; | 1366 | ha->isp_ops.read_nvram = qla2x00_read_nvram_data; |
1342 | ha->isp_ops.write_nvram = qla2x00_write_nvram_data; | 1367 | ha->isp_ops.write_nvram = qla2x00_write_nvram_data; |
1343 | ha->isp_ops.fw_dump = qla2100_fw_dump; | 1368 | ha->isp_ops.fw_dump = qla2100_fw_dump; |
@@ -1375,6 +1400,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1375 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; | 1400 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; |
1376 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; | 1401 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; |
1377 | ha->init_cb_size = sizeof(struct init_cb_24xx); | 1402 | ha->init_cb_size = sizeof(struct init_cb_24xx); |
1403 | ha->mgmt_svr_loop_id = 10; | ||
1378 | ha->isp_ops.pci_config = qla24xx_pci_config; | 1404 | ha->isp_ops.pci_config = qla24xx_pci_config; |
1379 | ha->isp_ops.reset_chip = qla24xx_reset_chip; | 1405 | ha->isp_ops.reset_chip = qla24xx_reset_chip; |
1380 | ha->isp_ops.chip_diag = qla24xx_chip_diag; | 1406 | ha->isp_ops.chip_diag = qla24xx_chip_diag; |
@@ -1395,6 +1421,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1395 | ha->isp_ops.fabric_login = qla24xx_login_fabric; | 1421 | ha->isp_ops.fabric_login = qla24xx_login_fabric; |
1396 | ha->isp_ops.fabric_logout = qla24xx_fabric_logout; | 1422 | ha->isp_ops.fabric_logout = qla24xx_fabric_logout; |
1397 | ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb; | 1423 | ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb; |
1424 | ha->isp_ops.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb; | ||
1398 | ha->isp_ops.read_nvram = qla24xx_read_nvram_data; | 1425 | ha->isp_ops.read_nvram = qla24xx_read_nvram_data; |
1399 | ha->isp_ops.write_nvram = qla24xx_write_nvram_data; | 1426 | ha->isp_ops.write_nvram = qla24xx_write_nvram_data; |
1400 | ha->isp_ops.fw_dump = qla24xx_fw_dump; | 1427 | ha->isp_ops.fw_dump = qla24xx_fw_dump; |
@@ -1558,8 +1585,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1558 | return 0; | 1585 | return 0; |
1559 | 1586 | ||
1560 | probe_failed: | 1587 | probe_failed: |
1561 | fc_remove_host(ha->host); | ||
1562 | |||
1563 | qla2x00_free_device(ha); | 1588 | qla2x00_free_device(ha); |
1564 | 1589 | ||
1565 | scsi_host_put(host); | 1590 | scsi_host_put(host); |
@@ -1601,10 +1626,6 @@ qla2x00_free_device(scsi_qla_host_t *ha) | |||
1601 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) | 1626 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) |
1602 | qla2x00_cancel_io_descriptors(ha); | 1627 | qla2x00_cancel_io_descriptors(ha); |
1603 | 1628 | ||
1604 | /* turn-off interrupts on the card */ | ||
1605 | if (ha->interrupts_on) | ||
1606 | ha->isp_ops.disable_intrs(ha); | ||
1607 | |||
1608 | /* Disable timer */ | 1629 | /* Disable timer */ |
1609 | if (ha->timer_active) | 1630 | if (ha->timer_active) |
1610 | qla2x00_stop_timer(ha); | 1631 | qla2x00_stop_timer(ha); |
@@ -1624,8 +1645,14 @@ qla2x00_free_device(scsi_qla_host_t *ha) | |||
1624 | } | 1645 | } |
1625 | } | 1646 | } |
1626 | 1647 | ||
1627 | qla2x00_mem_free(ha); | 1648 | /* Stop currently executing firmware. */ |
1649 | qla2x00_stop_firmware(ha); | ||
1650 | |||
1651 | /* turn-off interrupts on the card */ | ||
1652 | if (ha->interrupts_on) | ||
1653 | ha->isp_ops.disable_intrs(ha); | ||
1628 | 1654 | ||
1655 | qla2x00_mem_free(ha); | ||
1629 | 1656 | ||
1630 | ha->flags.online = 0; | 1657 | ha->flags.online = 0; |
1631 | 1658 | ||
@@ -1934,7 +1961,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha) | |||
1934 | { | 1961 | { |
1935 | struct list_head *fcpl, *fcptemp; | 1962 | struct list_head *fcpl, *fcptemp; |
1936 | fc_port_t *fcport; | 1963 | fc_port_t *fcport; |
1937 | unsigned long wtime;/* max wait time if mbx cmd is busy. */ | 1964 | unsigned int wtime;/* max wait time if mbx cmd is busy. */ |
1938 | 1965 | ||
1939 | if (ha == NULL) { | 1966 | if (ha == NULL) { |
1940 | /* error */ | 1967 | /* error */ |
@@ -1943,11 +1970,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha) | |||
1943 | } | 1970 | } |
1944 | 1971 | ||
1945 | /* Make sure all other threads are stopped. */ | 1972 | /* Make sure all other threads are stopped. */ |
1946 | wtime = 60 * HZ; | 1973 | wtime = 60 * 1000; |
1947 | while (ha->dpc_wait && wtime) { | 1974 | while (ha->dpc_wait && wtime) |
1948 | set_current_state(TASK_INTERRUPTIBLE); | 1975 | wtime = msleep_interruptible(wtime); |
1949 | wtime = schedule_timeout(wtime); | ||
1950 | } | ||
1951 | 1976 | ||
1952 | /* free ioctl memory */ | 1977 | /* free ioctl memory */ |
1953 | qla2x00_free_ioctl_mem(ha); | 1978 | qla2x00_free_ioctl_mem(ha); |
@@ -2478,15 +2503,15 @@ qla2x00_timer(scsi_qla_host_t *ha) | |||
2478 | int | 2503 | int |
2479 | qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) | 2504 | qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) |
2480 | { | 2505 | { |
2481 | const unsigned int step = HZ/10; | 2506 | const unsigned int step = 100; /* msecs */ |
2507 | unsigned int iterations = jiffies_to_msecs(timeout)/100; | ||
2482 | 2508 | ||
2483 | do { | 2509 | do { |
2484 | if (!down_trylock(sema)) | 2510 | if (!down_trylock(sema)) |
2485 | return 0; | 2511 | return 0; |
2486 | set_current_state(TASK_INTERRUPTIBLE); | 2512 | if (msleep_interruptible(step)) |
2487 | if (schedule_timeout(step)) | ||
2488 | break; | 2513 | break; |
2489 | } while ((timeout -= step) > 0); | 2514 | } while (--iterations >= 0); |
2490 | 2515 | ||
2491 | return -ETIMEDOUT; | 2516 | return -ETIMEDOUT; |
2492 | } | 2517 | } |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index d7f5c608009c..c14abf743b7c 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -468,21 +468,12 @@ qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
468 | uint32_t dwords) | 468 | uint32_t dwords) |
469 | { | 469 | { |
470 | uint32_t i; | 470 | uint32_t i; |
471 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
472 | |||
473 | /* Pause RISC. */ | ||
474 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); | ||
475 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
476 | 471 | ||
477 | /* Dword reads to flash. */ | 472 | /* Dword reads to flash. */ |
478 | for (i = 0; i < dwords; i++, faddr++) | 473 | for (i = 0; i < dwords; i++, faddr++) |
479 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, | 474 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, |
480 | flash_data_to_access_addr(faddr))); | 475 | flash_data_to_access_addr(faddr))); |
481 | 476 | ||
482 | /* Release RISC pause. */ | ||
483 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
484 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
485 | |||
486 | return dwptr; | 477 | return dwptr; |
487 | } | 478 | } |
488 | 479 | ||
@@ -532,10 +523,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
532 | 523 | ||
533 | ret = QLA_SUCCESS; | 524 | ret = QLA_SUCCESS; |
534 | 525 | ||
535 | /* Pause RISC. */ | ||
536 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); | ||
537 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
538 | |||
539 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); | 526 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); |
540 | DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__, | 527 | DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__, |
541 | ha->host_no, man_id, flash_id)); | 528 | ha->host_no, man_id, flash_id)); |
@@ -599,10 +586,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
599 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); | 586 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); |
600 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ | 587 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ |
601 | 588 | ||
602 | /* Release RISC pause. */ | ||
603 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
604 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
605 | |||
606 | return ret; | 589 | return ret; |
607 | } | 590 | } |
608 | 591 | ||
@@ -630,11 +613,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
630 | { | 613 | { |
631 | uint32_t i; | 614 | uint32_t i; |
632 | uint32_t *dwptr; | 615 | uint32_t *dwptr; |
633 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
634 | |||
635 | /* Pause RISC. */ | ||
636 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); | ||
637 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
638 | 616 | ||
639 | /* Dword reads to flash. */ | 617 | /* Dword reads to flash. */ |
640 | dwptr = (uint32_t *)buf; | 618 | dwptr = (uint32_t *)buf; |
@@ -642,10 +620,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
642 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, | 620 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, |
643 | nvram_data_to_access_addr(naddr))); | 621 | nvram_data_to_access_addr(naddr))); |
644 | 622 | ||
645 | /* Release RISC pause. */ | ||
646 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
647 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
648 | |||
649 | return buf; | 623 | return buf; |
650 | } | 624 | } |
651 | 625 | ||
@@ -690,10 +664,6 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
690 | 664 | ||
691 | ret = QLA_SUCCESS; | 665 | ret = QLA_SUCCESS; |
692 | 666 | ||
693 | /* Pause RISC. */ | ||
694 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); | ||
695 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
696 | |||
697 | /* Enable flash write. */ | 667 | /* Enable flash write. */ |
698 | WRT_REG_DWORD(®->ctrl_status, | 668 | WRT_REG_DWORD(®->ctrl_status, |
699 | RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); | 669 | RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); |
@@ -728,9 +698,5 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
728 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); | 698 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); |
729 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ | 699 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ |
730 | 700 | ||
731 | /* Release RISC pause. */ | ||
732 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
733 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | ||
734 | |||
735 | return ret; | 701 | return ret; |
736 | } | 702 | } |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index e3cd3618bc54..eae7d6edd531 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -19,9 +19,9 @@ | |||
19 | /* | 19 | /* |
20 | * Driver version | 20 | * Driver version |
21 | */ | 21 | */ |
22 | #define QLA2XXX_VERSION "8.01.00b5-k" | 22 | #define QLA2XXX_VERSION "8.01.00-k" |
23 | 23 | ||
24 | #define QLA_DRIVER_MAJOR_VER 8 | 24 | #define QLA_DRIVER_MAJOR_VER 8 |
25 | #define QLA_DRIVER_MINOR_VER 1 | 25 | #define QLA_DRIVER_MINOR_VER 1 |
26 | #define QLA_DRIVER_PATCH_VER 0 | 26 | #define QLA_DRIVER_PATCH_VER 0 |
27 | #define QLA_DRIVER_BETA_VER 5 | 27 | #define QLA_DRIVER_BETA_VER 0 |
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c new file mode 100644 index 000000000000..f1ea5027865f --- /dev/null +++ b/drivers/scsi/raid_class.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * RAID Attributes | ||
3 | */ | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/list.h> | ||
7 | #include <linux/raid_class.h> | ||
8 | #include <scsi/scsi_device.h> | ||
9 | #include <scsi/scsi_host.h> | ||
10 | |||
11 | #define RAID_NUM_ATTRS 3 | ||
12 | |||
13 | struct raid_internal { | ||
14 | struct raid_template r; | ||
15 | struct raid_function_template *f; | ||
16 | /* The actual attributes */ | ||
17 | struct class_device_attribute private_attrs[RAID_NUM_ATTRS]; | ||
18 | /* The array of null terminated pointers to attributes | ||
19 | * needed by scsi_sysfs.c */ | ||
20 | struct class_device_attribute *attrs[RAID_NUM_ATTRS + 1]; | ||
21 | }; | ||
22 | |||
23 | struct raid_component { | ||
24 | struct list_head node; | ||
25 | struct device *dev; | ||
26 | int num; | ||
27 | }; | ||
28 | |||
29 | #define to_raid_internal(tmpl) container_of(tmpl, struct raid_internal, r) | ||
30 | |||
31 | #define tc_to_raid_internal(tcont) ({ \ | ||
32 | struct raid_template *r = \ | ||
33 | container_of(tcont, struct raid_template, raid_attrs); \ | ||
34 | to_raid_internal(r); \ | ||
35 | }) | ||
36 | |||
37 | #define ac_to_raid_internal(acont) ({ \ | ||
38 | struct transport_container *tc = \ | ||
39 | container_of(acont, struct transport_container, ac); \ | ||
40 | tc_to_raid_internal(tc); \ | ||
41 | }) | ||
42 | |||
43 | #define class_device_to_raid_internal(cdev) ({ \ | ||
44 | struct attribute_container *ac = \ | ||
45 | attribute_container_classdev_to_container(cdev); \ | ||
46 | ac_to_raid_internal(ac); \ | ||
47 | }) | ||
48 | |||
49 | |||
50 | static int raid_match(struct attribute_container *cont, struct device *dev) | ||
51 | { | ||
52 | /* We have to look for every subsystem that could house | ||
53 | * emulated RAID devices, so start with SCSI */ | ||
54 | struct raid_internal *i = ac_to_raid_internal(cont); | ||
55 | |||
56 | if (scsi_is_sdev_device(dev)) { | ||
57 | struct scsi_device *sdev = to_scsi_device(dev); | ||
58 | |||
59 | if (i->f->cookie != sdev->host->hostt) | ||
60 | return 0; | ||
61 | |||
62 | return i->f->is_raid(dev); | ||
63 | } | ||
64 | /* FIXME: look at other subsystems too */ | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int raid_setup(struct transport_container *tc, struct device *dev, | ||
69 | struct class_device *cdev) | ||
70 | { | ||
71 | struct raid_data *rd; | ||
72 | |||
73 | BUG_ON(class_get_devdata(cdev)); | ||
74 | |||
75 | rd = kmalloc(sizeof(*rd), GFP_KERNEL); | ||
76 | if (!rd) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | memset(rd, 0, sizeof(*rd)); | ||
80 | INIT_LIST_HEAD(&rd->component_list); | ||
81 | class_set_devdata(cdev, rd); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int raid_remove(struct transport_container *tc, struct device *dev, | ||
87 | struct class_device *cdev) | ||
88 | { | ||
89 | struct raid_data *rd = class_get_devdata(cdev); | ||
90 | struct raid_component *rc, *next; | ||
91 | class_set_devdata(cdev, NULL); | ||
92 | list_for_each_entry_safe(rc, next, &rd->component_list, node) { | ||
93 | char buf[40]; | ||
94 | snprintf(buf, sizeof(buf), "component-%d", rc->num); | ||
95 | list_del(&rc->node); | ||
96 | sysfs_remove_link(&cdev->kobj, buf); | ||
97 | kfree(rc); | ||
98 | } | ||
99 | kfree(class_get_devdata(cdev)); | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static DECLARE_TRANSPORT_CLASS(raid_class, | ||
104 | "raid_devices", | ||
105 | raid_setup, | ||
106 | raid_remove, | ||
107 | NULL); | ||
108 | |||
109 | static struct { | ||
110 | enum raid_state value; | ||
111 | char *name; | ||
112 | } raid_states[] = { | ||
113 | { RAID_ACTIVE, "active" }, | ||
114 | { RAID_DEGRADED, "degraded" }, | ||
115 | { RAID_RESYNCING, "resyncing" }, | ||
116 | { RAID_OFFLINE, "offline" }, | ||
117 | }; | ||
118 | |||
119 | static const char *raid_state_name(enum raid_state state) | ||
120 | { | ||
121 | int i; | ||
122 | char *name = NULL; | ||
123 | |||
124 | for (i = 0; i < sizeof(raid_states)/sizeof(raid_states[0]); i++) { | ||
125 | if (raid_states[i].value == state) { | ||
126 | name = raid_states[i].name; | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | return name; | ||
131 | } | ||
132 | |||
133 | |||
134 | #define raid_attr_show_internal(attr, fmt, var, code) \ | ||
135 | static ssize_t raid_show_##attr(struct class_device *cdev, char *buf) \ | ||
136 | { \ | ||
137 | struct raid_data *rd = class_get_devdata(cdev); \ | ||
138 | code \ | ||
139 | return snprintf(buf, 20, #fmt "\n", var); \ | ||
140 | } | ||
141 | |||
142 | #define raid_attr_ro_states(attr, states, code) \ | ||
143 | raid_attr_show_internal(attr, %s, name, \ | ||
144 | const char *name; \ | ||
145 | code \ | ||
146 | name = raid_##states##_name(rd->attr); \ | ||
147 | ) \ | ||
148 | static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL) | ||
149 | |||
150 | |||
151 | #define raid_attr_ro_internal(attr, code) \ | ||
152 | raid_attr_show_internal(attr, %d, rd->attr, code) \ | ||
153 | static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL) | ||
154 | |||
155 | #define ATTR_CODE(attr) \ | ||
156 | struct raid_internal *i = class_device_to_raid_internal(cdev); \ | ||
157 | if (i->f->get_##attr) \ | ||
158 | i->f->get_##attr(cdev->dev); | ||
159 | |||
160 | #define raid_attr_ro(attr) raid_attr_ro_internal(attr, ) | ||
161 | #define raid_attr_ro_fn(attr) raid_attr_ro_internal(attr, ATTR_CODE(attr)) | ||
162 | #define raid_attr_ro_state(attr) raid_attr_ro_states(attr, attr, ATTR_CODE(attr)) | ||
163 | |||
164 | raid_attr_ro(level); | ||
165 | raid_attr_ro_fn(resync); | ||
166 | raid_attr_ro_state(state); | ||
167 | |||
168 | void raid_component_add(struct raid_template *r,struct device *raid_dev, | ||
169 | struct device *component_dev) | ||
170 | { | ||
171 | struct class_device *cdev = | ||
172 | attribute_container_find_class_device(&r->raid_attrs.ac, | ||
173 | raid_dev); | ||
174 | struct raid_component *rc; | ||
175 | struct raid_data *rd = class_get_devdata(cdev); | ||
176 | char buf[40]; | ||
177 | |||
178 | rc = kmalloc(sizeof(*rc), GFP_KERNEL); | ||
179 | if (!rc) | ||
180 | return; | ||
181 | |||
182 | INIT_LIST_HEAD(&rc->node); | ||
183 | rc->dev = component_dev; | ||
184 | rc->num = rd->component_count++; | ||
185 | |||
186 | snprintf(buf, sizeof(buf), "component-%d", rc->num); | ||
187 | list_add_tail(&rc->node, &rd->component_list); | ||
188 | sysfs_create_link(&cdev->kobj, &component_dev->kobj, buf); | ||
189 | } | ||
190 | EXPORT_SYMBOL(raid_component_add); | ||
191 | |||
192 | struct raid_template * | ||
193 | raid_class_attach(struct raid_function_template *ft) | ||
194 | { | ||
195 | struct raid_internal *i = kmalloc(sizeof(struct raid_internal), | ||
196 | GFP_KERNEL); | ||
197 | int count = 0; | ||
198 | |||
199 | if (unlikely(!i)) | ||
200 | return NULL; | ||
201 | |||
202 | memset(i, 0, sizeof(*i)); | ||
203 | |||
204 | i->f = ft; | ||
205 | |||
206 | i->r.raid_attrs.ac.class = &raid_class.class; | ||
207 | i->r.raid_attrs.ac.match = raid_match; | ||
208 | i->r.raid_attrs.ac.attrs = &i->attrs[0]; | ||
209 | |||
210 | attribute_container_register(&i->r.raid_attrs.ac); | ||
211 | |||
212 | i->attrs[count++] = &class_device_attr_level; | ||
213 | i->attrs[count++] = &class_device_attr_resync; | ||
214 | i->attrs[count++] = &class_device_attr_state; | ||
215 | |||
216 | i->attrs[count] = NULL; | ||
217 | BUG_ON(count > RAID_NUM_ATTRS); | ||
218 | |||
219 | return &i->r; | ||
220 | } | ||
221 | EXPORT_SYMBOL(raid_class_attach); | ||
222 | |||
223 | void | ||
224 | raid_class_release(struct raid_template *r) | ||
225 | { | ||
226 | struct raid_internal *i = to_raid_internal(r); | ||
227 | |||
228 | attribute_container_unregister(&i->r.raid_attrs.ac); | ||
229 | |||
230 | kfree(i); | ||
231 | } | ||
232 | EXPORT_SYMBOL(raid_class_release); | ||
233 | |||
234 | static __init int raid_init(void) | ||
235 | { | ||
236 | return transport_class_register(&raid_class); | ||
237 | } | ||
238 | |||
239 | static __exit void raid_exit(void) | ||
240 | { | ||
241 | transport_class_unregister(&raid_class); | ||
242 | } | ||
243 | |||
244 | MODULE_AUTHOR("James Bottomley"); | ||
245 | MODULE_DESCRIPTION("RAID device class"); | ||
246 | MODULE_LICENSE("GPL"); | ||
247 | |||
248 | module_init(raid_init); | ||
249 | module_exit(raid_exit); | ||
250 | |||
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index b444ec2e1c64..07b554affcf2 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c | |||
@@ -192,6 +192,7 @@ static struct { | |||
192 | {"SGI", "RAID5", "*", BLIST_SPARSELUN}, | 192 | {"SGI", "RAID5", "*", BLIST_SPARSELUN}, |
193 | {"SGI", "TP9100", "*", BLIST_REPORTLUN2}, | 193 | {"SGI", "TP9100", "*", BLIST_REPORTLUN2}, |
194 | {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, | 194 | {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, |
195 | {"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, | ||
195 | {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36}, | 196 | {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36}, |
196 | {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, | 197 | {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, |
197 | {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ | 198 | {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2686d5672e5e..895c9452be4c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/string.h> | 20 | #include <linux/string.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/kthread.h> | ||
23 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
24 | #include <linux/blkdev.h> | 25 | #include <linux/blkdev.h> |
25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
@@ -115,7 +116,6 @@ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, | |||
115 | 116 | ||
116 | add_timer(&scmd->eh_timeout); | 117 | add_timer(&scmd->eh_timeout); |
117 | } | 118 | } |
118 | EXPORT_SYMBOL(scsi_add_timer); | ||
119 | 119 | ||
120 | /** | 120 | /** |
121 | * scsi_delete_timer - Delete/cancel timer for a given function. | 121 | * scsi_delete_timer - Delete/cancel timer for a given function. |
@@ -143,7 +143,6 @@ int scsi_delete_timer(struct scsi_cmnd *scmd) | |||
143 | 143 | ||
144 | return rtn; | 144 | return rtn; |
145 | } | 145 | } |
146 | EXPORT_SYMBOL(scsi_delete_timer); | ||
147 | 146 | ||
148 | /** | 147 | /** |
149 | * scsi_times_out - Timeout function for normal scsi commands. | 148 | * scsi_times_out - Timeout function for normal scsi commands. |
@@ -776,9 +775,11 @@ retry_tur: | |||
776 | __FUNCTION__, scmd, rtn)); | 775 | __FUNCTION__, scmd, rtn)); |
777 | if (rtn == SUCCESS) | 776 | if (rtn == SUCCESS) |
778 | return 0; | 777 | return 0; |
779 | else if (rtn == NEEDS_RETRY) | 778 | else if (rtn == NEEDS_RETRY) { |
780 | if (retry_cnt--) | 779 | if (retry_cnt--) |
781 | goto retry_tur; | 780 | goto retry_tur; |
781 | return 0; | ||
782 | } | ||
782 | return 1; | 783 | return 1; |
783 | } | 784 | } |
784 | 785 | ||
@@ -1583,16 +1584,8 @@ int scsi_error_handler(void *data) | |||
1583 | int rtn; | 1584 | int rtn; |
1584 | DECLARE_MUTEX_LOCKED(sem); | 1585 | DECLARE_MUTEX_LOCKED(sem); |
1585 | 1586 | ||
1586 | /* | ||
1587 | * Flush resources | ||
1588 | */ | ||
1589 | |||
1590 | daemonize("scsi_eh_%d", shost->host_no); | ||
1591 | |||
1592 | current->flags |= PF_NOFREEZE; | 1587 | current->flags |= PF_NOFREEZE; |
1593 | |||
1594 | shost->eh_wait = &sem; | 1588 | shost->eh_wait = &sem; |
1595 | shost->ehandler = current; | ||
1596 | 1589 | ||
1597 | /* | 1590 | /* |
1598 | * Wake up the thread that created us. | 1591 | * Wake up the thread that created us. |
@@ -1600,8 +1593,6 @@ int scsi_error_handler(void *data) | |||
1600 | SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" | 1593 | SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" |
1601 | " scsi_eh_%d\n",shost->host_no)); | 1594 | " scsi_eh_%d\n",shost->host_no)); |
1602 | 1595 | ||
1603 | complete(shost->eh_notify); | ||
1604 | |||
1605 | while (1) { | 1596 | while (1) { |
1606 | /* | 1597 | /* |
1607 | * If we get a signal, it means we are supposed to go | 1598 | * If we get a signal, it means we are supposed to go |
@@ -1622,7 +1613,7 @@ int scsi_error_handler(void *data) | |||
1622 | * semaphores isn't unreasonable. | 1613 | * semaphores isn't unreasonable. |
1623 | */ | 1614 | */ |
1624 | down_interruptible(&sem); | 1615 | down_interruptible(&sem); |
1625 | if (shost->eh_kill) | 1616 | if (kthread_should_stop()) |
1626 | break; | 1617 | break; |
1627 | 1618 | ||
1628 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" | 1619 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" |
@@ -1661,22 +1652,6 @@ int scsi_error_handler(void *data) | |||
1661 | * Make sure that nobody tries to wake us up again. | 1652 | * Make sure that nobody tries to wake us up again. |
1662 | */ | 1653 | */ |
1663 | shost->eh_wait = NULL; | 1654 | shost->eh_wait = NULL; |
1664 | |||
1665 | /* | ||
1666 | * Knock this down too. From this point on, the host is flying | ||
1667 | * without a pilot. If this is because the module is being unloaded, | ||
1668 | * that's fine. If the user sent a signal to this thing, we are | ||
1669 | * potentially in real danger. | ||
1670 | */ | ||
1671 | shost->eh_active = 0; | ||
1672 | shost->ehandler = NULL; | ||
1673 | |||
1674 | /* | ||
1675 | * If anyone is waiting for us to exit (i.e. someone trying to unload | ||
1676 | * a driver), then wake up that process to let them know we are on | ||
1677 | * the way out the door. | ||
1678 | */ | ||
1679 | complete_and_exit(shost->eh_notify, 0); | ||
1680 | return 0; | 1655 | return 0; |
1681 | } | 1656 | } |
1682 | 1657 | ||
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 179a767d221d..b7fddac81347 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c | |||
@@ -30,20 +30,20 @@ | |||
30 | 30 | ||
31 | #define MAX_BUF PAGE_SIZE | 31 | #define MAX_BUF PAGE_SIZE |
32 | 32 | ||
33 | /* | 33 | /** |
34 | * If we are told to probe a host, we will return 0 if the host is not | 34 | * ioctl_probe -- return host identification |
35 | * present, 1 if the host is present, and will return an identifying | 35 | * @host: host to identify |
36 | * string at *arg, if arg is non null, filling to the length stored at | 36 | * @buffer: userspace buffer for identification |
37 | * (int *) arg | 37 | * |
38 | * Return an identifying string at @buffer, if @buffer is non-NULL, filling | ||
39 | * to the length stored at * (int *) @buffer. | ||
38 | */ | 40 | */ |
39 | |||
40 | static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) | 41 | static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) |
41 | { | 42 | { |
42 | unsigned int len, slen; | 43 | unsigned int len, slen; |
43 | const char *string; | 44 | const char *string; |
44 | int temp = host->hostt->present; | ||
45 | 45 | ||
46 | if (temp && buffer) { | 46 | if (buffer) { |
47 | if (get_user(len, (unsigned int __user *) buffer)) | 47 | if (get_user(len, (unsigned int __user *) buffer)) |
48 | return -EFAULT; | 48 | return -EFAULT; |
49 | 49 | ||
@@ -59,7 +59,7 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) | |||
59 | return -EFAULT; | 59 | return -EFAULT; |
60 | } | 60 | } |
61 | } | 61 | } |
62 | return temp; | 62 | return 1; |
63 | } | 63 | } |
64 | 64 | ||
65 | /* | 65 | /* |
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index d30d7f4e63ec..ee6de1768e53 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
@@ -63,6 +63,9 @@ extern int __init scsi_init_devinfo(void); | |||
63 | extern void scsi_exit_devinfo(void); | 63 | extern void scsi_exit_devinfo(void); |
64 | 64 | ||
65 | /* scsi_error.c */ | 65 | /* scsi_error.c */ |
66 | extern void scsi_add_timer(struct scsi_cmnd *, int, | ||
67 | void (*)(struct scsi_cmnd *)); | ||
68 | extern int scsi_delete_timer(struct scsi_cmnd *); | ||
66 | extern void scsi_times_out(struct scsi_cmnd *cmd); | 69 | extern void scsi_times_out(struct scsi_cmnd *cmd); |
67 | extern int scsi_error_handler(void *host); | 70 | extern int scsi_error_handler(void *host); |
68 | extern int scsi_decide_disposition(struct scsi_cmnd *cmd); | 71 | extern int scsi_decide_disposition(struct scsi_cmnd *cmd); |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 611ccde84778..de564b386052 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -972,7 +972,7 @@ static void | |||
972 | sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) | 972 | sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) |
973 | { | 973 | { |
974 | unsigned char cmd[10]; | 974 | unsigned char cmd[10]; |
975 | unsigned long spintime_value = 0; | 975 | unsigned long spintime_expire = 0; |
976 | int retries, spintime; | 976 | int retries, spintime; |
977 | unsigned int the_result; | 977 | unsigned int the_result; |
978 | struct scsi_sense_hdr sshdr; | 978 | struct scsi_sense_hdr sshdr; |
@@ -1049,12 +1049,27 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) | |||
1049 | scsi_execute_req(sdkp->device, cmd, DMA_NONE, | 1049 | scsi_execute_req(sdkp->device, cmd, DMA_NONE, |
1050 | NULL, 0, &sshdr, | 1050 | NULL, 0, &sshdr, |
1051 | SD_TIMEOUT, SD_MAX_RETRIES); | 1051 | SD_TIMEOUT, SD_MAX_RETRIES); |
1052 | spintime_value = jiffies; | 1052 | spintime_expire = jiffies + 100 * HZ; |
1053 | spintime = 1; | ||
1053 | } | 1054 | } |
1054 | spintime = 1; | ||
1055 | /* Wait 1 second for next try */ | 1055 | /* Wait 1 second for next try */ |
1056 | msleep(1000); | 1056 | msleep(1000); |
1057 | printk("."); | 1057 | printk("."); |
1058 | |||
1059 | /* | ||
1060 | * Wait for USB flash devices with slow firmware. | ||
1061 | * Yes, this sense key/ASC combination shouldn't | ||
1062 | * occur here. It's characteristic of these devices. | ||
1063 | */ | ||
1064 | } else if (sense_valid && | ||
1065 | sshdr.sense_key == UNIT_ATTENTION && | ||
1066 | sshdr.asc == 0x28) { | ||
1067 | if (!spintime) { | ||
1068 | spintime_expire = jiffies + 5 * HZ; | ||
1069 | spintime = 1; | ||
1070 | } | ||
1071 | /* Wait 1 second for next try */ | ||
1072 | msleep(1000); | ||
1058 | } else { | 1073 | } else { |
1059 | /* we don't understand the sense code, so it's | 1074 | /* we don't understand the sense code, so it's |
1060 | * probably pointless to loop */ | 1075 | * probably pointless to loop */ |
@@ -1066,8 +1081,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) | |||
1066 | break; | 1081 | break; |
1067 | } | 1082 | } |
1068 | 1083 | ||
1069 | } while (spintime && | 1084 | } while (spintime && time_before_eq(jiffies, spintime_expire)); |
1070 | time_after(spintime_value + 100 * HZ, jiffies)); | ||
1071 | 1085 | ||
1072 | if (spintime) { | 1086 | if (spintime) { |
1073 | if (scsi_status_is_good(the_result)) | 1087 | if (scsi_status_is_good(the_result)) |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 052d55c167d4..b1b69d738d08 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -61,7 +61,7 @@ static int sg_version_num = 30533; /* 2 digits for each component */ | |||
61 | 61 | ||
62 | #ifdef CONFIG_SCSI_PROC_FS | 62 | #ifdef CONFIG_SCSI_PROC_FS |
63 | #include <linux/proc_fs.h> | 63 | #include <linux/proc_fs.h> |
64 | static char *sg_version_date = "20050328"; | 64 | static char *sg_version_date = "20050901"; |
65 | 65 | ||
66 | static int sg_proc_init(void); | 66 | static int sg_proc_init(void); |
67 | static void sg_proc_cleanup(void); | 67 | static void sg_proc_cleanup(void); |
@@ -1794,12 +1794,12 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, | |||
1794 | unsigned long uaddr, size_t count, int rw, | 1794 | unsigned long uaddr, size_t count, int rw, |
1795 | unsigned long max_pfn) | 1795 | unsigned long max_pfn) |
1796 | { | 1796 | { |
1797 | unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
1798 | unsigned long start = uaddr >> PAGE_SHIFT; | ||
1799 | const int nr_pages = end - start; | ||
1797 | int res, i, j; | 1800 | int res, i, j; |
1798 | unsigned int nr_pages; | ||
1799 | struct page **pages; | 1801 | struct page **pages; |
1800 | 1802 | ||
1801 | nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; | ||
1802 | |||
1803 | /* User attempted Overflow! */ | 1803 | /* User attempted Overflow! */ |
1804 | if ((uaddr + count) < uaddr) | 1804 | if ((uaddr + count) < uaddr) |
1805 | return -EINVAL; | 1805 | return -EINVAL; |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 9aadf2fcad6a..a93308ae9736 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -17,7 +17,7 @@ | |||
17 | Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support | 17 | Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support |
18 | */ | 18 | */ |
19 | 19 | ||
20 | static char *verstr = "20050802"; | 20 | static char *verstr = "20050830"; |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | 23 | ||
@@ -4440,12 +4440,12 @@ static int st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pag | |||
4440 | static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, | 4440 | static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, |
4441 | unsigned long uaddr, size_t count, int rw) | 4441 | unsigned long uaddr, size_t count, int rw) |
4442 | { | 4442 | { |
4443 | unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
4444 | unsigned long start = uaddr >> PAGE_SHIFT; | ||
4445 | const int nr_pages = end - start; | ||
4443 | int res, i, j; | 4446 | int res, i, j; |
4444 | unsigned int nr_pages; | ||
4445 | struct page **pages; | 4447 | struct page **pages; |
4446 | 4448 | ||
4447 | nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; | ||
4448 | |||
4449 | /* User attempted Overflow! */ | 4449 | /* User attempted Overflow! */ |
4450 | if ((uaddr + count) < uaddr) | 4450 | if ((uaddr + count) < uaddr) |
4451 | return -EINVAL; | 4451 | return -EINVAL; |