blob: 30975ccd9947622de211661134bc74e94ceea254 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/message/fusion/mptctl.c
Moore, Eric Dean b6fe4dd2005-04-22 18:01:34 -04003 * mpt Ioctl driver.
4 * For use with LSI Logic PCI chip/adapters
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
6 *
Moore, Eric Dean b6fe4dd2005-04-22 18:01:34 -04007 * Copyright (c) 1999-2005 LSI Logic Corporation
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * (mailto:mpt_linux_developer@lsil.com)
9 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 */
11/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12/*
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; version 2 of the License.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 NO WARRANTY
23 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
24 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
25 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
26 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
27 solely responsible for determining the appropriateness of using and
28 distributing the Program and assumes all risks associated with its
29 exercise of rights under this Agreement, including but not limited to
30 the risks and costs of program errors, damage to or loss of data,
31 programs or equipment, and unavailability or interruption of operations.
32
33 DISCLAIMER OF LIABILITY
34 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
35 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
37 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
38 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
39 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
40 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
41
42 You should have received a copy of the GNU General Public License
43 along with this program; if not, write to the Free Software
44 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45*/
46/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include <linux/kernel.h>
49#include <linux/module.h>
50#include <linux/errno.h>
51#include <linux/init.h>
52#include <linux/slab.h>
53#include <linux/types.h>
54#include <linux/pci.h>
55#include <linux/delay.h> /* for mdelay */
56#include <linux/miscdevice.h>
57#include <linux/smp_lock.h>
58#include <linux/compat.h>
59
60#include <asm/io.h>
61#include <asm/uaccess.h>
62
63#include <scsi/scsi.h>
64#include <scsi/scsi_cmnd.h>
65#include <scsi/scsi_device.h>
66#include <scsi/scsi_host.h>
67#include <scsi/scsi_tcq.h>
68
Moore, Eric Dean b6fe4dd2005-04-22 18:01:34 -040069#define COPYRIGHT "Copyright (c) 1999-2005 LSI Logic Corporation"
70#define MODULEAUTHOR "LSI Logic Corporation"
Linus Torvalds1da177e2005-04-16 15:20:36 -070071#include "mptbase.h"
72#include "mptctl.h"
73
74/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
75#define my_NAME "Fusion MPT misc device (ioctl) driver"
76#define my_VERSION MPT_LINUX_VERSION_COMMON
77#define MYNAM "mptctl"
78
79MODULE_AUTHOR(MODULEAUTHOR);
80MODULE_DESCRIPTION(my_NAME);
81MODULE_LICENSE("GPL");
82
83/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
84
85static int mptctl_id = -1;
86
87static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
88
89/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
90
91struct buflist {
92 u8 *kptr;
93 int len;
94};
95
96/*
97 * Function prototypes. Called from OS entry point mptctl_ioctl.
98 * arg contents specific to function.
99 */
100static int mptctl_fw_download(unsigned long arg);
Moore, Eric Dean d485eb82005-05-11 17:37:26 -0600101static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
102static int mptctl_gettargetinfo(unsigned long arg);
103static int mptctl_readtest(unsigned long arg);
104static int mptctl_mpt_command(unsigned long arg);
105static int mptctl_eventquery(unsigned long arg);
106static int mptctl_eventenable(unsigned long arg);
107static int mptctl_eventreport(unsigned long arg);
108static int mptctl_replace_fw(unsigned long arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
110static int mptctl_do_reset(unsigned long arg);
111static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
112static int mptctl_hp_targetinfo(unsigned long arg);
113
114static int mptctl_probe(struct pci_dev *, const struct pci_device_id *);
115static void mptctl_remove(struct pci_dev *);
116
117#ifdef CONFIG_COMPAT
118static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg);
119#endif
120/*
121 * Private function calls.
122 */
Moore, Eric Dean d485eb82005-05-11 17:37:26 -0600123static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
Moore, Eric Dean d485eb82005-05-11 17:37:26 -0600125static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
Moore, Eric Dean d485eb82005-05-11 17:37:26 -0600127static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 struct buflist *buflist, MPT_ADAPTER *ioc);
129static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
130static int mptctl_bus_reset(MPT_IOCTL *ioctl);
131static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd);
132static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
133
134/*
135 * Reset Handler cleanup function
136 */
137static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
138
Moore, Ericea5a7a82006-02-02 17:20:01 -0700139/*
140 * Event Handler function
141 */
142static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
Moore, Ericc972c702006-03-14 09:14:06 -0700143static struct fasync_struct *async_queue=NULL;
Moore, Ericea5a7a82006-02-02 17:20:01 -0700144
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
146/*
147 * Scatter gather list (SGL) sizes and limits...
148 */
149//#define MAX_SCSI_FRAGS 9
150#define MAX_FRAGS_SPILL1 9
151#define MAX_FRAGS_SPILL2 15
152#define FRAGS_PER_BUCKET (MAX_FRAGS_SPILL2 + 1)
153
154//#define MAX_CHAIN_FRAGS 64
155//#define MAX_CHAIN_FRAGS (15+15+15+16)
156#define MAX_CHAIN_FRAGS (4 * MAX_FRAGS_SPILL2 + 1)
157
158// Define max sg LIST bytes ( == (#frags + #chains) * 8 bytes each)
159// Works out to: 592d bytes! (9+1)*8 + 4*(15+1)*8
160// ^----------------- 80 + 512
161#define MAX_SGL_BYTES ((MAX_FRAGS_SPILL1 + 1 + (4 * FRAGS_PER_BUCKET)) * 8)
162
163/* linux only seems to ever give 128kB MAX contiguous (GFP_USER) mem bytes */
164#define MAX_KMALLOC_SZ (128*1024)
165
166#define MPT_IOCTL_DEFAULT_TIMEOUT 10 /* Default timeout value (seconds) */
167
168/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
169/**
170 * mptctl_syscall_down - Down the MPT adapter syscall semaphore.
171 * @ioc: Pointer to MPT adapter
172 * @nonblock: boolean, non-zero if O_NONBLOCK is set
173 *
174 * All of the ioctl commands can potentially sleep, which is illegal
175 * with a spinlock held, thus we perform mutual exclusion here.
176 *
177 * Returns negative errno on error, or zero for success.
178 */
179static inline int
180mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
181{
182 int rc = 0;
183 dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
184
185 if (nonblock) {
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100186 if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 rc = -EAGAIN;
188 } else {
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100189 if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 rc = -ERESTARTSYS;
191 }
192 dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
193 return rc;
194}
195
196/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
197/*
198 * This is the callback for any message we have posted. The message itself
199 * will be returned to the message pool when we return from the IRQ
200 *
201 * This runs in irq context so be short and sweet.
202 */
203static int
204mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
205{
206 char *sense_data;
207 int sz, req_index;
208 u16 iocStatus;
209 u8 cmd;
210
211 dctlprintk(("mptctl_reply()!\n"));
212 if (req)
213 cmd = req->u.hdr.Function;
214 else
215 return 1;
216
217 if (ioc->ioctl) {
218
219 if (reply==NULL) {
220
221 dctlprintk(("mptctl_reply() NULL Reply "
222 "Function=%x!\n", cmd));
223
224 ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
225 ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
226
227 /* We are done, issue wake up
228 */
229 ioc->ioctl->wait_done = 1;
230 wake_up (&mptctl_wait);
231 return 1;
232
233 }
234
235 dctlprintk(("mptctl_reply() with req=%p "
236 "reply=%p Function=%x!\n", req, reply, cmd));
237
238 /* Copy the reply frame (which much exist
239 * for non-SCSI I/O) to the IOC structure.
240 */
241 dctlprintk(("Copying Reply Frame @%p to ioc%d!\n",
242 reply, ioc->id));
243 memcpy(ioc->ioctl->ReplyFrame, reply,
244 min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
245 ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
246
247 /* Set the command status to GOOD if IOC Status is GOOD
248 * OR if SCSI I/O cmd and data underrun or recovered error.
249 */
Christoph Hellwig637fa992005-08-18 16:25:44 +0200250 iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 if (iocStatus == MPI_IOCSTATUS_SUCCESS)
252 ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
253
254 if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
255 (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
256 ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
257
258 if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
259 (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
260 ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
261 }
262 }
263
264 /* Copy the sense data - if present
265 */
266 if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
267 (reply->u.sreply.SCSIState &
268 MPI_SCSI_STATE_AUTOSENSE_VALID)){
269 sz = req->u.scsireq.SenseBufferLength;
270 req_index =
271 le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
272 sense_data =
273 ((u8 *)ioc->sense_buf_pool +
274 (req_index * MPT_SENSE_BUFFER_ALLOC));
275 memcpy(ioc->ioctl->sense, sense_data, sz);
276 ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
277 }
278
279 if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
280 mptctl_free_tm_flags(ioc);
281
282 /* We are done, issue wake up
283 */
284 ioc->ioctl->wait_done = 1;
285 wake_up (&mptctl_wait);
286 }
287 return 1;
288}
289
290/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
291/* mptctl_timeout_expired
292 *
293 * Expecting an interrupt, however timed out.
294 *
295 */
296static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
297{
298 int rc = 1;
299
300 dctlprintk((KERN_NOTICE MYNAM ": Timeout Expired! Host %d\n",
301 ioctl->ioc->id));
302 if (ioctl == NULL)
303 return;
304
305 ioctl->wait_done = 0;
306 if (ioctl->reset & MPTCTL_RESET_OK)
307 rc = mptctl_bus_reset(ioctl);
308
309 if (rc) {
310 /* Issue a reset for this device.
311 * The IOC is not responding.
312 */
313 dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
314 ioctl->ioc->name));
315 mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
316 }
317 return;
318
319}
320
321/* mptctl_bus_reset
322 *
323 * Bus reset code.
324 *
325 */
326static int mptctl_bus_reset(MPT_IOCTL *ioctl)
327{
328 MPT_FRAME_HDR *mf;
329 SCSITaskMgmt_t *pScsiTm;
330 MPT_SCSI_HOST *hd;
331 int ii;
332 int retval;
333
334
335 ioctl->reset &= ~MPTCTL_RESET_OK;
336
337 if (ioctl->ioc->sh == NULL)
338 return -EPERM;
339
340 hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata;
341 if (hd == NULL)
342 return -EPERM;
343
344 /* Single threading ....
345 */
346 if (mptctl_set_tm_flags(hd) != 0)
347 return -EPERM;
348
349 /* Send request
350 */
351 if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc)) == NULL) {
352 dctlprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
353 ioctl->ioc->name));
354
355 mptctl_free_tm_flags(ioctl->ioc);
356 return -ENOMEM;
357 }
358
359 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
360 ioctl->ioc->name, mf));
361
362 pScsiTm = (SCSITaskMgmt_t *) mf;
363 pScsiTm->TargetID = ioctl->target;
364 pScsiTm->Bus = hd->port; /* 0 */
365 pScsiTm->ChainOffset = 0;
366 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
367 pScsiTm->Reserved = 0;
368 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
369 pScsiTm->Reserved1 = 0;
370 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
371
372 for (ii= 0; ii < 8; ii++)
373 pScsiTm->LUN[ii] = 0;
374
375 for (ii=0; ii < 7; ii++)
376 pScsiTm->Reserved2[ii] = 0;
377
378 pScsiTm->TaskMsgContext = 0;
379 dtmprintk((MYIOC_s_INFO_FMT
380 "mptctl_bus_reset: issued.\n", ioctl->ioc->name));
381
382 DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
383
384 ioctl->wait_done=0;
385 if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
386 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
387 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
388 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
389 hd->ioc, mf));
390 goto mptctl_bus_reset_done;
391 }
392
393 /* Now wait for the command to complete */
Moore, Eric86a7dca2006-02-02 17:19:37 -0700394 ii = wait_event_timeout(mptctl_wait,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 ioctl->wait_done == 1,
396 HZ*5 /* 5 second timeout */);
397
398 if(ii <=0 && (ioctl->wait_done != 1 )) {
Moore, Eric86a7dca2006-02-02 17:19:37 -0700399 mpt_free_msg_frame(hd->ioc, mf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 ioctl->wait_done = 0;
401 retval = -1; /* return failure */
402 }
403
404mptctl_bus_reset_done:
405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 mptctl_free_tm_flags(ioctl->ioc);
407 return retval;
408}
409
410static int
411mptctl_set_tm_flags(MPT_SCSI_HOST *hd) {
412 unsigned long flags;
413
414 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
415
416 if (hd->tmState == TM_STATE_NONE) {
417 hd->tmState = TM_STATE_IN_PROGRESS;
418 hd->tmPending = 1;
419 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
420 } else {
421 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
422 return -EBUSY;
423 }
424
425 return 0;
426}
427
428static void
429mptctl_free_tm_flags(MPT_ADAPTER *ioc)
430{
431 MPT_SCSI_HOST * hd;
432 unsigned long flags;
433
434 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
435 if (hd == NULL)
436 return;
437
438 spin_lock_irqsave(&ioc->FreeQlock, flags);
439
440 hd->tmState = TM_STATE_NONE;
441 hd->tmPending = 0;
442 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
443
444 return;
445}
446
447/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
448/* mptctl_ioc_reset
449 *
450 * Clean-up functionality. Used only if there has been a
451 * reload of the FW due.
452 *
453 */
454static int
455mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
456{
457 MPT_IOCTL *ioctl = ioc->ioctl;
458 dctlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to IOCTL driver!\n",
459 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
460 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
461
462 if(ioctl == NULL)
463 return 1;
464
465 switch(reset_phase) {
466 case MPT_IOC_SETUP_RESET:
467 ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
468 break;
469 case MPT_IOC_POST_RESET:
470 ioctl->status &= ~MPT_IOCTL_STATUS_DID_IOCRESET;
471 break;
472 case MPT_IOC_PRE_RESET:
473 default:
474 break;
475 }
476
477 return 1;
478}
479
480/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
Moore, Ericea5a7a82006-02-02 17:20:01 -0700481/* ASYNC Event Notification Support */
482static int
483mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
484{
485 u8 event;
486
487 event = le32_to_cpu(pEvReply->Event) & 0xFF;
488
489 dctlprintk(("%s() called\n", __FUNCTION__));
490 if(async_queue == NULL)
491 return 1;
492
493 /* Raise SIGIO for persistent events.
494 * TODO - this define is not in MPI spec yet,
495 * but they plan to set it to 0x21
496 */
497 if (event == 0x21 ) {
498 ioc->aen_event_read_flag=1;
499 dctlprintk(("Raised SIGIO to application\n"));
Moore, Eric3a892be2006-03-14 09:14:03 -0700500 devtverboseprintk(("Raised SIGIO to application\n"));
Moore, Ericea5a7a82006-02-02 17:20:01 -0700501 kill_fasync(&async_queue, SIGIO, POLL_IN);
502 return 1;
503 }
504
505 /* This flag is set after SIGIO was raised, and
506 * remains set until the application has read
507 * the event log via ioctl=MPTEVENTREPORT
508 */
509 if(ioc->aen_event_read_flag)
510 return 1;
511
512 /* Signal only for the events that are
513 * requested for by the application
514 */
515 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
516 ioc->aen_event_read_flag=1;
517 dctlprintk(("Raised SIGIO to application\n"));
Moore, Eric3a892be2006-03-14 09:14:03 -0700518 devtverboseprintk(("Raised SIGIO to application\n"));
Moore, Ericea5a7a82006-02-02 17:20:01 -0700519 kill_fasync(&async_queue, SIGIO, POLL_IN);
520 }
521 return 1;
522}
523
524static int
525mptctl_fasync(int fd, struct file *filep, int mode)
526{
527 MPT_ADAPTER *ioc;
528
529 list_for_each_entry(ioc, &ioc_list, list)
530 ioc->aen_event_read_flag=0;
531
532 dctlprintk(("%s() called\n", __FUNCTION__));
533 return fasync_helper(fd, filep, mode, &async_queue);
534}
535
536static int
537mptctl_release(struct inode *inode, struct file *filep)
538{
539 dctlprintk(("%s() called\n", __FUNCTION__));
540 return fasync_helper(-1, filep, 0, &async_queue);
541}
542
543/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544/*
545 * MPT ioctl handler
546 * cmd - specify the particular IOCTL command to be issued
547 * arg - data specific to the command. Must not be null.
548 */
549static long
550__mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
551{
552 mpt_ioctl_header __user *uhdr = (void __user *) arg;
553 mpt_ioctl_header khdr;
554 int iocnum;
555 unsigned iocnumX;
556 int nonblock = (file->f_flags & O_NONBLOCK);
557 int ret;
558 MPT_ADAPTER *iocp = NULL;
559
560 dctlprintk(("mptctl_ioctl() called\n"));
561
562 if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
563 printk(KERN_ERR "%s::mptctl_ioctl() @%d - "
564 "Unable to copy mpt_ioctl_header data @ %p\n",
565 __FILE__, __LINE__, uhdr);
566 return -EFAULT;
567 }
568 ret = -ENXIO; /* (-6) No such device or address */
569
570 /* Verify intended MPT adapter - set iocnum and the adapter
571 * pointer (iocp)
572 */
573 iocnumX = khdr.iocnum & 0xFF;
574 if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
575 (iocp == NULL)) {
576 dctlprintk((KERN_ERR "%s::mptctl_ioctl() @%d - ioc%d not found!\n",
577 __FILE__, __LINE__, iocnumX));
578 return -ENODEV;
579 }
580
581 if (!iocp->active) {
582 printk(KERN_ERR "%s::mptctl_ioctl() @%d - Controller disabled.\n",
583 __FILE__, __LINE__);
584 return -EFAULT;
585 }
586
587 /* Handle those commands that are just returning
588 * information stored in the driver.
589 * These commands should never time out and are unaffected
590 * by TM and FW reloads.
591 */
592 if ((cmd & ~IOCSIZE_MASK) == (MPTIOCINFO & ~IOCSIZE_MASK)) {
593 return mptctl_getiocinfo(arg, _IOC_SIZE(cmd));
594 } else if (cmd == MPTTARGETINFO) {
595 return mptctl_gettargetinfo(arg);
596 } else if (cmd == MPTTEST) {
597 return mptctl_readtest(arg);
598 } else if (cmd == MPTEVENTQUERY) {
599 return mptctl_eventquery(arg);
600 } else if (cmd == MPTEVENTENABLE) {
601 return mptctl_eventenable(arg);
602 } else if (cmd == MPTEVENTREPORT) {
603 return mptctl_eventreport(arg);
604 } else if (cmd == MPTFWREPLACE) {
605 return mptctl_replace_fw(arg);
606 }
607
608 /* All of these commands require an interrupt or
609 * are unknown/illegal.
610 */
611 if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
612 return ret;
613
614 dctlprintk((MYIOC_s_INFO_FMT ": mptctl_ioctl()\n", iocp->name));
615
616 if (cmd == MPTFWDOWNLOAD)
617 ret = mptctl_fw_download(arg);
618 else if (cmd == MPTCOMMAND)
619 ret = mptctl_mpt_command(arg);
620 else if (cmd == MPTHARDRESET)
621 ret = mptctl_do_reset(arg);
622 else if ((cmd & ~IOCSIZE_MASK) == (HP_GETHOSTINFO & ~IOCSIZE_MASK))
623 ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
624 else if (cmd == HP_GETTARGETINFO)
625 ret = mptctl_hp_targetinfo(arg);
626 else
627 ret = -EINVAL;
628
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100629 mutex_unlock(&iocp->ioctl->ioctl_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631 return ret;
632}
633
634static long
635mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
636{
637 long ret;
638 lock_kernel();
639 ret = __mptctl_ioctl(file, cmd, arg);
640 unlock_kernel();
641 return ret;
642}
643
644static int mptctl_do_reset(unsigned long arg)
645{
646 struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
647 struct mpt_ioctl_diag_reset krinfo;
648 MPT_ADAPTER *iocp;
649
650 dctlprintk((KERN_INFO "mptctl_do_reset called.\n"));
651
652 if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
653 printk(KERN_ERR "%s@%d::mptctl_do_reset - "
654 "Unable to copy mpt_ioctl_diag_reset struct @ %p\n",
655 __FILE__, __LINE__, urinfo);
656 return -EFAULT;
657 }
658
659 if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
660 dctlprintk((KERN_ERR "%s@%d::mptctl_do_reset - ioc%d not found!\n",
661 __FILE__, __LINE__, krinfo.hdr.iocnum));
662 return -ENODEV; /* (-6) No such device or address */
663 }
664
665 if (mpt_HardResetHandler(iocp, CAN_SLEEP) != 0) {
666 printk (KERN_ERR "%s@%d::mptctl_do_reset - reset failed.\n",
667 __FILE__, __LINE__);
668 return -1;
669 }
670
671 return 0;
672}
673
674/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
675/*
676 * MPT FW download function. Cast the arg into the mpt_fw_xfer structure.
677 * This structure contains: iocnum, firmware length (bytes),
678 * pointer to user space memory where the fw image is stored.
679 *
680 * Outputs: None.
681 * Return: 0 if successful
682 * -EFAULT if data unavailable
683 * -ENXIO if no such device
684 * -EAGAIN if resource problem
685 * -ENOMEM if no memory for SGE
686 * -EMLINK if too many chain buffers required
687 * -EBADRQC if adapter does not support FW download
688 * -EBUSY if adapter is busy
689 * -ENOMSG if FW upload returned bad status
690 */
691static int
692mptctl_fw_download(unsigned long arg)
693{
694 struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
695 struct mpt_fw_xfer kfwdl;
696
697 dctlprintk((KERN_INFO "mptctl_fwdl called. mptctl_id = %xh\n", mptctl_id)); //tc
698 if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) {
699 printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
700 "Unable to copy mpt_fw_xfer struct @ %p\n",
701 __FILE__, __LINE__, ufwdl);
702 return -EFAULT;
703 }
704
705 return mptctl_do_fw_download(kfwdl.iocnum, kfwdl.bufp, kfwdl.fwlen);
706}
707
708/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
709/*
710 * FW Download engine.
711 * Outputs: None.
712 * Return: 0 if successful
713 * -EFAULT if data unavailable
714 * -ENXIO if no such device
715 * -EAGAIN if resource problem
716 * -ENOMEM if no memory for SGE
717 * -EMLINK if too many chain buffers required
718 * -EBADRQC if adapter does not support FW download
719 * -EBUSY if adapter is busy
720 * -ENOMSG if FW upload returned bad status
721 */
722static int
723mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
724{
725 FWDownload_t *dlmsg;
726 MPT_FRAME_HDR *mf;
727 MPT_ADAPTER *iocp;
728 FWDownloadTCSGE_t *ptsge;
729 MptSge_t *sgl, *sgIn;
730 char *sgOut;
731 struct buflist *buflist;
732 struct buflist *bl;
733 dma_addr_t sgl_dma;
734 int ret;
735 int numfrags = 0;
736 int maxfrags;
737 int n = 0;
738 u32 sgdir;
739 u32 nib;
740 int fw_bytes_copied = 0;
741 int i;
742 int sge_offset = 0;
743 u16 iocstat;
744 pFWDownloadReply_t ReplyMsg = NULL;
745
Moore, Eric946cbf02006-02-02 17:19:50 -0700746 dctlprintk(("mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Moore, Eric946cbf02006-02-02 17:19:50 -0700748 dctlprintk(("DbG: kfwdl.bufp = %p\n", ufwbuf));
749 dctlprintk(("DbG: kfwdl.fwlen = %d\n", (int)fwlen));
750 dctlprintk(("DbG: kfwdl.ioc = %04xh\n", ioc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
Moore, Eric946cbf02006-02-02 17:19:50 -0700752 if (mpt_verify_adapter(ioc, &iocp) < 0) {
753 dctlprintk(("ioctl_fwdl - ioc%d not found!\n",
754 ioc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 return -ENODEV; /* (-6) No such device or address */
Moore, Eric946cbf02006-02-02 17:19:50 -0700756 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
Moore, Eric946cbf02006-02-02 17:19:50 -0700758 /* Valid device. Get a message frame and construct the FW download message.
759 */
760 if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
761 return -EAGAIN;
762 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 dlmsg = (FWDownload_t*) mf;
764 ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
765 sgOut = (char *) (ptsge + 1);
766
767 /*
768 * Construct f/w download request
769 */
770 dlmsg->ImageType = MPI_FW_DOWNLOAD_ITYPE_FW;
771 dlmsg->Reserved = 0;
772 dlmsg->ChainOffset = 0;
773 dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD;
774 dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0;
Moore, Eric946cbf02006-02-02 17:19:50 -0700775 if (iocp->facts.MsgVersion >= MPI_VERSION_01_05)
776 dlmsg->MsgFlags = MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT;
777 else
778 dlmsg->MsgFlags = 0;
779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
781 /* Set up the Transaction SGE.
782 */
783 ptsge->Reserved = 0;
784 ptsge->ContextSize = 0;
785 ptsge->DetailsLength = 12;
786 ptsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
787 ptsge->Reserved_0100_Checksum = 0;
788 ptsge->ImageOffset = 0;
789 ptsge->ImageSize = cpu_to_le32(fwlen);
790
791 /* Add the SGL
792 */
793
794 /*
795 * Need to kmalloc area(s) for holding firmware image bytes.
796 * But we need to do it piece meal, using a proper
797 * scatter gather list (with 128kB MAX hunks).
798 *
799 * A practical limit here might be # of sg hunks that fit into
800 * a single IOC request frame; 12 or 8 (see below), so:
801 * For FC9xx: 12 x 128kB == 1.5 mB (max)
802 * For C1030: 8 x 128kB == 1 mB (max)
803 * We could support chaining, but things get ugly(ier:)
804 *
805 * Set the sge_offset to the start of the sgl (bytes).
806 */
807 sgdir = 0x04000000; /* IOC will READ from sys mem */
808 sge_offset = sizeof(MPIHeader_t) + sizeof(FWDownloadTCSGE_t);
809 if ((sgl = kbuf_alloc_2_sgl(fwlen, sgdir, sge_offset,
810 &numfrags, &buflist, &sgl_dma, iocp)) == NULL)
811 return -ENOMEM;
812
813 /*
814 * We should only need SGL with 2 simple_32bit entries (up to 256 kB)
815 * for FC9xx f/w image, but calculate max number of sge hunks
816 * we can fit into a request frame, and limit ourselves to that.
817 * (currently no chain support)
818 * maxfrags = (Request Size - FWdownload Size ) / Size of 32 bit SGE
819 * Request maxfrags
820 * 128 12
821 * 96 8
822 * 64 4
823 */
824 maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t))
825 / (sizeof(dma_addr_t) + sizeof(u32));
826 if (numfrags > maxfrags) {
827 ret = -EMLINK;
828 goto fwdl_out;
829 }
830
Moore, Eric946cbf02006-02-02 17:19:50 -0700831 dctlprintk(("DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
833 /*
834 * Parse SG list, copying sgl itself,
835 * plus f/w image hunks from user space as we go...
836 */
837 ret = -EFAULT;
838 sgIn = sgl;
839 bl = buflist;
840 for (i=0; i < numfrags; i++) {
841
842 /* Get the SGE type: 0 - TCSGE, 3 - Chain, 1 - Simple SGE
843 * Skip everything but Simple. If simple, copy from
844 * user space into kernel space.
845 * Note: we should not have anything but Simple as
846 * Chain SGE are illegal.
847 */
848 nib = (sgIn->FlagsLength & 0x30000000) >> 28;
849 if (nib == 0 || nib == 3) {
850 ;
851 } else if (sgIn->Address) {
852 mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
853 n++;
854 if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
855 printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
856 "Unable to copy f/w buffer hunk#%d @ %p\n",
857 __FILE__, __LINE__, n, ufwbuf);
858 goto fwdl_out;
859 }
860 fw_bytes_copied += bl->len;
861 }
862 sgIn++;
863 bl++;
864 sgOut += (sizeof(dma_addr_t) + sizeof(u32));
865 }
866
867#ifdef MPT_DEBUG
868 {
869 u32 *m = (u32 *)mf;
870 printk(KERN_INFO MYNAM ": F/W download request:\n" KERN_INFO " ");
871 for (i=0; i < 7+numfrags*2; i++)
872 printk(" %08x", le32_to_cpu(m[i]));
873 printk("\n");
874 }
875#endif
876
877 /*
878 * Finally, perform firmware download.
879 */
Moore, Eric946cbf02006-02-02 17:19:50 -0700880 ReplyMsg = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 mpt_put_msg_frame(mptctl_id, iocp, mf);
882
883 /* Now wait for the command to complete */
Moore, Eric86a7dca2006-02-02 17:19:37 -0700884 ret = wait_event_timeout(mptctl_wait,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 iocp->ioctl->wait_done == 1,
886 HZ*60);
887
888 if(ret <=0 && (iocp->ioctl->wait_done != 1 )) {
889 /* Now we need to reset the board */
890 mptctl_timeout_expired(iocp->ioctl);
891 ret = -ENODATA;
892 goto fwdl_out;
893 }
894
895 if (sgl)
896 kfree_sgl(sgl, sgl_dma, buflist, iocp);
897
898 ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame;
899 iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
900 if (iocstat == MPI_IOCSTATUS_SUCCESS) {
901 printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name);
902 return 0;
903 } else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {
904 printk(KERN_WARNING MYNAM ": ?Hmmm... %s says it doesn't support F/W download!?!\n",
905 iocp->name);
906 printk(KERN_WARNING MYNAM ": (time to go bang on somebodies door)\n");
907 return -EBADRQC;
908 } else if (iocstat == MPI_IOCSTATUS_BUSY) {
909 printk(KERN_WARNING MYNAM ": Warning! %s says: IOC_BUSY!\n", iocp->name);
910 printk(KERN_WARNING MYNAM ": (try again later?)\n");
911 return -EBUSY;
912 } else {
913 printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR! %s returned [bad] status = %04xh\n",
914 iocp->name, iocstat);
915 printk(KERN_WARNING MYNAM ": (bad VooDoo)\n");
916 return -ENOMSG;
917 }
918 return 0;
919
920fwdl_out:
921 kfree_sgl(sgl, sgl_dma, buflist, iocp);
922 return ret;
923}
924
925/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
926/*
927 * SGE Allocation routine
928 *
929 * Inputs: bytes - number of bytes to be transferred
930 * sgdir - data direction
931 * sge_offset - offset (in bytes) from the start of the request
932 * frame to the first SGE
933 * ioc - pointer to the mptadapter
934 * Outputs: frags - number of scatter gather elements
935 * blp - point to the buflist pointer
936 * sglbuf_dma - pointer to the (dma) sgl
937 * Returns: Null if failes
938 * pointer to the (virtual) sgl if successful.
939 */
940static MptSge_t *
941kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
942 struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc)
943{
944 MptSge_t *sglbuf = NULL; /* pointer to array of SGE */
945 /* and chain buffers */
946 struct buflist *buflist = NULL; /* kernel routine */
947 MptSge_t *sgl;
948 int numfrags = 0;
949 int fragcnt = 0;
950 int alloc_sz = min(bytes,MAX_KMALLOC_SZ); // avoid kernel warning msg!
951 int bytes_allocd = 0;
952 int this_alloc;
953 dma_addr_t pa; // phys addr
954 int i, buflist_ent;
955 int sg_spill = MAX_FRAGS_SPILL1;
956 int dir;
957 /* initialization */
958 *frags = 0;
959 *blp = NULL;
960
961 /* Allocate and initialize an array of kernel
962 * structures for the SG elements.
963 */
964 i = MAX_SGL_BYTES / 8;
965 buflist = kmalloc(i, GFP_USER);
966 if (buflist == NULL)
967 return NULL;
968 memset(buflist, 0, i);
969 buflist_ent = 0;
970
971 /* Allocate a single block of memory to store the sg elements and
972 * the chain buffers. The calling routine is responsible for
973 * copying the data in this array into the correct place in the
974 * request and chain buffers.
975 */
976 sglbuf = pci_alloc_consistent(ioc->pcidev, MAX_SGL_BYTES, sglbuf_dma);
977 if (sglbuf == NULL)
978 goto free_and_fail;
979
980 if (sgdir & 0x04000000)
981 dir = PCI_DMA_TODEVICE;
982 else
983 dir = PCI_DMA_FROMDEVICE;
984
985 /* At start:
986 * sgl = sglbuf = point to beginning of sg buffer
987 * buflist_ent = 0 = first kernel structure
988 * sg_spill = number of SGE that can be written before the first
989 * chain element.
990 *
991 */
992 sgl = sglbuf;
993 sg_spill = ((ioc->req_sz - sge_offset)/(sizeof(dma_addr_t) + sizeof(u32))) - 1;
994 while (bytes_allocd < bytes) {
995 this_alloc = min(alloc_sz, bytes-bytes_allocd);
996 buflist[buflist_ent].len = this_alloc;
997 buflist[buflist_ent].kptr = pci_alloc_consistent(ioc->pcidev,
998 this_alloc,
999 &pa);
1000 if (buflist[buflist_ent].kptr == NULL) {
1001 alloc_sz = alloc_sz / 2;
1002 if (alloc_sz == 0) {
1003 printk(KERN_WARNING MYNAM "-SG: No can do - "
1004 "not enough memory! :-(\n");
1005 printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
1006 numfrags);
1007 goto free_and_fail;
1008 }
1009 continue;
1010 } else {
1011 dma_addr_t dma_addr;
1012
1013 bytes_allocd += this_alloc;
1014 sgl->FlagsLength = (0x10000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|this_alloc);
1015 dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir);
1016 sgl->Address = dma_addr;
1017
1018 fragcnt++;
1019 numfrags++;
1020 sgl++;
1021 buflist_ent++;
1022 }
1023
1024 if (bytes_allocd >= bytes)
1025 break;
1026
1027 /* Need to chain? */
1028 if (fragcnt == sg_spill) {
1029 printk(KERN_WARNING MYNAM "-SG: No can do - " "Chain required! :-(\n");
1030 printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags);
1031 goto free_and_fail;
1032 }
1033
1034 /* overflow check... */
1035 if (numfrags*8 > MAX_SGL_BYTES){
1036 /* GRRRRR... */
1037 printk(KERN_WARNING MYNAM "-SG: No can do - "
1038 "too many SG frags! :-(\n");
1039 printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
1040 numfrags);
1041 goto free_and_fail;
1042 }
1043 }
1044
1045 /* Last sge fixup: set LE+eol+eob bits */
1046 sgl[-1].FlagsLength |= 0xC1000000;
1047
1048 *frags = numfrags;
1049 *blp = buflist;
1050
1051 dctlprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - "
1052 "%d SG frags generated!\n",
1053 numfrags));
1054
1055 dctlprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - "
1056 "last (big) alloc_sz=%d\n",
1057 alloc_sz));
1058
1059 return sglbuf;
1060
1061free_and_fail:
1062 if (sglbuf != NULL) {
1063 int i;
1064
1065 for (i = 0; i < numfrags; i++) {
1066 dma_addr_t dma_addr;
1067 u8 *kptr;
1068 int len;
1069
1070 if ((sglbuf[i].FlagsLength >> 24) == 0x30)
1071 continue;
1072
1073 dma_addr = sglbuf[i].Address;
1074 kptr = buflist[i].kptr;
1075 len = buflist[i].len;
1076
1077 pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);
1078 }
1079 pci_free_consistent(ioc->pcidev, MAX_SGL_BYTES, sglbuf, *sglbuf_dma);
1080 }
1081 kfree(buflist);
1082 return NULL;
1083}
1084
1085/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1086/*
1087 * Routine to free the SGL elements.
1088 */
1089static void
1090kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc)
1091{
1092 MptSge_t *sg = sgl;
1093 struct buflist *bl = buflist;
1094 u32 nib;
1095 int dir;
1096 int n = 0;
1097
1098 if (sg->FlagsLength & 0x04000000)
1099 dir = PCI_DMA_TODEVICE;
1100 else
1101 dir = PCI_DMA_FROMDEVICE;
1102
1103 nib = (sg->FlagsLength & 0xF0000000) >> 28;
1104 while (! (nib & 0x4)) { /* eob */
1105 /* skip ignore/chain. */
1106 if (nib == 0 || nib == 3) {
1107 ;
1108 } else if (sg->Address) {
1109 dma_addr_t dma_addr;
1110 void *kptr;
1111 int len;
1112
1113 dma_addr = sg->Address;
1114 kptr = bl->kptr;
1115 len = bl->len;
1116 pci_unmap_single(ioc->pcidev, dma_addr, len, dir);
1117 pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);
1118 n++;
1119 }
1120 sg++;
1121 bl++;
1122 nib = (le32_to_cpu(sg->FlagsLength) & 0xF0000000) >> 28;
1123 }
1124
1125 /* we're at eob! */
1126 if (sg->Address) {
1127 dma_addr_t dma_addr;
1128 void *kptr;
1129 int len;
1130
1131 dma_addr = sg->Address;
1132 kptr = bl->kptr;
1133 len = bl->len;
1134 pci_unmap_single(ioc->pcidev, dma_addr, len, dir);
1135 pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);
1136 n++;
1137 }
1138
1139 pci_free_consistent(ioc->pcidev, MAX_SGL_BYTES, sgl, sgl_dma);
1140 kfree(buflist);
1141 dctlprintk((KERN_INFO MYNAM "-SG: Free'd 1 SGL buf + %d kbufs!\n", n));
1142}
1143
1144/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1145/*
1146 * mptctl_getiocinfo - Query the host adapter for IOC information.
1147 * @arg: User space argument
1148 *
1149 * Outputs: None.
1150 * Return: 0 if successful
1151 * -EFAULT if data unavailable
1152 * -ENODEV if no such device/adapter
1153 */
1154static int
1155mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
1156{
1157 struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
1158 struct mpt_ioctl_iocinfo *karg;
1159 MPT_ADAPTER *ioc;
1160 struct pci_dev *pdev;
1161 struct Scsi_Host *sh;
1162 MPT_SCSI_HOST *hd;
1163 int iocnum;
1164 int numDevices = 0;
1165 unsigned int max_id;
1166 int ii;
Moore, Eric Dean b6fe4dd2005-04-22 18:01:34 -04001167 unsigned int port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 int cim_rev;
1169 u8 revision;
1170
1171 dctlprintk((": mptctl_getiocinfo called.\n"));
1172 /* Add of PCI INFO results in unaligned access for
1173 * IA64 and Sparc. Reset long to int. Return no PCI
1174 * data for obsolete format.
1175 */
1176 if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev0))
1177 cim_rev = 0;
1178 else if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev1))
1179 cim_rev = 1;
1180 else if (data_size == sizeof(struct mpt_ioctl_iocinfo))
1181 cim_rev = 2;
1182 else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12))
1183 cim_rev = 0; /* obsolete */
1184 else
1185 return -EFAULT;
1186
1187 karg = kmalloc(data_size, GFP_KERNEL);
1188 if (karg == NULL) {
1189 printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
1190 __FILE__, __LINE__);
1191 return -ENOMEM;
1192 }
1193
1194 if (copy_from_user(karg, uarg, data_size)) {
1195 printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
1196 "Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
1197 __FILE__, __LINE__, uarg);
1198 kfree(karg);
1199 return -EFAULT;
1200 }
1201
1202 if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
1203 (ioc == NULL)) {
1204 dctlprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
1205 __FILE__, __LINE__, iocnum));
1206 kfree(karg);
1207 return -ENODEV;
1208 }
1209
Moore, Eric Dean b6fe4dd2005-04-22 18:01:34 -04001210 /* Verify the data transfer size is correct. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 if (karg->hdr.maxDataSize != data_size) {
1212 printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
1213 "Structure size mismatch. Command not completed.\n",
1214 __FILE__, __LINE__);
1215 kfree(karg);
1216 return -EFAULT;
1217 }
1218
1219 /* Fill in the data and return the structure to the calling
1220 * program
1221 */
Moore, Eric9cc1cfb2006-02-02 17:19:33 -07001222 if (ioc->bus_type == SAS)
1223 karg->adapterType = MPT_IOCTL_INTERFACE_SAS;
1224 else if (ioc->bus_type == FC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 karg->adapterType = MPT_IOCTL_INTERFACE_FC;
1226 else
1227 karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
1228
Moore, Eric Dean b6fe4dd2005-04-22 18:01:34 -04001229 if (karg->hdr.port > 1)
1230 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 port = karg->hdr.port;
1232
1233 karg->port = port;
1234 pdev = (struct pci_dev *) ioc->pcidev;
1235
1236 karg->pciId = pdev->device;
1237 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1238 karg->hwRev = revision;
1239 karg->subSystemDevice = pdev->subsystem_device;
1240 karg->subSystemVendor = pdev->subsystem_vendor;
1241
1242 if (cim_rev == 1) {
1243 /* Get the PCI bus, device, and function numbers for the IOC
1244 */
1245 karg->pciInfo.u.bits.busNumber = pdev->bus->number;
1246 karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
1247 karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
1248 } else if (cim_rev == 2) {
Moore, Eric86a7dca2006-02-02 17:19:37 -07001249 /* Get the PCI bus, device, function and segment ID numbers
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 for the IOC */
1251 karg->pciInfo.u.bits.busNumber = pdev->bus->number;
1252 karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
1253 karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 karg->pciInfo.segmentID = pci_domain_nr(pdev->bus);
1255 }
1256
1257 /* Get number of devices
1258 */
1259 if ((sh = ioc->sh) != NULL) {
1260 /* sh->max_id = maximum target ID + 1
1261 */
1262 max_id = sh->max_id - 1;
1263 hd = (MPT_SCSI_HOST *) sh->hostdata;
1264
1265 /* Check all of the target structures and
1266 * keep a counter.
1267 */
1268 if (hd && hd->Targets) {
1269 for (ii = 0; ii <= max_id; ii++) {
1270 if (hd->Targets[ii])
1271 numDevices++;
1272 }
1273 }
1274 }
1275 karg->numDevices = numDevices;
1276
1277 /* Set the BIOS and FW Version
1278 */
1279 karg->FWVersion = ioc->facts.FWVersion.Word;
1280 karg->BIOSVersion = ioc->biosVersion;
1281
1282 /* Set the Version Strings.
1283 */
1284 strncpy (karg->driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH);
1285 karg->driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0';
1286
1287 karg->busChangeEvent = 0;
1288 karg->hostId = ioc->pfacts[port].PortSCSIID;
1289 karg->rsvd[0] = karg->rsvd[1] = 0;
1290
1291 /* Copy the data from kernel memory to user memory
1292 */
1293 if (copy_to_user((char __user *)arg, karg, data_size)) {
1294 printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
1295 "Unable to write out mpt_ioctl_iocinfo struct @ %p\n",
1296 __FILE__, __LINE__, uarg);
1297 kfree(karg);
1298 return -EFAULT;
1299 }
1300
1301 kfree(karg);
1302 return 0;
1303}
1304
1305/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1306/*
1307 * mptctl_gettargetinfo - Query the host adapter for target information.
1308 * @arg: User space argument
1309 *
1310 * Outputs: None.
1311 * Return: 0 if successful
1312 * -EFAULT if data unavailable
1313 * -ENODEV if no such device/adapter
1314 */
1315static int
1316mptctl_gettargetinfo (unsigned long arg)
1317{
1318 struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
1319 struct mpt_ioctl_targetinfo karg;
1320 MPT_ADAPTER *ioc;
1321 struct Scsi_Host *sh;
1322 MPT_SCSI_HOST *hd;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -07001323 VirtTarget *vdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 char *pmem;
1325 int *pdata;
1326 IOCPage2_t *pIoc2;
1327 IOCPage3_t *pIoc3;
1328 int iocnum;
1329 int numDevices = 0;
1330 unsigned int max_id;
1331 int id, jj, indexed_lun, lun_index;
1332 u32 lun;
1333 int maxWordsLeft;
1334 int numBytes;
1335 u8 port, devType, bus_id;
1336
1337 dctlprintk(("mptctl_gettargetinfo called.\n"));
1338 if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
1339 printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
1340 "Unable to read in mpt_ioctl_targetinfo struct @ %p\n",
1341 __FILE__, __LINE__, uarg);
1342 return -EFAULT;
1343 }
1344
1345 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
1346 (ioc == NULL)) {
1347 dctlprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
1348 __FILE__, __LINE__, iocnum));
1349 return -ENODEV;
1350 }
1351
1352 /* Get the port number and set the maximum number of bytes
1353 * in the returned structure.
1354 * Ignore the port setting.
1355 */
1356 numBytes = karg.hdr.maxDataSize - sizeof(mpt_ioctl_header);
1357 maxWordsLeft = numBytes/sizeof(int);
1358 port = karg.hdr.port;
1359
1360 if (maxWordsLeft <= 0) {
1361 printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
1362 __FILE__, __LINE__);
1363 return -ENOMEM;
1364 }
1365
1366 /* Fill in the data and return the structure to the calling
1367 * program
1368 */
1369
1370 /* struct mpt_ioctl_targetinfo does not contain sufficient space
1371 * for the target structures so when the IOCTL is called, there is
1372 * not sufficient stack space for the structure. Allocate memory,
1373 * populate the memory, copy back to the user, then free memory.
1374 * targetInfo format:
1375 * bits 31-24: reserved
1376 * 23-16: LUN
1377 * 15- 8: Bus Number
1378 * 7- 0: Target ID
1379 */
1380 pmem = kmalloc(numBytes, GFP_KERNEL);
1381 if (pmem == NULL) {
1382 printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
1383 __FILE__, __LINE__);
1384 return -ENOMEM;
1385 }
1386 memset(pmem, 0, numBytes);
1387 pdata = (int *) pmem;
1388
1389 /* Get number of devices
1390 */
1391 if ((sh = ioc->sh) != NULL) {
1392
1393 max_id = sh->max_id - 1;
1394 hd = (MPT_SCSI_HOST *) sh->hostdata;
1395
1396 /* Check all of the target structures.
1397 * Save the Id and increment the counter,
1398 * if ptr non-null.
1399 * sh->max_id = maximum target ID + 1
1400 */
1401 if (hd && hd->Targets) {
1402 mpt_findImVolumes(ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001403 pIoc2 = ioc->raid_data.pIocPg2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 for ( id = 0; id <= max_id; ) {
1405 if ( pIoc2 && pIoc2->NumActiveVolumes ) {
1406 if ( id == pIoc2->RaidVolume[0].VolumeID ) {
1407 if (maxWordsLeft <= 0) {
1408 printk(KERN_ERR "mptctl_gettargetinfo - "
1409 "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
1410 goto data_space_full;
1411 }
1412 if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
1413 devType = 0x80;
1414 else
1415 devType = 0xC0;
1416 bus_id = pIoc2->RaidVolume[0].VolumeBus;
1417 numDevices++;
1418 *pdata = ( (devType << 24) | (bus_id << 8) | id );
1419 dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
1420 "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
1421 pdata++;
1422 --maxWordsLeft;
1423 goto next_id;
1424 } else {
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001425 pIoc3 = ioc->raid_data.pIocPg3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
1427 if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
1428 goto next_id;
1429 }
1430 }
1431 }
1432 if ( (vdev = hd->Targets[id]) ) {
1433 for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
1434 lun_index = (jj >> 5);
1435 indexed_lun = (jj % 32);
1436 lun = (1 << indexed_lun);
1437 if (vdev->luns[lun_index] & lun) {
1438 if (maxWordsLeft <= 0) {
1439 printk(KERN_ERR "mptctl_gettargetinfo - "
1440 "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
1441 goto data_space_full;
1442 }
1443 bus_id = vdev->bus_id;
1444 numDevices++;
1445 *pdata = ( (jj << 16) | (bus_id << 8) | id );
1446 dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
1447 "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
1448 pdata++;
1449 --maxWordsLeft;
1450 }
1451 }
1452 }
1453next_id:
1454 id++;
1455 }
1456 }
1457 }
1458data_space_full:
1459 karg.numDevices = numDevices;
1460
1461 /* Copy part of the data from kernel memory to user memory
1462 */
1463 if (copy_to_user((char __user *)arg, &karg,
1464 sizeof(struct mpt_ioctl_targetinfo))) {
1465 printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
1466 "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
1467 __FILE__, __LINE__, uarg);
1468 kfree(pmem);
1469 return -EFAULT;
1470 }
1471
1472 /* Copy the remaining data from kernel memory to user memory
1473 */
1474 if (copy_to_user(uarg->targetInfo, pmem, numBytes)) {
1475 printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
1476 "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
1477 __FILE__, __LINE__, pdata);
1478 kfree(pmem);
1479 return -EFAULT;
1480 }
1481
1482 kfree(pmem);
1483
1484 return 0;
1485}
1486
1487/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1488/* MPT IOCTL Test function.
1489 *
1490 * Outputs: None.
1491 * Return: 0 if successful
1492 * -EFAULT if data unavailable
1493 * -ENODEV if no such device/adapter
1494 */
1495static int
1496mptctl_readtest (unsigned long arg)
1497{
1498 struct mpt_ioctl_test __user *uarg = (void __user *) arg;
1499 struct mpt_ioctl_test karg;
1500 MPT_ADAPTER *ioc;
1501 int iocnum;
1502
1503 dctlprintk(("mptctl_readtest called.\n"));
1504 if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
1505 printk(KERN_ERR "%s@%d::mptctl_readtest - "
1506 "Unable to read in mpt_ioctl_test struct @ %p\n",
1507 __FILE__, __LINE__, uarg);
1508 return -EFAULT;
1509 }
1510
1511 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
1512 (ioc == NULL)) {
1513 dctlprintk((KERN_ERR "%s::mptctl_readtest() @%d - ioc%d not found!\n",
1514 __FILE__, __LINE__, iocnum));
1515 return -ENODEV;
1516 }
1517
1518 /* Fill in the data and return the structure to the calling
1519 * program
1520 */
1521
1522#ifdef MFCNT
1523 karg.chip_type = ioc->mfcnt;
1524#else
1525 karg.chip_type = ioc->pcidev->device;
1526#endif
1527 strncpy (karg.name, ioc->name, MPT_MAX_NAME);
1528 karg.name[MPT_MAX_NAME-1]='\0';
1529 strncpy (karg.product, ioc->prod_name, MPT_PRODUCT_LENGTH);
1530 karg.product[MPT_PRODUCT_LENGTH-1]='\0';
1531
1532 /* Copy the data from kernel memory to user memory
1533 */
1534 if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
1535 printk(KERN_ERR "%s@%d::mptctl_readtest - "
1536 "Unable to write out mpt_ioctl_test struct @ %p\n",
1537 __FILE__, __LINE__, uarg);
1538 return -EFAULT;
1539 }
1540
1541 return 0;
1542}
1543
1544/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1545/*
1546 * mptctl_eventquery - Query the host adapter for the event types
1547 * that are being logged.
1548 * @arg: User space argument
1549 *
1550 * Outputs: None.
1551 * Return: 0 if successful
1552 * -EFAULT if data unavailable
1553 * -ENODEV if no such device/adapter
1554 */
1555static int
1556mptctl_eventquery (unsigned long arg)
1557{
1558 struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
1559 struct mpt_ioctl_eventquery karg;
1560 MPT_ADAPTER *ioc;
1561 int iocnum;
1562
1563 dctlprintk(("mptctl_eventquery called.\n"));
1564 if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
1565 printk(KERN_ERR "%s@%d::mptctl_eventquery - "
1566 "Unable to read in mpt_ioctl_eventquery struct @ %p\n",
1567 __FILE__, __LINE__, uarg);
1568 return -EFAULT;
1569 }
1570
1571 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
1572 (ioc == NULL)) {
1573 dctlprintk((KERN_ERR "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
1574 __FILE__, __LINE__, iocnum));
1575 return -ENODEV;
1576 }
1577
Moore, Eric5b5ef4f2006-02-02 17:19:40 -07001578 karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 karg.eventTypes = ioc->eventTypes;
1580
1581 /* Copy the data from kernel memory to user memory
1582 */
1583 if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
1584 printk(KERN_ERR "%s@%d::mptctl_eventquery - "
1585 "Unable to write out mpt_ioctl_eventquery struct @ %p\n",
1586 __FILE__, __LINE__, uarg);
1587 return -EFAULT;
1588 }
1589 return 0;
1590}
1591
1592/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1593static int
1594mptctl_eventenable (unsigned long arg)
1595{
1596 struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
1597 struct mpt_ioctl_eventenable karg;
1598 MPT_ADAPTER *ioc;
1599 int iocnum;
1600
1601 dctlprintk(("mptctl_eventenable called.\n"));
1602 if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
1603 printk(KERN_ERR "%s@%d::mptctl_eventenable - "
1604 "Unable to read in mpt_ioctl_eventenable struct @ %p\n",
1605 __FILE__, __LINE__, uarg);
1606 return -EFAULT;
1607 }
1608
1609 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
1610 (ioc == NULL)) {
1611 dctlprintk((KERN_ERR "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
1612 __FILE__, __LINE__, iocnum));
1613 return -ENODEV;
1614 }
1615
1616 if (ioc->events == NULL) {
1617 /* Have not yet allocated memory - do so now.
1618 */
1619 int sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
1620 ioc->events = kmalloc(sz, GFP_KERNEL);
1621 if (ioc->events == NULL) {
1622 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1623 return -ENOMEM;
1624 }
1625 memset(ioc->events, 0, sz);
1626 ioc->alloc_total += sz;
1627
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 ioc->eventContext = 0;
1629 }
1630
1631 /* Update the IOC event logging flag.
1632 */
1633 ioc->eventTypes = karg.eventTypes;
1634
1635 return 0;
1636}
1637
1638/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1639static int
1640mptctl_eventreport (unsigned long arg)
1641{
1642 struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
1643 struct mpt_ioctl_eventreport karg;
1644 MPT_ADAPTER *ioc;
1645 int iocnum;
1646 int numBytes, maxEvents, max;
1647
1648 dctlprintk(("mptctl_eventreport called.\n"));
1649 if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
1650 printk(KERN_ERR "%s@%d::mptctl_eventreport - "
1651 "Unable to read in mpt_ioctl_eventreport struct @ %p\n",
1652 __FILE__, __LINE__, uarg);
1653 return -EFAULT;
1654 }
1655
1656 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
1657 (ioc == NULL)) {
1658 dctlprintk((KERN_ERR "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
1659 __FILE__, __LINE__, iocnum));
1660 return -ENODEV;
1661 }
1662
1663 numBytes = karg.hdr.maxDataSize - sizeof(mpt_ioctl_header);
1664 maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS);
1665
1666
Moore, Eric5b5ef4f2006-02-02 17:19:40 -07001667 max = MPTCTL_EVENT_LOG_SIZE < maxEvents ? MPTCTL_EVENT_LOG_SIZE : maxEvents;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
1669 /* If fewer than 1 event is requested, there must have
1670 * been some type of error.
1671 */
1672 if ((max < 1) || !ioc->events)
1673 return -ENODATA;
1674
Moore, Ericea5a7a82006-02-02 17:20:01 -07001675 /* reset this flag so SIGIO can restart */
1676 ioc->aen_event_read_flag=0;
1677
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 /* Copy the data from kernel memory to user memory
1679 */
1680 numBytes = max * sizeof(MPT_IOCTL_EVENTS);
1681 if (copy_to_user(uarg->eventData, ioc->events, numBytes)) {
1682 printk(KERN_ERR "%s@%d::mptctl_eventreport - "
1683 "Unable to write out mpt_ioctl_eventreport struct @ %p\n",
1684 __FILE__, __LINE__, ioc->events);
1685 return -EFAULT;
1686 }
1687
1688 return 0;
1689}
1690
1691/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1692static int
1693mptctl_replace_fw (unsigned long arg)
1694{
1695 struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
1696 struct mpt_ioctl_replace_fw karg;
1697 MPT_ADAPTER *ioc;
1698 int iocnum;
1699 int newFwSize;
1700
1701 dctlprintk(("mptctl_replace_fw called.\n"));
1702 if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
1703 printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
1704 "Unable to read in mpt_ioctl_replace_fw struct @ %p\n",
1705 __FILE__, __LINE__, uarg);
1706 return -EFAULT;
1707 }
1708
1709 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
1710 (ioc == NULL)) {
1711 dctlprintk((KERN_ERR "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
1712 __FILE__, __LINE__, iocnum));
1713 return -ENODEV;
1714 }
1715
1716 /* If caching FW, Free the old FW image
1717 */
1718 if (ioc->cached_fw == NULL)
1719 return 0;
1720
1721 mpt_free_fw_memory(ioc);
1722
1723 /* Allocate memory for the new FW image
1724 */
1725 newFwSize = karg.newImageSize;
1726
1727 if (newFwSize & 0x01)
1728 newFwSize += 1;
1729 if (newFwSize & 0x02)
1730 newFwSize += 2;
1731
1732 mpt_alloc_fw_memory(ioc, newFwSize);
1733 if (ioc->cached_fw == NULL)
1734 return -ENOMEM;
1735
1736 /* Copy the data from user memory to kernel space
1737 */
1738 if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
1739 printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
1740 "Unable to read in mpt_ioctl_replace_fw image "
1741 "@ %p\n", __FILE__, __LINE__, uarg);
1742 mpt_free_fw_memory(ioc);
1743 return -EFAULT;
1744 }
1745
1746 /* Update IOCFactsReply
1747 */
1748 ioc->facts.FWImageSize = newFwSize;
1749 return 0;
1750}
1751
1752/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1753/* MPT IOCTL MPTCOMMAND function.
1754 * Cast the arg into the mpt_ioctl_mpt_command structure.
1755 *
1756 * Outputs: None.
1757 * Return: 0 if successful
1758 * -EBUSY if previous command timout and IOC reset is not complete.
1759 * -EFAULT if data unavailable
1760 * -ENODEV if no such device/adapter
1761 * -ETIME if timer expires
1762 * -ENOMEM if memory allocation error
1763 */
1764static int
1765mptctl_mpt_command (unsigned long arg)
1766{
1767 struct mpt_ioctl_command __user *uarg = (void __user *) arg;
1768 struct mpt_ioctl_command karg;
1769 MPT_ADAPTER *ioc;
1770 int iocnum;
1771 int rc;
1772
1773 dctlprintk(("mptctl_command called.\n"));
1774
1775 if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) {
1776 printk(KERN_ERR "%s@%d::mptctl_mpt_command - "
1777 "Unable to read in mpt_ioctl_command struct @ %p\n",
1778 __FILE__, __LINE__, uarg);
1779 return -EFAULT;
1780 }
1781
1782 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
1783 (ioc == NULL)) {
1784 dctlprintk((KERN_ERR "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
1785 __FILE__, __LINE__, iocnum));
1786 return -ENODEV;
1787 }
1788
1789 rc = mptctl_do_mpt_command (karg, &uarg->MF);
1790
1791 return rc;
1792}
1793
1794/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1795/* Worker routine for the IOCTL MPTCOMMAND and MPTCOMMAND32 (sparc) commands.
1796 *
1797 * Outputs: None.
1798 * Return: 0 if successful
1799 * -EBUSY if previous command timout and IOC reset is not complete.
1800 * -EFAULT if data unavailable
1801 * -ENODEV if no such device/adapter
1802 * -ETIME if timer expires
1803 * -ENOMEM if memory allocation error
1804 * -EPERM if SCSI I/O and target is untagged
1805 */
1806static int
1807mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
1808{
1809 MPT_ADAPTER *ioc;
1810 MPT_FRAME_HDR *mf = NULL;
1811 MPIHeader_t *hdr;
1812 char *psge;
1813 struct buflist bufIn; /* data In buffer */
1814 struct buflist bufOut; /* data Out buffer */
1815 dma_addr_t dma_addr_in;
1816 dma_addr_t dma_addr_out;
1817 int sgSize = 0; /* Num SG elements */
1818 int iocnum, flagsLength;
1819 int sz, rc = 0;
1820 int msgContext;
1821 u16 req_idx;
1822 ulong timeout;
1823
1824 dctlprintk(("mptctl_do_mpt_command called.\n"));
1825 bufIn.kptr = bufOut.kptr = NULL;
1826
1827 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
1828 (ioc == NULL)) {
1829 dctlprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
1830 __FILE__, __LINE__, iocnum));
1831 return -ENODEV;
1832 }
1833 if (!ioc->ioctl) {
1834 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
1835 "No memory available during driver init.\n",
1836 __FILE__, __LINE__);
1837 return -ENOMEM;
1838 } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
1839 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
1840 "Busy with IOC Reset \n", __FILE__, __LINE__);
1841 return -EBUSY;
1842 }
1843
1844 /* Verify that the final request frame will not be too large.
1845 */
1846 sz = karg.dataSgeOffset * 4;
1847 if (karg.dataInSize > 0)
1848 sz += sizeof(dma_addr_t) + sizeof(u32);
1849 if (karg.dataOutSize > 0)
1850 sz += sizeof(dma_addr_t) + sizeof(u32);
1851
1852 if (sz > ioc->req_sz) {
1853 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
1854 "Request frame too large (%d) maximum (%d)\n",
1855 __FILE__, __LINE__, sz, ioc->req_sz);
1856 return -EFAULT;
1857 }
1858
1859 /* Get a free request frame and save the message context.
1860 */
1861 if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
1862 return -EAGAIN;
1863
1864 hdr = (MPIHeader_t *) mf;
1865 msgContext = le32_to_cpu(hdr->MsgContext);
1866 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1867
1868 /* Copy the request frame
1869 * Reset the saved message context.
1870 * Request frame in user space
1871 */
1872 if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) {
1873 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
1874 "Unable to read MF from mpt_ioctl_command struct @ %p\n",
1875 __FILE__, __LINE__, mfPtr);
1876 rc = -EFAULT;
1877 goto done_free_mem;
1878 }
1879 hdr->MsgContext = cpu_to_le32(msgContext);
1880
1881
1882 /* Verify that this request is allowed.
1883 */
1884 switch (hdr->Function) {
1885 case MPI_FUNCTION_IOC_FACTS:
1886 case MPI_FUNCTION_PORT_FACTS:
1887 karg.dataOutSize = karg.dataInSize = 0;
1888 break;
1889
1890 case MPI_FUNCTION_CONFIG:
1891 case MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND:
1892 case MPI_FUNCTION_FC_EX_LINK_SRVC_SEND:
1893 case MPI_FUNCTION_FW_UPLOAD:
1894 case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
1895 case MPI_FUNCTION_FW_DOWNLOAD:
1896 case MPI_FUNCTION_FC_PRIMITIVE_SEND:
Moore, Eric096f7a22006-02-02 17:19:30 -07001897 case MPI_FUNCTION_TOOLBOX:
1898 case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 break;
1900
1901 case MPI_FUNCTION_SCSI_IO_REQUEST:
1902 if (ioc->sh) {
1903 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -07001904 VirtTarget *pTarget = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 MPT_SCSI_HOST *hd = NULL;
1906 int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
1907 int scsidir = 0;
1908 int target = (int) pScsiReq->TargetID;
1909 int dataSize;
1910
1911 if ((target < 0) || (target >= ioc->sh->max_id)) {
1912 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
1913 "Target ID out of bounds. \n",
1914 __FILE__, __LINE__);
1915 rc = -ENODEV;
1916 goto done_free_mem;
1917 }
1918
Moore, Eric5f07e242006-02-02 17:19:44 -07001919 pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
1920 pScsiReq->MsgFlags |= mpt_msg_flags();
1921
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922
1923 /* verify that app has not requested
1924 * more sense data than driver
1925 * can provide, if so, reset this parameter
1926 * set the sense buffer pointer low address
1927 * update the control field to specify Q type
1928 */
1929 if (karg.maxSenseBytes > MPT_SENSE_BUFFER_SIZE)
1930 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1931 else
1932 pScsiReq->SenseBufferLength = karg.maxSenseBytes;
1933
1934 pScsiReq->SenseBufferLowAddr =
1935 cpu_to_le32(ioc->sense_buf_low_dma
1936 + (req_idx * MPT_SENSE_BUFFER_ALLOC));
1937
1938 if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) {
1939 if (hd->Targets)
1940 pTarget = hd->Targets[target];
1941 }
1942
1943 if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
1944 qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
1945
1946 /* Have the IOCTL driver set the direction based
1947 * on the dataOutSize (ordering issue with Sparc).
1948 */
1949 if (karg.dataOutSize > 0) {
1950 scsidir = MPI_SCSIIO_CONTROL_WRITE;
1951 dataSize = karg.dataOutSize;
1952 } else {
1953 scsidir = MPI_SCSIIO_CONTROL_READ;
1954 dataSize = karg.dataInSize;
1955 }
1956
1957 pScsiReq->Control = cpu_to_le32(scsidir | qtag);
1958 pScsiReq->DataLength = cpu_to_le32(dataSize);
1959
1960 ioc->ioctl->reset = MPTCTL_RESET_OK;
1961 ioc->ioctl->target = target;
1962
1963 } else {
1964 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
1965 "SCSI driver is not loaded. \n",
1966 __FILE__, __LINE__);
1967 rc = -EFAULT;
1968 goto done_free_mem;
1969 }
1970 break;
1971
Moore, Eric096f7a22006-02-02 17:19:30 -07001972 case MPI_FUNCTION_SMP_PASSTHROUGH:
1973 /* Check mf->PassthruFlags to determine if
1974 * transfer is ImmediateMode or not.
1975 * Immediate mode returns data in the ReplyFrame.
1976 * Else, we are sending request and response data
1977 * in two SGLs at the end of the mf.
1978 */
1979 break;
1980
1981 case MPI_FUNCTION_SATA_PASSTHROUGH:
1982 if (!ioc->sh) {
1983 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
1984 "SCSI driver is not loaded. \n",
1985 __FILE__, __LINE__);
1986 rc = -EFAULT;
1987 goto done_free_mem;
1988 }
1989 break;
1990
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 case MPI_FUNCTION_RAID_ACTION:
1992 /* Just add a SGE
1993 */
1994 break;
1995
1996 case MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
1997 if (ioc->sh) {
1998 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
1999 int qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
2000 int scsidir = MPI_SCSIIO_CONTROL_READ;
2001 int dataSize;
2002
Moore, Eric5f07e242006-02-02 17:19:44 -07002003 pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
2004 pScsiReq->MsgFlags |= mpt_msg_flags();
2005
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
2007 /* verify that app has not requested
2008 * more sense data than driver
2009 * can provide, if so, reset this parameter
2010 * set the sense buffer pointer low address
2011 * update the control field to specify Q type
2012 */
2013 if (karg.maxSenseBytes > MPT_SENSE_BUFFER_SIZE)
2014 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2015 else
2016 pScsiReq->SenseBufferLength = karg.maxSenseBytes;
2017
2018 pScsiReq->SenseBufferLowAddr =
2019 cpu_to_le32(ioc->sense_buf_low_dma
2020 + (req_idx * MPT_SENSE_BUFFER_ALLOC));
2021
2022 /* All commands to physical devices are tagged
2023 */
2024
2025 /* Have the IOCTL driver set the direction based
2026 * on the dataOutSize (ordering issue with Sparc).
2027 */
2028 if (karg.dataOutSize > 0) {
2029 scsidir = MPI_SCSIIO_CONTROL_WRITE;
2030 dataSize = karg.dataOutSize;
2031 } else {
2032 scsidir = MPI_SCSIIO_CONTROL_READ;
2033 dataSize = karg.dataInSize;
2034 }
2035
2036 pScsiReq->Control = cpu_to_le32(scsidir | qtag);
2037 pScsiReq->DataLength = cpu_to_le32(dataSize);
2038
2039 ioc->ioctl->reset = MPTCTL_RESET_OK;
2040 ioc->ioctl->target = pScsiReq->TargetID;
2041 } else {
2042 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
2043 "SCSI driver is not loaded. \n",
2044 __FILE__, __LINE__);
2045 rc = -EFAULT;
2046 goto done_free_mem;
2047 }
2048 break;
2049
2050 case MPI_FUNCTION_SCSI_TASK_MGMT:
2051 {
2052 MPT_SCSI_HOST *hd = NULL;
2053 if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) {
2054 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
2055 "SCSI driver not loaded or SCSI host not found. \n",
2056 __FILE__, __LINE__);
2057 rc = -EFAULT;
2058 goto done_free_mem;
2059 } else if (mptctl_set_tm_flags(hd) != 0) {
2060 rc = -EPERM;
2061 goto done_free_mem;
2062 }
2063 }
2064 break;
2065
2066 case MPI_FUNCTION_IOC_INIT:
2067 {
2068 IOCInit_t *pInit = (IOCInit_t *) mf;
2069 u32 high_addr, sense_high;
2070
2071 /* Verify that all entries in the IOC INIT match
2072 * existing setup (and in LE format).
2073 */
2074 if (sizeof(dma_addr_t) == sizeof(u64)) {
2075 high_addr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
2076 sense_high= cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2077 } else {
2078 high_addr = 0;
2079 sense_high= 0;
2080 }
2081
2082 if ((pInit->Flags != 0) || (pInit->MaxDevices != ioc->facts.MaxDevices) ||
2083 (pInit->MaxBuses != ioc->facts.MaxBuses) ||
2084 (pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||
2085 (pInit->HostMfaHighAddr != high_addr) ||
2086 (pInit->SenseBufferHighAddr != sense_high)) {
2087 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
2088 "IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n",
2089 __FILE__, __LINE__);
2090 rc = -EFAULT;
2091 goto done_free_mem;
2092 }
2093 }
2094 break;
2095 default:
2096 /*
2097 * MPI_FUNCTION_PORT_ENABLE
2098 * MPI_FUNCTION_TARGET_CMD_BUFFER_POST
2099 * MPI_FUNCTION_TARGET_ASSIST
2100 * MPI_FUNCTION_TARGET_STATUS_SEND
2101 * MPI_FUNCTION_TARGET_MODE_ABORT
2102 * MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET
2103 * MPI_FUNCTION_IO_UNIT_RESET
2104 * MPI_FUNCTION_HANDSHAKE
2105 * MPI_FUNCTION_REPLY_FRAME_REMOVAL
2106 * MPI_FUNCTION_EVENT_NOTIFICATION
2107 * (driver handles event notification)
2108 * MPI_FUNCTION_EVENT_ACK
2109 */
2110
2111 /* What to do with these??? CHECK ME!!!
2112 MPI_FUNCTION_FC_LINK_SRVC_BUF_POST
2113 MPI_FUNCTION_FC_LINK_SRVC_RSP
2114 MPI_FUNCTION_FC_ABORT
2115 MPI_FUNCTION_LAN_SEND
2116 MPI_FUNCTION_LAN_RECEIVE
2117 MPI_FUNCTION_LAN_RESET
2118 */
2119
2120 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
2121 "Illegal request (function 0x%x) \n",
2122 __FILE__, __LINE__, hdr->Function);
2123 rc = -EFAULT;
2124 goto done_free_mem;
2125 }
2126
2127 /* Add the SGL ( at most one data in SGE and one data out SGE )
2128 * In the case of two SGE's - the data out (write) will always
2129 * preceede the data in (read) SGE. psgList is used to free the
2130 * allocated memory.
2131 */
2132 psge = (char *) (((int *) mf) + karg.dataSgeOffset);
2133 flagsLength = 0;
2134
2135 /* bufIn and bufOut are used for user to kernel space transfers
2136 */
2137 bufIn.kptr = bufOut.kptr = NULL;
2138 bufIn.len = bufOut.len = 0;
2139
2140 if (karg.dataOutSize > 0)
2141 sgSize ++;
2142
2143 if (karg.dataInSize > 0)
2144 sgSize ++;
2145
2146 if (sgSize > 0) {
2147
2148 /* Set up the dataOut memory allocation */
2149 if (karg.dataOutSize > 0) {
2150 if (karg.dataInSize > 0) {
2151 flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2152 MPI_SGE_FLAGS_END_OF_BUFFER |
2153 MPI_SGE_FLAGS_DIRECTION |
2154 mpt_addr_size() )
2155 << MPI_SGE_FLAGS_SHIFT;
2156 } else {
2157 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
2158 }
2159 flagsLength |= karg.dataOutSize;
2160 bufOut.len = karg.dataOutSize;
2161 bufOut.kptr = pci_alloc_consistent(
2162 ioc->pcidev, bufOut.len, &dma_addr_out);
2163
2164 if (bufOut.kptr == NULL) {
2165 rc = -ENOMEM;
2166 goto done_free_mem;
2167 } else {
2168 /* Set up this SGE.
2169 * Copy to MF and to sglbuf
2170 */
2171 mpt_add_sge(psge, flagsLength, dma_addr_out);
2172 psge += (sizeof(u32) + sizeof(dma_addr_t));
2173
2174 /* Copy user data to kernel space.
2175 */
2176 if (copy_from_user(bufOut.kptr,
2177 karg.dataOutBufPtr,
2178 bufOut.len)) {
2179 printk(KERN_ERR
2180 "%s@%d::mptctl_do_mpt_command - Unable "
2181 "to read user data "
2182 "struct @ %p\n",
2183 __FILE__, __LINE__,karg.dataOutBufPtr);
2184 rc = -EFAULT;
2185 goto done_free_mem;
2186 }
2187 }
2188 }
2189
2190 if (karg.dataInSize > 0) {
2191 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
2192 flagsLength |= karg.dataInSize;
2193
2194 bufIn.len = karg.dataInSize;
2195 bufIn.kptr = pci_alloc_consistent(ioc->pcidev,
2196 bufIn.len, &dma_addr_in);
2197
2198 if (bufIn.kptr == NULL) {
2199 rc = -ENOMEM;
2200 goto done_free_mem;
2201 } else {
2202 /* Set up this SGE
2203 * Copy to MF and to sglbuf
2204 */
2205 mpt_add_sge(psge, flagsLength, dma_addr_in);
2206 }
2207 }
2208 } else {
2209 /* Add a NULL SGE
2210 */
2211 mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
2212 }
2213
2214 ioc->ioctl->wait_done = 0;
2215 if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
2216
2217 DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
2218
2219 if (mpt_send_handshake_request(mptctl_id, ioc,
2220 sizeof(SCSITaskMgmt_t), (u32*)mf,
2221 CAN_SLEEP) != 0) {
2222 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
2223 " (ioc %p, mf %p) \n", ioc->name,
2224 ioc, mf));
2225 mptctl_free_tm_flags(ioc);
2226 rc = -ENODATA;
2227 goto done_free_mem;
2228 }
2229
2230 } else
2231 mpt_put_msg_frame(mptctl_id, ioc, mf);
2232
2233 /* Now wait for the command to complete */
2234 timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
Moore, Eric86a7dca2006-02-02 17:19:37 -07002235 timeout = wait_event_timeout(mptctl_wait,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 ioc->ioctl->wait_done == 1,
2237 HZ*timeout);
2238
2239 if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
2240 /* Now we need to reset the board */
2241
2242 if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT)
2243 mptctl_free_tm_flags(ioc);
2244
2245 mptctl_timeout_expired(ioc->ioctl);
2246 rc = -ENODATA;
2247 goto done_free_mem;
2248 }
2249
2250 mf = NULL;
2251
2252 /* If a valid reply frame, copy to the user.
2253 * Offset 2: reply length in U32's
2254 */
2255 if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
2256 if (karg.maxReplyBytes < ioc->reply_sz) {
2257 sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);
2258 } else {
2259 sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);
2260 }
2261
2262 if (sz > 0) {
2263 if (copy_to_user(karg.replyFrameBufPtr,
2264 &ioc->ioctl->ReplyFrame, sz)){
2265 printk(KERN_ERR
2266 "%s@%d::mptctl_do_mpt_command - "
2267 "Unable to write out reply frame %p\n",
2268 __FILE__, __LINE__, karg.replyFrameBufPtr);
2269 rc = -ENODATA;
2270 goto done_free_mem;
2271 }
2272 }
2273 }
2274
2275 /* If valid sense data, copy to user.
2276 */
2277 if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
2278 sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
2279 if (sz > 0) {
2280 if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
2281 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
2282 "Unable to write sense data to user %p\n",
2283 __FILE__, __LINE__,
2284 karg.senseDataPtr);
2285 rc = -ENODATA;
2286 goto done_free_mem;
2287 }
2288 }
2289 }
2290
2291 /* If the overall status is _GOOD and data in, copy data
2292 * to user.
2293 */
2294 if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
2295 (karg.dataInSize > 0) && (bufIn.kptr)) {
2296
2297 if (copy_to_user(karg.dataInBufPtr,
2298 bufIn.kptr, karg.dataInSize)) {
2299 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
2300 "Unable to write data to user %p\n",
2301 __FILE__, __LINE__,
2302 karg.dataInBufPtr);
2303 rc = -ENODATA;
2304 }
2305 }
2306
2307done_free_mem:
2308
2309 ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD |
2310 MPT_IOCTL_STATUS_SENSE_VALID |
2311 MPT_IOCTL_STATUS_RF_VALID );
2312
2313 /* Free the allocated memory.
2314 */
2315 if (bufOut.kptr != NULL) {
2316 pci_free_consistent(ioc->pcidev,
2317 bufOut.len, (void *) bufOut.kptr, dma_addr_out);
2318 }
2319
2320 if (bufIn.kptr != NULL) {
2321 pci_free_consistent(ioc->pcidev,
2322 bufIn.len, (void *) bufIn.kptr, dma_addr_in);
2323 }
2324
2325 /* mf is null if command issued successfully
2326 * otherwise, failure occured after mf acquired.
2327 */
2328 if (mf)
2329 mpt_free_msg_frame(ioc, mf);
2330
2331 return rc;
2332}
2333
2334/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
Eric Mooreba856d32006-07-11 17:34:01 -06002335/* Prototype Routine for the HOST INFO command.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 *
2337 * Outputs: None.
2338 * Return: 0 if successful
2339 * -EFAULT if data unavailable
2340 * -EBUSY if previous command timout and IOC reset is not complete.
2341 * -ENODEV if no such device/adapter
2342 * -ETIME if timer expires
2343 * -ENOMEM if memory allocation error
2344 */
2345static int
2346mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
2347{
2348 hp_host_info_t __user *uarg = (void __user *) arg;
2349 MPT_ADAPTER *ioc;
2350 struct pci_dev *pdev;
Moore, Eric592f9c22006-02-02 17:19:47 -07002351 char *pbuf=NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 dma_addr_t buf_dma;
2353 hp_host_info_t karg;
2354 CONFIGPARMS cfg;
2355 ConfigPageHeader_t hdr;
2356 int iocnum;
2357 int rc, cim_rev;
Moore, Eric592f9c22006-02-02 17:19:47 -07002358 ToolboxIstwiReadWriteRequest_t *IstwiRWRequest;
2359 MPT_FRAME_HDR *mf = NULL;
2360 MPIHeader_t *mpi_hdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361
2362 dctlprintk((": mptctl_hp_hostinfo called.\n"));
2363 /* Reset long to int. Should affect IA64 and SPARC only
2364 */
2365 if (data_size == sizeof(hp_host_info_t))
2366 cim_rev = 1;
2367 else if (data_size == sizeof(hp_host_info_rev0_t))
2368 cim_rev = 0; /* obsolete */
2369 else
2370 return -EFAULT;
2371
2372 if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
2373 printk(KERN_ERR "%s@%d::mptctl_hp_host_info - "
2374 "Unable to read in hp_host_info struct @ %p\n",
2375 __FILE__, __LINE__, uarg);
2376 return -EFAULT;
2377 }
2378
2379 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
2380 (ioc == NULL)) {
2381 dctlprintk((KERN_ERR "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
2382 __FILE__, __LINE__, iocnum));
2383 return -ENODEV;
2384 }
2385
2386 /* Fill in the data and return the structure to the calling
2387 * program
2388 */
2389 pdev = (struct pci_dev *) ioc->pcidev;
2390
2391 karg.vendor = pdev->vendor;
2392 karg.device = pdev->device;
2393 karg.subsystem_id = pdev->subsystem_device;
2394 karg.subsystem_vendor = pdev->subsystem_vendor;
2395 karg.devfn = pdev->devfn;
2396 karg.bus = pdev->bus->number;
2397
2398 /* Save the SCSI host no. if
2399 * SCSI driver loaded
2400 */
2401 if (ioc->sh != NULL)
2402 karg.host_no = ioc->sh->host_no;
2403 else
2404 karg.host_no = -1;
2405
2406 /* Reformat the fw_version into a string
2407 */
2408 karg.fw_version[0] = ioc->facts.FWVersion.Struct.Major >= 10 ?
2409 ((ioc->facts.FWVersion.Struct.Major / 10) + '0') : '0';
2410 karg.fw_version[1] = (ioc->facts.FWVersion.Struct.Major % 10 ) + '0';
2411 karg.fw_version[2] = '.';
2412 karg.fw_version[3] = ioc->facts.FWVersion.Struct.Minor >= 10 ?
2413 ((ioc->facts.FWVersion.Struct.Minor / 10) + '0') : '0';
2414 karg.fw_version[4] = (ioc->facts.FWVersion.Struct.Minor % 10 ) + '0';
2415 karg.fw_version[5] = '.';
2416 karg.fw_version[6] = ioc->facts.FWVersion.Struct.Unit >= 10 ?
2417 ((ioc->facts.FWVersion.Struct.Unit / 10) + '0') : '0';
2418 karg.fw_version[7] = (ioc->facts.FWVersion.Struct.Unit % 10 ) + '0';
2419 karg.fw_version[8] = '.';
2420 karg.fw_version[9] = ioc->facts.FWVersion.Struct.Dev >= 10 ?
2421 ((ioc->facts.FWVersion.Struct.Dev / 10) + '0') : '0';
2422 karg.fw_version[10] = (ioc->facts.FWVersion.Struct.Dev % 10 ) + '0';
2423 karg.fw_version[11] = '\0';
2424
2425 /* Issue a config request to get the device serial number
2426 */
2427 hdr.PageVersion = 0;
2428 hdr.PageLength = 0;
2429 hdr.PageNumber = 0;
2430 hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
Christoph Hellwig69218ee2005-08-18 16:26:15 +02002431 cfg.cfghdr.hdr = &hdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 cfg.physAddr = -1;
2433 cfg.pageAddr = 0;
2434 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2435 cfg.dir = 0; /* read */
2436 cfg.timeout = 10;
2437
2438 strncpy(karg.serial_number, " ", 24);
2439 if (mpt_config(ioc, &cfg) == 0) {
Christoph Hellwig69218ee2005-08-18 16:26:15 +02002440 if (cfg.cfghdr.hdr->PageLength > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 /* Issue the second config page request */
2442 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2443
2444 pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
2445 if (pbuf) {
2446 cfg.physAddr = buf_dma;
2447 if (mpt_config(ioc, &cfg) == 0) {
2448 ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf;
2449 if (strlen(pdata->BoardTracerNumber) > 1) {
2450 strncpy(karg.serial_number, pdata->BoardTracerNumber, 24);
2451 karg.serial_number[24-1]='\0';
2452 }
2453 }
2454 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
2455 pbuf = NULL;
2456 }
2457 }
2458 }
2459 rc = mpt_GetIocState(ioc, 1);
2460 switch (rc) {
2461 case MPI_IOC_STATE_OPERATIONAL:
2462 karg.ioc_status = HP_STATUS_OK;
2463 break;
2464
2465 case MPI_IOC_STATE_FAULT:
2466 karg.ioc_status = HP_STATUS_FAILED;
2467 break;
2468
2469 case MPI_IOC_STATE_RESET:
2470 case MPI_IOC_STATE_READY:
2471 default:
2472 karg.ioc_status = HP_STATUS_OTHER;
2473 break;
2474 }
2475
2476 karg.base_io_addr = pci_resource_start(pdev, 0);
2477
Moore, Eric9cc1cfb2006-02-02 17:19:33 -07002478 if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 karg.bus_phys_width = HP_BUS_WIDTH_UNK;
2480 else
2481 karg.bus_phys_width = HP_BUS_WIDTH_16;
2482
2483 karg.hard_resets = 0;
2484 karg.soft_resets = 0;
2485 karg.timeouts = 0;
2486 if (ioc->sh != NULL) {
2487 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2488
2489 if (hd && (cim_rev == 1)) {
2490 karg.hard_resets = hd->hard_resets;
2491 karg.soft_resets = hd->soft_resets;
2492 karg.timeouts = hd->timeouts;
2493 }
2494 }
2495
Moore, Eric592f9c22006-02-02 17:19:47 -07002496 /*
2497 * Gather ISTWI(Industry Standard Two Wire Interface) Data
2498 */
2499 if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
2500 dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
2501 ioc->name,__FUNCTION__));
2502 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 }
2504
Moore, Eric592f9c22006-02-02 17:19:47 -07002505 IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf;
2506 mpi_hdr = (MPIHeader_t *) mf;
2507 memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t));
2508 IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX;
2509 IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
2510 IstwiRWRequest->MsgContext = mpi_hdr->MsgContext;
2511 IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ;
2512 IstwiRWRequest->NumAddressBytes = 0x01;
2513 IstwiRWRequest->DataLength = cpu_to_le16(0x04);
2514 if (pdev->devfn & 1)
2515 IstwiRWRequest->DeviceAddr = 0xB2;
2516 else
2517 IstwiRWRequest->DeviceAddr = 0xB0;
2518
2519 pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
2520 if (!pbuf)
2521 goto out;
2522 mpt_add_sge((char *)&IstwiRWRequest->SGL,
2523 (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
2524
2525 ioc->ioctl->wait_done = 0;
2526 mpt_put_msg_frame(mptctl_id, ioc, mf);
2527
2528 rc = wait_event_timeout(mptctl_wait,
2529 ioc->ioctl->wait_done == 1,
2530 HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
2531
2532 if(rc <=0 && (ioc->ioctl->wait_done != 1 )) {
2533 /*
2534 * Now we need to reset the board
2535 */
2536 mpt_free_msg_frame(ioc, mf);
2537 mptctl_timeout_expired(ioc->ioctl);
2538 goto out;
2539 }
2540
2541 /*
2542 *ISTWI Data Definition
2543 * pbuf[0] = FW_VERSION = 0x4
2544 * pbuf[1] = Bay Count = 6 or 4 or 2, depending on
2545 * the config, you should be seeing one out of these three values
2546 * pbuf[2] = Drive Installed Map = bit pattern depend on which
2547 * bays have drives in them
2548 * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3)
2549 */
2550 if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID)
2551 karg.rsvd = *(u32 *)pbuf;
2552
2553 out:
2554 if (pbuf)
2555 pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
2556
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 /* Copy the data from kernel memory to user memory
2558 */
2559 if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
2560 printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - "
2561 "Unable to write out hp_host_info @ %p\n",
2562 __FILE__, __LINE__, uarg);
2563 return -EFAULT;
2564 }
2565
2566 return 0;
2567
2568}
2569
2570/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
Eric Mooreba856d32006-07-11 17:34:01 -06002571/* Prototype Routine for the TARGET INFO command.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 *
2573 * Outputs: None.
2574 * Return: 0 if successful
2575 * -EFAULT if data unavailable
2576 * -EBUSY if previous command timout and IOC reset is not complete.
2577 * -ENODEV if no such device/adapter
2578 * -ETIME if timer expires
2579 * -ENOMEM if memory allocation error
2580 */
2581static int
2582mptctl_hp_targetinfo(unsigned long arg)
2583{
2584 hp_target_info_t __user *uarg = (void __user *) arg;
2585 SCSIDevicePage0_t *pg0_alloc;
2586 SCSIDevicePage3_t *pg3_alloc;
2587 MPT_ADAPTER *ioc;
2588 MPT_SCSI_HOST *hd = NULL;
2589 hp_target_info_t karg;
2590 int iocnum;
2591 int data_sz;
2592 dma_addr_t page_dma;
2593 CONFIGPARMS cfg;
2594 ConfigPageHeader_t hdr;
2595 int tmp, np, rc = 0;
2596
2597 dctlprintk((": mptctl_hp_targetinfo called.\n"));
2598 if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) {
2599 printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - "
2600 "Unable to read in hp_host_targetinfo struct @ %p\n",
2601 __FILE__, __LINE__, uarg);
2602 return -EFAULT;
2603 }
2604
2605 if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
2606 (ioc == NULL)) {
2607 dctlprintk((KERN_ERR "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
2608 __FILE__, __LINE__, iocnum));
2609 return -ENODEV;
2610 }
2611
2612 /* There is nothing to do for FCP parts.
2613 */
Moore, Eric9cc1cfb2006-02-02 17:19:33 -07002614 if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 return 0;
2616
2617 if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL))
2618 return 0;
2619
2620 if (ioc->sh->host_no != karg.hdr.host)
2621 return -ENODEV;
2622
2623 /* Get the data transfer speeds
2624 */
2625 data_sz = ioc->spi_data.sdp0length * 4;
2626 pg0_alloc = (SCSIDevicePage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
2627 if (pg0_alloc) {
2628 hdr.PageVersion = ioc->spi_data.sdp0version;
2629 hdr.PageLength = data_sz;
2630 hdr.PageNumber = 0;
2631 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
2632
Christoph Hellwig69218ee2005-08-18 16:26:15 +02002633 cfg.cfghdr.hdr = &hdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2635 cfg.dir = 0;
2636 cfg.timeout = 0;
2637 cfg.physAddr = page_dma;
2638
2639 cfg.pageAddr = (karg.hdr.channel << 8) | karg.hdr.id;
2640
2641 if ((rc = mpt_config(ioc, &cfg)) == 0) {
2642 np = le32_to_cpu(pg0_alloc->NegotiatedParameters);
2643 karg.negotiated_width = np & MPI_SCSIDEVPAGE0_NP_WIDE ?
2644 HP_BUS_WIDTH_16 : HP_BUS_WIDTH_8;
2645
2646 if (np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) {
2647 tmp = (np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
2648 if (tmp < 0x09)
2649 karg.negotiated_speed = HP_DEV_SPEED_ULTRA320;
2650 else if (tmp <= 0x09)
2651 karg.negotiated_speed = HP_DEV_SPEED_ULTRA160;
2652 else if (tmp <= 0x0A)
2653 karg.negotiated_speed = HP_DEV_SPEED_ULTRA2;
2654 else if (tmp <= 0x0C)
2655 karg.negotiated_speed = HP_DEV_SPEED_ULTRA;
2656 else if (tmp <= 0x25)
2657 karg.negotiated_speed = HP_DEV_SPEED_FAST;
2658 else
2659 karg.negotiated_speed = HP_DEV_SPEED_ASYNC;
2660 } else
2661 karg.negotiated_speed = HP_DEV_SPEED_ASYNC;
2662 }
2663
2664 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg0_alloc, page_dma);
2665 }
2666
2667 /* Set defaults
2668 */
2669 karg.message_rejects = -1;
2670 karg.phase_errors = -1;
2671 karg.parity_errors = -1;
2672 karg.select_timeouts = -1;
2673
2674 /* Get the target error parameters
2675 */
2676 hdr.PageVersion = 0;
2677 hdr.PageLength = 0;
2678 hdr.PageNumber = 3;
2679 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
2680
Christoph Hellwig69218ee2005-08-18 16:26:15 +02002681 cfg.cfghdr.hdr = &hdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2683 cfg.dir = 0;
2684 cfg.timeout = 0;
2685 cfg.physAddr = -1;
Christoph Hellwig69218ee2005-08-18 16:26:15 +02002686 if ((mpt_config(ioc, &cfg) == 0) && (cfg.cfghdr.hdr->PageLength > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 /* Issue the second config page request */
2688 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
Christoph Hellwig69218ee2005-08-18 16:26:15 +02002689 data_sz = (int) cfg.cfghdr.hdr->PageLength * 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent(
2691 ioc->pcidev, data_sz, &page_dma);
2692 if (pg3_alloc) {
2693 cfg.physAddr = page_dma;
2694 cfg.pageAddr = (karg.hdr.channel << 8) | karg.hdr.id;
2695 if ((rc = mpt_config(ioc, &cfg)) == 0) {
2696 karg.message_rejects = (u32) le16_to_cpu(pg3_alloc->MsgRejectCount);
2697 karg.phase_errors = (u32) le16_to_cpu(pg3_alloc->PhaseErrorCount);
2698 karg.parity_errors = (u32) le16_to_cpu(pg3_alloc->ParityErrorCount);
2699 }
2700 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg3_alloc, page_dma);
2701 }
2702 }
2703 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2704 if (hd != NULL)
2705 karg.select_timeouts = hd->sel_timeout[karg.hdr.id];
2706
2707 /* Copy the data from kernel memory to user memory
2708 */
2709 if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) {
2710 printk(KERN_ERR "%s@%d::mptctl_hp_target_info - "
2711 "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
2712 __FILE__, __LINE__, uarg);
2713 return -EFAULT;
2714 }
2715
2716 return 0;
2717}
2718
2719/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2720
2721static struct file_operations mptctl_fops = {
2722 .owner = THIS_MODULE,
2723 .llseek = no_llseek,
Moore, Ericea5a7a82006-02-02 17:20:01 -07002724 .release = mptctl_release,
2725 .fasync = mptctl_fasync,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 .unlocked_ioctl = mptctl_ioctl,
2727#ifdef CONFIG_COMPAT
2728 .compat_ioctl = compat_mpctl_ioctl,
2729#endif
2730};
2731
2732static struct miscdevice mptctl_miscdev = {
2733 MPT_MINOR,
2734 MYNAM,
2735 &mptctl_fops
2736};
2737
2738/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2739
2740#ifdef CONFIG_COMPAT
2741
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742static int
2743compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
2744 unsigned long arg)
2745{
2746 struct mpt_fw_xfer32 kfw32;
2747 struct mpt_fw_xfer kfw;
2748 MPT_ADAPTER *iocp = NULL;
2749 int iocnum, iocnumX;
2750 int nonblock = (filp->f_flags & O_NONBLOCK);
2751 int ret;
2752
2753 dctlprintk((KERN_INFO MYNAM "::compat_mptfwxfer_ioctl() called\n"));
2754
2755 if (copy_from_user(&kfw32, (char __user *)arg, sizeof(kfw32)))
2756 return -EFAULT;
2757
2758 /* Verify intended MPT adapter */
2759 iocnumX = kfw32.iocnum & 0xFF;
2760 if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
2761 (iocp == NULL)) {
2762 dctlprintk((KERN_ERR MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
2763 __LINE__, iocnumX));
2764 return -ENODEV;
2765 }
2766
2767 if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
2768 return ret;
2769
2770 kfw.iocnum = iocnum;
2771 kfw.fwlen = kfw32.fwlen;
2772 kfw.bufp = compat_ptr(kfw32.bufp);
2773
2774 ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
2775
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002776 mutex_unlock(&iocp->ioctl->ioctl_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
2778 return ret;
2779}
2780
2781static int
2782compat_mpt_command(struct file *filp, unsigned int cmd,
2783 unsigned long arg)
2784{
2785 struct mpt_ioctl_command32 karg32;
2786 struct mpt_ioctl_command32 __user *uarg = (struct mpt_ioctl_command32 __user *) arg;
2787 struct mpt_ioctl_command karg;
2788 MPT_ADAPTER *iocp = NULL;
2789 int iocnum, iocnumX;
2790 int nonblock = (filp->f_flags & O_NONBLOCK);
2791 int ret;
2792
2793 dctlprintk((KERN_INFO MYNAM "::compat_mpt_command() called\n"));
2794
2795 if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32)))
2796 return -EFAULT;
2797
2798 /* Verify intended MPT adapter */
2799 iocnumX = karg32.hdr.iocnum & 0xFF;
2800 if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
2801 (iocp == NULL)) {
2802 dctlprintk((KERN_ERR MYNAM "::compat_mpt_command @%d - ioc%d not found!\n",
2803 __LINE__, iocnumX));
2804 return -ENODEV;
2805 }
2806
2807 if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
2808 return ret;
2809
2810 /* Copy data to karg */
2811 karg.hdr.iocnum = karg32.hdr.iocnum;
2812 karg.hdr.port = karg32.hdr.port;
2813 karg.timeout = karg32.timeout;
2814 karg.maxReplyBytes = karg32.maxReplyBytes;
2815
2816 karg.dataInSize = karg32.dataInSize;
2817 karg.dataOutSize = karg32.dataOutSize;
2818 karg.maxSenseBytes = karg32.maxSenseBytes;
2819 karg.dataSgeOffset = karg32.dataSgeOffset;
2820
2821 karg.replyFrameBufPtr = (char __user *)(unsigned long)karg32.replyFrameBufPtr;
2822 karg.dataInBufPtr = (char __user *)(unsigned long)karg32.dataInBufPtr;
2823 karg.dataOutBufPtr = (char __user *)(unsigned long)karg32.dataOutBufPtr;
2824 karg.senseDataPtr = (char __user *)(unsigned long)karg32.senseDataPtr;
2825
2826 /* Pass new structure to do_mpt_command
2827 */
2828 ret = mptctl_do_mpt_command (karg, &uarg->MF);
2829
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002830 mutex_unlock(&iocp->ioctl->ioctl_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831
2832 return ret;
2833}
2834
2835static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
2836{
2837 long ret;
2838 lock_kernel();
2839 switch (cmd) {
2840 case MPTIOCINFO:
2841 case MPTIOCINFO1:
2842 case MPTIOCINFO2:
2843 case MPTTARGETINFO:
2844 case MPTEVENTQUERY:
2845 case MPTEVENTENABLE:
2846 case MPTEVENTREPORT:
2847 case MPTHARDRESET:
2848 case HP_GETHOSTINFO:
2849 case HP_GETTARGETINFO:
2850 case MPTTEST:
2851 ret = __mptctl_ioctl(f, cmd, arg);
2852 break;
2853 case MPTCOMMAND32:
2854 ret = compat_mpt_command(f, cmd, arg);
2855 break;
2856 case MPTFWDOWNLOAD32:
2857 ret = compat_mptfwxfer_ioctl(f, cmd, arg);
2858 break;
2859 default:
2860 ret = -ENOIOCTLCMD;
2861 break;
2862 }
2863 unlock_kernel();
2864 return ret;
2865}
2866
2867#endif
2868
2869
2870/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2871/*
2872 * mptctl_probe - Installs ioctl devices per bus.
2873 * @pdev: Pointer to pci_dev structure
2874 *
2875 * Returns 0 for success, non-zero for failure.
2876 *
2877 */
2878
2879static int
2880mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2881{
2882 int err;
2883 int sz;
2884 u8 *mem;
2885 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2886
2887 /*
2888 * Allocate and inite a MPT_IOCTL structure
2889 */
2890 sz = sizeof (MPT_IOCTL);
2891 mem = kmalloc(sz, GFP_KERNEL);
2892 if (mem == NULL) {
2893 err = -ENOMEM;
2894 goto out_fail;
2895 }
2896
2897 memset(mem, 0, sz);
2898 ioc->ioctl = (MPT_IOCTL *) mem;
2899 ioc->ioctl->ioc = ioc;
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002900 mutex_init(&ioc->ioctl->ioctl_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901 return 0;
2902
2903out_fail:
2904
2905 mptctl_remove(pdev);
2906 return err;
2907}
2908
2909/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2910/*
2911 * mptctl_remove - Removed ioctl devices
2912 * @pdev: Pointer to pci_dev structure
2913 *
2914 *
2915 */
2916static void
2917mptctl_remove(struct pci_dev *pdev)
2918{
2919 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2920
2921 kfree ( ioc->ioctl );
2922}
2923
2924static struct mpt_pci_driver mptctl_driver = {
2925 .probe = mptctl_probe,
2926 .remove = mptctl_remove,
2927};
2928
2929/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2930static int __init mptctl_init(void)
2931{
2932 int err;
2933 int where = 1;
2934
2935 show_mptmod_ver(my_NAME, my_VERSION);
2936
2937 if(mpt_device_driver_register(&mptctl_driver,
2938 MPTCTL_DRIVER) != 0 ) {
2939 dprintk((KERN_INFO MYNAM
2940 ": failed to register dd callbacks\n"));
2941 }
2942
2943 /* Register this device */
2944 err = misc_register(&mptctl_miscdev);
2945 if (err < 0) {
2946 printk(KERN_ERR MYNAM ": Can't register misc device [minor=%d].\n", MPT_MINOR);
2947 goto out_fail;
2948 }
2949 printk(KERN_INFO MYNAM ": Registered with Fusion MPT base driver\n");
2950 printk(KERN_INFO MYNAM ": /dev/%s @ (major,minor=%d,%d)\n",
2951 mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
2952
2953 /*
2954 * Install our handler
2955 */
2956 ++where;
2957 if ((mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER)) < 0) {
2958 printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n");
2959 misc_deregister(&mptctl_miscdev);
2960 err = -EBUSY;
2961 goto out_fail;
2962 }
2963
2964 if (mpt_reset_register(mptctl_id, mptctl_ioc_reset) == 0) {
2965 dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
2966 } else {
2967 /* FIXME! */
2968 }
2969
Moore, Ericea5a7a82006-02-02 17:20:01 -07002970 if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002971 devtverboseprintk((KERN_INFO MYNAM
Moore, Ericea5a7a82006-02-02 17:20:01 -07002972 ": Registered for IOC event notifications\n"));
2973 }
2974
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 return 0;
2976
2977out_fail:
2978
2979 mpt_device_driver_deregister(MPTCTL_DRIVER);
2980
2981 return err;
2982}
2983
2984/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2985static void mptctl_exit(void)
2986{
2987 misc_deregister(&mptctl_miscdev);
2988 printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",
2989 mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
2990
2991 /* De-register reset handler from base module */
2992 mpt_reset_deregister(mptctl_id);
2993 dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n"));
2994
2995 /* De-register callback handler from base module */
2996 mpt_deregister(mptctl_id);
2997 printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n");
2998
2999 mpt_device_driver_deregister(MPTCTL_DRIVER);
3000
3001}
3002
3003/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3004
3005module_init(mptctl_init);
3006module_exit(mptctl_exit);