mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Stephen Cameron <steve.cameron@hp.com>
To: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] 2.5.63 cciss fix unlikely startup problem
Date: Thu, 27 Feb 2003 14:39:53 +0600	[thread overview]
Message-ID: <20030227083953.GA3992@zuul.cca.cpqcorp.net> (raw)

Another cciss patch for 2.5.63

Add new big passthrough ioctl to allow large buffers.
Used by e.g. online array controller firmware flash utility.

-- steve

--- linux-2.5.63/drivers/block/cciss.c~bigioctl	2003-02-27 14:11:56.000000000 +0600
+++ linux-2.5.63-scameron/drivers/block/cciss.c	2003-02-27 14:11:56.000000000 +0600
@@ -728,7 +728,153 @@ static int cciss_ioctl(struct inode *ino
 		cmd_free(h, c, 0);
                 return(0);
 	} 
-
+	case CCISS_BIG_PASSTHRU: {
+		BIG_IOCTL_Command_struct *ioc;
+		ctlr_info_t *h = hba[ctlr];
+		CommandList_struct *c;
+		unsigned char **buff = NULL;
+		int	*buff_size = NULL;
+		u64bit	temp64;
+		unsigned long flags;
+		BYTE sg_used = 0;
+		int status = 0;
+		int i;
+		DECLARE_COMPLETION(wait);
+		__u32   left;
+		__u32	sz;
+		BYTE    *data_ptr;
+
+		if (!arg)
+			return -EINVAL;
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+		ioc = (BIG_IOCTL_Command_struct *) 
+			kmalloc(sizeof(*ioc), GFP_KERNEL);
+		if (!ioc) {
+			status = -ENOMEM;
+			goto cleanup1;
+		}
+		if (copy_from_user(ioc, (void *) arg, sizeof(*ioc)))
+			return -EFAULT;
+		if ((ioc->buf_size < 1) &&
+			(ioc->Request.Type.Direction != XFER_NONE))
+				return -EINVAL;
+		/* Check kmalloc limits  using all SGs */
+		if (ioc->malloc_size > MAX_KMALLOC_SIZE)
+			return -EINVAL;
+		if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES)
+			return -EINVAL;
+		buff = (unsigned char **) kmalloc(MAXSGENTRIES * 
+				sizeof(char *), GFP_KERNEL);
+		if (!buff) {
+			status = -ENOMEM;
+			goto cleanup1;
+		}
+		memset(buff, 0, MAXSGENTRIES);
+		buff_size = (int *) kmalloc(MAXSGENTRIES * sizeof(int), 
+					GFP_KERNEL);
+		if (!buff_size) {
+			status = -ENOMEM;
+			goto cleanup1;
+		}
+		left = ioc->buf_size;
+		data_ptr = (BYTE *) ioc->buf;
+		while (left) {
+			sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
+			buff_size[sg_used] = sz;
+			buff[sg_used] = kmalloc(sz, GFP_KERNEL);
+			if (buff[sg_used] == NULL) {
+				status = -ENOMEM;
+				goto cleanup1;
+			}
+			if (ioc->Request.Type.Direction == XFER_WRITE &&
+				copy_from_user(buff[sg_used], data_ptr, sz)) {
+					status = -ENOMEM;
+					goto cleanup1;			
+			}
+			left -= sz;
+			data_ptr += sz;
+			sg_used++;
+		}
+		if ((c = cmd_alloc(h , 0)) == NULL) {
+			status = -ENOMEM;
+			goto cleanup1;	
+		}
+		c->cmd_type = CMD_IOCTL_PEND;
+		c->Header.ReplyQueue = 0;
+		
+		if( ioc->buf_size > 0) {
+			c->Header.SGList = sg_used;
+			c->Header.SGTotal= sg_used;
+		} else { 
+			c->Header.SGList = 0;
+			c->Header.SGTotal= 0;
+		}
+		c->Header.LUN = ioc->LUN_info;
+		c->Header.Tag.lower = c->busaddr;
+		
+		c->Request = ioc->Request;
+		if (ioc->buf_size > 0 ) {
+			int i;
+			for(i=0; i<sg_used; i++) {
+				temp64.val = pci_map_single( h->pdev, buff[i],
+					buff_size[i],
+					PCI_DMA_BIDIRECTIONAL);
+				c->SG[i].Addr.lower = temp64.val32.lower;
+				c->SG[i].Addr.upper = temp64.val32.upper;
+				c->SG[i].Len = buff_size[i];
+				c->SG[i].Ext = 0;  /* we are not chaining */
+			}
+		}
+		c->waiting = &wait;
+		/* Put the request on the tail of the request queue */
+		spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+		addQ(&h->reqQ, c);
+		h->Qdepth++;
+		start_io(h);
+		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+		wait_for_completion(&wait);
+		/* unlock the buffers from DMA */
+		for(i=0; i<sg_used; i++) {
+			temp64.val32.lower = c->SG[i].Addr.lower;
+			temp64.val32.upper = c->SG[i].Addr.upper;
+			pci_unmap_single( h->pdev, (dma_addr_t) temp64.val,
+				buff_size[i], PCI_DMA_BIDIRECTIONAL);
+		}
+		/* Copy the error information out */
+		ioc->error_info = *(c->err_info);
+		if (copy_to_user((void *) arg, ioc, sizeof(*ioc))) {
+			cmd_free(h, c, 0);
+			status = -EFAULT;
+			goto cleanup1;
+		}
+		if (ioc->Request.Type.Direction == XFER_READ) {
+			/* Copy the data out of the buffer we created */
+			BYTE *ptr = (BYTE  *) ioc->buf;
+	        	for(i=0; i< sg_used; i++) {
+				if (copy_to_user(ptr, buff[i], buff_size[i])) {
+					cmd_free(h, c, 0);
+					status = -EFAULT;
+					goto cleanup1;
+				}
+				ptr += buff_size[i];
+			}
+		}
+		cmd_free(h, c, 0);
+		status = 0;
+cleanup1:
+		if (buff) {
+			for(i=0; i<sg_used; i++)
+				if(buff[i] != NULL)
+					kfree(buff[i]);
+			kfree(buff);
+		}
+		if (buff_size)
+			kfree(buff_size);
+		if (ioc)
+			kfree(ioc);
+		return(status);
+	}
 	default:
 		return -EBADRQC;
 	}
--- linux-2.5.63/include/linux/cciss_ioctl.h~bigioctl	2003-02-27 14:11:56.000000000 +0600
+++ linux-2.5.63-scameron/include/linux/cciss_ioctl.h	2003-02-27 14:11:56.000000000 +0600
@@ -33,6 +33,18 @@ typedef __u32 BusTypes_type;
 typedef char FirmwareVer_type[4];
 typedef __u32 DriverVer_type;
 
+#define MAX_KMALLOC_SIZE 128000
+
+typedef struct _BIG_IOCTL_Command_struct {
+  LUNAddr_struct	   LUN_info;
+  RequestBlock_struct      Request;
+  ErrorInfo_struct  	   error_info; 
+  DWORD			   malloc_size; /* < MAX_KMALLOC_SIZE in cciss.c */
+  DWORD			   buf_size;    /* size in bytes of the buf */
+  				        /* < malloc_size * MAXSGENTRIES */
+  BYTE			   *buf;
+} BIG_IOCTL_Command_struct;
+
 
 #ifndef CCISS_CMD_H
 // This defines are duplicated in cciss_cmd.h in the driver directory 
@@ -196,5 +208,6 @@ typedef struct _LogvolInfo_struct{
 
 #define CCISS_REGNEWD	   _IO(CCISS_IOC_MAGIC, 14)
 #define CCISS_GETLUNINFO   _IOR(CCISS_IOC_MAGIC, 17, LogvolInfo_struct)
+#define CCISS_BIG_PASSTHRU _IOWR(CCISS_IOC_MAGIC, 18, BIG_IOCTL_Command_struct)
 
 #endif  

_

             reply	other threads:[~2003-02-27 20:28 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-02-27  8:39 Stephen Cameron [this message]
  -- strict thread matches above, loose matches on Subject: below --
2003-02-27  8:36 Stephen Cameron
2003-02-27  8:24 Stephen Cameron
2003-02-27  7:30 Stephen Cameron
2003-02-27  7:23 Stephen Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030227083953.GA3992@zuul.cca.cpqcorp.net \
    --to=steve.cameron@hp.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®