Skip to contentSkip to conversation

Final 2.4.x SATA updates

PATCH In review Jeff Garzik 3 participants 7 messages Dec 1, 2005 – Dec 4, 2005 2 messages not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Now that ATAPI support is pretty stable, the 2.4 version of libata will be receiving its final updates soon. Here is the current backport, for testing and feedback.

Please report problems -- particularly any regressions -- to [email protected]. I may not be able to respond personally to each and every bug report, but rest assured all feedback is noted. Sometimes, solutions only become apparent after a few people report the same problem.

The 'combined' branch of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-2.4.git

http://www.kernel.org/pub/linux/kernel/people/jgarzik/libata/2.4.32-libata1.patch.bz2
(available as soon as kernel.org mirrors catch up)

contains the following updates:

 drivers/pci/quirks.c          |   86 ++
 drivers/scsi/ahci.c           |  305 ++++---
 drivers/scsi/ata_piix.c       |  136 +--
 drivers/scsi/libata-core.c    | 1743 +++++++++++++++++++++++++++---------------
 drivers/scsi/libata-scsi.c    | 1635 ++++++++++++++++++++++++++++++---------
 drivers/scsi/libata.h         |   68 -
 drivers/scsi/sata_nv.c        |   86 +-
 drivers/scsi/sata_promise.c   |  166 ++--
 drivers/scsi/sata_promise.h   |   33 
 drivers/scsi/sata_qstor.c     |  114 +-
 drivers/scsi/sata_sil.c       |  100 +-
 drivers/scsi/sata_sis.c       |  146 ++-
 drivers/scsi/sata_svw.c       |   85 +-
 drivers/scsi/sata_sx4.c       |  292 +++----
 drivers/scsi/sata_uli.c       |   66 -
 drivers/scsi/sata_via.c       |  110 +-
 drivers/scsi/sata_vsc.c       |   79 +
 include/linux/ata.h           |   86 +-
 include/linux/ioport.h        |    1 
 include/linux/libata-compat.h |  102 ++
 include/linux/libata.h        |  264 ++++--
 include/linux/pci_ids.h       |    6 
 include/scsi/scsi.h           |    4 
 kernel/ksyms.c                |    1 
 kernel/resource.c             |   10 
 25 files changed, 3957 insertions(+), 1767 deletions(-)

Jeff Garzik:
[libata] resync with kernel 2.6.13
[libata sata_sx4] trim trailing whitespace
[libata] resync with 2.6.14
[libata] resync with 2.6.15-rc3
[libata] fix build
[libata] combined mode support, using ugly ____request_resource() hack [libata] fix potential oops in pdev_printk() compat helper

#1 lore raw
Quoted 4 lines · Jeff Garzik

Now that ATAPI support is pretty stable, the 2.4 version of libata will be receiving its final updates soon. Here is the current backport, for testing and feedback.

Awesome. 2.4.x lacks KM_IRQ0 in kmap_types.h

gcc -D__KERNEL__ -I/usr/src/linux-2.4.32/include -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fomit-frame-pointer -Os -falign-functions=2 -falign-jumps=2 -falign-labels=2 -falign-loops=2 -pipe -mpreferred-stack-boundary=2 -march=i486 -DMODULE -nostdinc -iwithprefix include -DKBUILD_BASENAME=libata_core -DEXPORT_SYMTAB -c libata-core.c libata-core.c: In function `ata_sg_clean':
libata-core.c:2427: error: `KM_IRQ0' undeclared (first use in this function)
libata-core.c:2427: error: (Each undeclared identifier is reported only once
libata-core.c:2427: error: for each function it appears in.)
libata-core.c: In function `ata_sg_setup':
libata-core.c:2701: error: `KM_IRQ0' undeclared (first use in this function)
make[2]: *** [libata-core.o] Error 1

-Erik

--
Erik B. Andersen http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--

#2 lore raw
Quoted 9 lines · Erik Andersen
Quoted 3 lines · Jeff Garzik

Now that ATAPI support is pretty stable, the 2.4 version of libata will be receiving its final updates soon. Here is the current backport, for testing and feedback.

Awesome. 2.4.x lacks KM_IRQ0 in kmap_types.h

Quoted 8 lines

gcc -D__KERNEL__ -I/usr/src/linux-2.4.32/include -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fomit-frame-pointer -Os -falign-functions=2 -falign-jumps=2 -falign-labels=2 -falign-loops=2 -pipe -mpreferred-stack-boundary=2 -march=i486 -DMODULE -nostdinc -iwithprefix include -DKBUILD_BASENAME=libata_core -DEXPORT_SYMTAB -c libata-core.c libata-core.c: In function `ata_sg_clean':
libata-core.c:2427: error: `KM_IRQ0' undeclared (first use in this function)
libata-core.c:2427: error: (Each undeclared identifier is reported only once
libata-core.c:2427: error: for each function it appears in.)
libata-core.c: In function `ata_sg_setup':
libata-core.c:2701: error: `KM_IRQ0' undeclared (first use in this function)
make[2]: *** [libata-core.o] Error 1

hmmm, interesting. Easy enough to fix. I guess I didn't build on a highmem box.

Jeff

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

#5 lore raw

Draft libata GET_IDENTITY and DRIVE_TASKFILE

Here is a first draft patch adding support for HDIO_GET_IDENTITY and HDIO_DRIVE_TASKFILE to libata. Unlike the older ioctl-get-identity.patch, this returns the actual drive identity rather than kluding out a few fields. It needs a bit more cleanup, and review, but the IDENTITY stuff does produce output matching the sort coming from the ide driver and is enough to allow i.e. 'smartctl -i -a -d ata /dev/sda' to be happy doing its thing. If this goes in, smartctl will be able to Just Work for sata -- and there will be much rejoicing. :-)

I opted to copy and adapt the byteswapping code from ide_fix_driveid() rather than making a function call, since there is no guarantee the older ide driver would be compiled in and making the routine shared seems more bother than it's worth.

The TASKFILE stuff seems to sortof work, but could use some scrubbing from someone with a better understanding of how libata works, especialy the part doing 'switch (taskfile->data_phase)' where you can no doubt see I had no idea what I was doing.

It'd be great to get some review and extra eyeballs to weed out the problems doubtless lurking in here. Please CC me as I'm not currently subscribed to linux-ide.

-Erik

--
Erik B. Andersen http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--

drivers/scsi/libata-scsi.c renamed from drivers/scsi.orig/libata-scsi.c +393 -0
@@ -273,6 +273,366 @@
 	return rc;
 }
 
+/**
+ *	ata_taskfile_ioctl - Handler for HDIO_DRIVE_TASKFILE ioctl
+ *	@scsidev: Device to which we are issuing command
+ *	@arg: User provided data for issuing command
+ *
+ *	LOCKING:
+ *	Defined by the SCSI layer.  We don't really care.
+ *
+ *	RETURNS:
+ *	Zero on success, negative errno on error.
+ */
+int ata_taskfile_ioctl(struct scsi_device *scsidev, void __user *arg)
+{
+	int rc = 0, tasksize = sizeof(struct ide_task_request_s);
+	u8 *outbuf = NULL;
+	u8 *inbuf  = NULL;
+	u8 scsi_cmd[MAX_COMMAND_SIZE];
+	struct scsi_request *sreq;
+	struct ide_task_request_s *taskfile;
+	struct hd_drive_task_hdr *task;
+	struct hd_drive_hob_hdr *hob;
+
+	if (NULL == (void *)arg)
+		return -EINVAL;
+
+	taskfile = kmalloc(tasksize, GFP_KERNEL);
+	if (NULL == (void *)taskfile)
+		return -ENOMEM;
+	memset(taskfile, 0, tasksize);
+
+	if (copy_from_user(taskfile, arg, tasksize)) {
+		kfree(taskfile);
+		return -EFAULT;
+	}
+	task = (struct hd_drive_task_hdr *) taskfile->io_ports;
+	hob = (struct hd_drive_hob_hdr *) taskfile->hob_ports;
+
+	memset(scsi_cmd, 0, sizeof(scsi_cmd));
+	scsi_cmd[0]  = ATA_16;
+	//scsi_cmd[1]  = hob->data;
+	//scsi_cmd[2]  = task->data;
+	scsi_cmd[3]  = hob->feature;
+	scsi_cmd[4]  = task->feature;
+	scsi_cmd[5]  = hob->sector_count;
+	scsi_cmd[6]  = task->sector_count;
+	scsi_cmd[7]  = hob->sector_number;
+	scsi_cmd[8]  = task->sector_number;
+	scsi_cmd[9]  = hob->low_cylinder;
+	scsi_cmd[10] = task->low_cylinder;
+	scsi_cmd[11] = hob->high_cylinder;
+	scsi_cmd[12] = task->high_cylinder;
+	scsi_cmd[13] = hob->control;
+	scsi_cmd[14] = task->command;
+
+	sreq = scsi_allocate_request(scsidev);
+	if (!sreq) {
+		rc = -EINTR;
+		goto error;
+	}
+
+	switch (taskfile->data_phase)
+	{
+		case TASKFILE_IN:
+		case TASKFILE_MULTI_IN:
+			//sreq->sr_data_direction = SCSI_DATA_READ;
+			scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
+			scsi_cmd[2]  = 0x0e;
+			sreq->sr_data_direction = DMA_FROM_DEVICE;
+			break;
+		case TASKFILE_IN_DMA:
+		case TASKFILE_IN_DMAQ:
+			scsi_cmd[1]  = (6 << 1); /* DMA */
+			scsi_cmd[2]  = 0x0e;
+			sreq->sr_data_direction = DMA_FROM_DEVICE;
+			break;
+		case TASKFILE_OUT:
+		case TASKFILE_MULTI_OUT:
+			scsi_cmd[1]  = (5 << 1); /* PIO Data-out */
+			scsi_cmd[2]  = 0x0e;
+			//sreq->sr_data_direction = SCSI_DATA_WRITE;
+			sreq->sr_data_direction = DMA_TO_DEVICE;
+			break;
+		case TASKFILE_OUT_DMA:
+		case TASKFILE_OUT_DMAQ:
+			scsi_cmd[1]  = (6 << 1); /* DMA */
+			scsi_cmd[2]  = 0x0e;
+			sreq->sr_data_direction = DMA_TO_DEVICE;
+			break;
+		case TASKFILE_NO_DATA:
+			scsi_cmd[1]  = (3 << 1); /* Non-data */
+			scsi_cmd[2]  = 0;
+			sreq->sr_data_direction = DMA_NONE;
+			break;
+		default:
+			rc = -EFAULT;
+			goto error;
+	}
+
+	/* Given the nature of scsi_wait_req, we can either
+	 * read, or we can write.  Not both. */
+	if (taskfile->out_size && taskfile->in_size) {
+		rc = -EFAULT;
+		goto error;
+	}
+
+	if (taskfile->out_size) {
+		outbuf = kmalloc(taskfile->out_size, GFP_KERNEL);
+		if (outbuf == NULL) {
+			rc = -ENOMEM;
+			goto error;
+		}
+		memset(outbuf, 0, taskfile->out_size);
+		if (copy_from_user(outbuf, (void *)arg + tasksize,
+					taskfile->out_size))
+		{
+			rc = -EFAULT;
+			goto error;
+		}
+		/* Good values for timeout and retries?  Values below
+		   from scsi_ioctl_send_command() for default case... */
+		scsi_wait_req(sreq, scsi_cmd, outbuf,
+				taskfile->out_size, (10*HZ), 5);
+	} else if (taskfile->in_size) {
+		inbuf = kmalloc(taskfile->in_size, GFP_KERNEL);
+		if (inbuf == NULL) {
+			rc = -ENOMEM;
+			goto error;
+		}
+		memset(inbuf, 0, taskfile->in_size);
+		if (copy_from_user(inbuf, (void *)arg + tasksize +
+					taskfile->out_size, taskfile->in_size))
+		{
+			rc = -EFAULT;
+			goto error;
+		}
+		/* Good values for timeout and retries?  Values below
+		   from scsi_ioctl_send_command() for default case... */
+		scsi_wait_req(sreq, scsi_cmd, inbuf,
+				taskfile->in_size, (10*HZ), 5);
+	} else {
+		/* Good values for timeout and retries?  Values below
+		   from scsi_ioctl_send_command() for default case... */
+		scsi_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5);
+	}
+
+	if (sreq->sr_result) {
+		rc = -EIO;
+		goto error;
+	}
+
+	/* Need code to retrieve data from check condition? */
+
+	if (copy_to_user(arg, taskfile, tasksize)) {
+		rc = -EFAULT;
+		goto error;
+	}
+
+	if (taskfile->out_size && copy_to_user((void *)arg + tasksize,
+				outbuf, taskfile->out_size))
+	{
+		rc = -EFAULT;
+		goto error;
+	} else if (taskfile->in_size && copy_to_user(
+				(void *)arg + tasksize + taskfile->out_size,
+				inbuf, taskfile->in_size))
+	{
+		rc = -EFAULT;
+		goto error;
+	}
+
+
+error:
+	scsi_release_request(sreq);
+
+	kfree(taskfile);
+	if (inbuf)
+		kfree(inbuf);
+	if (outbuf)
+		kfree(outbuf);
+	return rc;
+}
+
+static void ide_fixstring (u8 *s, const int bytecount)
+{
+	u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */
+
+#ifndef __BIG_ENDIAN
+# ifdef __LITTLE_ENDIAN
+	/* convert from big-endian to host byte order */
+	for (p = end ; p != s;) {
+		unsigned short *pp = (unsigned short *) (p -= 2);
+		*pp = ntohs(*pp);
+	}
+# else
+#  error "Please fix <asm/byteorder.h>"
+# endif
+#endif
+	/* strip leading blanks */
+	while (s != end && *s == ' ')
+		++s;
+	/* compress internal blanks and strip trailing blanks */
+	while (s != end && *s) {
+		if (*s++ != ' ' || (s != end && *s && *s != ' '))
+			*p++ = *(s-1);
+	}
+	/* wipe out trailing garbage */
+	while (p != end)
+		*p++ = '\0';
+}
+
+static void ide_fix_driveid (struct hd_driveid *id)
+{
+#ifndef __LITTLE_ENDIAN
+# ifdef __BIG_ENDIAN
+	int i;
+	u16 *stringcast;
+
+	id->config         = __le16_to_cpu(id->config);
+	id->cyls           = __le16_to_cpu(id->cyls);
+	id->reserved2      = __le16_to_cpu(id->reserved2);
+	id->heads          = __le16_to_cpu(id->heads);
+	id->track_bytes    = __le16_to_cpu(id->track_bytes);
+	id->sector_bytes   = __le16_to_cpu(id->sector_bytes);
+	id->sectors        = __le16_to_cpu(id->sectors);
+	id->vendor0        = __le16_to_cpu(id->vendor0);
+	id->vendor1        = __le16_to_cpu(id->vendor1);
+	id->vendor2        = __le16_to_cpu(id->vendor2);
+	stringcast = (u16 *)&id->serial_no[0];
+	for (i = 0; i < (20/2); i++)
+		stringcast[i] = __le16_to_cpu(stringcast[i]);
+	id->buf_type       = __le16_to_cpu(id->buf_type);
+	id->buf_size       = __le16_to_cpu(id->buf_size);
+	id->ecc_bytes      = __le16_to_cpu(id->ecc_bytes);
+	stringcast = (u16 *)&id->fw_rev[0];
+	for (i = 0; i < (8/2); i++)
+		stringcast[i] = __le16_to_cpu(stringcast[i]);
+	stringcast = (u16 *)&id->model[0];
+	for (i = 0; i < (40/2); i++)
+		stringcast[i] = __le16_to_cpu(stringcast[i]);
+	id->dword_io       = __le16_to_cpu(id->dword_io);
+	id->reserved50     = __le16_to_cpu(id->reserved50);
+	id->field_valid    = __le16_to_cpu(id->field_valid);
+	id->cur_cyls       = __le16_to_cpu(id->cur_cyls);
+	id->cur_heads      = __le16_to_cpu(id->cur_heads);
+	id->cur_sectors    = __le16_to_cpu(id->cur_sectors);
+	id->cur_capacity0  = __le16_to_cpu(id->cur_capacity0);
+	id->cur_capacity1  = __le16_to_cpu(id->cur_capacity1);
+	id->lba_capacity   = __le32_to_cpu(id->lba_capacity);
+	id->dma_1word      = __le16_to_cpu(id->dma_1word);
+	id->dma_mword      = __le16_to_cpu(id->dma_mword);
+	id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
+	id->eide_dma_min   = __le16_to_cpu(id->eide_dma_min);
+	id->eide_dma_time  = __le16_to_cpu(id->eide_dma_time);
+	id->eide_pio       = __le16_to_cpu(id->eide_pio);
+	id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
+	for (i = 0; i < 2; ++i)
+		id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);
+	for (i = 0; i < 4; ++i)
+		id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);
+	id->queue_depth    = __le16_to_cpu(id->queue_depth);
+	for (i = 0; i < 4; ++i)
+		id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);
+	id->major_rev_num  = __le16_to_cpu(id->major_rev_num);
+	id->minor_rev_num  = __le16_to_cpu(id->minor_rev_num);
+	id->command_set_1  = __le16_to_cpu(id->command_set_1);
+	id->command_set_2  = __le16_to_cpu(id->command_set_2);
+	id->cfsse          = __le16_to_cpu(id->cfsse);
+	id->cfs_enable_1   = __le16_to_cpu(id->cfs_enable_1);
+	id->cfs_enable_2   = __le16_to_cpu(id->cfs_enable_2);
+	id->csf_default    = __le16_to_cpu(id->csf_default);
+	id->dma_ultra      = __le16_to_cpu(id->dma_ultra);
+	id->trseuc         = __le16_to_cpu(id->trseuc);
+	id->trsEuc         = __le16_to_cpu(id->trsEuc);
+	id->CurAPMvalues   = __le16_to_cpu(id->CurAPMvalues);
+	id->mprc           = __le16_to_cpu(id->mprc);
+	id->hw_config      = __le16_to_cpu(id->hw_config);
+	id->acoustic       = __le16_to_cpu(id->acoustic);
+	id->msrqs          = __le16_to_cpu(id->msrqs);
+	id->sxfert         = __le16_to_cpu(id->sxfert);
+	id->sal            = __le16_to_cpu(id->sal);
+	id->spg            = __le32_to_cpu(id->spg);
+	id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2);
+	for (i = 0; i < 22; i++)
+		id->words104_125[i]   = __le16_to_cpu(id->words104_125[i]);
+	id->last_lun       = __le16_to_cpu(id->last_lun);
+	id->word127        = __le16_to_cpu(id->word127);
+	id->dlf            = __le16_to_cpu(id->dlf);
+	id->csfo           = __le16_to_cpu(id->csfo);
+	for (i = 0; i < 26; i++)
+		id->words130_155[i] = __le16_to_cpu(id->words130_155[i]);
+	id->word156        = __le16_to_cpu(id->word156);
+	for (i = 0; i < 3; i++)
+		id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);
+	id->cfa_power      = __le16_to_cpu(id->cfa_power);
+	for (i = 0; i < 14; i++)
+		id->words161_175[i] = __le16_to_cpu(id->words161_175[i]);
+	for (i = 0; i < 31; i++)
+		id->words176_205[i] = __le16_to_cpu(id->words176_205[i]);
+	for (i = 0; i < 48; i++)
+		id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);
+	id->integrity_word  = __le16_to_cpu(id->integrity_word);
+# else
+#  error "Please fix <asm/byteorder.h>"
+# endif
+#endif
+	ide_fixstring(id->model,     sizeof(id->model));
+	ide_fixstring(id->fw_rev,    sizeof(id->fw_rev));
+	ide_fixstring(id->serial_no, sizeof(id->serial_no));
+}
+
+/**
+ *	ata_identify_ioctl - Handler for HDIO_GET_IDENTITY ioctl
+ *	@scsidev: Device to which we are issuing command
+ *	@id: a SECTOR_SIZE buffer in which to return the ATA identity
+ *
+ *	LOCKING:
+ *	Defined by the SCSI layer.  We don't really care.
+ *
+ *	RETURNS:
+ *	Zero on success, negative errno on error.
+ */
+int ata_identify_ioctl(struct scsi_device *scsidev,
+		int cmd, u8 *argbuf)
+{
+	int rc = 0;
+	u8 scsi_cmd[MAX_COMMAND_SIZE];
+	struct scsi_request *sreq;
+	struct hd_driveid *id;
+
+	sreq = scsi_allocate_request(scsidev);
+	if (!sreq)
+		return -EINTR;
+
+	memset(scsi_cmd, 0, sizeof(scsi_cmd));
+	scsi_cmd[0]  = ATA_16;
+	scsi_cmd[14] = cmd;      /* WIN_IDENTIFY or WIN_PIDENTIFY */
+	scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
+	scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
+				    block count in sector count field */
+	sreq->sr_data_direction = DMA_FROM_DEVICE;
+
+	/* Good values for timeout and retries?  Values below
+	   from scsi_ioctl_send_command() for default case... */
+	scsi_wait_req(sreq, scsi_cmd, argbuf, SECTOR_SIZE, (10*HZ), 5);
+
+	if (sreq->sr_result) {
+		rc = -EIO;
+		goto error;
+	}
+
+	/* Need code to retrieve data from check condition? */
+
+	id = (struct hd_driveid *) argbuf;
+	ide_fix_driveid(id);
+
+error:
+	scsi_release_request(sreq);
+	return rc;
+}
+
 int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
 {
 	struct ata_port *ap;
@@ -312,6 +672,39 @@
 			return -EACCES;
 		return ata_task_ioctl(scsidev, arg);
 
+	case HDIO_DRIVE_TASKFILE:
+		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+			return -EACCES;
+		return ata_taskfile_ioctl(scsidev, arg);
+
+	case HDIO_GET_IDENTITY:
+	case HDIO_OBSOLETE_IDENTITY:
+		{
+			int ret, idcmd;
+			u8 *argbuf;
+
+			if (!capable(CAP_SYS_RAWIO))
+				return -EACCES;
+
+			argbuf = kmalloc(SECTOR_SIZE, GFP_KERNEL);
+			if (NULL == (void *)argbuf) {
+				return -ENOMEM;
+			}
+
+			idcmd = WIN_IDENTIFY;
+			if (!atapi_enabled && dev->class == ATA_DEV_ATAPI) {
+				idcmd = WIN_PIDENTIFY;
+			}
+			ret = ata_identify_ioctl(scsidev, idcmd, argbuf);
+			if (ret!=0 || copy_to_user((char *)arg, (char *)argbuf,
+					(cmd == HDIO_GET_IDENTITY) ?
+					sizeof(struct hd_driveid) : 142))
+			{
+				ret = -EFAULT;
+			}
+			kfree(argbuf);
+			return ret;
+		}
 	default:
 		rc = -ENOTTY;
 		break;
#6 lore raw
In reply to Jeff Garzik

Hi Jeff,

Quoted 21 lines · Jeff Garzik
Quoted 20 lines · Erik Andersen
Quoted 3 lines · Jeff Garzik

Now that ATAPI support is pretty stable, the 2.4 version of libata will be receiving its final updates soon. Here is the current backport, for testing and feedback.

Awesome. 2.4.x lacks KM_IRQ0 in kmap_types.h

gcc -D__KERNEL__ -I/usr/src/linux-2.4.32/include -Wall

(quoted diff) +0 -5
-Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common 
-fomit-frame-pointer -Os -falign-functions=2 -falign-jumps=2 
-falign-labels=2 -falign-loops=2 -pipe -mpreferred-stack-boundary=2 
-march=i486  -DMODULE  -nostdinc -iwithprefix include 
-DKBUILD_BASENAME=libata_core  -DEXPORT_SYMTAB -c libata-core.c

libata-core.c: In function `ata_sg_clean':
libata-core.c:2427: error: `KM_IRQ0' undeclared (first use in this function)
libata-core.c:2427: error: (Each undeclared identifier is reported only once

Quoted 8 lines
Quoted 5 lines

libata-core.c:2427: error: for each function it appears in.) libata-core.c: In function `ata_sg_setup':
libata-core.c:2701: error: `KM_IRQ0' undeclared (first use in this function)
make[2]: *** [libata-core.o] Error 1

hmmm, interesting. Easy enough to fix. I guess I didn't build on a highmem box.

Same problem for me, but unfortunately, I don't know how to fix this. I've seen that KM_IRQ* are not defined on x86. I don't know if I can use other ones, not what would be the consequences. Would you please enlighten me a bit on this, I'm willing to test it but don't know how to build it first.

Thanks in advance,
Willy

#7 lore raw

PATCH 1/1 2.4.x SATA with highmem

Hi Jeff,

Quoted 6 lines · Willy Tarreau
Quoted 6 lines
Quoted 5 lines

libata-core.c:2427: error: for each function it appears in.) libata-core.c: In function `ata_sg_setup':
libata-core.c:2701: error: `KM_IRQ0' undeclared (first use in this function)
make[2]: *** [libata-core.o] Error 1

Quoted 7 lines
Quoted 2 lines

hmmm, interesting. Easy enough to fix. I guess I didn't build on a highmem box.

Same problem for me, but unfortunately, I don't know how to fix this. I've seen that KM_IRQ* are not defined on x86. I don't know if I can use other ones, not what would be the consequences. Would you please enlighten me a bit on this, I'm willing to test it but don't know how to build it first.

Well, after finding a good doc on kmap_atomic on lwn.net, I think I understood how to fix this. I grepped the whole kernel for kmap_atomic() and found that KM_BIO_IRQ was only used by ntfs, which had a comment stating that it was used to support highmem. So I thought we could share the same type and rediffed the patch, and now the kernel builds.

Here is my proposal, I hope it's correct.

Cheers,
Willy

drivers/scsi/libata-core.c +4 -4
diff -urN linux-2.4.32-libata1/drivers/scsi/libata-core.c linux-2.4.32-libata1-highmem/drivers/scsi/libata-core.c
@@ -2424,9 +2424,9 @@
 		sg[qc->orig_n_elem - 1].length += qc->pad_len;
 		if (pad_buf) {
 			struct scatterlist *psg = &qc->pad_sgent;
-			void *addr = kmap_atomic(psg->page, KM_IRQ0);
+			void *addr = kmap_atomic(psg->page, KM_BIO_IRQ);
 			memcpy(addr + psg->offset, pad_buf, qc->pad_len);
-			kunmap_atomic(psg->page, KM_IRQ0);
+			kunmap_atomic(psg->page, KM_BIO_IRQ);
 		}
 	} else {
 		if (sg_dma_len(&sg[0]) > 0)
@@ -2698,9 +2698,9 @@
 		psg->offset = offset_in_page(offset);
 
 		if (qc->tf.flags & ATA_TFLAG_WRITE) {
-			void *addr = kmap_atomic(psg->page, KM_IRQ0);
+			void *addr = kmap_atomic(psg->page, KM_BIO_IRQ);
 			memcpy(pad_buf, addr + psg->offset, qc->pad_len);
-			kunmap_atomic(psg->page, KM_IRQ0);
+			kunmap_atomic(psg->page, KM_BIO_IRQ);
 		}
 
 		sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
#8 lore raw

Re: [PATCH] 2.4.x SATA with highmem

Hi Again,

sorry for the noise. I applied this patch on an already patched kernel. KM_BIO_IRQ does not exist on vanilla 2.4.32. However, KM_SOFTIRQ0 is not used, so here is the patch reworked to use that instead.

Regards,
Willy

drivers/scsi/libata-core.c +4 -4
diff -urN linux-2.4.32-libata1/drivers/scsi/libata-core.c linux-2.4.32-libata1-highmem/drivers/scsi/libata-core.c
@@ -2424,9 +2424,9 @@
 		sg[qc->orig_n_elem - 1].length += qc->pad_len;
 		if (pad_buf) {
 			struct scatterlist *psg = &qc->pad_sgent;
-			void *addr = kmap_atomic(psg->page, KM_IRQ0);
+			void *addr = kmap_atomic(psg->page, KM_SOFTIRQ0);
 			memcpy(addr + psg->offset, pad_buf, qc->pad_len);
-			kunmap_atomic(psg->page, KM_IRQ0);
+			kunmap_atomic(psg->page, KM_SOFTIRQ0);
 		}
 	} else {
 		if (sg_dma_len(&sg[0]) > 0)
@@ -2698,9 +2698,9 @@
 		psg->offset = offset_in_page(offset);
 
 		if (qc->tf.flags & ATA_TFLAG_WRITE) {
-			void *addr = kmap_atomic(psg->page, KM_IRQ0);
+			void *addr = kmap_atomic(psg->page, KM_SOFTIRQ0);
 			memcpy(pad_buf, addr + psg->offset, qc->pad_len);
-			kunmap_atomic(psg->page, KM_IRQ0);
+			kunmap_atomic(psg->page, KM_SOFTIRQ0);
 		}
 
 		sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);