More SAS SES code download updates

This commit is contained in:
brking 2006-12-01 22:21:18 +00:00
commit 41dcb2e7c7
5 changed files with 243 additions and 105 deletions

View file

@ -1433,6 +1433,25 @@ static int print_ses_devices(struct ipr_ioa *ioa,
return num_lines;
}
static int print_sas_ses_devices(struct ipr_ioa *ioa,
i_container **i_con, char **buffer, int type)
{
struct ipr_dev *dev;
int k;
int num_lines = 0;
if (__ioa_is_spi(ioa))
return 0;
for_each_ses(ioa, dev) {
print_dev(k, dev, buffer, "%1", type+k);
*i_con = add_i_con(*i_con, "\0", dev);
num_lines++;
}
return num_lines;
}
static int print_vsets(struct ipr_ioa *ioa,
i_container **i_con, char **buffer, int type)
{
@ -1930,7 +1949,7 @@ static char *disk_details(char *body, struct ipr_dev *dev)
static char *ses_details(char *body, struct ipr_dev *dev)
{
int rc;
struct ipr_dasd_inquiry_page3 page3_inq;
u8 release_level[4];
char product_id[IPR_PROD_ID_LEN+1];
char vendor_id[IPR_VENDOR_ID_LEN+1];
char buffer[100];
@ -1943,18 +1962,16 @@ static char *ses_details(char *body, struct ipr_dev *dev)
body = add_line_to_body(body,_("Manufacturer"), vendor_id);
body = add_line_to_body(body,_("Product ID"), product_id);
rc = ipr_inquiry(dev, 0x03, &page3_inq, sizeof(page3_inq));
rc = ipr_get_fw_version(dev, release_level);
if (!rc) {
len = sprintf(buffer, "%X%X%X%X", page3_inq.release_level[0],
page3_inq.release_level[1], page3_inq.release_level[2],
page3_inq.release_level[3]);
len = sprintf(buffer, "%X%X%X%X", release_level[0], release_level[1],
release_level[2], release_level[3]);
if (isalnum(page3_inq.release_level[0]) && isalnum(page3_inq.release_level[1]) &&
isalnum(page3_inq.release_level[2]) && isalnum(page3_inq.release_level[3])) {
sprintf(buffer + len, " (%c%c%c%c)", page3_inq.release_level[0],
page3_inq.release_level[1], page3_inq.release_level[2],
page3_inq.release_level[3]);
if (isalnum(release_level[0]) && isalnum(release_level[1]) &&
isalnum(release_level[2]) && isalnum(release_level[3])) {
sprintf(buffer + len, " (%c%c%c%c)", release_level[0],
release_level[1], release_level[2], release_level[3]);
}
body = add_line_to_body(body, _("Firmware Version"), buffer);
@ -7839,9 +7856,7 @@ int download_ucode(i_container * i_con)
continue;
num_lines += print_standalone_disks(ioa, &i_con, buffer, 0);
/* xxx
num_lines += print_ses_devices(ioa, &i_con, buffer, 0);
*/
num_lines += print_sas_ses_devices(ioa, &i_con, buffer, 0);
num_lines += print_hotspare_disks(ioa, &i_con, buffer, 0);
/* print volume set associated devices*/
@ -7887,7 +7902,7 @@ static int update_ucode(struct ipr_dev *dev, struct ipr_fw_images *fw_image)
char *body;
int header_lines, status, time = 0;
pid_t pid, done;
struct ipr_dasd_inquiry_page3 page3_inq;
u8 release_level[5];
u32 fw_version;
int rc = 0;
@ -7912,13 +7927,15 @@ static int update_ucode(struct ipr_dev *dev, struct ipr_fw_images *fw_image)
exit(0);
}
memset(&page3_inq, 0, sizeof(page3_inq));
ipr_inquiry(dev, 3, &page3_inq, sizeof(page3_inq));
ipr_get_fw_version(dev, release_level);
fw_version = page3_inq.release_level[0] << 24 |
page3_inq.release_level[1] << 16 |
page3_inq.release_level[2] << 8 |
page3_inq.release_level[3];
if (ipr_is_ses(dev)) {
release_level[4] = '\0';
fw_version = strtoul((char *)release_level, NULL, 16);
} else {
fw_version = release_level[0] << 24 | release_level[1] << 16 |
release_level[2] << 8 | release_level[3];
}
if (fw_version != fw_image->version)
rc = 67 | EXIT_FLAG;
@ -7944,16 +7961,14 @@ int process_choose_ucode(struct ipr_dev *dev)
int version_swp;
char *version;
struct screen_output *s_out;
struct ipr_dasd_inquiry_page3 page3_inq;
u8 release_level[4];
if (!dev->scsi_dev_data)
return 67 | EXIT_FLAG;
if (dev->scsi_dev_data->type == IPR_TYPE_ADAPTER)
rc = get_ioa_firmware_image_list(dev->ioa, &list);
/* xxx
else if (dev->scsi_dev_data->type == TYPE_ENCLOSURE || dev->scsi_dev_data->type == TYPE_PROCESSOR)
rc = get_ses_firmware_image_list(dev, &list);
*/
else
rc = get_dasd_firmware_image_list(dev, &list);
@ -7962,8 +7977,7 @@ int process_choose_ucode(struct ipr_dev *dev)
else
list_count = rc;
memset(&page3_inq, 0, sizeof(page3_inq));
ipr_inquiry(dev, 3, &page3_inq, sizeof(page3_inq));
ipr_get_fw_version(dev, release_level);
if (dev->scsi_dev_data &&
dev->scsi_dev_data->type == IPR_TYPE_ADAPTER) {
@ -7985,27 +7999,21 @@ int process_choose_ucode(struct ipr_dev *dev)
body = add_string_to_body(body, buffer, "", &header_lines);
if (isprint(page3_inq.release_level[0]) &&
isprint(page3_inq.release_level[1]) &&
isprint(page3_inq.release_level[2]) &&
isprint(page3_inq.release_level[3]))
if (isprint(release_level[0]) &&
isprint(release_level[1]) &&
isprint(release_level[2]) &&
isprint(release_level[3]))
sprintf(buffer, "%s%02X%02X%02X%02X (%c%c%c%c)\n\n",
_("The current microcode for this device is: "),
page3_inq.release_level[0],
page3_inq.release_level[1],
page3_inq.release_level[2],
page3_inq.release_level[3],
page3_inq.release_level[0],
page3_inq.release_level[1],
page3_inq.release_level[2],
page3_inq.release_level[3]);
release_level[0], release_level[1],
release_level[2], release_level[3],
release_level[0], release_level[1],
release_level[2], release_level[3]);
else
sprintf(buffer, "%s%02X%02X%02X%02X\n\n",
_("The current microcode for this device is: "),
page3_inq.release_level[0],
page3_inq.release_level[1],
page3_inq.release_level[2],
page3_inq.release_level[3]);
release_level[0], release_level[1],
release_level[2], release_level[3]);
body = add_string_to_body(body, buffer, "", &header_lines);
body = __body_init(body, n_choose_ucode.header, &header_lines);
@ -8057,7 +8065,7 @@ int process_choose_ucode(struct ipr_dev *dev)
if (!found)
goto leave;
body = body_init(n_confirm_download_ucode.header, &header_lines);
version_swp = htonl(fw_image->version);
version = (char *)&version_swp;

242
iprlib.c
View file

@ -10,7 +10,7 @@
*/
/*
* $Header: /cvsroot/iprdd/iprutils/iprlib.c,v 1.103 2006/11/16 20:31:25 brking Exp $
* $Header: /cvsroot/iprdd/iprutils/iprlib.c,v 1.104 2006/12/01 22:21:18 brking Exp $
*/
#ifndef iprlib_h
@ -32,6 +32,7 @@ int ipr_force = 0;
int ipr_sg_required = 0;
int polling_mode = 0;
int ipr_fast = 0;
static int ipr_mode5_write_buffer = 0;
struct sysfs_dev *head_zdev = NULL;
struct sysfs_dev *tail_zdev = NULL;
@ -710,16 +711,12 @@ static enum ipr_tcq_mode ioa_get_tcq_mode(struct ipr_ioa *ioa)
return IPR_TCQ_FROZEN;
}
int ioa_is_spi(struct ipr_ioa *ioa)
int __ioa_is_spi(struct ipr_ioa *ioa)
{
struct ipr_mode_pages mode_pages;
struct sense_data_t sense_data;
const struct ioa_details *details = get_ioa_details(ioa);
int rc;
if (details)
return details->is_spi;
rc = mode_sense(&ioa->ioa, 0x28, &mode_pages, &sense_data);
if (rc && sense_data.sense_key == ILLEGAL_REQUEST)
@ -727,6 +724,15 @@ int ioa_is_spi(struct ipr_ioa *ioa)
return 1;
}
int ioa_is_spi(struct ipr_ioa *ioa)
{
const struct ioa_details *details = get_ioa_details(ioa);
if (details)
return details->is_spi;
return __ioa_is_spi(ioa);
}
static const char *raid_desc = "PCI-X SCSI RAID Adapter";
static const char *jbod_desc = "PCI-X SCSI Adapter";
static const char *sas_raid_desc = "PCI-X SAS RAID Adapter";
@ -988,6 +994,8 @@ int parse_option(char *opt)
ipr_force_uevents = 1;
else if (strcmp(opt, "--fast") == 0)
ipr_fast = 1;
else if (strcmp(opt, "--mode5-write-buffer") == 0)
ipr_mode5_write_buffer = 1;
else
return 0;
@ -2174,7 +2182,6 @@ int __ipr_test_unit_ready(struct ipr_dev *dev,
close(fd);
return rc;
}
int ipr_test_unit_ready(struct ipr_dev *dev,
@ -2183,6 +2190,7 @@ int ipr_test_unit_ready(struct ipr_dev *dev,
int rc = __ipr_test_unit_ready(dev, sense_data);
if (rc != 0 && sense_data->sense_key != NOT_READY &&
sense_data->sense_key != UNIT_ATTENTION &&
(!strcmp(tool_name, "iprconfig") || ipr_debug))
scsi_cmd_err(dev, sense_data, "Test Unit Ready", rc);
@ -2362,6 +2370,25 @@ int ipr_inquiry(struct ipr_dev *dev, u8 page, void *buff, u8 length)
return rc;
}
int ipr_get_fw_version(struct ipr_dev *dev, u8 release_level[4])
{
struct ipr_dasd_inquiry_page3 page3_inq;
int rc;
memset(&page3_inq, 0, sizeof(page3_inq));
rc = ipr_inquiry(dev, 3, &page3_inq, sizeof(page3_inq));
if (rc)
return rc;
if (ipr_is_ses(dev) && !__ioa_is_spi(dev->ioa))
memcpy(release_level, page3_inq.load_id, 4);
else
memcpy(release_level, page3_inq.release_level, 4);
return 0;
}
static void ipr_init_res_addr_aliases(struct ipr_res_addr_aliases *aliases,
struct ipr_res_addr *res_addr)
{
@ -2561,23 +2588,96 @@ fail:
return dev->gen_name;
}
int ipr_write_buffer(struct ipr_dev *dev, void *buff, int length)
static int ipr_resume_device_bus(struct ipr_ioa *ioa,
struct ipr_res_addr *res_addr)
{
int fd, rc, i;
int fd, rc;
u8 cdb[IPR_CCB_CDB_LEN];
struct sense_data_t sense_data;
struct ipr_disk_attr attr;
int old_qdepth;
int length = 0;
if (strlen(ioa->ioa.gen_name) == 0)
return -ENOENT;
fd = open(ioa->ioa.gen_name, O_RDWR);
if (fd <= 1) {
if (!strcmp(tool_name, "iprconfig") || ipr_debug)
syslog(LOG_ERR, "Could not open %s. %m\n", ioa->ioa.gen_name);
return errno;
}
memset(cdb, 0, IPR_CCB_CDB_LEN);
cdb[0] = IPR_RESUME_DEV_BUS;
cdb[1] = IPR_RDB_UNQUIESCE_AND_REBALANCE;
cdb[3] = res_addr->bus;
cdb[4] = res_addr->target;
cdb[5] = res_addr->lun;
rc = sg_ioctl(fd, cdb, NULL,
length, SG_DXFER_FROM_DEV,
&sense_data, IPR_SUSPEND_DEV_BUS_TIMEOUT);
close(fd);
return rc;
}
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;
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;
}
memset(cdb, 0, IPR_CCB_CDB_LEN);
cdb[0] = WRITE_BUFFER;
cdb[1] = mode;
cdb[6] = (length & 0xff0000) >> 16;
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);
close(fd);
return rc;
}
int ipr_write_buffer(struct ipr_dev *dev, void *buff, int length)
{
int rc, i;
struct sense_data_t sense_data;
struct ipr_disk_attr attr;
int old_qdepth;
int sas_ses = 0;
int mode5 = 1;
if ((rc = ipr_get_dev_attr(dev, &attr))) {
scsi_dbg(dev, "Failed to get device attributes. rc=%d\n", rc);
return rc;
}
if (ipr_is_ses(dev) && !__ioa_is_spi(dev->ioa))
sas_ses = 1;
if (sas_ses && !ipr_mode5_write_buffer)
mode5 = 0;
/*
* Set the queue depth to 1 for the duration of the code download.
* This prevents us from getting I/O errors during the code update
@ -2589,53 +2689,59 @@ int ipr_write_buffer(struct ipr_dev *dev, void *buff, int length)
return rc;
}
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;
}
if (sas_ses) {
if (!mode5) {
rc = __ipr_write_buffer(dev, 0x0e, buff, length, &sense_data);
if (rc && sense_data.sense_key == ILLEGAL_REQUEST)
mode5 = 1;
else if (rc)
goto out;
}
memset(cdb, 0, IPR_CCB_CDB_LEN);
rc = ipr_suspend_device_bus(dev->ioa, &dev->res_addr[0],
IPR_SDB_CHECK_AND_QUIESCE_ENC);
cdb[0] = WRITE_BUFFER;
cdb[1] = 5;
cdb[6] = (length & 0xff0000) >> 16;
cdb[7] = (length & 0x00ff00) >> 8;
cdb[8] = length & 0x0000ff;
if (rc) {
scsi_dbg(dev, "Failed to quiesce the SAS port.\n");
goto out;
}
rc = sg_ioctl(fd, cdb, buff,
length, SG_DXFER_TO_DEV,
&sense_data, IPR_WRITE_BUFFER_TIMEOUT);
if (rc != 0) {
scsi_cmd_err(dev, &sense_data, "Write buffer", rc);
} else {
if (ipr_is_ses(dev))
sleep(120);
if (mode5)
rc = __ipr_write_buffer(dev, 5, buff, length, &sense_data);
else
sleep(5);
rc = __ipr_write_buffer(dev, 0x0f, NULL, 0, &sense_data);
/* Wait for the device to come back to life */
for (i = 0, rc = -1; rc && (i < 60); i ++)
rc = __ipr_test_unit_ready(dev, &sense_data);
if (rc) {
scsi_dbg(dev, "Write buffer %sfailed.\n", mode5 ? "" : "activate ");
goto out_resume;
}
} else {
if ((rc = __ipr_write_buffer(dev, 5, buff, length, &sense_data)))
goto out;
}
close(fd);
scsi_dbg(dev, "Waiting for device to come ready after download\n");
sleep(sas_ses ? 120 : 5);
for (i = 0, rc = -1; rc && (i < 60); i++, sleep(1))
rc = __ipr_test_unit_ready(dev, &sense_data);
out_resume:
if (sas_ses)
ipr_resume_device_bus(dev->ioa, &dev->res_addr[0]);
out:
attr.queue_depth = old_qdepth;
ipr_set_dev_attr(dev, &attr, 0);
return rc;
}
int ipr_suspend_device_bus(struct ipr_ioa *ioa,
struct ipr_res_addr *res_addr, u8 option)
{
int fd;
int fd, rc;
u8 cdb[IPR_CCB_CDB_LEN];
struct sense_data_t sense_data;
int rc;
int length = 0;
if (strlen(ioa->ioa.gen_name) == 0)
@ -2660,7 +2766,6 @@ int ipr_suspend_device_bus(struct ipr_ioa *ioa,
length, SG_DXFER_FROM_DEV,
&sense_data, IPR_SUSPEND_DEV_BUS_TIMEOUT);
/* FIXME will rc != 0 if sense data */
close(fd);
return rc;
}
@ -3529,7 +3634,7 @@ void check_current_config(bool allow_rebuild_refresh)
/* Send Test Unit Ready to start device if its a volume set */
/* xxx try to remove this */
if (!ipr_fast && ipr_is_volume_set(&ioa->dev[device_count]))
ipr_test_unit_ready(&ioa->dev[device_count], &sense_data);
__ipr_test_unit_ready(&ioa->dev[device_count], &sense_data);
device_count++;
} else if (scsi_dev_data->type == IPR_TYPE_ADAPTER) {
@ -4694,19 +4799,18 @@ u32 get_dasd_ucode_version(char *ucode_file, int has_hdr)
u32 get_dev_fw_version(struct ipr_dev *dev)
{
struct ipr_dasd_inquiry_page3 page3_inq;
u8 release_level[4];
int rc;
memset(&page3_inq, 0, sizeof(page3_inq));
rc = ipr_inquiry(dev, 3, &page3_inq, sizeof(page3_inq));
rc = ipr_get_fw_version(dev, release_level);
if (rc != 0) {
scsi_dbg(dev, "Inquiry failed\n");
return 0;
}
rc = page3_inq.release_level[0] << 24 | page3_inq.release_level[1] << 16 |
page3_inq.release_level[2] << 8 | page3_inq.release_level[3];
rc = release_level[0] << 24 | release_level[1] << 16 |
release_level[2] << 8 | release_level[3];
return rc;
}
@ -4875,38 +4979,51 @@ int get_dasd_firmware_image_list(struct ipr_dev *dev,
return len;
}
static int get_ses_load_id(struct ipr_dev *dev, u8 load_id[4])
{
struct ipr_dasd_inquiry_page3 page3_inq;
int rc;
memset(&page3_inq, 0, sizeof(page3_inq));
rc = ipr_inquiry(dev, 3, &page3_inq, sizeof(page3_inq));
if (rc)
return rc;
if (ipr_is_ses(dev) && !__ioa_is_spi(dev->ioa))
memcpy(load_id, page3_inq.release_level, 4);
else
memcpy(load_id, page3_inq.load_id, 4);
return 0;
}
int get_ses_firmware_image_list(struct ipr_dev *dev,
struct ipr_fw_images **list)
{
char buf[100];
struct ipr_fw_images *ret = NULL;
struct ipr_dasd_inquiry_page3 page3_inq;
u8 load_id[4];
int rc;
int len = 0;
/* xxx */
return 0;
*list = NULL;
memset(&page3_inq, 0, sizeof(page3_inq));
rc = ipr_inquiry(dev, 3, &page3_inq, sizeof(page3_inq));
rc = get_ses_load_id(dev, load_id);
if (rc != 0) {
scsi_dbg(dev, "Inquiry failed\n");
return -EIO;
}
sprintf(buf, "%02X%02X%02X%02X",
page3_inq.load_id[0], page3_inq.load_id[1],
page3_inq.load_id[2], page3_inq.load_id[3]);
sprintf(buf, "%02X%02X%02X%02X", load_id[0], load_id[1],
load_id[2], load_id[3]);
len = scan_fw_dir(UCODE_BASE_DIR, buf, &ret, len,
init_disk_ucode_entry_nohdr);
sprintf(buf, "IBM-%02X%02X%02X%02X",
page3_inq.load_id[0], page3_inq.load_id[1],
page3_inq.load_id[2], page3_inq.load_id[3]);
sprintf(buf, "IBM-%02X%02X%02X%02X", load_id[0], load_id[1],
load_id[2], load_id[3]);
len = scan_fw_dir(LINUX_UCODE_BASE_DIR, buf, &ret, len,
init_disk_ucode_entry_nohdr);
@ -5395,8 +5512,11 @@ static void init_gpdd_dev(struct ipr_dev *dev)
if (polling_mode && !dev->should_init)
return;
if (ipr_test_unit_ready(dev, &sense_data))
return;
if (ipr_test_unit_ready(dev, &sense_data)) {
if ((sense_data.sense_key != UNIT_ATTENTION) ||
ipr_test_unit_ready(dev, &sense_data))
return;
}
if (enable_af(dev))
return;
if (ipr_get_dev_attr(dev, &attr))

View file

@ -12,7 +12,7 @@
*/
/*
* $Header: /cvsroot/iprdd/iprutils/iprlib.h,v 1.87 2006/11/16 20:31:25 brking Exp $
* $Header: /cvsroot/iprdd/iprutils/iprlib.h,v 1.88 2006/12/01 22:21:18 brking Exp $
*/
#include <stdarg.h>
@ -82,6 +82,8 @@
#define IPR_RECLAIM_NUM_BLOCKS_MULTIPLIER 256
#define IPR_SDB_CHECK_AND_QUIESCE 0x00
#define IPR_SDB_CHECK_ONLY 0x40
#define IPR_SDB_CHECK_AND_QUIESCE_ENC 0x0e
#define IPR_RDB_UNQUIESCE_AND_REBALANCE 0x20
#define IPR_MAX_NUM_SUPP_INQ_PAGES 36
#define IPR_DUMP_TRACE_ENTRY_SIZE 8192
#define IPR_MODE_SENSE_LENGTH 255
@ -138,6 +140,7 @@
#define IPR_QUERY_RESOURCE_STATE 0xC2
#define IPR_QUERY_COMMAND_STATUS 0xCB
#define IPR_SUSPEND_DEV_BUS 0xC8
#define IPR_RESUME_DEV_BUS 0xC9
#define IPR_IOA_SERVICE_ACTION 0xD2
#define IPR_QUERY_RES_ADDR_ALIASES 0x10
#define IPR_DISRUPT_DEVICE 0x11
@ -1947,6 +1950,7 @@ void ipr_log_ucode_error(struct ipr_ioa *);
u32 get_dasd_ucode_version(char *, int);
const char *get_ioa_desc(struct ipr_ioa *);
int ioa_is_spi(struct ipr_ioa *);
int __ioa_is_spi(struct ipr_ioa *);
int page0x0a_setup(struct ipr_dev *);
int handle_events(void (*) (void), int, void (*) (char *));
struct ipr_ioa *find_ioa(int);
@ -1966,6 +1970,7 @@ struct ipr_array_cap_entry *get_cap_entry(struct ipr_supported_arrays *, char *)
int ipr_get_blk_size(struct ipr_dev *);
u32 get_ioa_ucode_version(char *);
int ipr_improper_device_type(struct ipr_dev *);
int ipr_get_fw_version(struct ipr_dev *, u8 release_level[4]);
static inline int ipr_is_af_dasd_device(struct ipr_dev *device)
{

View file

@ -56,9 +56,14 @@ rm -rf $RPM_BUILD_ROOT
%{_sysconfdir}/init.d/*
%changelog
* Wed Nov 29 2006 Brian King <brking@us.ibm.com>
- Fixes for SES microcode download on SAS.
* Mon Nov 20 2006 Brian King <brking@us.ibm.com>
- Change to handle UA responses in the JBOD iprinit sequence.
* Thu Nov 16 2006 Brian King <brking@us.ibm.com>
- Fix segfault in iprconfig if /var/log does not exist.
- Allow IOA microcode download to a secondary IOA.
- Fix to prevent errors during SAS SES microcode download.
* Tue Oct 10 2006 Brian King <brking@us.ibm.com>
- Add a couple utility functions for SAS
ipr_query_sas_expander_info

View file

@ -8,7 +8,7 @@ IPR_MAJOR_RELEASE=2
IPR_MINOR_RELEASE=2
IPR_FIX_LEVEL=3
IPR_RELEASE=1
IPR_FIX_DATE=(November 15, 2006)
IPR_FIX_DATE=(November 20, 2006)
IPR_VERSION_STR=$(IPR_MAJOR_RELEASE).$(IPR_MINOR_RELEASE).$(IPR_FIX_LEVEL) $(IPR_FIX_DATE)