[Iprdd-commit] iprutils iprlib.c,1.117,1.118
Brought to you by:
brking
|
From: Tseng-Hui \(Frank\) L. <tse...@us...> - 2008-05-14 20:17:15
|
Update of /cvsroot/iprdd/iprutils In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv15590/iprutils Modified Files: iprlib.c Log Message: Change disk microcode download device to /dev/sdX Index: iprlib.c =================================================================== RCS file: /cvsroot/iprdd/iprutils/iprlib.c,v retrieving revision 1.117 retrieving revision 1.118 diff -u -d -r1.117 -r1.118 --- iprlib.c 9 Apr 2008 19:34:51 -0000 1.117 +++ iprlib.c 14 May 2008 20:17:08 -0000 1.118 @@ -346,6 +346,14 @@ {"VSBPD1H U3SCSI", "XXXXXXX*XXXXXXXX", 160, 0} }; + +/*---------- static subroutine/function declearation starts here --------*/ + +static int sg_ioctl_by_name(char *, u8 *, void *, u32, u32, + struct sense_data_t *, u32); + +/*---------- subroutine/function code starts here ---------*/ + static const struct ses_table_entry *get_ses_entry(struct ipr_ioa *ioa, int bus) { int i, j, matches; @@ -2873,24 +2881,25 @@ return rc; } +/* + * Issue WRITE_BUFFER command. + * In older kernels, max_sectors_kb is not big enough and would return + * -EIO when using dev_name to issue SG_IO ioctl(). In that case, we have + * to use gen_name. Also, in case dev_name does not exist, we need to use + * gen_name. Hence, we try dev_name first and switch to gen_name if we get + * -ENOENT or -EIO. + */ + static int __ipr_write_buffer(struct ipr_dev *dev, u8 mode, void *buff, int length, struct sense_data_t *sense_data) { - char *name = get_write_buffer_dev(dev); u32 direction = length ? SG_DXFER_TO_DEV : SG_DXFER_NONE; u8 cdb[IPR_CCB_CDB_LEN]; - int fd, rc; + int rc; - if (strlen(name) == 0) + if ((strlen(dev->dev_name) == 0) && (strlen(dev->gen_name) == 0)) return -ENOENT; - fd = open(name, O_RDWR); - if (fd <= 1) { - if (!strcmp(tool_name, "iprconfig") || ipr_debug) - syslog(LOG_ERR, "Could not open %s.\n", name); - return errno; - } - memset(cdb, 0, IPR_CCB_CDB_LEN); cdb[0] = WRITE_BUFFER; @@ -2899,14 +2908,31 @@ cdb[7] = (length & 0x00ff00) >> 8; cdb[8] = length & 0x0000ff; - rc = sg_ioctl(fd, cdb, buff, - length, direction, - sense_data, IPR_WRITE_BUFFER_TIMEOUT); - - if (rc != 0) - scsi_cmd_err(dev, sense_data, "Write buffer", rc); + rc = sg_ioctl_by_name(dev->dev_name, cdb, buff, + length, direction, + sense_data, IPR_WRITE_BUFFER_TIMEOUT); + if (rc != 0) { + if ((rc == -ENOENT) || (rc == -EIO)) { + syslog_dbg("Write buffer failed on sd device %s. %m\n", dev->dev_name); + rc = sg_ioctl_by_name(dev->gen_name, cdb, buff, + length, direction, + sense_data, IPR_WRITE_BUFFER_TIMEOUT); + if (rc != 0) { + scsi_cmd_err(dev, sense_data, + "Write buffer using sg device", rc); + if (rc == -ENOMEM) + syslog(LOG_ERR, + "Cannot get enough memory to " + "perform microcode download " + "through %s. Reduce system " + "memory usage and try again.\n", + dev->gen_name); + } + } else + scsi_cmd_err(dev, sense_data, + "Write buffer using sd device", rc); + } - close(fd); return rc; } @@ -3261,8 +3287,15 @@ return 0; } +/* + * Scatter/gather list buffers are checked against the value returned + * by queue_dma_alignment(), which defaults to 511 in Linux 2.6, + * for alignment if a SG_IO ioctl request is sent through a /dev/sdX device. + */ +#define IPR_S_G_BUFF_ALIGNMENT 512 #define IPR_MAX_XFER 0x8000 + const int cdb_size[] ={6, 10, 10, 0, 16, 12, 16, 16}; static int _sg_ioctl(int fd, u8 cdb[IPR_CCB_CDB_LEN], void *data, u32 xfer_len, u32 data_direction, @@ -3287,7 +3320,7 @@ segment_size = IPR_MAX_XFER; for (i = 0; (i < iovec_count) && (buff_len != 0); i++) { - iovec[i].iov_base = malloc(segment_size); + posix_memalign(&(iovec[i].iov_base), IPR_S_G_BUFF_ALIGNMENT, segment_size); if (data_direction == SG_DXFER_TO_DEV) memcpy(iovec[i].iov_base, data + (IPR_MAX_XFER * i), segment_size); iovec[i].iov_len = segment_size; @@ -3366,6 +3399,31 @@ sense_data, timeout_in_sec, 0); }; +static int sg_ioctl_by_name(char *name, u8 cdb[IPR_CCB_CDB_LEN], + void *data, u32 xfer_len, u32 data_direction, + struct sense_data_t *sense_data, + u32 timeout_in_sec) +{ + int fd, rc; + + if (strlen(name) <= 0) + return -ENOENT; + + fd = open(name, O_RDWR); + if (fd <= 1) { + if (!strcmp(tool_name, "iprconfig") || ipr_debug) + syslog(LOG_ERR, "Could not open %s.\n", name); + return errno; + } + + rc = sg_ioctl(fd, cdb, data, + xfer_len, data_direction, + sense_data, timeout_in_sec); + close(fd); + + return rc; +} + int ipr_set_ha_mode(struct ipr_ioa *ioa, int gscsi_only_ha) { int rc, len; |