diff options
Diffstat (limited to 'drivers/scsi/stex.c')
-rw-r--r-- | drivers/scsi/stex.c | 282 |
1 files changed, 190 insertions, 92 deletions
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 09fa8861fc58..3058bb1aff95 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c | |||
@@ -36,11 +36,11 @@ | |||
36 | #include <scsi/scsi_eh.h> | 36 | #include <scsi/scsi_eh.h> |
37 | 37 | ||
38 | #define DRV_NAME "stex" | 38 | #define DRV_NAME "stex" |
39 | #define ST_DRIVER_VERSION "4.6.0000.3" | 39 | #define ST_DRIVER_VERSION "4.6.0000.4" |
40 | #define ST_VER_MAJOR 4 | 40 | #define ST_VER_MAJOR 4 |
41 | #define ST_VER_MINOR 6 | 41 | #define ST_VER_MINOR 6 |
42 | #define ST_OEM 0 | 42 | #define ST_OEM 0 |
43 | #define ST_BUILD_VER 3 | 43 | #define ST_BUILD_VER 4 |
44 | 44 | ||
45 | enum { | 45 | enum { |
46 | /* MU register offset */ | 46 | /* MU register offset */ |
@@ -64,24 +64,24 @@ enum { | |||
64 | YH2I_REQ_HI = 0xc4, | 64 | YH2I_REQ_HI = 0xc4, |
65 | 65 | ||
66 | /* MU register value */ | 66 | /* MU register value */ |
67 | MU_INBOUND_DOORBELL_HANDSHAKE = 1, | 67 | MU_INBOUND_DOORBELL_HANDSHAKE = (1 << 0), |
68 | MU_INBOUND_DOORBELL_REQHEADCHANGED = 2, | 68 | MU_INBOUND_DOORBELL_REQHEADCHANGED = (1 << 1), |
69 | MU_INBOUND_DOORBELL_STATUSTAILCHANGED = 4, | 69 | MU_INBOUND_DOORBELL_STATUSTAILCHANGED = (1 << 2), |
70 | MU_INBOUND_DOORBELL_HMUSTOPPED = 8, | 70 | MU_INBOUND_DOORBELL_HMUSTOPPED = (1 << 3), |
71 | MU_INBOUND_DOORBELL_RESET = 16, | 71 | MU_INBOUND_DOORBELL_RESET = (1 << 4), |
72 | 72 | ||
73 | MU_OUTBOUND_DOORBELL_HANDSHAKE = 1, | 73 | MU_OUTBOUND_DOORBELL_HANDSHAKE = (1 << 0), |
74 | MU_OUTBOUND_DOORBELL_REQUESTTAILCHANGED = 2, | 74 | MU_OUTBOUND_DOORBELL_REQUESTTAILCHANGED = (1 << 1), |
75 | MU_OUTBOUND_DOORBELL_STATUSHEADCHANGED = 4, | 75 | MU_OUTBOUND_DOORBELL_STATUSHEADCHANGED = (1 << 2), |
76 | MU_OUTBOUND_DOORBELL_BUSCHANGE = 8, | 76 | MU_OUTBOUND_DOORBELL_BUSCHANGE = (1 << 3), |
77 | MU_OUTBOUND_DOORBELL_HASEVENT = 16, | 77 | MU_OUTBOUND_DOORBELL_HASEVENT = (1 << 4), |
78 | MU_OUTBOUND_DOORBELL_REQUEST_RESET = (1 << 27), | ||
78 | 79 | ||
79 | /* MU status code */ | 80 | /* MU status code */ |
80 | MU_STATE_STARTING = 1, | 81 | MU_STATE_STARTING = 1, |
81 | MU_STATE_FMU_READY_FOR_HANDSHAKE = 2, | 82 | MU_STATE_STARTED = 2, |
82 | MU_STATE_SEND_HANDSHAKE_FRAME = 3, | 83 | MU_STATE_RESETTING = 3, |
83 | MU_STATE_STARTED = 4, | 84 | MU_STATE_FAILED = 4, |
84 | MU_STATE_RESETTING = 5, | ||
85 | 85 | ||
86 | MU_MAX_DELAY = 120, | 86 | MU_MAX_DELAY = 120, |
87 | MU_HANDSHAKE_SIGNATURE = 0x55aaaa55, | 87 | MU_HANDSHAKE_SIGNATURE = 0x55aaaa55, |
@@ -111,6 +111,8 @@ enum { | |||
111 | 111 | ||
112 | SS_H2I_INT_RESET = 0x100, | 112 | SS_H2I_INT_RESET = 0x100, |
113 | 113 | ||
114 | SS_I2H_REQUEST_RESET = 0x2000, | ||
115 | |||
114 | SS_MU_OPERATIONAL = 0x80000000, | 116 | SS_MU_OPERATIONAL = 0x80000000, |
115 | 117 | ||
116 | STEX_CDB_LENGTH = 16, | 118 | STEX_CDB_LENGTH = 16, |
@@ -160,6 +162,7 @@ enum { | |||
160 | INQUIRY_EVPD = 0x01, | 162 | INQUIRY_EVPD = 0x01, |
161 | 163 | ||
162 | ST_ADDITIONAL_MEM = 0x200000, | 164 | ST_ADDITIONAL_MEM = 0x200000, |
165 | ST_ADDITIONAL_MEM_MIN = 0x80000, | ||
163 | }; | 166 | }; |
164 | 167 | ||
165 | struct st_sgitem { | 168 | struct st_sgitem { |
@@ -311,6 +314,10 @@ struct st_hba { | |||
311 | struct st_ccb *wait_ccb; | 314 | struct st_ccb *wait_ccb; |
312 | __le32 *scratch; | 315 | __le32 *scratch; |
313 | 316 | ||
317 | char work_q_name[20]; | ||
318 | struct workqueue_struct *work_q; | ||
319 | struct work_struct reset_work; | ||
320 | wait_queue_head_t reset_waitq; | ||
314 | unsigned int mu_status; | 321 | unsigned int mu_status; |
315 | unsigned int cardtype; | 322 | unsigned int cardtype; |
316 | int msi_enabled; | 323 | int msi_enabled; |
@@ -577,6 +584,9 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) | |||
577 | lun = cmd->device->lun; | 584 | lun = cmd->device->lun; |
578 | hba = (struct st_hba *) &host->hostdata[0]; | 585 | hba = (struct st_hba *) &host->hostdata[0]; |
579 | 586 | ||
587 | if (unlikely(hba->mu_status == MU_STATE_RESETTING)) | ||
588 | return SCSI_MLQUEUE_HOST_BUSY; | ||
589 | |||
580 | switch (cmd->cmnd[0]) { | 590 | switch (cmd->cmnd[0]) { |
581 | case MODE_SENSE_10: | 591 | case MODE_SENSE_10: |
582 | { | 592 | { |
@@ -841,7 +851,6 @@ static irqreturn_t stex_intr(int irq, void *__hba) | |||
841 | void __iomem *base = hba->mmio_base; | 851 | void __iomem *base = hba->mmio_base; |
842 | u32 data; | 852 | u32 data; |
843 | unsigned long flags; | 853 | unsigned long flags; |
844 | int handled = 0; | ||
845 | 854 | ||
846 | spin_lock_irqsave(hba->host->host_lock, flags); | 855 | spin_lock_irqsave(hba->host->host_lock, flags); |
847 | 856 | ||
@@ -852,12 +861,16 @@ static irqreturn_t stex_intr(int irq, void *__hba) | |||
852 | writel(data, base + ODBL); | 861 | writel(data, base + ODBL); |
853 | readl(base + ODBL); /* flush */ | 862 | readl(base + ODBL); /* flush */ |
854 | stex_mu_intr(hba, data); | 863 | stex_mu_intr(hba, data); |
855 | handled = 1; | 864 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
865 | if (unlikely(data & MU_OUTBOUND_DOORBELL_REQUEST_RESET && | ||
866 | hba->cardtype == st_shasta)) | ||
867 | queue_work(hba->work_q, &hba->reset_work); | ||
868 | return IRQ_HANDLED; | ||
856 | } | 869 | } |
857 | 870 | ||
858 | spin_unlock_irqrestore(hba->host->host_lock, flags); | 871 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
859 | 872 | ||
860 | return IRQ_RETVAL(handled); | 873 | return IRQ_NONE; |
861 | } | 874 | } |
862 | 875 | ||
863 | static void stex_ss_mu_intr(struct st_hba *hba) | 876 | static void stex_ss_mu_intr(struct st_hba *hba) |
@@ -939,7 +952,6 @@ static irqreturn_t stex_ss_intr(int irq, void *__hba) | |||
939 | void __iomem *base = hba->mmio_base; | 952 | void __iomem *base = hba->mmio_base; |
940 | u32 data; | 953 | u32 data; |
941 | unsigned long flags; | 954 | unsigned long flags; |
942 | int handled = 0; | ||
943 | 955 | ||
944 | spin_lock_irqsave(hba->host->host_lock, flags); | 956 | spin_lock_irqsave(hba->host->host_lock, flags); |
945 | 957 | ||
@@ -948,12 +960,15 @@ static irqreturn_t stex_ss_intr(int irq, void *__hba) | |||
948 | /* clear the interrupt */ | 960 | /* clear the interrupt */ |
949 | writel(data, base + YI2H_INT_C); | 961 | writel(data, base + YI2H_INT_C); |
950 | stex_ss_mu_intr(hba); | 962 | stex_ss_mu_intr(hba); |
951 | handled = 1; | 963 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
964 | if (unlikely(data & SS_I2H_REQUEST_RESET)) | ||
965 | queue_work(hba->work_q, &hba->reset_work); | ||
966 | return IRQ_HANDLED; | ||
952 | } | 967 | } |
953 | 968 | ||
954 | spin_unlock_irqrestore(hba->host->host_lock, flags); | 969 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
955 | 970 | ||
956 | return IRQ_RETVAL(handled); | 971 | return IRQ_NONE; |
957 | } | 972 | } |
958 | 973 | ||
959 | static int stex_common_handshake(struct st_hba *hba) | 974 | static int stex_common_handshake(struct st_hba *hba) |
@@ -1001,7 +1016,7 @@ static int stex_common_handshake(struct st_hba *hba) | |||
1001 | h->partner_type = HMU_PARTNER_TYPE; | 1016 | h->partner_type = HMU_PARTNER_TYPE; |
1002 | if (hba->extra_offset) { | 1017 | if (hba->extra_offset) { |
1003 | h->extra_offset = cpu_to_le32(hba->extra_offset); | 1018 | h->extra_offset = cpu_to_le32(hba->extra_offset); |
1004 | h->extra_size = cpu_to_le32(ST_ADDITIONAL_MEM); | 1019 | h->extra_size = cpu_to_le32(hba->dma_size - hba->extra_offset); |
1005 | } else | 1020 | } else |
1006 | h->extra_offset = h->extra_size = 0; | 1021 | h->extra_offset = h->extra_size = 0; |
1007 | 1022 | ||
@@ -1046,7 +1061,7 @@ static int stex_ss_handshake(struct st_hba *hba) | |||
1046 | struct st_msg_header *msg_h; | 1061 | struct st_msg_header *msg_h; |
1047 | struct handshake_frame *h; | 1062 | struct handshake_frame *h; |
1048 | __le32 *scratch; | 1063 | __le32 *scratch; |
1049 | u32 data; | 1064 | u32 data, scratch_size; |
1050 | unsigned long before; | 1065 | unsigned long before; |
1051 | int ret = 0; | 1066 | int ret = 0; |
1052 | 1067 | ||
@@ -1074,13 +1089,16 @@ static int stex_ss_handshake(struct st_hba *hba) | |||
1074 | stex_gettime(&h->hosttime); | 1089 | stex_gettime(&h->hosttime); |
1075 | h->partner_type = HMU_PARTNER_TYPE; | 1090 | h->partner_type = HMU_PARTNER_TYPE; |
1076 | h->extra_offset = h->extra_size = 0; | 1091 | h->extra_offset = h->extra_size = 0; |
1077 | h->scratch_size = cpu_to_le32((hba->sts_count+1)*sizeof(u32)); | 1092 | scratch_size = (hba->sts_count+1)*sizeof(u32); |
1093 | h->scratch_size = cpu_to_le32(scratch_size); | ||
1078 | 1094 | ||
1079 | data = readl(base + YINT_EN); | 1095 | data = readl(base + YINT_EN); |
1080 | data &= ~4; | 1096 | data &= ~4; |
1081 | writel(data, base + YINT_EN); | 1097 | writel(data, base + YINT_EN); |
1082 | writel((hba->dma_handle >> 16) >> 16, base + YH2I_REQ_HI); | 1098 | writel((hba->dma_handle >> 16) >> 16, base + YH2I_REQ_HI); |
1099 | readl(base + YH2I_REQ_HI); | ||
1083 | writel(hba->dma_handle, base + YH2I_REQ); | 1100 | writel(hba->dma_handle, base + YH2I_REQ); |
1101 | readl(base + YH2I_REQ); /* flush */ | ||
1084 | 1102 | ||
1085 | scratch = hba->scratch; | 1103 | scratch = hba->scratch; |
1086 | before = jiffies; | 1104 | before = jiffies; |
@@ -1096,7 +1114,7 @@ static int stex_ss_handshake(struct st_hba *hba) | |||
1096 | msleep(1); | 1114 | msleep(1); |
1097 | } | 1115 | } |
1098 | 1116 | ||
1099 | *scratch = 0; | 1117 | memset(scratch, 0, scratch_size); |
1100 | msg_h->flag = 0; | 1118 | msg_h->flag = 0; |
1101 | return ret; | 1119 | return ret; |
1102 | } | 1120 | } |
@@ -1105,19 +1123,24 @@ static int stex_handshake(struct st_hba *hba) | |||
1105 | { | 1123 | { |
1106 | int err; | 1124 | int err; |
1107 | unsigned long flags; | 1125 | unsigned long flags; |
1126 | unsigned int mu_status; | ||
1108 | 1127 | ||
1109 | err = (hba->cardtype == st_yel) ? | 1128 | err = (hba->cardtype == st_yel) ? |
1110 | stex_ss_handshake(hba) : stex_common_handshake(hba); | 1129 | stex_ss_handshake(hba) : stex_common_handshake(hba); |
1130 | spin_lock_irqsave(hba->host->host_lock, flags); | ||
1131 | mu_status = hba->mu_status; | ||
1111 | if (err == 0) { | 1132 | if (err == 0) { |
1112 | spin_lock_irqsave(hba->host->host_lock, flags); | ||
1113 | hba->req_head = 0; | 1133 | hba->req_head = 0; |
1114 | hba->req_tail = 0; | 1134 | hba->req_tail = 0; |
1115 | hba->status_head = 0; | 1135 | hba->status_head = 0; |
1116 | hba->status_tail = 0; | 1136 | hba->status_tail = 0; |
1117 | hba->out_req_cnt = 0; | 1137 | hba->out_req_cnt = 0; |
1118 | hba->mu_status = MU_STATE_STARTED; | 1138 | hba->mu_status = MU_STATE_STARTED; |
1119 | spin_unlock_irqrestore(hba->host->host_lock, flags); | 1139 | } else |
1120 | } | 1140 | hba->mu_status = MU_STATE_FAILED; |
1141 | if (mu_status == MU_STATE_RESETTING) | ||
1142 | wake_up_all(&hba->reset_waitq); | ||
1143 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
1121 | return err; | 1144 | return err; |
1122 | } | 1145 | } |
1123 | 1146 | ||
@@ -1137,17 +1160,11 @@ static int stex_abort(struct scsi_cmnd *cmd) | |||
1137 | 1160 | ||
1138 | base = hba->mmio_base; | 1161 | base = hba->mmio_base; |
1139 | spin_lock_irqsave(host->host_lock, flags); | 1162 | spin_lock_irqsave(host->host_lock, flags); |
1140 | if (tag < host->can_queue && hba->ccb[tag].cmd == cmd) | 1163 | if (tag < host->can_queue && |
1164 | hba->ccb[tag].req && hba->ccb[tag].cmd == cmd) | ||
1141 | hba->wait_ccb = &hba->ccb[tag]; | 1165 | hba->wait_ccb = &hba->ccb[tag]; |
1142 | else { | 1166 | else |
1143 | for (tag = 0; tag < host->can_queue; tag++) | 1167 | goto out; |
1144 | if (hba->ccb[tag].cmd == cmd) { | ||
1145 | hba->wait_ccb = &hba->ccb[tag]; | ||
1146 | break; | ||
1147 | } | ||
1148 | if (tag >= host->can_queue) | ||
1149 | goto out; | ||
1150 | } | ||
1151 | 1168 | ||
1152 | if (hba->cardtype == st_yel) { | 1169 | if (hba->cardtype == st_yel) { |
1153 | data = readl(base + YI2H_INT); | 1170 | data = readl(base + YI2H_INT); |
@@ -1221,6 +1238,37 @@ static void stex_hard_reset(struct st_hba *hba) | |||
1221 | hba->pdev->saved_config_space[i]); | 1238 | hba->pdev->saved_config_space[i]); |
1222 | } | 1239 | } |
1223 | 1240 | ||
1241 | static int stex_yos_reset(struct st_hba *hba) | ||
1242 | { | ||
1243 | void __iomem *base; | ||
1244 | unsigned long flags, before; | ||
1245 | int ret = 0; | ||
1246 | |||
1247 | base = hba->mmio_base; | ||
1248 | writel(MU_INBOUND_DOORBELL_RESET, base + IDBL); | ||
1249 | readl(base + IDBL); /* flush */ | ||
1250 | before = jiffies; | ||
1251 | while (hba->out_req_cnt > 0) { | ||
1252 | if (time_after(jiffies, before + ST_INTERNAL_TIMEOUT * HZ)) { | ||
1253 | printk(KERN_WARNING DRV_NAME | ||
1254 | "(%s): reset timeout\n", pci_name(hba->pdev)); | ||
1255 | ret = -1; | ||
1256 | break; | ||
1257 | } | ||
1258 | msleep(1); | ||
1259 | } | ||
1260 | |||
1261 | spin_lock_irqsave(hba->host->host_lock, flags); | ||
1262 | if (ret == -1) | ||
1263 | hba->mu_status = MU_STATE_FAILED; | ||
1264 | else | ||
1265 | hba->mu_status = MU_STATE_STARTED; | ||
1266 | wake_up_all(&hba->reset_waitq); | ||
1267 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
1268 | |||
1269 | return ret; | ||
1270 | } | ||
1271 | |||
1224 | static void stex_ss_reset(struct st_hba *hba) | 1272 | static void stex_ss_reset(struct st_hba *hba) |
1225 | { | 1273 | { |
1226 | writel(SS_H2I_INT_RESET, hba->mmio_base + YH2I_INT); | 1274 | writel(SS_H2I_INT_RESET, hba->mmio_base + YH2I_INT); |
@@ -1228,66 +1276,86 @@ static void stex_ss_reset(struct st_hba *hba) | |||
1228 | ssleep(5); | 1276 | ssleep(5); |
1229 | } | 1277 | } |
1230 | 1278 | ||
1231 | static int stex_reset(struct scsi_cmnd *cmd) | 1279 | static int stex_do_reset(struct st_hba *hba) |
1232 | { | 1280 | { |
1233 | struct st_hba *hba; | 1281 | struct st_ccb *ccb; |
1234 | void __iomem *base; | 1282 | unsigned long flags; |
1235 | unsigned long flags, before; | 1283 | unsigned int mu_status = MU_STATE_RESETTING; |
1284 | u16 tag; | ||
1236 | 1285 | ||
1237 | hba = (struct st_hba *) &cmd->device->host->hostdata[0]; | 1286 | spin_lock_irqsave(hba->host->host_lock, flags); |
1287 | if (hba->mu_status == MU_STATE_STARTING) { | ||
1288 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
1289 | printk(KERN_INFO DRV_NAME "(%s): request reset during init\n", | ||
1290 | pci_name(hba->pdev)); | ||
1291 | return 0; | ||
1292 | } | ||
1293 | while (hba->mu_status == MU_STATE_RESETTING) { | ||
1294 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
1295 | wait_event_timeout(hba->reset_waitq, | ||
1296 | hba->mu_status != MU_STATE_RESETTING, | ||
1297 | MU_MAX_DELAY * HZ); | ||
1298 | spin_lock_irqsave(hba->host->host_lock, flags); | ||
1299 | mu_status = hba->mu_status; | ||
1300 | } | ||
1238 | 1301 | ||
1239 | printk(KERN_INFO DRV_NAME | 1302 | if (mu_status != MU_STATE_RESETTING) { |
1240 | "(%s): resetting host\n", pci_name(hba->pdev)); | 1303 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
1241 | scsi_print_command(cmd); | 1304 | return (mu_status == MU_STATE_STARTED) ? 0 : -1; |
1305 | } | ||
1242 | 1306 | ||
1243 | hba->mu_status = MU_STATE_RESETTING; | 1307 | hba->mu_status = MU_STATE_RESETTING; |
1308 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
1309 | |||
1310 | if (hba->cardtype == st_yosemite) | ||
1311 | return stex_yos_reset(hba); | ||
1244 | 1312 | ||
1245 | if (hba->cardtype == st_shasta) | 1313 | if (hba->cardtype == st_shasta) |
1246 | stex_hard_reset(hba); | 1314 | stex_hard_reset(hba); |
1247 | else if (hba->cardtype == st_yel) | 1315 | else if (hba->cardtype == st_yel) |
1248 | stex_ss_reset(hba); | 1316 | stex_ss_reset(hba); |
1249 | 1317 | ||
1250 | if (hba->cardtype != st_yosemite) { | 1318 | spin_lock_irqsave(hba->host->host_lock, flags); |
1251 | if (stex_handshake(hba)) { | 1319 | for (tag = 0; tag < hba->host->can_queue; tag++) { |
1252 | printk(KERN_WARNING DRV_NAME | 1320 | ccb = &hba->ccb[tag]; |
1253 | "(%s): resetting: handshake failed\n", | 1321 | if (ccb->req == NULL) |
1254 | pci_name(hba->pdev)); | 1322 | continue; |
1255 | return FAILED; | 1323 | ccb->req = NULL; |
1324 | if (ccb->cmd) { | ||
1325 | scsi_dma_unmap(ccb->cmd); | ||
1326 | ccb->cmd->result = DID_RESET << 16; | ||
1327 | ccb->cmd->scsi_done(ccb->cmd); | ||
1328 | ccb->cmd = NULL; | ||
1256 | } | 1329 | } |
1257 | return SUCCESS; | ||
1258 | } | 1330 | } |
1331 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
1259 | 1332 | ||
1260 | /* st_yosemite */ | 1333 | if (stex_handshake(hba) == 0) |
1261 | writel(MU_INBOUND_DOORBELL_RESET, hba->mmio_base + IDBL); | 1334 | return 0; |
1262 | readl(hba->mmio_base + IDBL); /* flush */ | ||
1263 | before = jiffies; | ||
1264 | while (hba->out_req_cnt > 0) { | ||
1265 | if (time_after(jiffies, before + ST_INTERNAL_TIMEOUT * HZ)) { | ||
1266 | printk(KERN_WARNING DRV_NAME | ||
1267 | "(%s): reset timeout\n", pci_name(hba->pdev)); | ||
1268 | return FAILED; | ||
1269 | } | ||
1270 | msleep(1); | ||
1271 | } | ||
1272 | 1335 | ||
1273 | base = hba->mmio_base; | 1336 | printk(KERN_WARNING DRV_NAME "(%s): resetting: handshake failed\n", |
1274 | writel(0, base + IMR0); | 1337 | pci_name(hba->pdev)); |
1275 | readl(base + IMR0); | 1338 | return -1; |
1276 | writel(0, base + OMR0); | 1339 | } |
1277 | readl(base + OMR0); | 1340 | |
1278 | writel(0, base + IMR1); | 1341 | static int stex_reset(struct scsi_cmnd *cmd) |
1279 | readl(base + IMR1); | 1342 | { |
1280 | writel(0, base + OMR1); | 1343 | struct st_hba *hba; |
1281 | readl(base + OMR1); /* flush */ | 1344 | |
1282 | spin_lock_irqsave(hba->host->host_lock, flags); | 1345 | hba = (struct st_hba *) &cmd->device->host->hostdata[0]; |
1283 | hba->req_head = 0; | 1346 | |
1284 | hba->req_tail = 0; | 1347 | printk(KERN_INFO DRV_NAME |
1285 | hba->status_head = 0; | 1348 | "(%s): resetting host\n", pci_name(hba->pdev)); |
1286 | hba->status_tail = 0; | 1349 | scsi_print_command(cmd); |
1287 | hba->out_req_cnt = 0; | 1350 | |
1288 | hba->mu_status = MU_STATE_STARTED; | 1351 | return stex_do_reset(hba) ? FAILED : SUCCESS; |
1289 | spin_unlock_irqrestore(hba->host->host_lock, flags); | 1352 | } |
1290 | return SUCCESS; | 1353 | |
1354 | static void stex_reset_work(struct work_struct *work) | ||
1355 | { | ||
1356 | struct st_hba *hba = container_of(work, struct st_hba, reset_work); | ||
1357 | |||
1358 | stex_do_reset(hba); | ||
1291 | } | 1359 | } |
1292 | 1360 | ||
1293 | static int stex_biosparam(struct scsi_device *sdev, | 1361 | static int stex_biosparam(struct scsi_device *sdev, |
@@ -1420,8 +1488,8 @@ static int stex_set_dma_mask(struct pci_dev * pdev) | |||
1420 | { | 1488 | { |
1421 | int ret; | 1489 | int ret; |
1422 | 1490 | ||
1423 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) | 1491 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) |
1424 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) | 1492 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) |
1425 | return 0; | 1493 | return 0; |
1426 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | 1494 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
1427 | if (!ret) | 1495 | if (!ret) |
@@ -1528,10 +1596,24 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1528 | hba->dma_mem = dma_alloc_coherent(&pdev->dev, | 1596 | hba->dma_mem = dma_alloc_coherent(&pdev->dev, |
1529 | hba->dma_size, &hba->dma_handle, GFP_KERNEL); | 1597 | hba->dma_size, &hba->dma_handle, GFP_KERNEL); |
1530 | if (!hba->dma_mem) { | 1598 | if (!hba->dma_mem) { |
1531 | err = -ENOMEM; | 1599 | /* Retry minimum coherent mapping for st_seq and st_vsc */ |
1532 | printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n", | 1600 | if (hba->cardtype == st_seq || |
1533 | pci_name(pdev)); | 1601 | (hba->cardtype == st_vsc && (pdev->subsystem_device & 1))) { |
1534 | goto out_iounmap; | 1602 | printk(KERN_WARNING DRV_NAME |
1603 | "(%s): allocating min buffer for controller\n", | ||
1604 | pci_name(pdev)); | ||
1605 | hba->dma_size = hba->extra_offset | ||
1606 | + ST_ADDITIONAL_MEM_MIN; | ||
1607 | hba->dma_mem = dma_alloc_coherent(&pdev->dev, | ||
1608 | hba->dma_size, &hba->dma_handle, GFP_KERNEL); | ||
1609 | } | ||
1610 | |||
1611 | if (!hba->dma_mem) { | ||
1612 | err = -ENOMEM; | ||
1613 | printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n", | ||
1614 | pci_name(pdev)); | ||
1615 | goto out_iounmap; | ||
1616 | } | ||
1535 | } | 1617 | } |
1536 | 1618 | ||
1537 | hba->ccb = kcalloc(ci->rq_count, sizeof(struct st_ccb), GFP_KERNEL); | 1619 | hba->ccb = kcalloc(ci->rq_count, sizeof(struct st_ccb), GFP_KERNEL); |
@@ -1568,12 +1650,24 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1568 | 1650 | ||
1569 | hba->host = host; | 1651 | hba->host = host; |
1570 | hba->pdev = pdev; | 1652 | hba->pdev = pdev; |
1653 | init_waitqueue_head(&hba->reset_waitq); | ||
1654 | |||
1655 | snprintf(hba->work_q_name, sizeof(hba->work_q_name), | ||
1656 | "stex_wq_%d", host->host_no); | ||
1657 | hba->work_q = create_singlethread_workqueue(hba->work_q_name); | ||
1658 | if (!hba->work_q) { | ||
1659 | printk(KERN_ERR DRV_NAME "(%s): create workqueue failed\n", | ||
1660 | pci_name(pdev)); | ||
1661 | err = -ENOMEM; | ||
1662 | goto out_ccb_free; | ||
1663 | } | ||
1664 | INIT_WORK(&hba->reset_work, stex_reset_work); | ||
1571 | 1665 | ||
1572 | err = stex_request_irq(hba); | 1666 | err = stex_request_irq(hba); |
1573 | if (err) { | 1667 | if (err) { |
1574 | printk(KERN_ERR DRV_NAME "(%s): request irq failed\n", | 1668 | printk(KERN_ERR DRV_NAME "(%s): request irq failed\n", |
1575 | pci_name(pdev)); | 1669 | pci_name(pdev)); |
1576 | goto out_ccb_free; | 1670 | goto out_free_wq; |
1577 | } | 1671 | } |
1578 | 1672 | ||
1579 | err = stex_handshake(hba); | 1673 | err = stex_handshake(hba); |
@@ -1602,6 +1696,8 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1602 | 1696 | ||
1603 | out_free_irq: | 1697 | out_free_irq: |
1604 | stex_free_irq(hba); | 1698 | stex_free_irq(hba); |
1699 | out_free_wq: | ||
1700 | destroy_workqueue(hba->work_q); | ||
1605 | out_ccb_free: | 1701 | out_ccb_free: |
1606 | kfree(hba->ccb); | 1702 | kfree(hba->ccb); |
1607 | out_pci_free: | 1703 | out_pci_free: |
@@ -1669,6 +1765,8 @@ static void stex_hba_free(struct st_hba *hba) | |||
1669 | { | 1765 | { |
1670 | stex_free_irq(hba); | 1766 | stex_free_irq(hba); |
1671 | 1767 | ||
1768 | destroy_workqueue(hba->work_q); | ||
1769 | |||
1672 | iounmap(hba->mmio_base); | 1770 | iounmap(hba->mmio_base); |
1673 | 1771 | ||
1674 | pci_release_regions(hba->pdev); | 1772 | pci_release_regions(hba->pdev); |