iprutils/iprupdate.c
brking 4c5eeb2ffc - Removed mention of primary/secondary adapters in some error
screens since multi-initiator RAID is not supported and the
  messages will just cause confusion.
- iprconfig: During disk hotplug, wait for sd devices to show
  up. Fixes errors getting logged by iprconfig during hotplug.
- iprconfig: Fix cancel path on concurrent add/remove of disks
- Don't display current bus width and speed for SAS disks
- Fix scoping bug caught by gcc 4.0.
- Stop iprupdate from continually logging errors for adapters with
  backlevel adapter firmware.
2005-03-25 22:21:00 +00:00

223 lines
4.4 KiB
C

/**
* IBM IPR adapter microcode update utility
*
* (C) Copyright 2000, 2004
* International Business Machines Corporation and others.
* All Rights Reserved. This program and the accompanying
* materials are made available under the terms of the
* Common Public License v1.0 which accompanies this distribution.
*
*/
/*
* $Header: /cvsroot/iprdd/iprutils/iprupdate.c,v 1.21 2005/03/25 22:21:02 brking Exp $
*/
#include <unistd.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>
#include <sys/stat.h>
#ifndef iprlib_h
#include "iprlib.h"
#endif
#include <sys/mman.h>
char *tool_name = "iprupdate";
static int force_devs;
static int force_ioas;
static int ioa_needs_update(struct ipr_ioa *ioa, int silent)
{
u32 fw_version = get_ioa_fw_version(ioa);
if (fw_version >= ioa->msl)
return 0;
if (!silent)
ioa_info(ioa, "Adapter needs microcode update\n");
return 1;
}
static int dev_needs_update(struct ipr_dev *dev)
{
struct ipr_std_inq_data std_inq_data;
struct ipr_dasd_inquiry_page3 page3_inq;
struct unsupported_af_dasd *unsupp_af;
if (!dev->scsi_dev_data || ipr_is_volume_set(dev) ||
(dev->scsi_dev_data->type != TYPE_DISK &&
dev->scsi_dev_data->type != IPR_TYPE_AF_DISK))
return 0;
memset(&std_inq_data, 0, sizeof(std_inq_data));
if (ipr_inquiry(dev, IPR_STD_INQUIRY, &std_inq_data, sizeof(std_inq_data)))
return 0;
if (ipr_inquiry(dev, 3, &page3_inq, sizeof(page3_inq)))
return 0;
unsupp_af = get_unsupp_af(&std_inq_data, &page3_inq);
if (!unsupp_af)
return 0;
if (!disk_needs_msl(unsupp_af, &std_inq_data))
return 0;
scsi_info(dev, "Device needs microcode update\n");
return 1;
}
static void update_ioa_fw(struct ipr_ioa *ioa, int force)
{
int rc;
struct ipr_fw_images *list;
if (!ioa_needs_update(ioa, 1))
return;
rc = get_ioa_firmware_image_list(ioa, &list);
if (rc < 1) {
if (ioa->should_init)
ipr_log_ucode_error(ioa);
return;
}
ipr_update_ioa_fw(ioa, list, force);
free(list);
}
static void update_disk_fw(struct ipr_dev *dev)
{
int rc;
struct ipr_fw_images *list;
if (polling_mode && !dev->should_init)
return;
if (!dev->scsi_dev_data || ipr_is_volume_set(dev) ||
(dev->scsi_dev_data->type != TYPE_DISK &&
dev->scsi_dev_data->type != IPR_TYPE_AF_DISK))
return;
rc = get_dasd_firmware_image_list(dev, &list);
if (rc > 0) {
ipr_update_disk_fw(dev, list, force_devs);
free(list);
}
return;
}
static int download_needed(struct ipr_ioa *ioa)
{
struct ipr_dev *dev;
int rc = 0;
rc |= ioa_needs_update(ioa, 0);
for_each_dev(ioa, dev)
rc |= dev_needs_update(dev);
return rc;
}
static int any_download_needed()
{
struct ipr_ioa *ioa;
int rc = 0;
tool_init(1);
check_current_config(false);
for_each_ioa(ioa)
rc |= download_needed(ioa);
return rc;
}
static void update_ioa(struct ipr_ioa *ioa)
{
struct ipr_dev *dev;
if (polling_mode && !ioa->should_init)
return;
update_ioa_fw(ioa, force_ioas);
for_each_dev(ioa, dev)
update_disk_fw(dev);
}
static void update_all()
{
struct ipr_ioa *ioa;
polling_mode = 1;
tool_init(1);
check_current_config(false);
for_each_ioa(ioa)
update_ioa(ioa);
}
static void kevent_handler(char *buf)
{
polling_mode = 0;
if (!strncmp(buf, "change@/class/scsi_host", 23))
scsi_host_kevent(buf, update_ioa);
else if (!strncmp(buf, "add@/class/scsi_generic", 23))
scsi_dev_kevent(buf, find_gen_dev, update_disk_fw);
else if (!strncmp(buf, "add@/block/sd", 13))
scsi_dev_kevent(buf, find_blk_dev, update_disk_fw);
}
int main(int argc, char *argv[])
{
int i;
int check_levels = 0;
openlog("iprupdate", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
for (i = 1; i < argc; i++) {
if (parse_option(argv[i]))
continue;
else if (strcmp(argv[i], "--force-devs") == 0)
force_devs = 1;
else if (strcmp(argv[i], "--force-ioas") == 0)
force_ioas = 1;
else if (strcmp(argv[i], "--check_only") == 0)
check_levels = 1;
else {
printf("Usage: iprupdate [options]\n");
printf(" Options: --version Print iprupdate version\n");
printf(" --daemon Run as a daemon\n");
printf(" --check_only Check for needed updates\n");
exit(1);
}
}
if (ipr_force)
force_devs = force_ioas = 1;
ipr_sg_required = 1;
if (check_levels)
return any_download_needed();
update_all();
if (!daemonize)
return 0;
force_devs = force_ioas = 0;
ipr_daemonize();
return handle_events(update_all, 60, kevent_handler);
}