debian/patches/features/all/drivers: Remove, all backports.
svn path=/dists/trunk/linux-2.6/; revision=7911
This commit is contained in:
parent
566be40e55
commit
5210a0f4b4
|
@ -1,500 +0,0 @@
|
|||
From: Mike Miller (OS Dev) <mikem@beardog.cca.cpqcorp.net>
|
||||
Date: Sun, 1 Oct 2006 06:27:23 +0000 (-0700)
|
||||
Subject: [PATCH] cciss: support for >2TB logical volumes
|
||||
X-Git-Tag: v2.6.19-rc1
|
||||
X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=00988a3514bbc0cce781c067cf52559741d88b80
|
||||
|
||||
[PATCH] cciss: support for >2TB logical volumes
|
||||
|
||||
Add support for logical volumes >2TB. All SAS/SATA controllers support
|
||||
large volumes.
|
||||
|
||||
Signed-off-by: Mike Miller <mike.miller@hp.com>
|
||||
Cc: Jens Axboe <axboe@suse.de>
|
||||
Signed-off-by: Andrew Morton <akpm@osdl.org>
|
||||
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
||||
---
|
||||
|
||||
--- a/drivers/block/cciss.c
|
||||
+++ b/drivers/block/cciss.c
|
||||
@@ -144,13 +144,13 @@ static int rebuild_lun_table(ctlr_info_t
|
||||
static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
|
||||
int clear_all);
|
||||
|
||||
-static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
|
||||
- int withirq, unsigned int *total_size,
|
||||
- unsigned int *block_size);
|
||||
-static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq,
|
||||
- unsigned int total_size,
|
||||
- unsigned int block_size,
|
||||
- InquiryData_struct *inq_buff,
|
||||
+static void cciss_read_capacity(int ctlr, int logvol, int withirq,
|
||||
+ sector_t *total_size, unsigned int *block_size);
|
||||
+static void cciss_read_capacity_16(int ctlr, int logvol, int withirq,
|
||||
+ sector_t *total_size, unsigned int *block_size);
|
||||
+static void cciss_geometry_inquiry(int ctlr, int logvol,
|
||||
+ int withirq, sector_t total_size,
|
||||
+ unsigned int block_size, InquiryData_struct *inq_buff,
|
||||
drive_info_struct *drv);
|
||||
static void cciss_getgeometry(int cntl_num);
|
||||
static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
|
||||
@@ -1325,10 +1325,9 @@ static void cciss_update_drive_info(int
|
||||
{
|
||||
ctlr_info_t *h = hba[ctlr];
|
||||
struct gendisk *disk;
|
||||
- ReadCapdata_struct *size_buff = NULL;
|
||||
InquiryData_struct *inq_buff = NULL;
|
||||
unsigned int block_size;
|
||||
- unsigned int total_size;
|
||||
+ sector_t total_size;
|
||||
unsigned long flags = 0;
|
||||
int ret = 0;
|
||||
|
||||
@@ -1347,15 +1346,25 @@ static void cciss_update_drive_info(int
|
||||
return;
|
||||
|
||||
/* Get information about the disk and modify the driver structure */
|
||||
- size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
|
||||
- if (size_buff == NULL)
|
||||
- goto mem_msg;
|
||||
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
|
||||
if (inq_buff == NULL)
|
||||
goto mem_msg;
|
||||
|
||||
- cciss_read_capacity(ctlr, drv_index, size_buff, 1,
|
||||
+ cciss_read_capacity(ctlr, drv_index, 1,
|
||||
&total_size, &block_size);
|
||||
+
|
||||
+ /* total size = last LBA + 1 */
|
||||
+ /* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */
|
||||
+ /* so we assume this volume this must be >2TB in size */
|
||||
+ if (total_size == (__u32) 0) {
|
||||
+ cciss_read_capacity_16(ctlr, drv_index, 1,
|
||||
+ &total_size, &block_size);
|
||||
+ h->cciss_read = CCISS_READ_16;
|
||||
+ h->cciss_write = CCISS_WRITE_16;
|
||||
+ } else {
|
||||
+ h->cciss_read = CCISS_READ_10;
|
||||
+ h->cciss_write = CCISS_WRITE_10;
|
||||
+ }
|
||||
cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
|
||||
inq_buff, &h->drv[drv_index]);
|
||||
|
||||
@@ -1391,7 +1400,6 @@ static void cciss_update_drive_info(int
|
||||
}
|
||||
|
||||
freeret:
|
||||
- kfree(size_buff);
|
||||
kfree(inq_buff);
|
||||
return;
|
||||
mem_msg:
|
||||
@@ -1716,6 +1724,22 @@ static int fill_cmd(CommandList_struct *
|
||||
c->Request.Timeout = 0;
|
||||
c->Request.CDB[0] = cmd;
|
||||
break;
|
||||
+ case CCISS_READ_CAPACITY_16:
|
||||
+ c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID;
|
||||
+ c->Header.LUN.LogDev.Mode = 1;
|
||||
+ c->Request.CDBLen = 16;
|
||||
+ c->Request.Type.Attribute = ATTR_SIMPLE;
|
||||
+ c->Request.Type.Direction = XFER_READ;
|
||||
+ c->Request.Timeout = 0;
|
||||
+ c->Request.CDB[0] = cmd;
|
||||
+ c->Request.CDB[1] = 0x10;
|
||||
+ c->Request.CDB[10] = (size >> 24) & 0xFF;
|
||||
+ c->Request.CDB[11] = (size >> 16) & 0xFF;
|
||||
+ c->Request.CDB[12] = (size >> 8) & 0xFF;
|
||||
+ c->Request.CDB[13] = size & 0xFF;
|
||||
+ c->Request.Timeout = 0;
|
||||
+ c->Request.CDB[0] = cmd;
|
||||
+ break;
|
||||
case CCISS_CACHE_FLUSH:
|
||||
c->Request.CDBLen = 12;
|
||||
c->Request.Type.Attribute = ATTR_SIMPLE;
|
||||
@@ -1749,6 +1773,7 @@ static int fill_cmd(CommandList_struct *
|
||||
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
|
||||
c->Request.CDB[0] = cmd; /* reset */
|
||||
c->Request.CDB[1] = 0x04; /* reset a LUN */
|
||||
+ break;
|
||||
case 3: /* No-Op message */
|
||||
c->Request.CDBLen = 1;
|
||||
c->Request.Type.Attribute = ATTR_SIMPLE;
|
||||
@@ -1892,12 +1917,15 @@ static int sendcmd_withirq(__u8 cmd,
|
||||
}
|
||||
|
||||
static void cciss_geometry_inquiry(int ctlr, int logvol,
|
||||
- int withirq, unsigned int total_size,
|
||||
+ int withirq, sector_t total_size,
|
||||
unsigned int block_size,
|
||||
InquiryData_struct *inq_buff,
|
||||
drive_info_struct *drv)
|
||||
{
|
||||
int return_code;
|
||||
+ unsigned long t;
|
||||
+ unsigned long rem;
|
||||
+
|
||||
memset(inq_buff, 0, sizeof(InquiryData_struct));
|
||||
if (withirq)
|
||||
return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
|
||||
@@ -1916,10 +1944,10 @@ static void cciss_geometry_inquiry(int c
|
||||
drv->nr_blocks = total_size;
|
||||
drv->heads = 255;
|
||||
drv->sectors = 32; // Sectors per track
|
||||
- drv->cylinders = total_size / 255 / 32;
|
||||
+ t = drv->heads * drv->sectors;
|
||||
+ drv->cylinders = total_size;
|
||||
+ rem = do_div(drv->cylinders, t);
|
||||
} else {
|
||||
- unsigned int t;
|
||||
-
|
||||
drv->block_size = block_size;
|
||||
drv->nr_blocks = total_size;
|
||||
drv->heads = inq_buff->data_byte[6];
|
||||
@@ -1929,7 +1957,8 @@ static void cciss_geometry_inquiry(int c
|
||||
drv->raid_level = inq_buff->data_byte[8];
|
||||
t = drv->heads * drv->sectors;
|
||||
if (t > 1) {
|
||||
- drv->cylinders = total_size / t;
|
||||
+ drv->cylinders = total_size;
|
||||
+ rem = do_div(drv->cylinders, t);
|
||||
}
|
||||
}
|
||||
} else { /* Get geometry failed */
|
||||
@@ -1940,31 +1969,72 @@ static void cciss_geometry_inquiry(int c
|
||||
}
|
||||
|
||||
static void
|
||||
-cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
|
||||
- int withirq, unsigned int *total_size,
|
||||
+cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
|
||||
unsigned int *block_size)
|
||||
{
|
||||
+ ReadCapdata_struct *buf;
|
||||
int return_code;
|
||||
- memset(buf, 0, sizeof(*buf));
|
||||
+ buf = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
|
||||
+ if (buf == NULL) {
|
||||
+ printk(KERN_WARNING "cciss: out of memory\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ memset(buf, 0, sizeof(ReadCapdata_struct));
|
||||
if (withirq)
|
||||
return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
|
||||
- ctlr, buf, sizeof(*buf), 1,
|
||||
- logvol, 0, TYPE_CMD);
|
||||
+ ctlr, buf, sizeof(ReadCapdata_struct),
|
||||
+ 1, logvol, 0, TYPE_CMD);
|
||||
else
|
||||
return_code = sendcmd(CCISS_READ_CAPACITY,
|
||||
- ctlr, buf, sizeof(*buf), 1, logvol, 0,
|
||||
- NULL, TYPE_CMD);
|
||||
+ ctlr, buf, sizeof(ReadCapdata_struct),
|
||||
+ 1, logvol, 0, NULL, TYPE_CMD);
|
||||
+ if (return_code == IO_OK) {
|
||||
+ *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1;
|
||||
+ *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
|
||||
+ } else { /* read capacity command failed */
|
||||
+ printk(KERN_WARNING "cciss: read capacity failed\n");
|
||||
+ *total_size = 0;
|
||||
+ *block_size = BLOCK_SIZE;
|
||||
+ }
|
||||
+ if (*total_size != (__u32) 0)
|
||||
+ printk(KERN_INFO " blocks= %lld block_size= %d\n",
|
||||
+ *total_size, *block_size);
|
||||
+ kfree(buf);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size)
|
||||
+{
|
||||
+ ReadCapdata_struct_16 *buf;
|
||||
+ int return_code;
|
||||
+ buf = kmalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL);
|
||||
+ if (buf == NULL) {
|
||||
+ printk(KERN_WARNING "cciss: out of memory\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ memset(buf, 0, sizeof(ReadCapdata_struct_16));
|
||||
+ if (withirq) {
|
||||
+ return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
|
||||
+ ctlr, buf, sizeof(ReadCapdata_struct_16),
|
||||
+ 1, logvol, 0, TYPE_CMD);
|
||||
+ }
|
||||
+ else {
|
||||
+ return_code = sendcmd(CCISS_READ_CAPACITY_16,
|
||||
+ ctlr, buf, sizeof(ReadCapdata_struct_16),
|
||||
+ 1, logvol, 0, NULL, TYPE_CMD);
|
||||
+ }
|
||||
if (return_code == IO_OK) {
|
||||
- *total_size =
|
||||
- be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1;
|
||||
- *block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0]));
|
||||
+ *total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1;
|
||||
+ *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
|
||||
} else { /* read capacity command failed */
|
||||
printk(KERN_WARNING "cciss: read capacity failed\n");
|
||||
*total_size = 0;
|
||||
*block_size = BLOCK_SIZE;
|
||||
}
|
||||
- printk(KERN_INFO " blocks= %u block_size= %d\n",
|
||||
+ printk(KERN_INFO " blocks= %lld block_size= %d\n",
|
||||
*total_size, *block_size);
|
||||
+ kfree(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1975,8 +2045,7 @@ static int cciss_revalidate(struct gendi
|
||||
int logvol;
|
||||
int FOUND = 0;
|
||||
unsigned int block_size;
|
||||
- unsigned int total_size;
|
||||
- ReadCapdata_struct *size_buff = NULL;
|
||||
+ sector_t total_size;
|
||||
InquiryData_struct *inq_buff = NULL;
|
||||
|
||||
for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
|
||||
@@ -1989,27 +2058,24 @@ static int cciss_revalidate(struct gendi
|
||||
if (!FOUND)
|
||||
return 1;
|
||||
|
||||
- size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
|
||||
- if (size_buff == NULL) {
|
||||
- printk(KERN_WARNING "cciss: out of memory\n");
|
||||
- return 1;
|
||||
- }
|
||||
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
|
||||
if (inq_buff == NULL) {
|
||||
printk(KERN_WARNING "cciss: out of memory\n");
|
||||
- kfree(size_buff);
|
||||
return 1;
|
||||
}
|
||||
-
|
||||
- cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size,
|
||||
- &block_size);
|
||||
+ if (h->cciss_read == CCISS_READ_10) {
|
||||
+ cciss_read_capacity(h->ctlr, logvol, 1,
|
||||
+ &total_size, &block_size);
|
||||
+ } else {
|
||||
+ cciss_read_capacity_16(h->ctlr, logvol, 1,
|
||||
+ &total_size, &block_size);
|
||||
+ }
|
||||
cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
|
||||
inq_buff, drv);
|
||||
|
||||
blk_queue_hardsect_size(drv->queue, drv->block_size);
|
||||
set_capacity(disk, drv->nr_blocks);
|
||||
|
||||
- kfree(size_buff);
|
||||
kfree(inq_buff);
|
||||
return 0;
|
||||
}
|
||||
@@ -2418,7 +2484,8 @@ static void do_cciss_request(request_que
|
||||
{
|
||||
ctlr_info_t *h = q->queuedata;
|
||||
CommandList_struct *c;
|
||||
- int start_blk, seg;
|
||||
+ sector_t start_blk;
|
||||
+ int seg;
|
||||
struct request *creq;
|
||||
u64bit temp64;
|
||||
struct scatterlist tmp_sg[MAXSGENTRIES];
|
||||
@@ -2462,10 +2529,10 @@ static void do_cciss_request(request_que
|
||||
c->Request.Type.Type = TYPE_CMD; // It is a command.
|
||||
c->Request.Type.Attribute = ATTR_SIMPLE;
|
||||
c->Request.Type.Direction =
|
||||
- (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE;
|
||||
+ (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
|
||||
c->Request.Timeout = 0; // Don't time out
|
||||
c->Request.CDB[0] =
|
||||
- (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE;
|
||||
+ (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
|
||||
start_blk = creq->sector;
|
||||
#ifdef CCISS_DEBUG
|
||||
printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector,
|
||||
@@ -2499,15 +2566,33 @@ static void do_cciss_request(request_que
|
||||
#endif /* CCISS_DEBUG */
|
||||
|
||||
c->Header.SGList = c->Header.SGTotal = seg;
|
||||
- c->Request.CDB[1] = 0;
|
||||
- c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB
|
||||
- c->Request.CDB[3] = (start_blk >> 16) & 0xff;
|
||||
- c->Request.CDB[4] = (start_blk >> 8) & 0xff;
|
||||
- c->Request.CDB[5] = start_blk & 0xff;
|
||||
- c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB
|
||||
- c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
|
||||
- c->Request.CDB[8] = creq->nr_sectors & 0xff;
|
||||
- c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
|
||||
+ if(h->cciss_read == CCISS_READ_10) {
|
||||
+ c->Request.CDB[1] = 0;
|
||||
+ c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB
|
||||
+ c->Request.CDB[3] = (start_blk >> 16) & 0xff;
|
||||
+ c->Request.CDB[4] = (start_blk >> 8) & 0xff;
|
||||
+ c->Request.CDB[5] = start_blk & 0xff;
|
||||
+ c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB
|
||||
+ c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
|
||||
+ c->Request.CDB[8] = creq->nr_sectors & 0xff;
|
||||
+ c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
|
||||
+ } else {
|
||||
+ c->Request.CDBLen = 16;
|
||||
+ c->Request.CDB[1]= 0;
|
||||
+ c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB
|
||||
+ c->Request.CDB[3]= (start_blk >> 48) & 0xff;
|
||||
+ c->Request.CDB[4]= (start_blk >> 40) & 0xff;
|
||||
+ c->Request.CDB[5]= (start_blk >> 32) & 0xff;
|
||||
+ c->Request.CDB[6]= (start_blk >> 24) & 0xff;
|
||||
+ c->Request.CDB[7]= (start_blk >> 16) & 0xff;
|
||||
+ c->Request.CDB[8]= (start_blk >> 8) & 0xff;
|
||||
+ c->Request.CDB[9]= start_blk & 0xff;
|
||||
+ c->Request.CDB[10]= (creq->nr_sectors >> 24) & 0xff;
|
||||
+ c->Request.CDB[11]= (creq->nr_sectors >> 16) & 0xff;
|
||||
+ c->Request.CDB[12]= (creq->nr_sectors >> 8) & 0xff;
|
||||
+ c->Request.CDB[13]= creq->nr_sectors & 0xff;
|
||||
+ c->Request.CDB[14] = c->Request.CDB[15] = 0;
|
||||
+ }
|
||||
|
||||
spin_lock_irq(q->queue_lock);
|
||||
|
||||
@@ -2517,9 +2602,9 @@ static void do_cciss_request(request_que
|
||||
h->maxQsinceinit = h->Qdepth;
|
||||
|
||||
goto queue;
|
||||
- full:
|
||||
+full:
|
||||
blk_stop_queue(q);
|
||||
- startio:
|
||||
+startio:
|
||||
/* We will already have the driver lock here so not need
|
||||
* to lock it.
|
||||
*/
|
||||
@@ -2947,31 +3032,23 @@ static int cciss_pci_init(ctlr_info_t *c
|
||||
static void cciss_getgeometry(int cntl_num)
|
||||
{
|
||||
ReportLunData_struct *ld_buff;
|
||||
- ReadCapdata_struct *size_buff;
|
||||
InquiryData_struct *inq_buff;
|
||||
int return_code;
|
||||
int i;
|
||||
int listlength = 0;
|
||||
__u32 lunid = 0;
|
||||
int block_size;
|
||||
- int total_size;
|
||||
+ sector_t total_size;
|
||||
|
||||
ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
|
||||
if (ld_buff == NULL) {
|
||||
printk(KERN_ERR "cciss: out of memory\n");
|
||||
return;
|
||||
}
|
||||
- size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
|
||||
- if (size_buff == NULL) {
|
||||
- printk(KERN_ERR "cciss: out of memory\n");
|
||||
- kfree(ld_buff);
|
||||
- return;
|
||||
- }
|
||||
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
|
||||
if (inq_buff == NULL) {
|
||||
printk(KERN_ERR "cciss: out of memory\n");
|
||||
kfree(ld_buff);
|
||||
- kfree(size_buff);
|
||||
return;
|
||||
}
|
||||
/* Get the firmware version */
|
||||
@@ -3026,7 +3103,6 @@ static void cciss_getgeometry(int cntl_n
|
||||
#endif /* CCISS_DEBUG */
|
||||
|
||||
hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1;
|
||||
-// for(i=0; i< hba[cntl_num]->num_luns; i++)
|
||||
for (i = 0; i < CISS_MAX_LUN; i++) {
|
||||
if (i < hba[cntl_num]->num_luns) {
|
||||
lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
|
||||
@@ -3045,8 +3121,26 @@ static void cciss_getgeometry(int cntl_n
|
||||
ld_buff->LUN[i][2], ld_buff->LUN[i][3],
|
||||
hba[cntl_num]->drv[i].LunID);
|
||||
#endif /* CCISS_DEBUG */
|
||||
- cciss_read_capacity(cntl_num, i, size_buff, 0,
|
||||
+
|
||||
+ /* testing to see if 16-byte CDBs are already being used */
|
||||
+ if(hba[cntl_num]->cciss_read == CCISS_READ_16) {
|
||||
+ cciss_read_capacity_16(cntl_num, i, 0,
|
||||
&total_size, &block_size);
|
||||
+ goto geo_inq;
|
||||
+ }
|
||||
+ cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size);
|
||||
+
|
||||
+ /* total_size = last LBA + 1 */
|
||||
+ if(total_size == (__u32) 0) {
|
||||
+ cciss_read_capacity_16(cntl_num, i, 0,
|
||||
+ &total_size, &block_size);
|
||||
+ hba[cntl_num]->cciss_read = CCISS_READ_16;
|
||||
+ hba[cntl_num]->cciss_write = CCISS_WRITE_16;
|
||||
+ } else {
|
||||
+ hba[cntl_num]->cciss_read = CCISS_READ_10;
|
||||
+ hba[cntl_num]->cciss_write = CCISS_WRITE_10;
|
||||
+ }
|
||||
+geo_inq:
|
||||
cciss_geometry_inquiry(cntl_num, i, 0, total_size,
|
||||
block_size, inq_buff,
|
||||
&hba[cntl_num]->drv[i]);
|
||||
@@ -3056,7 +3150,6 @@ static void cciss_getgeometry(int cntl_n
|
||||
}
|
||||
}
|
||||
kfree(ld_buff);
|
||||
- kfree(size_buff);
|
||||
kfree(inq_buff);
|
||||
}
|
||||
|
||||
--- a/drivers/block/cciss.h
|
||||
+++ b/drivers/block/cciss.h
|
||||
@@ -76,6 +76,9 @@ struct ctlr_info
|
||||
unsigned int intr[4];
|
||||
unsigned int msix_vector;
|
||||
unsigned int msi_vector;
|
||||
+ BYTE cciss_read;
|
||||
+ BYTE cciss_write;
|
||||
+ BYTE cciss_read_capacity;
|
||||
|
||||
// information about each logical volume
|
||||
drive_info_struct drv[CISS_MAX_LUN];
|
||||
--- a/drivers/block/cciss_cmd.h
|
||||
+++ b/drivers/block/cciss_cmd.h
|
||||
@@ -118,11 +118,34 @@ typedef struct _ReadCapdata_struct
|
||||
BYTE block_size[4]; // Size of blocks in bytes
|
||||
} ReadCapdata_struct;
|
||||
|
||||
-// 12 byte commands not implemented in firmware yet.
|
||||
-// #define CCISS_READ 0xa8 // Read(12)
|
||||
-// #define CCISS_WRITE 0xaa // Write(12)
|
||||
- #define CCISS_READ 0x28 // Read(10)
|
||||
- #define CCISS_WRITE 0x2a // Write(10)
|
||||
+#define CCISS_READ_CAPACITY_16 0x9e /* Read Capacity 16 */
|
||||
+
|
||||
+/* service action to differentiate a 16 byte read capacity from
|
||||
+ other commands that use the 0x9e SCSI op code */
|
||||
+
|
||||
+#define CCISS_READ_CAPACITY_16_SERVICE_ACT 0x10
|
||||
+
|
||||
+typedef struct _ReadCapdata_struct_16
|
||||
+{
|
||||
+ BYTE total_size[8]; /* Total size in blocks */
|
||||
+ BYTE block_size[4]; /* Size of blocks in bytes */
|
||||
+ BYTE prot_en:1; /* protection enable bit */
|
||||
+ BYTE rto_en:1; /* reference tag own enable bit */
|
||||
+ BYTE reserved:6; /* reserved bits */
|
||||
+ BYTE reserved2[18]; /* reserved bytes per spec */
|
||||
+} ReadCapdata_struct_16;
|
||||
+
|
||||
+/* Define the supported read/write commands for cciss based controllers */
|
||||
+
|
||||
+#define CCISS_READ_10 0x28 /* Read(10) */
|
||||
+#define CCISS_WRITE_10 0x2a /* Write(10) */
|
||||
+#define CCISS_READ_16 0x88 /* Read(16) */
|
||||
+#define CCISS_WRITE_16 0x8a /* Write(16) */
|
||||
+
|
||||
+/* Define the CDB lengths supported by cciss based controllers */
|
||||
+
|
||||
+#define CDB_LEN10 10
|
||||
+#define CDB_LEN16 16
|
||||
|
||||
// BMIC commands
|
||||
#define BMIC_READ 0x26
|
File diff suppressed because it is too large
Load Diff
|
@ -1,183 +0,0 @@
|
|||
# [PATCH] The redefinition of ahci_start_engine() and ahci_stop_engine()
|
||||
# 5457f2194ad198a0aba4190ec99a6a81846fdca5
|
||||
|
||||
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
|
||||
index 77e7202..f1516ca 100644
|
||||
--- a/drivers/scsi/ahci.c
|
||||
+++ b/drivers/scsi/ahci.c
|
||||
@@ -205,6 +205,8 @@ static irqreturn_t ahci_interrupt (int i
|
||||
static void ahci_irq_clear(struct ata_port *ap);
|
||||
static int ahci_port_start(struct ata_port *ap);
|
||||
static void ahci_port_stop(struct ata_port *ap);
|
||||
+static int ahci_start_engine(void __iomem *port_mmio);
|
||||
+static int ahci_stop_engine(void __iomem *port_mmio);
|
||||
static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
|
||||
static void ahci_qc_prep(struct ata_queued_cmd *qc);
|
||||
static u8 ahci_check_status(struct ata_port *ap);
|
||||
@@ -508,41 +510,64 @@ static void ahci_scr_write (struct ata_p
|
||||
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
|
||||
}
|
||||
|
||||
-static int ahci_stop_engine(struct ata_port *ap)
|
||||
+static int ahci_stop_engine(void __iomem *port_mmio)
|
||||
{
|
||||
- void __iomem *mmio = ap->host_set->mmio_base;
|
||||
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
- int work;
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
+
|
||||
+ /* Check if the HBA is idle */
|
||||
+ if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Setting HBA to idle */
|
||||
tmp &= ~PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
|
||||
- /* wait for engine to stop. TODO: this could be
|
||||
+ /* wait for engine to stop. This could be
|
||||
* as long as 500 msec
|
||||
*/
|
||||
- work = 1000;
|
||||
- while (work-- > 0) {
|
||||
- tmp = readl(port_mmio + PORT_CMD);
|
||||
- if ((tmp & PORT_CMD_LIST_ON) == 0)
|
||||
- return 0;
|
||||
- udelay(10);
|
||||
- }
|
||||
+ tmp = ata_wait_register(port_mmio + PORT_CMD,
|
||||
+ PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
|
||||
+ if(tmp & PORT_CMD_LIST_ON)
|
||||
+ return -EIO;
|
||||
|
||||
- return -EIO;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-static void ahci_start_engine(struct ata_port *ap)
|
||||
+static int ahci_start_engine(void __iomem *port_mmio)
|
||||
{
|
||||
- void __iomem *mmio = ap->host_set->mmio_base;
|
||||
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
u32 tmp;
|
||||
|
||||
+ /*
|
||||
+ * Get current status
|
||||
+ */
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
+
|
||||
+ /*
|
||||
+ * AHCI rev 1.1 section 10.3.1:
|
||||
+ * Software shall not set PxCMD.ST to '1' until it verifies
|
||||
+ * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
|
||||
+ */
|
||||
+ if ((tmp & PORT_CMD_FIS_RX) == 0)
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ /*
|
||||
+ * wait for engine to become idle.
|
||||
+ */
|
||||
+ tmp = ata_wait_register(port_mmio + PORT_CMD,
|
||||
+ PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
|
||||
+ if(tmp & PORT_CMD_LIST_ON)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ /*
|
||||
+ * Start DMA
|
||||
+ */
|
||||
tmp |= PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
readl(port_mmio + PORT_CMD); /* flush */
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static unsigned int ahci_dev_classify(struct ata_port *ap)
|
||||
@@ -626,7 +651,7 @@ static int ahci_softreset(struct ata_por
|
||||
}
|
||||
|
||||
/* prepare for SRST (AHCI-1.1 10.4.1) */
|
||||
- rc = ahci_stop_engine(ap);
|
||||
+ rc = ahci_stop_engine(port_mmio);
|
||||
if (rc) {
|
||||
reason = "failed to stop engine";
|
||||
goto fail_restart;
|
||||
@@ -647,7 +672,7 @@ static int ahci_softreset(struct ata_por
|
||||
}
|
||||
|
||||
/* restart engine */
|
||||
- ahci_start_engine(ap);
|
||||
+ ahci_start_engine(port_mmio);
|
||||
|
||||
ata_tf_init(ap->device, &tf);
|
||||
fis = pp->cmd_tbl;
|
||||
@@ -706,7 +731,7 @@ static int ahci_softreset(struct ata_por
|
||||
return 0;
|
||||
|
||||
fail_restart:
|
||||
- ahci_start_engine(ap);
|
||||
+ ahci_start_engine(port_mmio);
|
||||
fail:
|
||||
ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
|
||||
return rc;
|
||||
@@ -717,11 +742,13 @@ static int ahci_hardreset(struct ata_por
|
||||
struct ahci_port_priv *pp = ap->private_data;
|
||||
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
|
||||
struct ata_taskfile tf;
|
||||
+ void __iomem *mmio = ap->host_set->mmio_base;
|
||||
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
int rc;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
- ahci_stop_engine(ap);
|
||||
+ ahci_stop_engine(port_mmio);
|
||||
|
||||
/* clear D2H reception area to properly wait for D2H FIS */
|
||||
ata_tf_init(ap->device, &tf);
|
||||
@@ -730,7 +757,7 @@ static int ahci_hardreset(struct ata_por
|
||||
|
||||
rc = sata_std_hardreset(ap, class);
|
||||
|
||||
- ahci_start_engine(ap);
|
||||
+ ahci_start_engine(port_mmio);
|
||||
|
||||
if (rc == 0 && ata_port_online(ap))
|
||||
*class = ahci_dev_classify(ap);
|
||||
@@ -1052,10 +1079,13 @@ static void ahci_thaw(struct ata_port *a
|
||||
|
||||
static void ahci_error_handler(struct ata_port *ap)
|
||||
{
|
||||
+ void __iomem *mmio = ap->host_set->mmio_base;
|
||||
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
+
|
||||
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
|
||||
/* restart engine */
|
||||
- ahci_stop_engine(ap);
|
||||
- ahci_start_engine(ap);
|
||||
+ ahci_stop_engine(port_mmio);
|
||||
+ ahci_start_engine(port_mmio);
|
||||
}
|
||||
|
||||
/* perform recovery */
|
||||
@@ -1066,14 +1096,16 @@ static void ahci_error_handler(struct at
|
||||
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
+ void __iomem *mmio = ap->host_set->mmio_base;
|
||||
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
|
||||
if (qc->flags & ATA_QCFLAG_FAILED)
|
||||
qc->err_mask |= AC_ERR_OTHER;
|
||||
|
||||
if (qc->err_mask) {
|
||||
/* make DMA engine forget about the failed command */
|
||||
- ahci_stop_engine(ap);
|
||||
- ahci_start_engine(ap);
|
||||
+ ahci_stop_engine(port_mmio);
|
||||
+ ahci_start_engine(port_mmio);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,297 +0,0 @@
|
|||
# [PATCH] ahci: relocate several internal functions
|
||||
# 254950cd56fee220c9d548f3e57211b95976ba64
|
||||
|
||||
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
|
||||
index f1516ca..92e2b95 100644
|
||||
--- a/drivers/scsi/ahci.c
|
||||
+++ b/drivers/scsi/ahci.c
|
||||
@@ -205,8 +205,6 @@ static irqreturn_t ahci_interrupt (int i
|
||||
static void ahci_irq_clear(struct ata_port *ap);
|
||||
static int ahci_port_start(struct ata_port *ap);
|
||||
static void ahci_port_stop(struct ata_port *ap);
|
||||
-static int ahci_start_engine(void __iomem *port_mmio);
|
||||
-static int ahci_stop_engine(void __iomem *port_mmio);
|
||||
static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
|
||||
static void ahci_qc_prep(struct ata_queued_cmd *qc);
|
||||
static u8 ahci_check_status(struct ata_port *ap);
|
||||
@@ -374,108 +372,6 @@ static inline void __iomem *ahci_port_ba
|
||||
return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
|
||||
}
|
||||
|
||||
-static int ahci_port_start(struct ata_port *ap)
|
||||
-{
|
||||
- struct device *dev = ap->host_set->dev;
|
||||
- struct ahci_host_priv *hpriv = ap->host_set->private_data;
|
||||
- struct ahci_port_priv *pp;
|
||||
- void __iomem *mmio = ap->host_set->mmio_base;
|
||||
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
- void *mem;
|
||||
- dma_addr_t mem_dma;
|
||||
- int rc;
|
||||
-
|
||||
- pp = kmalloc(sizeof(*pp), GFP_KERNEL);
|
||||
- if (!pp)
|
||||
- return -ENOMEM;
|
||||
- memset(pp, 0, sizeof(*pp));
|
||||
-
|
||||
- rc = ata_pad_alloc(ap, dev);
|
||||
- if (rc) {
|
||||
- kfree(pp);
|
||||
- return rc;
|
||||
- }
|
||||
-
|
||||
- mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
|
||||
- if (!mem) {
|
||||
- ata_pad_free(ap, dev);
|
||||
- kfree(pp);
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
- memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
|
||||
-
|
||||
- /*
|
||||
- * First item in chunk of DMA memory: 32-slot command table,
|
||||
- * 32 bytes each in size
|
||||
- */
|
||||
- pp->cmd_slot = mem;
|
||||
- pp->cmd_slot_dma = mem_dma;
|
||||
-
|
||||
- mem += AHCI_CMD_SLOT_SZ;
|
||||
- mem_dma += AHCI_CMD_SLOT_SZ;
|
||||
-
|
||||
- /*
|
||||
- * Second item: Received-FIS area
|
||||
- */
|
||||
- pp->rx_fis = mem;
|
||||
- pp->rx_fis_dma = mem_dma;
|
||||
-
|
||||
- mem += AHCI_RX_FIS_SZ;
|
||||
- mem_dma += AHCI_RX_FIS_SZ;
|
||||
-
|
||||
- /*
|
||||
- * Third item: data area for storing a single command
|
||||
- * and its scatter-gather table
|
||||
- */
|
||||
- pp->cmd_tbl = mem;
|
||||
- pp->cmd_tbl_dma = mem_dma;
|
||||
-
|
||||
- ap->private_data = pp;
|
||||
-
|
||||
- if (hpriv->cap & HOST_CAP_64)
|
||||
- writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
|
||||
- writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
|
||||
- readl(port_mmio + PORT_LST_ADDR); /* flush */
|
||||
-
|
||||
- if (hpriv->cap & HOST_CAP_64)
|
||||
- writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
|
||||
- writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
|
||||
- readl(port_mmio + PORT_FIS_ADDR); /* flush */
|
||||
-
|
||||
- writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
|
||||
- PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
|
||||
- PORT_CMD_START, port_mmio + PORT_CMD);
|
||||
- readl(port_mmio + PORT_CMD); /* flush */
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static void ahci_port_stop(struct ata_port *ap)
|
||||
-{
|
||||
- struct device *dev = ap->host_set->dev;
|
||||
- struct ahci_port_priv *pp = ap->private_data;
|
||||
- void __iomem *mmio = ap->host_set->mmio_base;
|
||||
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
- u32 tmp;
|
||||
-
|
||||
- tmp = readl(port_mmio + PORT_CMD);
|
||||
- tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX);
|
||||
- writel(tmp, port_mmio + PORT_CMD);
|
||||
- readl(port_mmio + PORT_CMD); /* flush */
|
||||
-
|
||||
- /* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so
|
||||
- * this is slightly incorrect.
|
||||
- */
|
||||
- msleep(500);
|
||||
-
|
||||
- ap->private_data = NULL;
|
||||
- dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
|
||||
- pp->cmd_slot, pp->cmd_slot_dma);
|
||||
- ata_pad_free(ap, dev);
|
||||
- kfree(pp);
|
||||
-}
|
||||
-
|
||||
static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
|
||||
{
|
||||
unsigned int sc_reg;
|
||||
@@ -510,31 +406,6 @@ static void ahci_scr_write (struct ata_p
|
||||
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
|
||||
}
|
||||
|
||||
-static int ahci_stop_engine(void __iomem *port_mmio)
|
||||
-{
|
||||
- u32 tmp;
|
||||
-
|
||||
- tmp = readl(port_mmio + PORT_CMD);
|
||||
-
|
||||
- /* Check if the HBA is idle */
|
||||
- if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
|
||||
- return 0;
|
||||
-
|
||||
- /* Setting HBA to idle */
|
||||
- tmp &= ~PORT_CMD_START;
|
||||
- writel(tmp, port_mmio + PORT_CMD);
|
||||
-
|
||||
- /* wait for engine to stop. This could be
|
||||
- * as long as 500 msec
|
||||
- */
|
||||
- tmp = ata_wait_register(port_mmio + PORT_CMD,
|
||||
- PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
|
||||
- if(tmp & PORT_CMD_LIST_ON)
|
||||
- return -EIO;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int ahci_start_engine(void __iomem *port_mmio)
|
||||
{
|
||||
u32 tmp;
|
||||
@@ -570,6 +441,31 @@ static int ahci_start_engine(void __iome
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int ahci_stop_engine(void __iomem *port_mmio)
|
||||
+{
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ tmp = readl(port_mmio + PORT_CMD);
|
||||
+
|
||||
+ /* Check if the HBA is idle */
|
||||
+ if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Setting HBA to idle */
|
||||
+ tmp &= ~PORT_CMD_START;
|
||||
+ writel(tmp, port_mmio + PORT_CMD);
|
||||
+
|
||||
+ /* wait for engine to stop. This could be
|
||||
+ * as long as 500 msec
|
||||
+ */
|
||||
+ tmp = ata_wait_register(port_mmio + PORT_CMD,
|
||||
+ PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
|
||||
+ if(tmp & PORT_CMD_LIST_ON)
|
||||
+ return -EIO;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static unsigned int ahci_dev_classify(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
|
||||
@@ -1109,6 +1005,107 @@ static void ahci_post_internal_cmd(struc
|
||||
}
|
||||
}
|
||||
|
||||
+static int ahci_port_start(struct ata_port *ap)
|
||||
+{
|
||||
+ struct device *dev = ap->host_set->dev;
|
||||
+ struct ahci_host_priv *hpriv = ap->host_set->private_data;
|
||||
+ struct ahci_port_priv *pp;
|
||||
+ void __iomem *mmio = ap->host_set->mmio_base;
|
||||
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
+ void *mem;
|
||||
+ dma_addr_t mem_dma;
|
||||
+ int rc;
|
||||
+
|
||||
+ pp = kmalloc(sizeof(*pp), GFP_KERNEL);
|
||||
+ if (!pp)
|
||||
+ return -ENOMEM;
|
||||
+ memset(pp, 0, sizeof(*pp));
|
||||
+
|
||||
+ rc = ata_pad_alloc(ap, dev);
|
||||
+ if (rc) {
|
||||
+ kfree(pp);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
|
||||
+ if (!mem) {
|
||||
+ ata_pad_free(ap, dev);
|
||||
+ kfree(pp);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
|
||||
+
|
||||
+ /*
|
||||
+ * First item in chunk of DMA memory: 32-slot command table,
|
||||
+ * 32 bytes each in size
|
||||
+ */
|
||||
+ pp->cmd_slot = mem;
|
||||
+ pp->cmd_slot_dma = mem_dma;
|
||||
+
|
||||
+ mem += AHCI_CMD_SLOT_SZ;
|
||||
+ mem_dma += AHCI_CMD_SLOT_SZ;
|
||||
+
|
||||
+ /*
|
||||
+ * Second item: Received-FIS area
|
||||
+ */
|
||||
+ pp->rx_fis = mem;
|
||||
+ pp->rx_fis_dma = mem_dma;
|
||||
+
|
||||
+ mem += AHCI_RX_FIS_SZ;
|
||||
+ mem_dma += AHCI_RX_FIS_SZ;
|
||||
+
|
||||
+ /*
|
||||
+ * Third item: data area for storing a single command
|
||||
+ * and its scatter-gather table
|
||||
+ */
|
||||
+ pp->cmd_tbl = mem;
|
||||
+ pp->cmd_tbl_dma = mem_dma;
|
||||
+
|
||||
+ ap->private_data = pp;
|
||||
+
|
||||
+ if (hpriv->cap & HOST_CAP_64)
|
||||
+ writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
|
||||
+ writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
|
||||
+ readl(port_mmio + PORT_LST_ADDR); /* flush */
|
||||
+
|
||||
+ if (hpriv->cap & HOST_CAP_64)
|
||||
+ writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
|
||||
+ writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
|
||||
+ readl(port_mmio + PORT_FIS_ADDR); /* flush */
|
||||
+
|
||||
+ writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
|
||||
+ PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
|
||||
+ PORT_CMD_START, port_mmio + PORT_CMD);
|
||||
+ readl(port_mmio + PORT_CMD); /* flush */
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void ahci_port_stop(struct ata_port *ap)
|
||||
+{
|
||||
+ struct device *dev = ap->host_set->dev;
|
||||
+ struct ahci_port_priv *pp = ap->private_data;
|
||||
+ void __iomem *mmio = ap->host_set->mmio_base;
|
||||
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ tmp = readl(port_mmio + PORT_CMD);
|
||||
+ tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX);
|
||||
+ writel(tmp, port_mmio + PORT_CMD);
|
||||
+ readl(port_mmio + PORT_CMD); /* flush */
|
||||
+
|
||||
+ /* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so
|
||||
+ * this is slightly incorrect.
|
||||
+ */
|
||||
+ msleep(500);
|
||||
+
|
||||
+ ap->private_data = NULL;
|
||||
+ dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
|
||||
+ pp->cmd_slot, pp->cmd_slot_dma);
|
||||
+ ata_pad_free(ap, dev);
|
||||
+ kfree(pp);
|
||||
+}
|
||||
+
|
||||
static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
|
||||
unsigned int port_idx)
|
||||
{
|
|
@ -1,68 +0,0 @@
|
|||
# [PATCH] ahci: cosmetic changes to ahci_start/stop_engine()
|
||||
# d8fcd116d203dfe2f6c272d0cd67724b172f1bc2
|
||||
|
||||
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
|
||||
index 92e2b95..ee00aed 100644
|
||||
--- a/drivers/scsi/ahci.c
|
||||
+++ b/drivers/scsi/ahci.c
|
||||
@@ -410,30 +410,23 @@ static int ahci_start_engine(void __iome
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
- /*
|
||||
- * Get current status
|
||||
- */
|
||||
+ /* get current status */
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
|
||||
- /*
|
||||
- * AHCI rev 1.1 section 10.3.1:
|
||||
+ /* AHCI rev 1.1 section 10.3.1:
|
||||
* Software shall not set PxCMD.ST to '1' until it verifies
|
||||
* that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
|
||||
*/
|
||||
if ((tmp & PORT_CMD_FIS_RX) == 0)
|
||||
return -EPERM;
|
||||
|
||||
- /*
|
||||
- * wait for engine to become idle.
|
||||
- */
|
||||
+ /* wait for engine to become idle */
|
||||
tmp = ata_wait_register(port_mmio + PORT_CMD,
|
||||
PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
|
||||
- if(tmp & PORT_CMD_LIST_ON)
|
||||
+ if (tmp & PORT_CMD_LIST_ON)
|
||||
return -EBUSY;
|
||||
|
||||
- /*
|
||||
- * Start DMA
|
||||
- */
|
||||
+ /* start DMA */
|
||||
tmp |= PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
readl(port_mmio + PORT_CMD); /* flush */
|
||||
@@ -447,20 +440,18 @@ static int ahci_stop_engine(void __iomem
|
||||
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
|
||||
- /* Check if the HBA is idle */
|
||||
+ /* check if the HBA is idle */
|
||||
if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
|
||||
return 0;
|
||||
|
||||
- /* Setting HBA to idle */
|
||||
+ /* setting HBA to idle */
|
||||
tmp &= ~PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
|
||||
- /* wait for engine to stop. This could be
|
||||
- * as long as 500 msec
|
||||
- */
|
||||
+ /* wait for engine to stop. This could be as long as 500 msec */
|
||||
tmp = ata_wait_register(port_mmio + PORT_CMD,
|
||||
PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
|
||||
- if(tmp & PORT_CMD_LIST_ON)
|
||||
+ if (tmp & PORT_CMD_LIST_ON)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
|
@ -1,42 +0,0 @@
|
|||
# [PATCH] ahci: simplify ahci_start_engine()
|
||||
# 9f5920567bfabbd1be26112a31c44652b6587394
|
||||
|
||||
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
|
||||
index ee00aed..e02b9c6 100644
|
||||
--- a/drivers/scsi/ahci.c
|
||||
+++ b/drivers/scsi/ahci.c
|
||||
@@ -406,32 +406,15 @@ static void ahci_scr_write (struct ata_p
|
||||
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
|
||||
}
|
||||
|
||||
-static int ahci_start_engine(void __iomem *port_mmio)
|
||||
+static void ahci_start_engine(void __iomem *port_mmio)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
- /* get current status */
|
||||
- tmp = readl(port_mmio + PORT_CMD);
|
||||
-
|
||||
- /* AHCI rev 1.1 section 10.3.1:
|
||||
- * Software shall not set PxCMD.ST to '1' until it verifies
|
||||
- * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
|
||||
- */
|
||||
- if ((tmp & PORT_CMD_FIS_RX) == 0)
|
||||
- return -EPERM;
|
||||
-
|
||||
- /* wait for engine to become idle */
|
||||
- tmp = ata_wait_register(port_mmio + PORT_CMD,
|
||||
- PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
|
||||
- if (tmp & PORT_CMD_LIST_ON)
|
||||
- return -EBUSY;
|
||||
-
|
||||
/* start DMA */
|
||||
+ tmp = readl(port_mmio + PORT_CMD);
|
||||
tmp |= PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
readl(port_mmio + PORT_CMD); /* flush */
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
|
||||
static int ahci_stop_engine(void __iomem *port_mmio)
|
|
@ -1,281 +0,0 @@
|
|||
# [PATCH] libata: improve driver initialization and deinitialization
|
||||
# 0be0aa98985dfec42502c0d0af2a1baff9bdb19f
|
||||
|
||||
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
|
||||
index e02b9c6..fb71fa7 100644
|
||||
--- a/drivers/scsi/ahci.c
|
||||
+++ b/drivers/scsi/ahci.c
|
||||
@@ -92,7 +92,9 @@ enum {
|
||||
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
|
||||
|
||||
/* HOST_CAP bits */
|
||||
+ HOST_CAP_SSC = (1 << 14), /* Slumber capable */
|
||||
HOST_CAP_CLO = (1 << 24), /* Command List Override support */
|
||||
+ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
|
||||
HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
|
||||
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
|
||||
|
||||
@@ -155,6 +157,7 @@ enum {
|
||||
PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
|
||||
PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
|
||||
|
||||
+ PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */
|
||||
PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
|
||||
PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
|
||||
PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
|
||||
@@ -440,6 +443,135 @@ static int ahci_stop_engine(void __iomem
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
|
||||
+ dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
|
||||
+{
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ /* set FIS registers */
|
||||
+ if (cap & HOST_CAP_64)
|
||||
+ writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
|
||||
+ writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
|
||||
+
|
||||
+ if (cap & HOST_CAP_64)
|
||||
+ writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
|
||||
+ writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
|
||||
+
|
||||
+ /* enable FIS reception */
|
||||
+ tmp = readl(port_mmio + PORT_CMD);
|
||||
+ tmp |= PORT_CMD_FIS_RX;
|
||||
+ writel(tmp, port_mmio + PORT_CMD);
|
||||
+
|
||||
+ /* flush */
|
||||
+ readl(port_mmio + PORT_CMD);
|
||||
+}
|
||||
+
|
||||
+static int ahci_stop_fis_rx(void __iomem *port_mmio)
|
||||
+{
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ /* disable FIS reception */
|
||||
+ tmp = readl(port_mmio + PORT_CMD);
|
||||
+ tmp &= ~PORT_CMD_FIS_RX;
|
||||
+ writel(tmp, port_mmio + PORT_CMD);
|
||||
+
|
||||
+ /* wait for completion, spec says 500ms, give it 1000 */
|
||||
+ tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
|
||||
+ PORT_CMD_FIS_ON, 10, 1000);
|
||||
+ if (tmp & PORT_CMD_FIS_ON)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void ahci_power_up(void __iomem *port_mmio, u32 cap)
|
||||
+{
|
||||
+ u32 cmd;
|
||||
+
|
||||
+ cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
|
||||
+
|
||||
+ /* spin up device */
|
||||
+ if (cap & HOST_CAP_SSS) {
|
||||
+ cmd |= PORT_CMD_SPIN_UP;
|
||||
+ writel(cmd, port_mmio + PORT_CMD);
|
||||
+ }
|
||||
+
|
||||
+ /* wake up link */
|
||||
+ writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
|
||||
+}
|
||||
+
|
||||
+static void ahci_power_down(void __iomem *port_mmio, u32 cap)
|
||||
+{
|
||||
+ u32 cmd, scontrol;
|
||||
+
|
||||
+ cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
|
||||
+
|
||||
+ if (cap & HOST_CAP_SSC) {
|
||||
+ /* enable transitions to slumber mode */
|
||||
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
|
||||
+ if ((scontrol & 0x0f00) > 0x100) {
|
||||
+ scontrol &= ~0xf00;
|
||||
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
|
||||
+ }
|
||||
+
|
||||
+ /* put device into slumber mode */
|
||||
+ writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD);
|
||||
+
|
||||
+ /* wait for the transition to complete */
|
||||
+ ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER,
|
||||
+ PORT_CMD_ICC_SLUMBER, 1, 50);
|
||||
+ }
|
||||
+
|
||||
+ /* put device into listen mode */
|
||||
+ if (cap & HOST_CAP_SSS) {
|
||||
+ /* first set PxSCTL.DET to 0 */
|
||||
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
|
||||
+ scontrol &= ~0xf;
|
||||
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
|
||||
+
|
||||
+ /* then set PxCMD.SUD to 0 */
|
||||
+ cmd &= ~PORT_CMD_SPIN_UP;
|
||||
+ writel(cmd, port_mmio + PORT_CMD);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void ahci_init_port(void __iomem *port_mmio, u32 cap,
|
||||
+ dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
|
||||
+{
|
||||
+ /* power up */
|
||||
+ ahci_power_up(port_mmio, cap);
|
||||
+
|
||||
+ /* enable FIS reception */
|
||||
+ ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
|
||||
+
|
||||
+ /* enable DMA */
|
||||
+ ahci_start_engine(port_mmio);
|
||||
+}
|
||||
+
|
||||
+static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
|
||||
+{
|
||||
+ int rc;
|
||||
+
|
||||
+ /* disable DMA */
|
||||
+ rc = ahci_stop_engine(port_mmio);
|
||||
+ if (rc) {
|
||||
+ *emsg = "failed to stop engine";
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ /* disable FIS reception */
|
||||
+ rc = ahci_stop_fis_rx(port_mmio);
|
||||
+ if (rc) {
|
||||
+ *emsg = "failed stop FIS RX";
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ /* put device into slumber mode */
|
||||
+ ahci_power_down(port_mmio, cap);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static unsigned int ahci_dev_classify(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
|
||||
@@ -1037,20 +1169,8 @@ static int ahci_port_start(struct ata_po
|
||||
|
||||
ap->private_data = pp;
|
||||
|
||||
- if (hpriv->cap & HOST_CAP_64)
|
||||
- writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
|
||||
- writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
|
||||
- readl(port_mmio + PORT_LST_ADDR); /* flush */
|
||||
-
|
||||
- if (hpriv->cap & HOST_CAP_64)
|
||||
- writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
|
||||
- writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
|
||||
- readl(port_mmio + PORT_FIS_ADDR); /* flush */
|
||||
-
|
||||
- writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
|
||||
- PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
|
||||
- PORT_CMD_START, port_mmio + PORT_CMD);
|
||||
- readl(port_mmio + PORT_CMD); /* flush */
|
||||
+ /* initialize port */
|
||||
+ ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1058,20 +1178,17 @@ static int ahci_port_start(struct ata_po
|
||||
static void ahci_port_stop(struct ata_port *ap)
|
||||
{
|
||||
struct device *dev = ap->host_set->dev;
|
||||
+ struct ahci_host_priv *hpriv = ap->host_set->private_data;
|
||||
struct ahci_port_priv *pp = ap->private_data;
|
||||
void __iomem *mmio = ap->host_set->mmio_base;
|
||||
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
- u32 tmp;
|
||||
-
|
||||
- tmp = readl(port_mmio + PORT_CMD);
|
||||
- tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX);
|
||||
- writel(tmp, port_mmio + PORT_CMD);
|
||||
- readl(port_mmio + PORT_CMD); /* flush */
|
||||
+ const char *emsg = NULL;
|
||||
+ int rc;
|
||||
|
||||
- /* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so
|
||||
- * this is slightly incorrect.
|
||||
- */
|
||||
- msleep(500);
|
||||
+ /* de-initialize port */
|
||||
+ rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
|
||||
+ if (rc)
|
||||
+ ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
|
||||
|
||||
ap->private_data = NULL;
|
||||
dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
|
||||
@@ -1099,7 +1216,7 @@ static int ahci_host_init(struct ata_pro
|
||||
struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
|
||||
void __iomem *mmio = probe_ent->mmio_base;
|
||||
u32 tmp, cap_save;
|
||||
- unsigned int i, j, using_dac;
|
||||
+ unsigned int i, using_dac;
|
||||
int rc;
|
||||
void __iomem *port_mmio;
|
||||
|
||||
@@ -1175,6 +1292,8 @@ static int ahci_host_init(struct ata_pro
|
||||
}
|
||||
|
||||
for (i = 0; i < probe_ent->n_ports; i++) {
|
||||
+ const char *emsg = NULL;
|
||||
+
|
||||
#if 0 /* BIOSen initialize this incorrectly */
|
||||
if (!(hpriv->port_map & (1 << i)))
|
||||
continue;
|
||||
@@ -1187,43 +1306,24 @@ #endif
|
||||
(unsigned long) mmio, i);
|
||||
|
||||
/* make sure port is not active */
|
||||
- tmp = readl(port_mmio + PORT_CMD);
|
||||
- VPRINTK("PORT_CMD 0x%x\n", tmp);
|
||||
- if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
|
||||
- PORT_CMD_FIS_RX | PORT_CMD_START)) {
|
||||
- tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
|
||||
- PORT_CMD_FIS_RX | PORT_CMD_START);
|
||||
- writel(tmp, port_mmio + PORT_CMD);
|
||||
- readl(port_mmio + PORT_CMD); /* flush */
|
||||
-
|
||||
- /* spec says 500 msecs for each bit, so
|
||||
- * this is slightly incorrect.
|
||||
- */
|
||||
- msleep(500);
|
||||
- }
|
||||
-
|
||||
- writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD);
|
||||
-
|
||||
- j = 0;
|
||||
- while (j < 100) {
|
||||
- msleep(10);
|
||||
- tmp = readl(port_mmio + PORT_SCR_STAT);
|
||||
- if ((tmp & 0xf) == 0x3)
|
||||
- break;
|
||||
- j++;
|
||||
- }
|
||||
+ rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
|
||||
+ if (rc)
|
||||
+ dev_printk(KERN_WARNING, &pdev->dev,
|
||||
+ "%s (%d)\n", emsg, rc);
|
||||
|
||||
+ /* clear SError */
|
||||
tmp = readl(port_mmio + PORT_SCR_ERR);
|
||||
VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
|
||||
writel(tmp, port_mmio + PORT_SCR_ERR);
|
||||
|
||||
- /* ack any pending irq events for this port */
|
||||
+ /* clear & turn off port IRQ */
|
||||
tmp = readl(port_mmio + PORT_IRQ_STAT);
|
||||
VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
|
||||
if (tmp)
|
||||
writel(tmp, port_mmio + PORT_IRQ_STAT);
|
||||
|
||||
writel(1 << i, mmio + HOST_IRQ_STAT);
|
||||
+ writel(0, port_mmio + PORT_IRQ_MASK);
|
||||
}
|
||||
|
||||
tmp = readl(mmio + HOST_CTL);
|
|
@ -1,203 +0,0 @@
|
|||
# [PATCH] ahci: separate out ahci_reset_controller() and ahci_init_controller()
|
||||
# d91542c11f3981768367815cf087ad36e792ea4a
|
||||
|
||||
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
|
||||
index fb71fa7..a9e0c5f 100644
|
||||
--- a/drivers/scsi/ahci.c
|
||||
+++ b/drivers/scsi/ahci.c
|
||||
@@ -572,6 +572,94 @@ static int ahci_deinit_port(void __iomem
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
|
||||
+{
|
||||
+ u32 cap_save, tmp;
|
||||
+
|
||||
+ cap_save = readl(mmio + HOST_CAP);
|
||||
+ cap_save &= ( (1<<28) | (1<<17) );
|
||||
+ cap_save |= (1 << 27);
|
||||
+
|
||||
+ /* global controller reset */
|
||||
+ tmp = readl(mmio + HOST_CTL);
|
||||
+ if ((tmp & HOST_RESET) == 0) {
|
||||
+ writel(tmp | HOST_RESET, mmio + HOST_CTL);
|
||||
+ readl(mmio + HOST_CTL); /* flush */
|
||||
+ }
|
||||
+
|
||||
+ /* reset must complete within 1 second, or
|
||||
+ * the hardware should be considered fried.
|
||||
+ */
|
||||
+ ssleep(1);
|
||||
+
|
||||
+ tmp = readl(mmio + HOST_CTL);
|
||||
+ if (tmp & HOST_RESET) {
|
||||
+ dev_printk(KERN_ERR, &pdev->dev,
|
||||
+ "controller reset failed (0x%x)\n", tmp);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ writel(HOST_AHCI_EN, mmio + HOST_CTL);
|
||||
+ (void) readl(mmio + HOST_CTL); /* flush */
|
||||
+ writel(cap_save, mmio + HOST_CAP);
|
||||
+ writel(0xf, mmio + HOST_PORTS_IMPL);
|
||||
+ (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
|
||||
+
|
||||
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
|
||||
+ u16 tmp16;
|
||||
+
|
||||
+ /* configure PCS */
|
||||
+ pci_read_config_word(pdev, 0x92, &tmp16);
|
||||
+ tmp16 |= 0xf;
|
||||
+ pci_write_config_word(pdev, 0x92, tmp16);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
|
||||
+ int n_ports, u32 cap)
|
||||
+{
|
||||
+ int i, rc;
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ for (i = 0; i < n_ports; i++) {
|
||||
+ void __iomem *port_mmio = ahci_port_base(mmio, i);
|
||||
+ const char *emsg = NULL;
|
||||
+
|
||||
+#if 0 /* BIOSen initialize this incorrectly */
|
||||
+ if (!(hpriv->port_map & (1 << i)))
|
||||
+ continue;
|
||||
+#endif
|
||||
+
|
||||
+ /* make sure port is not active */
|
||||
+ rc = ahci_deinit_port(port_mmio, cap, &emsg);
|
||||
+ if (rc)
|
||||
+ dev_printk(KERN_WARNING, &pdev->dev,
|
||||
+ "%s (%d)\n", emsg, rc);
|
||||
+
|
||||
+ /* clear SError */
|
||||
+ tmp = readl(port_mmio + PORT_SCR_ERR);
|
||||
+ VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
|
||||
+ writel(tmp, port_mmio + PORT_SCR_ERR);
|
||||
+
|
||||
+ /* clear & turn off port IRQ */
|
||||
+ tmp = readl(port_mmio + PORT_IRQ_STAT);
|
||||
+ VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
|
||||
+ if (tmp)
|
||||
+ writel(tmp, port_mmio + PORT_IRQ_STAT);
|
||||
+
|
||||
+ writel(1 << i, mmio + HOST_IRQ_STAT);
|
||||
+ writel(0, port_mmio + PORT_IRQ_MASK);
|
||||
+ }
|
||||
+
|
||||
+ tmp = readl(mmio + HOST_CTL);
|
||||
+ VPRINTK("HOST_CTL 0x%x\n", tmp);
|
||||
+ writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
|
||||
+ tmp = readl(mmio + HOST_CTL);
|
||||
+ VPRINTK("HOST_CTL 0x%x\n", tmp);
|
||||
+}
|
||||
+
|
||||
static unsigned int ahci_dev_classify(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
|
||||
@@ -1215,47 +1303,12 @@ static int ahci_host_init(struct ata_pro
|
||||
struct ahci_host_priv *hpriv = probe_ent->private_data;
|
||||
struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
|
||||
void __iomem *mmio = probe_ent->mmio_base;
|
||||
- u32 tmp, cap_save;
|
||||
unsigned int i, using_dac;
|
||||
int rc;
|
||||
- void __iomem *port_mmio;
|
||||
-
|
||||
- cap_save = readl(mmio + HOST_CAP);
|
||||
- cap_save &= ( (1<<28) | (1<<17) );
|
||||
- cap_save |= (1 << 27);
|
||||
-
|
||||
- /* global controller reset */
|
||||
- tmp = readl(mmio + HOST_CTL);
|
||||
- if ((tmp & HOST_RESET) == 0) {
|
||||
- writel(tmp | HOST_RESET, mmio + HOST_CTL);
|
||||
- readl(mmio + HOST_CTL); /* flush */
|
||||
- }
|
||||
-
|
||||
- /* reset must complete within 1 second, or
|
||||
- * the hardware should be considered fried.
|
||||
- */
|
||||
- ssleep(1);
|
||||
-
|
||||
- tmp = readl(mmio + HOST_CTL);
|
||||
- if (tmp & HOST_RESET) {
|
||||
- dev_printk(KERN_ERR, &pdev->dev,
|
||||
- "controller reset failed (0x%x)\n", tmp);
|
||||
- return -EIO;
|
||||
- }
|
||||
|
||||
- writel(HOST_AHCI_EN, mmio + HOST_CTL);
|
||||
- (void) readl(mmio + HOST_CTL); /* flush */
|
||||
- writel(cap_save, mmio + HOST_CAP);
|
||||
- writel(0xf, mmio + HOST_PORTS_IMPL);
|
||||
- (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
|
||||
-
|
||||
- if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
|
||||
- u16 tmp16;
|
||||
-
|
||||
- pci_read_config_word(pdev, 0x92, &tmp16);
|
||||
- tmp16 |= 0xf;
|
||||
- pci_write_config_word(pdev, 0x92, tmp16);
|
||||
- }
|
||||
+ rc = ahci_reset_controller(mmio, pdev);
|
||||
+ if (rc)
|
||||
+ return rc;
|
||||
|
||||
hpriv->cap = readl(mmio + HOST_CAP);
|
||||
hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
|
||||
@@ -1291,46 +1344,10 @@ static int ahci_host_init(struct ata_pro
|
||||
}
|
||||
}
|
||||
|
||||
- for (i = 0; i < probe_ent->n_ports; i++) {
|
||||
- const char *emsg = NULL;
|
||||
-
|
||||
-#if 0 /* BIOSen initialize this incorrectly */
|
||||
- if (!(hpriv->port_map & (1 << i)))
|
||||
- continue;
|
||||
-#endif
|
||||
+ for (i = 0; i < probe_ent->n_ports; i++)
|
||||
+ ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
|
||||
|
||||
- port_mmio = ahci_port_base(mmio, i);
|
||||
- VPRINTK("mmio %p port_mmio %p\n", mmio, port_mmio);
|
||||
-
|
||||
- ahci_setup_port(&probe_ent->port[i],
|
||||
- (unsigned long) mmio, i);
|
||||
-
|
||||
- /* make sure port is not active */
|
||||
- rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
|
||||
- if (rc)
|
||||
- dev_printk(KERN_WARNING, &pdev->dev,
|
||||
- "%s (%d)\n", emsg, rc);
|
||||
-
|
||||
- /* clear SError */
|
||||
- tmp = readl(port_mmio + PORT_SCR_ERR);
|
||||
- VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
|
||||
- writel(tmp, port_mmio + PORT_SCR_ERR);
|
||||
-
|
||||
- /* clear & turn off port IRQ */
|
||||
- tmp = readl(port_mmio + PORT_IRQ_STAT);
|
||||
- VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
|
||||
- if (tmp)
|
||||
- writel(tmp, port_mmio + PORT_IRQ_STAT);
|
||||
-
|
||||
- writel(1 << i, mmio + HOST_IRQ_STAT);
|
||||
- writel(0, port_mmio + PORT_IRQ_MASK);
|
||||
- }
|
||||
-
|
||||
- tmp = readl(mmio + HOST_CTL);
|
||||
- VPRINTK("HOST_CTL 0x%x\n", tmp);
|
||||
- writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
|
||||
- tmp = readl(mmio + HOST_CTL);
|
||||
- VPRINTK("HOST_CTL 0x%x\n", tmp);
|
||||
+ ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
# [PATCH] ahci: implement Power Management support
|
||||
# c1332875cbe0c148c7f200d4f9b36b64e34d9872
|
||||
|
||||
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
|
||||
index a9e0c5f..909a4dc 100644
|
||||
--- a/drivers/scsi/ahci.c
|
||||
+++ b/drivers/scsi/ahci.c
|
||||
@@ -215,6 +215,10 @@ static void ahci_freeze(struct ata_port
|
||||
static void ahci_thaw(struct ata_port *ap);
|
||||
static void ahci_error_handler(struct ata_port *ap);
|
||||
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
|
||||
+static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
|
||||
+static int ahci_port_resume(struct ata_port *ap);
|
||||
+static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
|
||||
+static int ahci_pci_device_resume(struct pci_dev *pdev);
|
||||
static void ahci_remove_one (struct pci_dev *pdev);
|
||||
|
||||
static struct scsi_host_template ahci_sht = {
|
||||
@@ -234,6 +238,8 @@ static struct scsi_host_template ahci_sh
|
||||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
+ .suspend = ata_scsi_device_suspend,
|
||||
+ .resume = ata_scsi_device_resume,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations ahci_ops = {
|
||||
@@ -260,6 +266,9 @@ static const struct ata_port_operations
|
||||
.error_handler = ahci_error_handler,
|
||||
.post_internal_cmd = ahci_post_internal_cmd,
|
||||
|
||||
+ .port_suspend = ahci_port_suspend,
|
||||
+ .port_resume = ahci_port_resume,
|
||||
+
|
||||
.port_start = ahci_port_start,
|
||||
.port_stop = ahci_port_stop,
|
||||
};
|
||||
@@ -361,6 +370,8 @@ static struct pci_driver ahci_pci_driver
|
||||
.name = DRV_NAME,
|
||||
.id_table = ahci_pci_tbl,
|
||||
.probe = ahci_init_one,
|
||||
+ .suspend = ahci_pci_device_suspend,
|
||||
+ .resume = ahci_pci_device_resume,
|
||||
.remove = ahci_remove_one,
|
||||
};
|
||||
|
||||
@@ -1199,6 +1210,79 @@ static void ahci_post_internal_cmd(struc
|
||||
}
|
||||
}
|
||||
|
||||
+static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
|
||||
+{
|
||||
+ struct ahci_host_priv *hpriv = ap->host_set->private_data;
|
||||
+ struct ahci_port_priv *pp = ap->private_data;
|
||||
+ void __iomem *mmio = ap->host_set->mmio_base;
|
||||
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
+ const char *emsg = NULL;
|
||||
+ int rc;
|
||||
+
|
||||
+ rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
|
||||
+ if (rc) {
|
||||
+ ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
|
||||
+ ahci_init_port(port_mmio, hpriv->cap,
|
||||
+ pp->cmd_slot_dma, pp->rx_fis_dma);
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int ahci_port_resume(struct ata_port *ap)
|
||||
+{
|
||||
+ struct ahci_port_priv *pp = ap->private_data;
|
||||
+ struct ahci_host_priv *hpriv = ap->host_set->private_data;
|
||||
+ void __iomem *mmio = ap->host_set->mmio_base;
|
||||
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
+
|
||||
+ ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
|
||||
+{
|
||||
+ struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
|
||||
+ void __iomem *mmio = host_set->mmio_base;
|
||||
+ u32 ctl;
|
||||
+
|
||||
+ if (mesg.event == PM_EVENT_SUSPEND) {
|
||||
+ /* AHCI spec rev1.1 section 8.3.3:
|
||||
+ * Software must disable interrupts prior to requesting a
|
||||
+ * transition of the HBA to D3 state.
|
||||
+ */
|
||||
+ ctl = readl(mmio + HOST_CTL);
|
||||
+ ctl &= ~HOST_IRQ_EN;
|
||||
+ writel(ctl, mmio + HOST_CTL);
|
||||
+ readl(mmio + HOST_CTL); /* flush */
|
||||
+ }
|
||||
+
|
||||
+ return ata_pci_device_suspend(pdev, mesg);
|
||||
+}
|
||||
+
|
||||
+static int ahci_pci_device_resume(struct pci_dev *pdev)
|
||||
+{
|
||||
+ struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
|
||||
+ struct ahci_host_priv *hpriv = host_set->private_data;
|
||||
+ void __iomem *mmio = host_set->mmio_base;
|
||||
+ int rc;
|
||||
+
|
||||
+ ata_pci_device_do_resume(pdev);
|
||||
+
|
||||
+ if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
|
||||
+ rc = ahci_reset_controller(mmio, pdev);
|
||||
+ if (rc)
|
||||
+ return rc;
|
||||
+
|
||||
+ ahci_init_controller(mmio, pdev, host_set->n_ports, hpriv->cap);
|
||||
+ }
|
||||
+
|
||||
+ ata_host_set_resume(host_set);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ahci_port_start(struct ata_port *ap)
|
||||
{
|
||||
struct device *dev = ap->host_set->dev;
|
File diff suppressed because it is too large
Load Diff
|
@ -1,49 +0,0 @@
|
|||
# [SCSI] areca sysfs fix
|
||||
# 43d6b68dc38867e489995e21649bb82f6ee7b5d3
|
||||
|
||||
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
|
||||
index 0459f41..c96f714 100644
|
||||
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
|
||||
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
|
||||
@@ -240,15 +240,11 @@ int arcmsr_alloc_sysfs_attr(struct Adapt
|
||||
}
|
||||
return 0;
|
||||
error_bin_file_message_clear:
|
||||
- error = sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
+ sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
&arcmsr_sysfs_message_write_attr);
|
||||
- if (error)
|
||||
- printk(KERN_ERR "arcmsr: sysfs_remove_bin_file mu_write failed\n");
|
||||
error_bin_file_message_write:
|
||||
- error = sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
+ sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
&arcmsr_sysfs_message_read_attr);
|
||||
- if (error)
|
||||
- printk(KERN_ERR "arcmsr: sysfs_remove_bin_file mu_read failed\n");
|
||||
error_bin_file_message_read:
|
||||
return error;
|
||||
}
|
||||
@@ -256,20 +252,13 @@ error_bin_file_message_read:
|
||||
void
|
||||
arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
|
||||
struct Scsi_Host *host = acb->host;
|
||||
- int error;
|
||||
|
||||
- error = sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
+ sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
&arcmsr_sysfs_message_clear_attr);
|
||||
- if (error)
|
||||
- printk(KERN_ERR "arcmsr: free sysfs mu_clear failed\n");
|
||||
- error = sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
+ sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
&arcmsr_sysfs_message_write_attr);
|
||||
- if (error)
|
||||
- printk(KERN_ERR "arcmsr: free sysfs mu_write failed\n");
|
||||
- error = sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
+ sysfs_remove_bin_file(&host->shost_classdev.kobj,
|
||||
&arcmsr_sysfs_message_read_attr);
|
||||
- if (error)
|
||||
- printk(KERN_ERR "arcmsr: free sysfss mu_read failed\n");
|
||||
}
|
||||
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
# [SCSI] arcmsr: fix up sysfs values
|
||||
# d67a70aca200f67be42428e74eb3353f20ad1130
|
||||
|
||||
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
|
||||
index c96f714..12497da 100644
|
||||
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
|
||||
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
|
||||
@@ -265,7 +265,7 @@ arcmsr_free_sysfs_attr(struct AdapterCon
|
||||
static ssize_t
|
||||
arcmsr_attr_host_driver_version(struct class_device *cdev, char *buf) {
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "ARCMSR: %s\n",
|
||||
+ "%s\n",
|
||||
ARCMSR_DRIVER_VERSION);
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ arcmsr_attr_host_driver_posted_cmd(struc
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "Current commands posted: %4d\n",
|
||||
+ "%4d\n",
|
||||
atomic_read(&acb->ccboutstandingcount));
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ arcmsr_attr_host_driver_reset(struct cla
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "SCSI Host Resets: %4d\n",
|
||||
+ "%4d\n",
|
||||
acb->num_resets);
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ arcmsr_attr_host_driver_abort(struct cla
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "SCSI Aborts/Timeouts: %4d\n",
|
||||
+ "%4d\n",
|
||||
acb->num_aborts);
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ arcmsr_attr_host_fw_model(struct class_d
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "Adapter Model: %s\n",
|
||||
+ "%s\n",
|
||||
acb->firm_model);
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ arcmsr_attr_host_fw_version(struct class
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "Firmware Version: %s\n",
|
||||
+ "%s\n",
|
||||
acb->firm_version);
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ arcmsr_attr_host_fw_request_len(struct c
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "Reguest Lenth: %4d\n",
|
||||
+ "%4d\n",
|
||||
acb->firm_request_len);
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ arcmsr_attr_host_fw_numbers_queue(struct
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "Numbers of Queue: %4d\n",
|
||||
+ "%4d\n",
|
||||
acb->firm_numbers_queue);
|
||||
}
|
||||
|
||||
@@ -341,7 +341,7 @@ arcmsr_attr_host_fw_sdram_size(struct cl
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "SDRAM Size: %4d\n",
|
||||
+ "%4d\n",
|
||||
acb->firm_sdram_size);
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ arcmsr_attr_host_fw_hd_channels(struct c
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
- "Hard Disk Channels: %4d\n",
|
||||
+ "%4d\n",
|
||||
acb->firm_hd_channels);
|
||||
}
|
||||
|
Loading…
Reference in New Issue