• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* gdth_proc.c
2  * $Id: gdth_proc.c,v 1.43 2006/01/11 16:15:00 achim Exp $
3  */
4 
5 #include <linux/completion.h>
6 #include <linux/slab.h>
7 
gdth_set_info(struct Scsi_Host * host,char * buffer,int length)8 int gdth_set_info(struct Scsi_Host *host, char *buffer, int length)
9 {
10     gdth_ha_str *ha = shost_priv(host);
11     int ret_val = -EINVAL;
12 
13     TRACE2(("gdth_set_info() ha %d\n",ha->hanum,));
14 
15     if (length >= 4) {
16         if (strncmp(buffer,"gdth",4) == 0) {
17             buffer += 5;
18             length -= 5;
19             ret_val = gdth_set_asc_info(host, buffer, length, ha);
20         }
21     }
22 
23     return ret_val;
24 }
25 
gdth_set_asc_info(struct Scsi_Host * host,char * buffer,int length,gdth_ha_str * ha)26 static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
27                         int length, gdth_ha_str *ha)
28 {
29     int orig_length, drive, wb_mode;
30     int i, found;
31     gdth_cmd_str    gdtcmd;
32     gdth_cpar_str   *pcpar;
33     u64         paddr;
34 
35     char            cmnd[MAX_COMMAND_SIZE];
36     memset(cmnd, 0xff, 12);
37     memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
38 
39     TRACE2(("gdth_set_asc_info() ha %d\n",ha->hanum));
40     orig_length = length + 5;
41     drive = -1;
42     wb_mode = 0;
43     found = FALSE;
44 
45     if (length >= 5 && strncmp(buffer,"flush",5)==0) {
46         buffer += 6;
47         length -= 6;
48         if (length && *buffer>='0' && *buffer<='9') {
49             drive = (int)(*buffer-'0');
50             ++buffer; --length;
51             if (length && *buffer>='0' && *buffer<='9') {
52                 drive = drive*10 + (int)(*buffer-'0');
53                 ++buffer; --length;
54             }
55             printk("GDT: Flushing host drive %d .. ",drive);
56         } else {
57             printk("GDT: Flushing all host drives .. ");
58         }
59         for (i = 0; i < MAX_HDRIVES; ++i) {
60             if (ha->hdr[i].present) {
61                 if (drive != -1 && i != drive)
62                     continue;
63                 found = TRUE;
64                 gdtcmd.Service = CACHESERVICE;
65                 gdtcmd.OpCode = GDT_FLUSH;
66                 if (ha->cache_feat & GDT_64BIT) {
67                     gdtcmd.u.cache64.DeviceNo = i;
68                     gdtcmd.u.cache64.BlockNo = 1;
69                 } else {
70                     gdtcmd.u.cache.DeviceNo = i;
71                     gdtcmd.u.cache.BlockNo = 1;
72                 }
73 
74                 gdth_execute(host, &gdtcmd, cmnd, 30, NULL);
75             }
76         }
77         if (!found)
78             printk("\nNo host drive found !\n");
79         else
80             printk("Done.\n");
81         return(orig_length);
82     }
83 
84     if (length >= 7 && strncmp(buffer,"wbp_off",7)==0) {
85         buffer += 8;
86         length -= 8;
87         printk("GDT: Disabling write back permanently .. ");
88         wb_mode = 1;
89     } else if (length >= 6 && strncmp(buffer,"wbp_on",6)==0) {
90         buffer += 7;
91         length -= 7;
92         printk("GDT: Enabling write back permanently .. ");
93         wb_mode = 2;
94     } else if (length >= 6 && strncmp(buffer,"wb_off",6)==0) {
95         buffer += 7;
96         length -= 7;
97         printk("GDT: Disabling write back commands .. ");
98         if (ha->cache_feat & GDT_WR_THROUGH) {
99             gdth_write_through = TRUE;
100             printk("Done.\n");
101         } else {
102             printk("Not supported !\n");
103         }
104         return(orig_length);
105     } else if (length >= 5 && strncmp(buffer,"wb_on",5)==0) {
106         buffer += 6;
107         length -= 6;
108         printk("GDT: Enabling write back commands .. ");
109         gdth_write_through = FALSE;
110         printk("Done.\n");
111         return(orig_length);
112     }
113 
114     if (wb_mode) {
115         if (!gdth_ioctl_alloc(ha, sizeof(gdth_cpar_str), TRUE, &paddr))
116             return(-EBUSY);
117         pcpar = (gdth_cpar_str *)ha->pscratch;
118         memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
119         gdtcmd.Service = CACHESERVICE;
120         gdtcmd.OpCode = GDT_IOCTL;
121         gdtcmd.u.ioctl.p_param = paddr;
122         gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str);
123         gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
124         gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
125         pcpar->write_back = wb_mode==1 ? 0:1;
126 
127         gdth_execute(host, &gdtcmd, cmnd, 30, NULL);
128 
129         gdth_ioctl_free(ha, GDTH_SCRATCH, ha->pscratch, paddr);
130         printk("Done.\n");
131         return(orig_length);
132     }
133 
134     printk("GDT: Unknown command: %s  Length: %d\n",buffer,length);
135     return(-EINVAL);
136 }
137 
gdth_show_info(struct seq_file * m,struct Scsi_Host * host)138 int gdth_show_info(struct seq_file *m, struct Scsi_Host *host)
139 {
140     gdth_ha_str *ha = shost_priv(host);
141     int hlen;
142     int id, i, j, k, sec, flag;
143     int no_mdrv = 0, drv_no, is_mirr;
144     u32 cnt;
145     u64 paddr;
146     int rc = -ENOMEM;
147 
148     gdth_cmd_str *gdtcmd;
149     gdth_evt_str *estr;
150     char hrec[161];
151     struct timeval tv;
152 
153     char *buf;
154     gdth_dskstat_str *pds;
155     gdth_diskinfo_str *pdi;
156     gdth_arrayinf_str *pai;
157     gdth_defcnt_str *pdef;
158     gdth_cdrinfo_str *pcdi;
159     gdth_hget_str *phg;
160     char cmnd[MAX_COMMAND_SIZE];
161 
162     gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL);
163     estr = kmalloc(sizeof(*estr), GFP_KERNEL);
164     if (!gdtcmd || !estr)
165         goto free_fail;
166 
167     memset(cmnd, 0xff, 12);
168     memset(gdtcmd, 0, sizeof(gdth_cmd_str));
169 
170     TRACE2(("gdth_get_info() ha %d\n",ha->hanum));
171 
172 
173     /* request is i.e. "cat /proc/scsi/gdth/0" */
174     /* format: %-15s\t%-10s\t%-15s\t%s */
175     /* driver parameters */
176     seq_printf(m, "Driver Parameters:\n");
177     if (reserve_list[0] == 0xff)
178         strcpy(hrec, "--");
179     else {
180         hlen = sprintf(hrec, "%d", reserve_list[0]);
181         for (i = 1;  i < MAX_RES_ARGS; i++) {
182             if (reserve_list[i] == 0xff)
183                 break;
184             hlen += snprintf(hrec + hlen , 161 - hlen, ",%d", reserve_list[i]);
185         }
186     }
187     seq_printf(m,
188                    " reserve_mode: \t%d         \treserve_list:  \t%s\n",
189                    reserve_mode, hrec);
190     seq_printf(m,
191                    " max_ids:      \t%-3d       \thdr_channel:   \t%d\n",
192                    max_ids, hdr_channel);
193 
194     /* controller information */
195     seq_printf(m,"\nDisk Array Controller Information:\n");
196     seq_printf(m,
197                    " Number:       \t%d         \tName:          \t%s\n",
198                    ha->hanum, ha->binfo.type_string);
199 
200     seq_printf(m,
201                    " Driver Ver.:  \t%-10s\tFirmware Ver.: \t",
202                    GDTH_VERSION_STR);
203     if (ha->more_proc)
204         seq_printf(m, "%d.%02d.%02d-%c%03X\n",
205                 (u8)(ha->binfo.upd_fw_ver>>24),
206                 (u8)(ha->binfo.upd_fw_ver>>16),
207                 (u8)(ha->binfo.upd_fw_ver),
208                 ha->bfeat.raid ? 'R':'N',
209                 ha->binfo.upd_revision);
210     else
211         seq_printf(m, "%d.%02d\n", (u8)(ha->cpar.version>>8),
212                 (u8)(ha->cpar.version));
213 
214     if (ha->more_proc)
215         /* more information: 1. about controller */
216         seq_printf(m,
217                        " Serial No.:   \t0x%8X\tCache RAM size:\t%d KB\n",
218                        ha->binfo.ser_no, ha->binfo.memsize / 1024);
219 
220 #ifdef GDTH_DMA_STATISTICS
221     /* controller statistics */
222     seq_printf(m,"\nController Statistics:\n");
223     seq_printf(m,
224                    " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n",
225                    ha->dma32_cnt, ha->dma64_cnt);
226 #endif
227 
228     if (ha->more_proc) {
229         /* more information: 2. about physical devices */
230         seq_printf(m, "\nPhysical Devices:");
231         flag = FALSE;
232 
233         buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
234         if (!buf)
235             goto stop_output;
236         for (i = 0; i < ha->bus_cnt; ++i) {
237             /* 2.a statistics (and retries/reassigns) */
238             TRACE2(("pdr_statistics() chn %d\n",i));
239             pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4);
240             gdtcmd->Service = CACHESERVICE;
241             gdtcmd->OpCode = GDT_IOCTL;
242             gdtcmd->u.ioctl.p_param = paddr + GDTH_SCRATCH/4;
243             gdtcmd->u.ioctl.param_size = 3*GDTH_SCRATCH/4;
244             gdtcmd->u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
245             gdtcmd->u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
246             pds->bid = ha->raw[i].local_no;
247             pds->first = 0;
248             pds->entries = ha->raw[i].pdev_cnt;
249             cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(u32)) /
250                 sizeof(pds->list[0]);
251             if (pds->entries > cnt)
252                 pds->entries = cnt;
253 
254             if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK)
255                 pds->count = 0;
256 
257             /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
258             for (j = 0; j < ha->raw[i].pdev_cnt; ++j) {
259                 /* 2.b drive info */
260                 TRACE2(("scsi_drv_info() chn %d dev %d\n",
261                     i, ha->raw[i].id_list[j]));
262                 pdi = (gdth_diskinfo_str *)buf;
263                 gdtcmd->Service = CACHESERVICE;
264                 gdtcmd->OpCode = GDT_IOCTL;
265                 gdtcmd->u.ioctl.p_param = paddr;
266                 gdtcmd->u.ioctl.param_size = sizeof(gdth_diskinfo_str);
267                 gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
268                 gdtcmd->u.ioctl.channel =
269                     ha->raw[i].address | ha->raw[i].id_list[j];
270 
271                 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
272                     strncpy(hrec,pdi->vendor,8);
273                     strncpy(hrec+8,pdi->product,16);
274                     strncpy(hrec+24,pdi->revision,4);
275                     hrec[28] = 0;
276                     seq_printf(m,
277                                    "\n Chn/ID/LUN:   \t%c/%02d/%d    \tName:          \t%s\n",
278                                    'A'+i,pdi->target_id,pdi->lun,hrec);
279                     flag = TRUE;
280                     pdi->no_ldrive &= 0xffff;
281                     if (pdi->no_ldrive == 0xffff)
282                         strcpy(hrec,"--");
283                     else
284                         sprintf(hrec,"%d",pdi->no_ldrive);
285                     seq_printf(m,
286                                    " Capacity [MB]:\t%-6d    \tTo Log. Drive: \t%s\n",
287                                    pdi->blkcnt/(1024*1024/pdi->blksize),
288                                    hrec);
289                 } else {
290                     pdi->devtype = 0xff;
291                 }
292 
293                 if (pdi->devtype == 0) {
294                     /* search retries/reassigns */
295                     for (k = 0; k < pds->count; ++k) {
296                         if (pds->list[k].tid == pdi->target_id &&
297                             pds->list[k].lun == pdi->lun) {
298                             seq_printf(m,
299                                            " Retries:      \t%-6d    \tReassigns:     \t%d\n",
300                                            pds->list[k].retries,
301                                            pds->list[k].reassigns);
302                             break;
303                         }
304                     }
305                     /* 2.c grown defects */
306                     TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
307                             i, ha->raw[i].id_list[j]));
308                     pdef = (gdth_defcnt_str *)buf;
309                     gdtcmd->Service = CACHESERVICE;
310                     gdtcmd->OpCode = GDT_IOCTL;
311                     gdtcmd->u.ioctl.p_param = paddr;
312                     gdtcmd->u.ioctl.param_size = sizeof(gdth_defcnt_str);
313                     gdtcmd->u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
314                     gdtcmd->u.ioctl.channel =
315                         ha->raw[i].address | ha->raw[i].id_list[j];
316                     pdef->sddc_type = 0x08;
317 
318                     if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
319                         seq_printf(m,
320                                        " Grown Defects:\t%d\n",
321                                        pdef->sddc_cnt);
322                     }
323                 }
324             }
325         }
326         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
327 
328         if (!flag)
329             seq_printf(m, "\n --\n");
330 
331         /* 3. about logical drives */
332         seq_printf(m,"\nLogical Drives:");
333         flag = FALSE;
334 
335         buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
336         if (!buf)
337             goto stop_output;
338         for (i = 0; i < MAX_LDRIVES; ++i) {
339             if (!ha->hdr[i].is_logdrv)
340                 continue;
341             drv_no = i;
342             j = k = 0;
343             is_mirr = FALSE;
344             do {
345                 /* 3.a log. drive info */
346                 TRACE2(("cache_drv_info() drive no %d\n",drv_no));
347                 pcdi = (gdth_cdrinfo_str *)buf;
348                 gdtcmd->Service = CACHESERVICE;
349                 gdtcmd->OpCode = GDT_IOCTL;
350                 gdtcmd->u.ioctl.p_param = paddr;
351                 gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
352                 gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO;
353                 gdtcmd->u.ioctl.channel = drv_no;
354                 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK)
355                     break;
356                 pcdi->ld_dtype >>= 16;
357                 j++;
358                 if (pcdi->ld_dtype > 2) {
359                     strcpy(hrec, "missing");
360                 } else if (pcdi->ld_error & 1) {
361                     strcpy(hrec, "fault");
362                 } else if (pcdi->ld_error & 2) {
363                     strcpy(hrec, "invalid");
364                     k++; j--;
365                 } else {
366                     strcpy(hrec, "ok");
367                 }
368 
369                 if (drv_no == i) {
370                     seq_printf(m,
371                                    "\n Number:       \t%-2d        \tStatus:        \t%s\n",
372                                    drv_no, hrec);
373                     flag = TRUE;
374                     no_mdrv = pcdi->cd_ldcnt;
375                     if (no_mdrv > 1 || pcdi->ld_slave != -1) {
376                         is_mirr = TRUE;
377                         strcpy(hrec, "RAID-1");
378                     } else if (pcdi->ld_dtype == 0) {
379                         strcpy(hrec, "Disk");
380                     } else if (pcdi->ld_dtype == 1) {
381                         strcpy(hrec, "RAID-0");
382                     } else if (pcdi->ld_dtype == 2) {
383                         strcpy(hrec, "Chain");
384                     } else {
385                         strcpy(hrec, "???");
386                     }
387                     seq_printf(m,
388                                    " Capacity [MB]:\t%-6d    \tType:          \t%s\n",
389                                    pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
390                                    hrec);
391                 } else {
392                     seq_printf(m,
393                                    " Slave Number: \t%-2d        \tStatus:        \t%s\n",
394                                    drv_no & 0x7fff, hrec);
395                 }
396                 drv_no = pcdi->ld_slave;
397             } while (drv_no != -1);
398 
399             if (is_mirr)
400                 seq_printf(m,
401                                " Missing Drv.: \t%-2d        \tInvalid Drv.:  \t%d\n",
402                                no_mdrv - j - k, k);
403 
404             if (!ha->hdr[i].is_arraydrv)
405                 strcpy(hrec, "--");
406             else
407                 sprintf(hrec, "%d", ha->hdr[i].master_no);
408             seq_printf(m,
409                            " To Array Drv.:\t%s\n", hrec);
410         }
411         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
412 
413         if (!flag)
414             seq_printf(m, "\n --\n");
415 
416         /* 4. about array drives */
417         seq_printf(m,"\nArray Drives:");
418         flag = FALSE;
419 
420         buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
421         if (!buf)
422             goto stop_output;
423         for (i = 0; i < MAX_LDRIVES; ++i) {
424             if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master))
425                 continue;
426             /* 4.a array drive info */
427             TRACE2(("array_info() drive no %d\n",i));
428             pai = (gdth_arrayinf_str *)buf;
429             gdtcmd->Service = CACHESERVICE;
430             gdtcmd->OpCode = GDT_IOCTL;
431             gdtcmd->u.ioctl.p_param = paddr;
432             gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str);
433             gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
434             gdtcmd->u.ioctl.channel = i;
435             if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
436                 if (pai->ai_state == 0)
437                     strcpy(hrec, "idle");
438                 else if (pai->ai_state == 2)
439                     strcpy(hrec, "build");
440                 else if (pai->ai_state == 4)
441                     strcpy(hrec, "ready");
442                 else if (pai->ai_state == 6)
443                     strcpy(hrec, "fail");
444                 else if (pai->ai_state == 8 || pai->ai_state == 10)
445                     strcpy(hrec, "rebuild");
446                 else
447                     strcpy(hrec, "error");
448                 if (pai->ai_ext_state & 0x10)
449                     strcat(hrec, "/expand");
450                 else if (pai->ai_ext_state & 0x1)
451                     strcat(hrec, "/patch");
452                 seq_printf(m,
453                                "\n Number:       \t%-2d        \tStatus:        \t%s\n",
454                                i,hrec);
455                 flag = TRUE;
456 
457                 if (pai->ai_type == 0)
458                     strcpy(hrec, "RAID-0");
459                 else if (pai->ai_type == 4)
460                     strcpy(hrec, "RAID-4");
461                 else if (pai->ai_type == 5)
462                     strcpy(hrec, "RAID-5");
463                 else
464                     strcpy(hrec, "RAID-10");
465                 seq_printf(m,
466                                " Capacity [MB]:\t%-6d    \tType:          \t%s\n",
467                                pai->ai_size/(1024*1024/pai->ai_secsize),
468                                hrec);
469             }
470         }
471         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
472 
473         if (!flag)
474             seq_printf(m, "\n --\n");
475 
476         /* 5. about host drives */
477         seq_printf(m,"\nHost Drives:");
478         flag = FALSE;
479 
480         buf = gdth_ioctl_alloc(ha, sizeof(gdth_hget_str), FALSE, &paddr);
481         if (!buf)
482             goto stop_output;
483         for (i = 0; i < MAX_LDRIVES; ++i) {
484             if (!ha->hdr[i].is_logdrv ||
485                 (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master))
486                 continue;
487             /* 5.a get host drive list */
488             TRACE2(("host_get() drv_no %d\n",i));
489             phg = (gdth_hget_str *)buf;
490             gdtcmd->Service = CACHESERVICE;
491             gdtcmd->OpCode = GDT_IOCTL;
492             gdtcmd->u.ioctl.p_param = paddr;
493             gdtcmd->u.ioctl.param_size = sizeof(gdth_hget_str);
494             gdtcmd->u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
495             gdtcmd->u.ioctl.channel = i;
496             phg->entries = MAX_HDRIVES;
497             phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]);
498             if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
499                 ha->hdr[i].ldr_no = i;
500                 ha->hdr[i].rw_attribs = 0;
501                 ha->hdr[i].start_sec = 0;
502             } else {
503                 for (j = 0; j < phg->entries; ++j) {
504                     k = phg->entry[j].host_drive;
505                     if (k >= MAX_LDRIVES)
506                         continue;
507                     ha->hdr[k].ldr_no = phg->entry[j].log_drive;
508                     ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs;
509                     ha->hdr[k].start_sec = phg->entry[j].start_sec;
510                 }
511             }
512         }
513         gdth_ioctl_free(ha, sizeof(gdth_hget_str), buf, paddr);
514 
515         for (i = 0; i < MAX_HDRIVES; ++i) {
516             if (!(ha->hdr[i].present))
517                 continue;
518 
519             seq_printf(m,
520                            "\n Number:       \t%-2d        \tArr/Log. Drive:\t%d\n",
521                            i, ha->hdr[i].ldr_no);
522             flag = TRUE;
523 
524             seq_printf(m,
525                            " Capacity [MB]:\t%-6d    \tStart Sector:  \t%d\n",
526                            (u32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec);
527         }
528 
529         if (!flag)
530             seq_printf(m, "\n --\n");
531     }
532 
533     /* controller events */
534     seq_printf(m,"\nController Events:\n");
535 
536     for (id = -1;;) {
537         id = gdth_read_event(ha, id, estr);
538         if (estr->event_source == 0)
539             break;
540         if (estr->event_data.eu.driver.ionode == ha->hanum &&
541             estr->event_source == ES_ASYNC) {
542             gdth_log_event(&estr->event_data, hrec);
543             do_gettimeofday(&tv);
544             sec = (int)(tv.tv_sec - estr->first_stamp);
545             if (sec < 0) sec = 0;
546             seq_printf(m," date- %02d:%02d:%02d\t%s\n",
547                            sec/3600, sec%3600/60, sec%60, hrec);
548         }
549         if (id == -1)
550             break;
551     }
552 stop_output:
553     rc = 0;
554 free_fail:
555     kfree(gdtcmd);
556     kfree(estr);
557     return rc;
558 }
559 
gdth_ioctl_alloc(gdth_ha_str * ha,int size,int scratch,u64 * paddr)560 static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch,
561                               u64 *paddr)
562 {
563     unsigned long flags;
564     char *ret_val;
565 
566     if (size == 0)
567         return NULL;
568 
569     spin_lock_irqsave(&ha->smp_lock, flags);
570 
571     if (!ha->scratch_busy && size <= GDTH_SCRATCH) {
572         ha->scratch_busy = TRUE;
573         ret_val = ha->pscratch;
574         *paddr = ha->scratch_phys;
575     } else if (scratch) {
576         ret_val = NULL;
577     } else {
578         dma_addr_t dma_addr;
579 
580         ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr);
581         *paddr = dma_addr;
582     }
583 
584     spin_unlock_irqrestore(&ha->smp_lock, flags);
585     return ret_val;
586 }
587 
gdth_ioctl_free(gdth_ha_str * ha,int size,char * buf,u64 paddr)588 static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, u64 paddr)
589 {
590     unsigned long flags;
591 
592     if (buf == ha->pscratch) {
593 	spin_lock_irqsave(&ha->smp_lock, flags);
594         ha->scratch_busy = FALSE;
595 	spin_unlock_irqrestore(&ha->smp_lock, flags);
596     } else {
597         pci_free_consistent(ha->pdev, size, buf, paddr);
598     }
599 }
600 
601 #ifdef GDTH_IOCTL_PROC
gdth_ioctl_check_bin(gdth_ha_str * ha,u16 size)602 static int gdth_ioctl_check_bin(gdth_ha_str *ha, u16 size)
603 {
604     unsigned long flags;
605     int ret_val;
606 
607     spin_lock_irqsave(&ha->smp_lock, flags);
608 
609     ret_val = FALSE;
610     if (ha->scratch_busy) {
611         if (((gdth_iord_str *)ha->pscratch)->size == (u32)size)
612             ret_val = TRUE;
613     }
614     spin_unlock_irqrestore(&ha->smp_lock, flags);
615     return ret_val;
616 }
617 #endif
618 
gdth_wait_completion(gdth_ha_str * ha,int busnum,int id)619 static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id)
620 {
621     unsigned long flags;
622     int i;
623     Scsi_Cmnd *scp;
624     struct gdth_cmndinfo *cmndinfo;
625     u8 b, t;
626 
627     spin_lock_irqsave(&ha->smp_lock, flags);
628 
629     for (i = 0; i < GDTH_MAXCMDS; ++i) {
630         scp = ha->cmd_tab[i].cmnd;
631         cmndinfo = gdth_cmnd_priv(scp);
632 
633         b = scp->device->channel;
634         t = scp->device->id;
635         if (!SPECIAL_SCP(scp) && t == (u8)id &&
636             b == (u8)busnum) {
637             cmndinfo->wait_for_completion = 0;
638             spin_unlock_irqrestore(&ha->smp_lock, flags);
639             while (!cmndinfo->wait_for_completion)
640                 barrier();
641             spin_lock_irqsave(&ha->smp_lock, flags);
642         }
643     }
644     spin_unlock_irqrestore(&ha->smp_lock, flags);
645 }
646